/***************************************************************************** ** ** ** 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; }