/***************************************************************************** ** ** ** COPYRIGHT (C) 2000, 2001 MKNET CORPORATION ** ** DEVELOPED FOR THE MK7100-BASED VFIR PCI CONTROLLER. ** ** ** *****************************************************************************/ /********************************************************************** Module Name: MKINIT.C Routines: ClaimAdapter SetupIrIoMapping SetupAdapterInfo AllocAdapterMemory ReleaseAdapterMemory FreeAdapterObject SetupTransmitQueues SetupReceiveQueues InitializeMK7 InitializeAdapter StartAdapter MK7ResetComplete ResetTransmitQueues ResetReceiveQueues Comments: Various one-time inits. This involves a combo of inits to the NDIS env and the MK7100 hw. **********************************************************************/ #include "precomp.h" #include "protot.h" #pragma hdrstop //----------------------------------------------------------------------------- // Procedure: [ClaimAdapter] // // Description: Locate a MK7-based adapter and assign (claim) the adapter // hardware. This routine also stores the slot, base IO Address, and IRQ. // // 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 ClaimAdapter(PMK7_ADAPTER Adapter, NDIS_HANDLE WrapperConfigurationContext) { USHORT NumPciBoardsFound; ULONG Bus; UINT i,j; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; USHORT VendorID = MKNET_PCI_VENDOR_ID; USHORT DeviceID = MK7_PCI_DEVICE_ID; PCI_CARDS_FOUND_STRUC PciCardsFound; PNDIS_RESOURCE_LIST AssignedResources; DBGLOG("=> ClaimAdapter", 0); // "Bus" is not used?? Bus = (ULONG) Adapter->BusNumber; if (Adapter->MKBusType != PCIBUS) { //Not supported - ISA, EISA or MicroChannel DBGLOG("<= ClaimAdapter (ERR - 1", 0); return (NDIS_STATUS_FAILURE); } NumPciBoardsFound = FindAndSetupPciDevice(Adapter, WrapperConfigurationContext, VendorID, DeviceID, &PciCardsFound); if(NumPciBoardsFound) { #if DBG DBGSTR(("\n\n Found the following adapters\n")); for(i=0; i < NumPciBoardsFound; i++) { DBGSTR(("slot=%x, io=%x, irq=%x \n", PciCardsFound.PciSlotInfo[i].SlotNumber, PciCardsFound.PciSlotInfo[i].BaseIo, PciCardsFound.PciSlotInfo[i].Irq)); } #endif } else { DBGSTR(("our PCI board was not found!!!!!!\n")); MKLogError(Adapter, EVENT_16, NDIS_ERROR_CODE_ADAPTER_NOT_FOUND, 0); DBGLOG("<= ClaimAdapter (ERR - 2", 0); return (NDIS_STATUS_FAILURE); } i = 0; // only one adapter in the system // NOTE: i == the index into PciCardsFound that we want to use. //**************************************** // Store our allocated resources in Adapter struct //**************************************** Adapter->MKSlot = PciCardsFound.PciSlotInfo[i].SlotNumber; Adapter->MKInterrupt = PciCardsFound.PciSlotInfo[i].Irq; Adapter->MKBaseIo = PciCardsFound.PciSlotInfo[i].BaseIo; DBGLOG("<= ClaimAdapter", 0); return (NDIS_STATUS_SUCCESS); } //----------------------------------------------------------------------------- // Procedure: [SetupIrIoMapping] // // Description: This sets up our assigned PCI I/O space w/ NDIS. // // Arguments: // Adapter - ptr to Adapter object instance // // Returns: // NDIS_STATUS_SUCCESS // not NDIS_STATUS_SUCCESS //----------------------------------------------------------------------------- NDIS_STATUS SetupIrIoMapping(PMK7_ADAPTER Adapter) { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; DBGFUNC("SetupIrIoMapping"); DBGLOG("=> SetupIrIoMapping", 0); Adapter->MappedIoRange = Adapter->MKBaseSize; Status = NdisMRegisterIoPortRange( (PVOID *) &Adapter->MappedIoBase, Adapter->MK7AdapterHandle, (UINT) Adapter->MKBaseIo, Adapter->MappedIoRange); DBGSTR(("SetupPciRegs: io=%x, size=%x, stat=%x\n", Adapter->MKBaseIo, Adapter->MappedIoRange, Status)); if (Status != NDIS_STATUS_SUCCESS) { DBGSTR(("ERROR: NdisMRegisterIoPortRange failed (Status = 0x%x)\n", Status)); DBGLOG("<= SetupIrIoMapping (ERR)", 0); return (Status); } DBGLOG("<= SetupIrIoMapping", 0); return (Status); } //----------------------------------------------------------------------------- // Procedure: [SetupAdapterInfo] // // Description: Sets up the various adapter fields in the specified Adapter // object. // Arguments: // Adapter - ptr to Adapter object instance // // Returns: // NDIS_STATUS_SUCCESS - If an adapter's IO mapping was setup correctly // not NDIS_STATUS_SUCCESS- If an adapter's IO space could not be registered //----------------------------------------------------------------------------- NDIS_STATUS SetupAdapterInfo(PMK7_ADAPTER Adapter) { NDIS_STATUS Status; DBGFUNC("SetupAdapterInfo"); DBGLOG("=> SetupAdapterInfo", 0); // Setup the IR Registers I/O mapping Status = SetupIrIoMapping(Adapter); Adapter->InterruptMode = NdisInterruptLevelSensitive; // Adapter->InterruptMode = NdisInterruptLatched; DBGLOG("<= SetupAdapterInfo", 0); return (Status); } //----------------------------------------------------------------------------- // Procedure: [AllocAdapterMemory] // // Description: Allocte and setup memory (control structures, shared memory // data buffers, ring buffers, etc.) for the MK7. Additional setups // may also be done later on, e.g., TX/RX CB lists, buffer lists, etc. // // Arguments: // Adapter - the adapter structure to allocate for. // // Returns: // NDIS_STATUS_SUCCESS - If the shared memory structures were setup // not NDIS_STATUS_SUCCESS- If not enough memory or map registers could be // allocated //----------------------------------------------------------------------------- NDIS_STATUS AllocAdapterMemory(PMK7_ADAPTER Adapter) { NDIS_STATUS Status; ULONG alignedphys; DBGFUNC("AllocAdapterMemory"); DBGLOG("=> SetupAdapterMemory", 0); Adapter->MaxPhysicalMappings = MK7_MAXIMUM_PACKET_SIZE_ESC; //**************************************** // We allocate several chunks of memory. They fall into 2 categories: // cached and non-cached. Memory that is shared w/ the hw is non-cached // for reason of simplicity. Cached memory is used for our internal // sw runtime operations. // // The following is done: // 1. Allocate RRDs and TRDs from non-cached memory. This is the // Ring descriptors for the hw. (The base address of this is // set in the Phoenix's Base Address Reg.) // 2. RX memory -- // I. Alloc cached memory for RCBs and RPDs. // II. Alloc non-cached for RX DMA data buffers (these are // mapped to RX packet->buffers). // 3. TX memory -- // I. Alloc cached for TCBs. // II. Alloc non-cached for TX DMA data buffers. //**************************************** //**************************************** // Since we use shared memory (NdisMAllocateSharedMemory), we have to // call NdisMAllocateMapRegisters even though we don't use such // mapping. So just ask for 1 map reg. //**************************************** Adapter->NumMapRegisters = 1; Status = NdisMAllocateMapRegisters( Adapter->MK7AdapterHandle, 0, FALSE, Adapter->NumMapRegisters, Adapter->MaxPhysicalMappings ); if (Status != NDIS_STATUS_SUCCESS) { Adapter->NumMapRegisters = 0; MKLogError(Adapter, EVENT_11, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 0); DBGSTR(("NdisMAllocateMapRegister Failed - %x\n", Status)); DBGLOG("<= SetupAdapterMemory: (ERR - NdisMAllocateMapRegister)", 0); return(Status); } //**************************************** // RRDs & TRDs (RX/TX Ring Descriptors) // // Allocate shared memory for the Phoenix Ring buffers. Each TRD and // RRD has a max count (we may not use all). This contiguous space // holds both the RRDs and TRDs. The 1st 64 entries are RRDs followed // immediately by 64 TRDs. Hence, the 1st TRD is always a max ring count // (64x8=512 bytes) from the 1st RRD. We always allocate the max for // simplicity. Allocate enough extras to align on 1k boundary. //**************************************** Adapter->RxTxUnCachedSize = 1024 + ( (sizeof(RRD) + sizeof(TRD)) * MAX_RING_SIZE ); NdisMAllocateSharedMemory(Adapter->MK7AdapterHandle, Adapter->RxTxUnCachedSize, FALSE, // non-cached (PVOID) &Adapter->RxTxUnCached, &Adapter->RxTxUnCachedPhys); if (Adapter->RxTxUnCached == NULL) { Adapter->pRrd = Adapter->pTrd = NULL; MKLogError(Adapter, EVENT_12, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 0); DBGSTR(("ERROR: Failed alloc for RRDs & TRDs\n")); DBGLOG("<= SetupAdapterMemory: (ERR - RRD/TRD mem)", Adapter->RxTxUnCachedSize); return (NDIS_STATUS_FAILURE); } // Align to 1K boundary. // NOTE: We don't modify RxTxUnCached. We need it for release later. alignedphys = NdisGetPhysicalAddressLow(Adapter->RxTxUnCachedPhys); alignedphys += 0x000003FF; alignedphys &= (~0x000003FF); Adapter->pRrdTrdPhysAligned = alignedphys; Adapter->pRrdTrd = Adapter->RxTxUnCached + (alignedphys - NdisGetPhysicalAddressLow(Adapter->RxTxUnCachedPhys)); Adapter->pRrd = Adapter->pRrdTrd; Adapter->pRrdPhys = Adapter->pRrdTrdPhysAligned; // TRDs are right after RRDs (see Phoenix doc) Adapter->pTrd = Adapter->pRrd + (sizeof(RRD) * MAX_RING_SIZE); Adapter->pTrdPhys = Adapter->pRrdPhys + (sizeof(RRD) * MAX_RING_SIZE); //**************************************** // Allocate RX memory // // 1. Cacheable control structures (RCBs, RPDs), // 2. Non-cacheable DMA buffers. //**************************************** // RCBs and RPDs (cached) Adapter->RecvCachedSize = ( Adapter->NumRcb * sizeof(RCB) + Adapter->NumRpd * sizeof(RPD) ); Status = ALLOC_SYS_MEM(&Adapter->RecvCached, Adapter->RecvCachedSize); if (Status != NDIS_STATUS_SUCCESS) { Adapter->RecvCached = (PUCHAR) 0; MKLogError(Adapter, EVENT_13, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 0); DBGSTR(("ERROR: Failed allocate %d bytes for RecvCached mem\n", Adapter->RecvCachedSize)); DBGLOG("<= SetupAdapterMemory: (ERR - RCB/RPD mem)", Adapter->RecvCachedSize); return (Status); } DBGSTR(("Allocated %08x %8d bytes for RecvCached mem\n", Adapter->RecvCached, Adapter->RecvCachedSize)); NdisZeroMemory((PVOID) Adapter->RecvCached, Adapter->RecvCachedSize); // RX data buffers (non-cached) // Alignment!? Adapter->RecvUnCachedSize = (Adapter->NumRpd * RPD_BUFFER_SIZE); NdisMAllocateSharedMemory( Adapter->MK7AdapterHandle, Adapter->RecvUnCachedSize, FALSE, // non-cached (PVOID) &Adapter->RecvUnCached, &Adapter->RecvUnCachedPhys ); if (Adapter->RecvUnCached == NULL) { MKLogError(Adapter, EVENT_14, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 0); DBGSTR(("ERROR: Failed allocate %d bytes for RecvUnCached mem\n", Adapter->RecvUnCachedSize)); DBGLOG("<= SetupAdapterMemory: (ERR - RPD buff mem)", Adapter->RecvUnCachedSize); return (NDIS_STATUS_FAILURE); } DBGSTR(("Allocated %08x %8d bytes for RecvUnCached mem\n", Adapter->RecvUnCached, Adapter->RecvUnCachedSize)); NdisZeroMemory((PVOID) Adapter->RecvUnCached, Adapter->RecvUnCachedSize); //**************************************** // Allocate TX memory // // 1. Cacheable control structure (TCBs), // 2. Non-cacheable DMA buffers (coalesce). //**************************************** // TCBs (cached) Adapter->XmitCachedSize = (Adapter->NumTcb * sizeof(TCB)); Status = ALLOC_SYS_MEM(&Adapter->XmitCached, Adapter->XmitCachedSize); if (Status != NDIS_STATUS_SUCCESS) { Adapter->XmitCached = (PUCHAR) 0; MKLogError(Adapter, EVENT_13, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 0); DBGSTR(("ERROR: Failed allocate %d bytes for XmitCached mem\n", Adapter->XmitCachedSize)); DBGLOG("<= SetupAdapterMemory: (ERR - TCB mem)", Adapter->XmitCachedSize); return (Status); } DBGSTR(("Allocated %08x %8d bytes for XmitCached mem\n", Adapter->XmitCached, Adapter->XmitCachedSize)); NdisZeroMemory((PVOID) Adapter->XmitCached, Adapter->XmitCachedSize); // TX coalesce data buffers (non-cached) Adapter->XmitUnCachedSize = ((Adapter->NumTcb + 1) * COALESCE_BUFFER_SIZE); //**************************************** // Do we need to paragraph align this memory? //**************************************** NdisMAllocateSharedMemory( Adapter->MK7AdapterHandle, Adapter->XmitUnCachedSize, FALSE, (PVOID) &Adapter->XmitUnCached, &Adapter->XmitUnCachedPhys); if (Adapter->XmitUnCached == NULL) { MKLogError(Adapter, EVENT_15, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 0); DBGSTR(("ERROR: Failed allocate %d bytes for XmitUnCached mem\n", Adapter->XmitUnCachedSize)); DBGLOG("<= SetupAdapterMemory: (ERR - TX buff mem)", (ULONG)0); return (NDIS_STATUS_FAILURE); } DBGSTR(("Allocated %08x %8d bytes for XmitUnCached mem\n", Adapter->XmitUnCached, Adapter->XmitUnCachedSize)); // initialize this recently allocated area to zeros NdisZeroMemory((PVOID) Adapter->XmitUnCached, Adapter->XmitUnCachedSize); DBGLOG("<= SetupAdapterMemory", 0); return (NDIS_STATUS_SUCCESS); } //----------------------------------------------------------------------------- // Procedure: [ReleaseAdapterMemory] // // Description: This is the reverse of AllocAdapterMemory(). We deallocate the // shared memory data structures for the Adapter structure. This includes // the both the cached and uncached memory allocations. We also free any // allocated map registers in this routine. // // Arguments: // Adapter - Ptr to the Adapter structure // // Returns: (none) //----------------------------------------------------------------------------- VOID ReleaseAdapterMemory(PMK7_ADAPTER Adapter) { UINT i; PRCB rcb; PRPD rpd; DBGFUNC("ReleaseAdapterMemory"); DBGLOG("=> ReleaseAdapterMemory", 0); //******************** // Release RX memory //******************** // Packet and buffer descriptors and pools if (Adapter->ReceivePacketPool) { DBGLOG("Freeing Packet Pool resources\n", 0); rcb = Adapter->pRcb; for (i=0; iNumRcb; i++) { NdisFreeBuffer(rcb->rpd->ReceiveBuffer); NdisFreePacket(rcb->rpd->ReceivePacket); rcb++; } rpd = (PRPD) QueuePopHead(&Adapter->FreeRpdList); while (rpd != (PRPD)NULL) { NdisFreeBuffer(rpd->ReceiveBuffer); NdisFreePacket(rpd->ReceivePacket); rpd = (PRPD) QueuePopHead(&Adapter->FreeRpdList); } NdisFreeBufferPool(Adapter->ReceiveBufferPool); NdisFreePacketPool(Adapter->ReceivePacketPool); } // RCBs (cacheable) if (Adapter->RecvCached) { DBGLOG("Freeing %d bytes RecvCached\n", Adapter->RecvCachedSize); NdisFreeMemory((PVOID) Adapter->RecvCached, Adapter->RecvCachedSize, 0); Adapter->RecvCached = (PUCHAR) 0; } // RX shared data buffer memory (non-cacheable) if (Adapter->RecvUnCached) { DBGLOG("Freeing %d bytes RecvUnCached\n", Adapter->RecvUnCachedSize); NdisMFreeSharedMemory( Adapter->MK7AdapterHandle, Adapter->RecvUnCachedSize, FALSE, (PVOID) Adapter->RecvUnCached, Adapter->RecvUnCachedPhys); Adapter->RecvUnCached = (PUCHAR) 0; } //******************** // Release TX memory //******************** // TCBs (cacheable) if (Adapter->XmitCached) { DBGLOG("Freeing %d bytes XmitCached\n", Adapter->XmitCachedSize); NdisFreeMemory((PVOID) Adapter->XmitCached, Adapter->XmitCachedSize, 0); Adapter->XmitCached = (PUCHAR) 0; } // TX shared data buffer memory (non-cacheable) if (Adapter->XmitUnCached) { DBGLOG("Freeing %d bytes XmitUnCached\n", Adapter->XmitUnCachedSize); // Now free the shared memory that was used for the command blocks and // transmit buffers. NdisMFreeSharedMemory( Adapter->MK7AdapterHandle, Adapter->XmitUnCachedSize, FALSE, (PVOID) Adapter->XmitUnCached, Adapter->XmitUnCachedPhys ); Adapter->XmitUnCached = (PUCHAR) 0; } //******************** // RRDs/TRDs (Ring) & Reg Map (non-cacheable) //******************** // If this is a miniport driver we must free our allocated map registers if (Adapter->NumMapRegisters) { NdisMFreeMapRegisters(Adapter->MK7AdapterHandle); } // Now the TRDs & RRDs if (Adapter->RxTxUnCached) { NdisMFreeSharedMemory( Adapter->MK7AdapterHandle, Adapter->RxTxUnCachedSize, FALSE, (PVOID) Adapter->RxTxUnCached, Adapter->RxTxUnCachedPhys ); } DBGLOG("<= ReleaseAdapterMemory", 0); } //----------------------------------------------------------------------------- // Procedure: [FreeAdapterObject] // // Description: Free all allocated resources for the adapter. // // Arguments: // Adapter - ptr to Adapter object instance // // Returns: (none) //----------------------------------------------------------------------------- VOID FreeAdapterObject(PMK7_ADAPTER Adapter) { DBGFUNC("FreeAdapterObject"); // The reverse of AllocAdapterMemory(). ReleaseAdapterMemory(Adapter); // Delete any IO mappings that we have registered if (Adapter->MappedIoBase) { NdisMDeregisterIoPortRange( Adapter->MK7AdapterHandle, (UINT) Adapter->MKBaseIo, Adapter->MappedIoRange, (PVOID) Adapter->MappedIoBase); } // free the adapter object itself FREE_SYS_MEM(Adapter, sizeof(MK7_ADAPTER)); } //----------------------------------------------------------------------------- // Procedure: [SetupTransmitQueues] // // Description: Setup TRBs, TRDs and TX data buffs at INIT time. This routine // may also be called at RESET time. // // Arguments: // Adapter - ptr to Adapter object instance // DebugPrint - A boolean value that will be TRUE if this routine is to // write all of transmit queue debug info to the debug terminal. // // Returns: (none) //----------------------------------------------------------------------------- VOID SetupTransmitQueues(PMK7_ADAPTER Adapter, BOOLEAN DebugPrint) { UINT i; PTCB tcb; PTRD trd; PUCHAR databuff; ULONG databuffphys; DBGLOG("=> SetupTransmitQueues", 0); Adapter->nextAvailTcbIdx = 0; Adapter->nextReturnTcbIdx = 0; Adapter->pTcb = (PTCB)Adapter->XmitCached; tcb = Adapter->pTcb; // TCB trd = (PTRD)Adapter->pTrd; // TRD databuff = Adapter->XmitUnCached; databuffphys = NdisGetPhysicalAddressLow(Adapter->XmitUnCachedPhys);// shared data buffer //**************************************** // Pair up a TCB w/ a TRD, and init ownership of TRDs to the driver. // Setup the physical buffer to the Ring descriptor (TRD). //**************************************** for (i=0; iNumTcb; i++) { tcb->trd = trd; tcb->buff = databuff; tcb->buffphy = databuffphys; LOGTXPHY(databuffphys); // for debug trd->count = 0; trd->status = 0; trd->addr = (UINT)databuffphys; GrantTrdToDrv(trd); Adapter->pTcbArray[i] = tcb; tcb++; trd++; databuff += COALESCE_BUFFER_SIZE; databuffphys += COALESCE_BUFFER_SIZE; } // Initialize the Transmit queueing pointers to NULL Adapter->FirstTxQueue = (PNDIS_PACKET) NULL; Adapter->LastTxQueue = (PNDIS_PACKET) NULL; Adapter->NumPacketsQueued = 0; DBGLOG("<= SetupTransmitQueues", 0); } //----------------------------------------------------------------------------- // Procedure: [SetupReceiveQueues] // // Description: Setup all rx-related descriptors, buffers, etc. using memory // allocated during init. Also setup our buffers for NDIS 5 and multiple // receive indications through a packet array. // // Arguments: // Adapter - ptr to Adapter object instance // // Returns: (none) //----------------------------------------------------------------------------- VOID SetupReceiveQueues(PMK7_ADAPTER Adapter) { UINT i; PRCB rcb; PRRD rrd; PRPD rpd; PUCHAR databuff; ULONG databuffphys; PRPD *TempPtr; NDIS_STATUS status; DBGLOG("=> SetupReceiveQueues", 0); QueueInitList(&Adapter->FreeRpdList); Adapter->nextRxRcbIdx = 0; // 4.0.1 BOC Adapter->UsedRpdCount = 0; Adapter->rcbPendRpdCnt = 0; // April 8, 2001. // 4.0.1 EOC Adapter->pRcb = (PRCB)Adapter->RecvCached; //**************************************** // Our driver does not currently use async allocs. However, it's // still true that we have only one buffer per rx packet. //**************************************** NdisAllocatePacketPool(&status, &Adapter->ReceivePacketPool, Adapter->NumRpd, NUM_BYTES_PROTOCOL_RESERVED_SECTION); ASSERT(status == NDIS_STATUS_SUCCESS); NdisAllocateBufferPool(&status, &Adapter->ReceiveBufferPool, Adapter->NumRpd); ASSERT(status == NDIS_STATUS_SUCCESS); //**************************************** // Pair up a RCB w/ a RRD //**************************************** rcb = Adapter->pRcb; rrd = (PRRD)Adapter->pRrd; for (i=0; iNumRcb; i++) { rcb->rrd = rrd; rrd->count = 0; GrantRrdToHw(rrd); Adapter->pRcbArray[i] = rcb; rcb++; rrd++; } //**************************************** // Now set up the RPDs and the data buffers. The RPDs come right // after the RCBs in RecvCached memory. Put the RPDs on FreeRpdList. // Map the databuff to NDIS Packet/Buffer. // "Adapter->pRcb + Adapter->NumRcb" will skip over (NumRcb * sizeof(RCB)) // bytes to get to RPDs because pRcb is ptr to RCB. //**************************************** rpd = (PRPD) (Adapter->pRcb + Adapter->NumRcb); databuff = Adapter->RecvUnCached; databuffphys = NdisGetPhysicalAddressLow(Adapter->RecvUnCachedPhys); for (i=0; iNumRpd; i++) { rpd->databuff = databuff; rpd->databuffphys = databuffphys; LOGRXPHY(databuffphys); NdisAllocatePacket(&status, &rpd->ReceivePacket, Adapter->ReceivePacketPool); ASSERT(status== NDIS_STATUS_SUCCESS); //**************************************** // Set the medium-specific header size in OOB data block. //**************************************** NDIS_SET_PACKET_HEADER_SIZE(rpd->ReceivePacket, ADDR_SIZE+CONTROL_SIZE); NdisAllocateBuffer(&status, &rpd->ReceiveBuffer, Adapter->ReceiveBufferPool, (PVOID)databuff, MK7_MAXIMUM_PACKET_SIZE); ASSERT(status == NDIS_STATUS_SUCCESS); NdisChainBufferAtFront(rpd->ReceivePacket, rpd->ReceiveBuffer); QueuePutTail(&Adapter->FreeRpdList, &rpd->link); TempPtr = (PRPD *)&rpd->ReceivePacket->MiniportReserved; *TempPtr = rpd; rpd++; databuff += RPD_BUFFER_SIZE; databuffphys += RPD_BUFFER_SIZE; } //**************************************** // Assign a RPB to each RCB, and setup the related RRD's data ptr. //**************************************** rcb = Adapter->pRcb; rrd = rcb->rrd; for (i=0; iNumRcb; i++) { rpd = (PRPD) QueuePopHead(&Adapter->FreeRpdList); rcb->rpd = rpd; rrd->addr = rpd->databuffphys; rcb++; rrd = rcb->rrd; } } //----------------------------------------------------------------------------- // Procedure: [InitializeMK7] (RYM-IRDA) // // Description: Init the Phoenix core to SIR mode. // // Arguments: // Adapter - ptr to Adapter object instance // // Returns: // TRUE // FALSE //----------------------------------------------------------------------------- BOOLEAN InitializeMK7(PMK7_ADAPTER Adapter) { ULONG phyaddr; MK7REG mk7reg; DBGFUNC("InitializeMK7"); //**************************************** // Setup Ring Base Address & Ring Size. Need to shift down/right // 10 bits first. //**************************************** phyaddr = (Adapter->pRrdTrdPhysAligned >> 10); MK7Reg_Write(Adapter, R_RBAL, (USHORT)phyaddr); MK7Reg_Write(Adapter, R_RBAU, (USHORT)(phyaddr >> 16)); //**************************************** // RX & TX ring sizes // // Now need to do this for RX & TX separately. //**************************************** mk7reg = 0; switch(Adapter->NumRcb) { case 4: mk7reg = RINGSIZE_RX4; break; case 8: mk7reg = RINGSIZE_RX8; break; case 16: mk7reg = RINGSIZE_RX16; break; case 32: mk7reg = RINGSIZE_RX32; break; case 64: mk7reg = RINGSIZE_RX64; break; } switch(Adapter->NumTcb) { case 4: mk7reg |= RINGSIZE_TX4; break; case 8: mk7reg |= RINGSIZE_TX8; break; case 16: mk7reg |= RINGSIZE_TX16; break; case 32: mk7reg |= RINGSIZE_TX32; break; case 64: mk7reg |= RINGSIZE_TX64; break; } MK7Reg_Write(Adapter, R_RSIZ, mk7reg); //**************************************** // The following is based on Phoenix's Programming Model // for SIR mode. //**************************************** //**************************************** // Step 1: clear IRENALBE // This is the only writeable bit in this reg so just write it. //**************************************** MK7Reg_Write(Adapter, R_ENAB, ~B_ENAB_IRENABLE); //**************************************** // Step 2: MAXRXALLOW //**************************************** MK7Reg_Write(Adapter, R_MPLN, MK7_MAXIMUM_PACKET_SIZE_ESC); //**************************************** // Step 3: // IRCONFIG0 - We init in SIR w/ filter, RX, etc. //**************************************** #if DBG if (Adapter->LB == LOOPBACK_HW) { DBGLOG(" Loopback HW", 0); // MK7Reg_Write(Adapter, R_CFG0, 0x5C40); // HW loopback: ENTX, ENRX, + below MK7Reg_Write(Adapter, R_CFG0, 0xDC40); // HW loopback: ENTX, ENRX, + below } else { #endif // We need to clear EN_MEMSCHD in IRCONFIG0 to reset the TX/RX // indexes to 0. Eveytime we init we need to do this. Actually we // just set eveything to zero since we're in ~B_ENAB_IRENABLE mode // anyway & we do the real setup right away below. MK7Reg_Write(Adapter, R_CFG0, 0x0000); if (Adapter->Wireless) { // WIRELESS: ..., no invert TX MK7Reg_Write(Adapter, R_CFG0, 0x0E18); } else { // WIRED: ENRX, DMA, small pkts, SIR, SIR RX filter, invert TX MK7Reg_Write(Adapter, R_CFG0, 0x0E1A); } #if DBG } #endif //**************************************** // Step 4: // Infrared Phy Reg - Baude Rate & Pulse width //**************************************** mk7reg = HW_SIR_SPEED_9600; MK7Reg_Write(Adapter, R_CFG2, mk7reg); //**************************************** // Setup CFG3 - 48Mhz, etc. //**************************************** //MK7Reg_Write(Adapter, R_CFG3, 0xF606); // We want to set the following: // Bit 1 - 1 for 1 RCV pin (for all speeds) // 2/3 - 48MHz // 8 - 0 to disable interrupt // 9 - 0 for SIR // 11 - 0 for burst mode MK7Reg_Write(Adapter, R_CFG3, 0xF406); // Set SEL0/1 for power level control for the 8102. This // should not affect the 8100. // IMPORTANT: The FIRSL bit in this register is the same // as the FIRSL bit in CFG3! MK7Reg_Write(Adapter, R_GANA, 0x0000); // // More one-time inits are done later when we startup the controller // (see StartMK7()). // return (TRUE); } //----------------------------------------------------------------------------- // Procedure: [InitializeAdapter] // // Description: // // Arguments: // Adapter - ptr to Adapter object instance // // Returns: // TRUE - If the adapter was initialized // FALSE - If the adapter failed initialization //----------------------------------------------------------------------------- BOOLEAN InitializeAdapter(PMK7_ADAPTER Adapter) { UINT i; DBGFUNC("InitializeAdapter"); for (i=0; iMaxConnSpeed) { Adapter->AllowedSpeedMask |= supportedBaudRateTable[i].ndisCode; } } Adapter->supportedSpeedsMask = ALL_IRDA_SPEEDS; Adapter->linkSpeedInfo = &supportedBaudRateTable[BAUDRATE_9600]; Adapter->CurrentSpeed = DEFAULT_BAUD_RATE; // 9600 //Adapter->extraBOFsRequired = MAX_EXTRA_SIR_BOFS; Now configurable Adapter->writePending = FALSE; // Set both TRUE to allow Windows to let us know when it wants an update. Adapter->mediaBusy = TRUE; // Adapter->haveIndicatedMediaBusy = TRUE; // 1.0.0 NdisMInitializeTimer(&Adapter->MinTurnaroundTxTimer, Adapter->MK7AdapterHandle, (PNDIS_TIMER_FUNCTION)MinTurnaroundTxTimeout, (PVOID)Adapter); // 1.0.0 NdisMInitializeTimer(&Adapter->MK7AsyncResetTimer, Adapter->MK7AdapterHandle, (PNDIS_TIMER_FUNCTION) MK7ResetComplete, (PVOID) Adapter); return (InitializeMK7(Adapter)); } //---------------------------------------------------------------------- // Procedure: [StartMK7] // // Description: All inits are done. Now we can enable the MK7 to // be able to do RXs and TXs. // //---------------------------------------------------------------------- VOID StartMK7(PMK7_ADAPTER Adapter) { MK7REG mk7reg; //**************************************** // The following is based on Phoenix's Programming Model // for SIR mode. //**************************************** //**************************************** // Step 5: IR_ENABLE // Now finish where InitializeMK7() left off. This completes // the one-time init of the MK7 core. //**************************************** MK7Reg_Write(Adapter, R_ENAB, B_ENAB_IRENABLE); MK7Reg_Read(Adapter, R_ENAB, &mk7reg); // ASSERT(mk7reg == 0x8FFF); // Still need to do the 1st Prompt. This will be done later // when we call MK7EnableInterrupt(). } //---------------------------------------------------------------------- // Procedure: [StartAdapter] // // Description: All inits are done. Now we can enable the adapter to // be able to do RXs and TXs. // //---------------------------------------------------------------------- VOID StartAdapter(PMK7_ADAPTER Adapter) { StartMK7(Adapter); } //----------------------------------------------------------------------------- // Procedure; [MKResetComplete] // // Description: This function is called by a timer indicating our // reset is done (by way of .5 seconds expiring) // // Arguements: NDIS_HANDLE MiniportAdapterContext // // Return: nothing, but sets NdisMResetComplete and enables ints. //----------------------------------------------------------------------------- VOID MK7ResetComplete(PVOID sysspiff1, NDIS_HANDLE MiniportAdapterContext, PVOID sysspiff2, PVOID sysspiff3) { PMK7_ADAPTER Adapter; MK7REG mk7reg; // DEBUGFUNC("MKResetComplete"); // INITSTR(("\n")); Adapter = PMK7_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext); // NdisAcquireSpinLock(&Adapter->Lock); 4.0.1 MK7Reg_Read(Adapter, R_INTS, &Adapter->recentInt); Adapter->recentInt = 0; MK7SwitchToRXMode(Adapter); NdisMResetComplete(Adapter->MK7AdapterHandle, (NDIS_STATUS) NDIS_STATUS_SUCCESS, TRUE); Adapter->hardwareStatus = NdisHardwareStatusReady; Adapter->ResetInProgress = FALSE; StartMK7(Adapter); MK7EnableInterrupt(Adapter); // PSTR("=> NDIS RESET COMPLETE\n\r"); // NdisReleaseSpinLock(&Adapter->Lock); // 4.0.1 } //----------------------------------------------------------------------------- // Procedure: [ResetTransmitQueues] // // Description: Setup TRBs, TRDs and TX data buffs at INIT time. And Reset // TCB/RCB Index to zero in both hardware and software // // Arguments: // Adapter - ptr to Adapter object instance // DebugPrint - A boolean value that will be TRUE if this routine is to // write all of transmit queue debug info to the debug terminal. // // Returns: (none) //----------------------------------------------------------------------------- VOID ResetTransmitQueues(PMK7_ADAPTER Adapter, BOOLEAN DebugPrint) { UINT i; PTCB tcb; PTRD trd; PUCHAR databuff; ULONG databuffphys; MK7REG mk7reg; DBGLOG("=> SetupTransmitQueues", 0); Adapter->nextAvailTcbIdx = 0; Adapter->nextReturnTcbIdx = 0; MK7Reg_Read(Adapter, R_CFG0, &mk7reg); mk7reg &= 0xfbff; MK7Reg_Write(Adapter, R_CFG0, mk7reg); mk7reg |= 0x0400; MK7Reg_Write(Adapter, R_CFG0, mk7reg); Adapter->pTcb = (PTCB)Adapter->XmitCached; tcb = Adapter->pTcb; // TCB trd = (PTRD)Adapter->pTrd; // TRD databuff = Adapter->XmitUnCached; databuffphys = NdisGetPhysicalAddressLow(Adapter->XmitUnCachedPhys);// shared data buffer //**************************************** // Pair up a TCB w/ a TRD, and init ownership of TRDs to the driver. // Setup the physical buffer to the Ring descriptor (TRD). //**************************************** for (i=0; iNumTcb; i++) { tcb->trd = trd; tcb->buff = databuff; tcb->buffphy = databuffphys; trd->count = 0; trd->status = 0; trd->addr = (UINT)databuffphys; GrantTrdToDrv(trd); Adapter->pTcbArray[i] = tcb; tcb++; trd++; databuff += COALESCE_BUFFER_SIZE; databuffphys += COALESCE_BUFFER_SIZE; } // Initialize the Transmit queueing pointers to NULL Adapter->FirstTxQueue = (PNDIS_PACKET) NULL; Adapter->LastTxQueue = (PNDIS_PACKET) NULL; Adapter->NumPacketsQueued = 0; DBGLOG("<= SetupTransmitQueues", 0); } //----------------------------------------------------------------------------- // Procedure: [ResetReceiveQueues] // // Description: Reset all the rrd's Ownership to HW // and byte_counts to zero. All other // setting (such as rpd) will remain // same. We do not reset all, because // some data buffers may still hold by // by the upper protocol layers. // // Arguments: // Adapter - ptr to Adapter object instance // // Returns: (none) //----------------------------------------------------------------------------- VOID ResetReceiveQueues(PMK7_ADAPTER Adapter) { UINT i; PRCB rcb; PRRD rrd; DBGLOG("=> SetupReceiveQueues", 0); Adapter->nextRxRcbIdx = 0; Adapter->pRcb = (PRCB)Adapter->RecvCached; //**************************************** // Pair up a RCB w/ a RRD //**************************************** rcb = Adapter->pRcb; rrd = (PRRD)Adapter->pRrd; for (i=0; iNumRcb; i++) { rcb->rrd = rrd; rrd->count = 0; GrantRrdToHw(rrd); Adapter->pRcbArray[i] = rcb; rcb++; rrd++; } }