|
|
/*****************************************************************************
** ** ** COPYRIGHT (C) 2000, 2001 MKNET CORPORATION ** ** DEVELOPED FOR THE MK7100-BASED VFIR PCI CONTROLLER. ** ** ** *****************************************************************************/
/**********************************************************************
Module Name: MK7COMM.C
Routines: MK7Reg_Write MK7Reg_Read MK7DisableInterrupt MK7EnableInterrupt MK7SwitchToRXMode MK7SwitchToTXMode SetSpeed MK7ChangeSpeedNow
Comments:
**********************************************************************/
#include "precomp.h"
#include "protot.h"
#pragma hdrstop
baudRateInfo supportedBaudRateTable[NUM_BAUDRATES] = { { BAUDRATE_2400, // Table index
2400, // bps
NDIS_IRDA_SPEED_2400, // NDIS bit mask code (NOTE: We don't support
// 2400. We set this bit to 0.)
}, { BAUDRATE_9600, 9600, NDIS_IRDA_SPEED_9600, }, { BAUDRATE_19200, 19200, NDIS_IRDA_SPEED_19200, }, { BAUDRATE_38400, 38400, NDIS_IRDA_SPEED_38400, }, { BAUDRATE_57600, 57600, NDIS_IRDA_SPEED_57600, }, { BAUDRATE_115200, 115200, NDIS_IRDA_SPEED_115200, }, { BAUDRATE_576000, 576000, NDIS_IRDA_SPEED_576K, }, { BAUDRATE_1152000, 1152000, NDIS_IRDA_SPEED_1152K, }, { BAUDRATE_4M, 4000000, NDIS_IRDA_SPEED_4M, }, { BAUDRATE_16M, 16000000, NDIS_IRDA_SPEED_16M, } };
// Write to IRCONFIG2 w/ these to set SIR/MIR speeds
MK7REG HwSirMirSpeedTable[] = { HW_SIR_SPEED_2400, HW_SIR_SPEED_9600, HW_SIR_SPEED_19200, HW_SIR_SPEED_38400, HW_SIR_SPEED_57600, HW_SIR_SPEED_115200, HW_MIR_SPEED_576000, HW_MIR_SPEED_1152000 };
#if DBG
//----------------------------------------------------------------------
//
// NOTE: The following Write and Read routines are bracketed w/ DBG
// switch. In the non-debug version, these 2 calls are inline
// macros for faster execution.
//
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// Procedure: [MK7Reg_Write]
//
// Description: Write to the MK7100 register.
// (Note: In the free build, this is an inline macro. It's
// here in the checked build for debugging.)
//----------------------------------------------------------------------
VOID MK7Reg_Write(PMK7_ADAPTER Adapter, ULONG port, USHORT val) { PUCHAR ioport;
// Break this out for debugging
ioport = Adapter->MappedIoBase + port; NdisRawWritePortUshort(ioport, val); }
//----------------------------------------------------------------------
// Procedure: [MK7Reg_Read]
//
// Description: Read from MK7100 register.
// (Note: In the free build, this is an inline macro. It's
// here in the checked build for debugging.)
//----------------------------------------------------------------------
VOID MK7Reg_Read(PMK7_ADAPTER Adapter, ULONG port, USHORT *pval) { PUCHAR ioport;
// Break this out for debugging
ioport = Adapter->MappedIoBase + port; NdisRawReadPortUshort(ioport, pval); }
#endif
//----------------------------------------------------------------------
// Procedure: [MK7DisableInterrupt]
//
// Description: Disable all interrupts on the MK7
//
// Arguments:
// Adapter - ptr to Adapter object instance
//
// Returns:
// NDIS_STATUS_SUCCESS - If an adapter is successfully found and claimed
// NDIS_STATUS_FAILURE - If an adapter is not found/claimed
//
//----------------------------------------------------------------------
NDIS_STATUS MK7DisableInterrupt(PMK7_ADAPTER Adapter) { MK7REG mk7reg; UINT i;
// NOTE: Workaround for potential hw problem where 0xFFFF is returned
for (i=0; i<50; i++) { MK7Reg_Read(Adapter, R_CFG3, &mk7reg); if (mk7reg != 0xFFFF) { break; } } ASSERT(i < 50);
mk7reg &= (~B_ENAB_INT);
MK7Reg_Write(Adapter, R_CFG3, mk7reg); return(NDIS_STATUS_SUCCESS); }
//----------------------------------------------------------------------
// Procedure: [MK7EnableInterrupt]
//
// Description: Enable all interrupts on the MK7
//
// Arguments:
// Adapter - ptr to Adapter object instance
//
// Returns:
// NDIS_STATUS_SUCCESS - If an adapter is successfully found and claimed
// NDIS_STATUS_FAILURE - If an adapter is not found/claimed
//
//----------------------------------------------------------------------
NDIS_STATUS MK7EnableInterrupt(PMK7_ADAPTER Adapter) { MK7REG mk7reg; UINT i;
// NOTE: Workaround for potential hw problem where 0xFFFF is returned
for (i=0; i<50; i++) { MK7Reg_Read(Adapter, R_CFG3, &mk7reg); if (mk7reg != 0xFFFF) { break; } } ASSERT(i < 50);
mk7reg |= B_ENAB_INT;
MK7Reg_Write(Adapter, R_CFG3, mk7reg);
// PROMPT - Always after an Enable
MK7Reg_Write(Adapter, R_PRMT, 0);
return(NDIS_STATUS_SUCCESS); }
//----------------------------------------------------------------------
// Procedure: [MK7SwitchToRXMode]
//
// Description: Put hw in receive mode.
//
// Actions:
// - Hw registers are programmed accordingly.
// - IOMode set to RX_MODE.
// - SlaveTXStuckCnt reset.
//----------------------------------------------------------------------
VOID MK7SwitchToRXMode(PMK7_ADAPTER Adapter) { MK7REG mk7reg;
MK7Reg_Read(Adapter, R_CFG0, &mk7reg); mk7reg &= (~B_CFG0_ENTX); MK7Reg_Write(Adapter, R_CFG0, mk7reg); Adapter->IOMode = RX_MODE;
DBGLOG("- Switch to RX mode", 0); }
//----------------------------------------------------------------------
// Procedure: [MK7SwitchToTXMode]
//
// Description: Put hw in receive mode.
//
// Actions:
// - Hw registers are programmed accordingly.
// - IOMode set to TX_MODE.
//----------------------------------------------------------------------
VOID MK7SwitchToTXMode(PMK7_ADAPTER Adapter) { MK7REG mk7reg;
MK7Reg_Read(Adapter, R_CFG0, &mk7reg); mk7reg |= B_CFG0_ENTX; MK7Reg_Write(Adapter, R_CFG0, mk7reg); Adapter->IOMode = TX_MODE;
DBGLOG("- Switch to TX mode", 0); }
//----------------------------------------------------------------------
// Procedure: [SetSpeed]
//
// Description:
// Set the hw to a new speed.
// [IMPORTANT: This should be called only from xxxSetInformation().]
//
// Actions:
//----------------------------------------------------------------------
BOOLEAN SetSpeed(PMK7_ADAPTER Adapter) { UINT i, bps; MK7REG mk7reg; PTCB tcb;
//******************************
// The idea is any sends that came before the change-speed command are
// sent at the old speed. There are 3 scenarios here:
// 1. There's no TXs outstanding -- We can change speed right away.
// 2. There's TXs oustanding in the TX ring but none in the TX q -- We
// do not change speed right away.
// 3. There's TXs oustanding in the TX q (may be also in the TX ring) --
// We do not change speed right away.
//******************************
DBGLOG("=> SetSpeed", 0);
// If we're already waiting to change speed, fail all such requests
// until the original is done. (Is this good?)
//if (Adapter->changeSpeedPending) {
// LOG("SetSpeed: already pending", 0);
// return (FALSE);
//}
// This means 1 TX is already active. Change speed on completion.
if (Adapter->NumPacketsQueued == 1) { Adapter->changeSpeedPending = CHANGESPEED_ON_DONE; // After the latest tx
DBGLOG("<= SetSpeed: Q", 0); return (TRUE); } else if (Adapter->NumPacketsQueued > 1) { Adapter->changeSpeedAfterThisPkt = Adapter->LastTxQueue; Adapter->changeSpeedPending = CHANGESPEED_ON_Q; DBGLOG("<= SetSpeed: Qs", 0); return (TRUE); }
// There's nothing pending TX or TX completion we must be
// changing speed in RX mode.
MK7ChangeSpeedNow(Adapter);
return(TRUE); }
//----------------------------------------------------------------------
// Procedure: [MK7ChangeSpeedNow]
//
// Description:
// Set the hw to a new speed.
//
// Actions:
//----------------------------------------------------------------------
VOID MK7ChangeSpeedNow(PMK7_ADAPTER Adapter) { UINT i, bps; MK7REG mk7reg, mk7reg_cfg3, mk7reg_w;
DBGLOG("=> MK7ChangeSpeedNow", 0);
bps = Adapter->linkSpeedInfo->bitsPerSec;
//****************************************
// Clear IRENABLE Bit
// This is the only writeable bit in this reg so just write it.
//****************************************
MK7Reg_Write(Adapter, R_ENAB, ~B_ENAB_IRENABLE);
// NOTE: Workaround for potential hw problem where 0xFFFF is returned.
// (See aLSO MK7EnableInterrupt & MK7DisableInterrupt)
for (i=0; i<50; i++) { MK7Reg_Read(Adapter, R_CFG3, &mk7reg_cfg3); if (mk7reg_cfg3 != 0xFFFF) { break; } } ASSERT(i < 50);
// Need distinguish between changing speed in RX or TX mode.
// Prep the bit that says TX or RX
if (Adapter->IOMode == TX_MODE) { mk7reg_w = 0x1000; } else { mk7reg_w = 0; }
if (bps <= MAX_SIR_SPEED) { // SIR
if (Adapter->Wireless) { // WIRELESS: ... no INVERTTX
mk7reg_w |= 0x0E18; } else { // WIRED: ENRX, DMA, small pkts, SIR, SIR RX filter, INVERTTX
mk7reg_w |= 0x0E1A; } MK7Reg_Write(Adapter, R_CFG0, mk7reg_w);
// Baud rate & pulse width
i = Adapter->linkSpeedInfo->tableIndex; mk7reg = HwSirMirSpeedTable[i]; MK7Reg_Write(Adapter, R_CFG2, mk7reg);
mk7reg_cfg3 &= ~B_FAST_TX; MK7Reg_Write(Adapter, R_CFG3, mk7reg_cfg3);
DBGLOG(" SIR", 0); } else if (bps < MIN_FIR_SPEED) { // MIR
if (Adapter->Wireless) { // WIRELESS: ... no INVERTTX
mk7reg_w |= 0x0CA0; } else { // WIRED: ENRX, DMA, 16-bit CRC, MIR, INVERTTX
mk7reg_w |= 0x0CA2; } MK7Reg_Write(Adapter, R_CFG0, mk7reg_w); // Baud rate & pulse width, & preamble
i = Adapter->linkSpeedInfo->tableIndex; mk7reg = HwSirMirSpeedTable[i]; mk7reg |= 0x0001; // Preamble
MK7Reg_Write(Adapter, R_CFG2, mk7reg);
mk7reg_cfg3 |= B_FAST_TX; MK7Reg_Write(Adapter, R_CFG3, mk7reg_cfg3);
DBGLOG(" MIR", 0); } else if (bps < VFIR_SPEED) { // FIR
if (Adapter->Wireless) { // WIRELESS: ... no INVERTTX
mk7reg_w |= 0x0C40; } else { // WIRED: ENRX, DMA, 32-bit CRC, FIR, INVERTTX
mk7reg_w |= 0x0C42; } MK7Reg_Write(Adapter, R_CFG0, mk7reg_w);
MK7Reg_Write(Adapter, R_CFG2, 0x000A); // 10 Preambles
mk7reg_cfg3 |= B_FAST_TX; MK7Reg_Write(Adapter, R_CFG3, mk7reg_cfg3);
DBGLOG(" FIR", 0); } else { // VFIR
// For testing 4Mbps in VFIR mode.
//if (Adapter->Wireless) {
// WIRELESS: ... no INVERTTX
// mk7reg_w |= 0x0C40;
//}
//else {
// WIRED: ENRX, DMA, 32-bit CRC, FIR, INVERTTX
// mk7reg_w |= 0x0C42;
//}
//MK7Reg_Write(Adapter, R_CFG0, mk7reg_w);
if (Adapter->Wireless) { // WIRELESS: ... no INVERTTX
mk7reg_w |= 0x2C00; } else { // WIRED: VFIR, ENRX, DMA, 32-bit CRC, FIR, INVERTTX
mk7reg_w |= 0x2C02; } MK7Reg_Write(Adapter, R_CFG0, mk7reg_w);
MK7Reg_Write(Adapter, R_CFG2, 0x000A); // 10 Preambles
mk7reg_cfg3 |= B_FAST_TX; MK7Reg_Write(Adapter, R_CFG3, mk7reg_cfg3);
DBGLOG(" VFIR", 0); }
Adapter->CurrentSpeed = bps;
//****************************************
// Set IRENABLE Bit
//****************************************
MK7Reg_Write(Adapter, R_ENAB, B_ENAB_IRENABLE);
//****************************************
// PROMPT
//****************************************
MK7Reg_Write(Adapter, R_PRMT, 0);
return; }
|