|
|
/*++
Copyright (c) 1999 Microsoft Corporation
Module Name: mp_init.c
Abstract: This module contains miniport initialization related routines
Revision History: Who When What -------- -------- ---------------------------------------------- DChen 11-01-99 created
Notes:
--*/
#include "precomp.h"
#if DBG
#define _FILENUMBER 'TINI'
#endif
typedef struct _MP_REG_ENTRY { NDIS_STRING RegName; // variable name text
BOOLEAN bRequired; // 1 -> required, 0 -> optional
UINT FieldOffset; // offset to MP_ADAPTER field
UINT FieldSize; // size (in bytes) of the field
UINT Default; // default value to use
UINT Min; // minimum value allowed
UINT Max; // maximum value allowed
} MP_REG_ENTRY, *PMP_REG_ENTRY;
MP_REG_ENTRY NICRegTable[] = { // reg value name Offset in MP_ADAPTER Field size Default Value Min Max
#if DBG
{NDIS_STRING_CONST("Debug"), 0, MP_OFFSET(Debug), MP_SIZE(Debug), MP_WARN, 0, 0xffffffff}, #endif
{NDIS_STRING_CONST("NumRfd"), 0, MP_OFFSET(NumRfd), MP_SIZE(NumRfd), 32, NIC_MIN_RFDS, NIC_MAX_RFDS}, {NDIS_STRING_CONST("NumTcb"), 0, MP_OFFSET(NumTcb), MP_SIZE(NumTcb), NIC_DEF_TCBS, 1, NIC_MAX_TCBS}, {NDIS_STRING_CONST("NumCoalesce"), 0, MP_OFFSET(NumBuffers), MP_SIZE(NumBuffers), 8, 1, 32}, {NDIS_STRING_CONST("PhyAddress"), 0, MP_OFFSET(PhyAddress), MP_SIZE(PhyAddress), 0xFF, 0, 0xFF}, {NDIS_STRING_CONST("Connector"), 0, MP_OFFSET(Connector), MP_SIZE(Connector), 0, 0, 0x2}, {NDIS_STRING_CONST("TxFifo"), 0, MP_OFFSET(AiTxFifo), MP_SIZE(AiTxFifo), DEFAULT_TX_FIFO_LIMIT, 0, 15}, {NDIS_STRING_CONST("RxFifo"), 0, MP_OFFSET(AiRxFifo), MP_SIZE(AiRxFifo), DEFAULT_RX_FIFO_LIMIT, 0, 15}, {NDIS_STRING_CONST("TxDmaCount"), 0, MP_OFFSET(AiTxDmaCount), MP_SIZE(AiTxDmaCount), 0, 0, 63}, {NDIS_STRING_CONST("RxDmaCount"), 0, MP_OFFSET(AiRxDmaCount), MP_SIZE(AiRxDmaCount), 0, 0, 63}, {NDIS_STRING_CONST("UnderrunRetry"), 0, MP_OFFSET(AiUnderrunRetry), MP_SIZE(AiUnderrunRetry), DEFAULT_UNDERRUN_RETRY, 0, 3}, {NDIS_STRING_CONST("Threshold"), 0, MP_OFFSET(AiThreshold), MP_SIZE(AiThreshold), 200, 0, 200}, {NDIS_STRING_CONST("MWIEnable"), 0, MP_OFFSET(MWIEnable), MP_SIZE(MWIEnable), 1, 0, 1}, {NDIS_STRING_CONST("Congest"), 0, MP_OFFSET(Congest), MP_SIZE(Congest), 0, 0, 0x1}, {NDIS_STRING_CONST("SpeedDuplex"), 0, MP_OFFSET(SpeedDuplex), MP_SIZE(SpeedDuplex), 0, 0, 4} };
#define NIC_NUM_REG_PARAMS (sizeof (NICRegTable) / sizeof(MP_REG_ENTRY))
#if LBFO
NDIS_STRING strBundleId = NDIS_STRING_CONST("BundleId"); #endif
NDIS_STATUS MpFindAdapter( IN PMP_ADAPTER Adapter, IN NDIS_HANDLE WrapperConfigurationContext ) /*++
Routine Description:
Find the adapter and get all the assigned resources
Arguments:
Adapter Pointer to our adapter
Return Value:
NDIS_STATUS_SUCCESS NDIS_STATUS_ADAPTER_NOT_FOUND (event is logged as well)
--*/ {
#define NIC_PCI_E100_HDR_LENGTH 0xe2
NDIS_STATUS Status = NDIS_STATUS_ADAPTER_NOT_FOUND; ULONG ErrorCode; ULONG ErrorValue;
ULONG ulResult; UCHAR buffer[NIC_PCI_E100_HDR_LENGTH ]; PPCI_COMMON_CONFIG pPciConfig = (PPCI_COMMON_CONFIG) buffer; USHORT usPciCommand; UCHAR resBuf[NIC_RESOURCE_BUF_SIZE]; PNDIS_RESOURCE_LIST resList = (PNDIS_RESOURCE_LIST)resBuf; UINT bufSize = NIC_RESOURCE_BUF_SIZE; PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDesc; ULONG index; BOOLEAN bResPort = FALSE, bResInterrupt = FALSE, bResMemory = FALSE;
DBGPRINT(MP_TRACE, ("---> MpFindAdapter\n"));
do { //
// Find our adapter - read in the device and vendor IDs
//
ulResult = NdisReadPciSlotInformation( Adapter->AdapterHandle, 0, // not used
FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID), buffer, NIC_PCI_E100_HDR_LENGTH );
if (ulResult != NIC_PCI_E100_HDR_LENGTH ) { DBGPRINT(MP_ERROR, ("NdisReadPciSlotInformation (PCI_COMMON_CONFIG) ulResult=%d\n", ulResult));
ErrorCode = NDIS_ERROR_CODE_ADAPTER_NOT_FOUND; ErrorValue = ERRLOG_READ_PCI_SLOT_FAILED; break; }
//
// Right type of adapter?
//
if (pPciConfig->VendorID != NIC_PCI_VENDOR_ID || pPciConfig->DeviceID != NIC_PCI_DEVICE_ID) { DBGPRINT(MP_ERROR, ("VendorID/DeviceID don't match - %x/%x\n", pPciConfig->VendorID, pPciConfig->DeviceID));
ErrorCode = NDIS_ERROR_CODE_ADAPTER_NOT_FOUND; ErrorValue = ERRLOG_VENDOR_DEVICE_NOMATCH;
break; }
DBGPRINT(MP_INFO, ("Adapter is found - VendorID/DeviceID=%x/%x\n", pPciConfig->VendorID, pPciConfig->DeviceID));
// save info from config space
Adapter->RevsionID = pPciConfig->RevisionID; Adapter->SubVendorID = pPciConfig->u.type0.SubVendorID; Adapter->SubSystemID = pPciConfig->u.type0.SubSystemID; MpExtractPMInfoFromPciSpace (Adapter, (PUCHAR)pPciConfig); // --- HW_START
usPciCommand = pPciConfig->Command; if ((usPciCommand & PCI_ENABLE_WRITE_AND_INVALIDATE) && (Adapter->MWIEnable)) Adapter->MWIEnable = TRUE; else Adapter->MWIEnable = FALSE;
// Enable bus matering if it isn't enabled by the BIOS
if (!(usPciCommand & PCI_ENABLE_BUS_MASTER)) { DBGPRINT(MP_WARN, ("Bus master is not enabled by BIOS! usPciCommand=%x\n", usPciCommand));
usPciCommand |= CMD_BUS_MASTER;
ulResult = NdisWritePciSlotInformation( Adapter->AdapterHandle, 0, FIELD_OFFSET(PCI_COMMON_CONFIG, Command), &usPciCommand, sizeof(USHORT)); if (ulResult != sizeof(USHORT)) { DBGPRINT(MP_ERROR, ("NdisWritePciSlotInformation (Command) ulResult=%d\n", ulResult));
ErrorCode = NDIS_ERROR_CODE_ADAPTER_NOT_FOUND; ErrorValue = ERRLOG_WRITE_PCI_SLOT_FAILED;
break; }
ulResult = NdisReadPciSlotInformation( Adapter->AdapterHandle, 0, FIELD_OFFSET(PCI_COMMON_CONFIG, Command), &usPciCommand, sizeof(USHORT)); if (ulResult != sizeof(USHORT)) { DBGPRINT(MP_ERROR, ("NdisReadPciSlotInformation (Command) ulResult=%d\n", ulResult));
ErrorCode = NDIS_ERROR_CODE_ADAPTER_NOT_FOUND; ErrorValue = ERRLOG_READ_PCI_SLOT_FAILED;
break; }
if (!(usPciCommand & PCI_ENABLE_BUS_MASTER)) { DBGPRINT(MP_ERROR, ("Failed to enable bus master! usPciCommand=%x\n", usPciCommand));
ErrorCode = NDIS_ERROR_CODE_ADAPTER_DISABLED; ErrorValue = ERRLOG_BUS_MASTER_DISABLED;
break; } }
DBGPRINT(MP_INFO, ("Bus master is enabled. usPciCommand=%x\n", usPciCommand));
// --- HW_END
//
// Adapter is found. Now get the assigned resources
//
NdisMQueryAdapterResources( &Status, WrapperConfigurationContext, resList, &bufSize); if (Status != NDIS_STATUS_SUCCESS) { ErrorCode = NDIS_ERROR_CODE_RESOURCE_CONFLICT; ErrorValue = ERRLOG_QUERY_ADAPTER_RESOURCES; break; }
for (index=0; index < resList->Count; index++) { pResDesc = &resList->PartialDescriptors[index];
switch(pResDesc->Type) { case CmResourceTypePort: Adapter->IoBaseAddress = NdisGetPhysicalAddressLow(pResDesc->u.Port.Start); Adapter->IoRange = pResDesc->u.Port.Length; bResPort = TRUE;
DBGPRINT(MP_INFO, ("IoBaseAddress = 0x%x\n", Adapter->IoBaseAddress)); DBGPRINT(MP_INFO, ("IoRange = x%x\n", Adapter->IoRange)); break;
case CmResourceTypeInterrupt: Adapter->InterruptLevel = pResDesc->u.Interrupt.Level; bResInterrupt = TRUE; DBGPRINT(MP_INFO, ("InterruptLevel = x%x\n", Adapter->InterruptLevel)); break;
case CmResourceTypeMemory: // Our CSR memory space should be 0x1000, other memory is for
// flash address, a boot ROM address, etc.
if (pResDesc->u.Memory.Length == 0x1000) { Adapter->MemPhysAddress = pResDesc->u.Memory.Start; bResMemory = TRUE; DBGPRINT(MP_INFO, ("MemPhysAddress(Low) = 0x%0x\n", NdisGetPhysicalAddressLow(Adapter->MemPhysAddress))); DBGPRINT(MP_INFO, ("MemPhysAddress(High) = 0x%0x\n", NdisGetPhysicalAddressHigh(Adapter->MemPhysAddress))); } break; } } if (!bResPort || !bResInterrupt || !bResMemory) { Status = NDIS_STATUS_RESOURCE_CONFLICT; ErrorCode = NDIS_ERROR_CODE_RESOURCE_CONFLICT; if (!bResPort) { ErrorValue = ERRLOG_NO_IO_RESOURCE; } else if (!bResInterrupt) { ErrorValue = ERRLOG_NO_INTERRUPT_RESOURCE; } else { ErrorValue = ERRLOG_NO_MEMORY_RESOURCE; } break; } Status = NDIS_STATUS_SUCCESS;
} while (FALSE); if (Status != NDIS_STATUS_SUCCESS) { NdisWriteErrorLogEntry( Adapter->AdapterHandle, ErrorCode, 1, ErrorValue); }
DBGPRINT_S(Status, ("<--- MpFindAdapter, Status=%x\n", Status));
return Status;
}
NDIS_STATUS NICReadAdapterInfo( IN PMP_ADAPTER Adapter) /*++
Routine Description:
Read the mac addresss from the adapter
Arguments:
Adapter Pointer to our adapter
Return Value:
NDIS_STATUS_SUCCESS NDIS_STATUS_INVALID_ADDRESS
--*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; USHORT usValue; int i;
DBGPRINT(MP_TRACE, ("--> NICReadAdapterInfo\n"));
Adapter->EepromAddressSize = GetEEpromAddressSize(GetEEpromSize(Adapter->PortOffset)); DBGPRINT(MP_WARN, ("EepromAddressSize = %d\n", Adapter->EepromAddressSize)); // Read node address from the EEPROM
for (i=0; i<6; i += 2) { usValue = ReadEEprom(Adapter->PortOffset, (USHORT)(EEPROM_NODE_ADDRESS_BYTE_0 + (i/2)), Adapter->EepromAddressSize);
*((PUSHORT)(&Adapter->PermanentAddress[i])) = usValue; }
DBGPRINT(MP_INFO, ("Permanent Address = %02x-%02x-%02x-%02x-%02x-%02x\n", Adapter->PermanentAddress[0], Adapter->PermanentAddress[1], Adapter->PermanentAddress[2], Adapter->PermanentAddress[3], Adapter->PermanentAddress[4], Adapter->PermanentAddress[5]));
if (ETH_IS_MULTICAST(Adapter->PermanentAddress) || ETH_IS_BROADCAST(Adapter->PermanentAddress)) { DBGPRINT(MP_ERROR, ("Permanent address is invalid\n"));
NdisWriteErrorLogEntry( Adapter->AdapterHandle, NDIS_ERROR_CODE_NETWORK_ADDRESS, 0); Status = NDIS_STATUS_INVALID_ADDRESS; } else { if (!Adapter->bOverrideAddress) { ETH_COPY_NETWORK_ADDRESS(Adapter->CurrentAddress, Adapter->PermanentAddress); }
DBGPRINT(MP_INFO, ("Current Address = %02x-%02x-%02x-%02x-%02x-%02x\n", Adapter->CurrentAddress[0], Adapter->CurrentAddress[1], Adapter->CurrentAddress[2], Adapter->CurrentAddress[3], Adapter->CurrentAddress[4], Adapter->CurrentAddress[5])); }
DBGPRINT_S(Status, ("<-- NICReadAdapterInfo, Status=%x\n", Status));
return Status; }
NDIS_STATUS MpAllocAdapterBlock( OUT PMP_ADAPTER *pAdapter) /*++
Routine Description:
Allocate MP_ADAPTER data block and do some initialization
Arguments:
Adapter Pointer to receive pointer to our adapter
Return Value:
NDIS_STATUS_SUCCESS NDIS_STATUS_FAILURE
--*/ { PMP_ADAPTER Adapter; NDIS_HANDLE PacketPoolHandle; NDIS_HANDLE BufferPoolHandle; PNDIS_PACKET Packet; PNDIS_BUFFER Buffer; NDIS_STATUS Status; LONG index;
DBGPRINT(MP_TRACE, ("--> NICAllocAdapter\n"));
*pAdapter = NULL;
do { // Allocate MP_ADAPTER block
Status = MP_ALLOCMEMTAG(&Adapter, sizeof(MP_ADAPTER)); if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT(MP_ERROR, ("Failed to allocate memory - ADAPTER\n")); break; }
// Clean up the memory block
NdisZeroMemory(Adapter, sizeof(MP_ADAPTER));
MP_INC_REF(Adapter);
// Init lists, spinlocks, etc.
InitializeQueueHeader(&Adapter->SendWaitQueue); InitializeQueueHeader(&Adapter->SendCancelQueue);
InitializeListHead(&Adapter->RecvList); InitializeListHead(&Adapter->RecvPendList); InitializeListHead(&Adapter->PoMgmt.PatternList);
NdisInitializeEvent(&Adapter->ExitEvent); NdisInitializeEvent(&Adapter->AllPacketsReturnedEvent); MP_INC_RCV_REF(Adapter);
NdisAllocateSpinLock(&Adapter->Lock); NdisAllocateSpinLock(&Adapter->SendLock); NdisAllocateSpinLock(&Adapter->RcvLock);
} while (FALSE);
*pAdapter = Adapter;
DBGPRINT_S(Status, ("<-- NICAllocAdapter, Status=%x\n", Status));
return Status;
}
VOID MpFreeAdapter( IN PMP_ADAPTER Adapter) /*++
Routine Description:
Free all the resources and MP_ADAPTER data block
Arguments:
Adapter Pointer to our adapter
Return Value:
None
--*/ { PMP_TXBUF pMpTxBuf; PMP_RFD pMpRfd;
DBGPRINT(MP_TRACE, ("--> NICFreeAdapter\n"));
// No active and waiting sends
ASSERT(Adapter->nBusySend == 0); ASSERT(Adapter->nWaitSend == 0); ASSERT(IsQueueEmpty(&Adapter->SendWaitQueue)); ASSERT(IsQueueEmpty(&Adapter->SendCancelQueue));
// No other pending operations
ASSERT(IsListEmpty(&Adapter->RecvPendList)); ASSERT(Adapter->bAllocNewRfd == FALSE); ASSERT(!MP_TEST_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION)); ASSERT(MP_GET_REF(Adapter) == 0);
//
// Free hardware resources
//
if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_INTERRUPT_IN_USE)) { NdisMDeregisterInterrupt(&Adapter->Interrupt); MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_INTERRUPT_IN_USE); }
if (Adapter->CSRAddress) { NdisMUnmapIoSpace( Adapter->AdapterHandle, Adapter->CSRAddress, NIC_MAP_IOSPACE_LENGTH); Adapter->CSRAddress = NULL; }
if (Adapter->PortOffset) { NdisMDeregisterIoPortRange( Adapter->AdapterHandle, Adapter->IoBaseAddress, Adapter->IoRange, Adapter->PortOffset); Adapter->PortOffset = NULL; }
//
// Free RECV memory/NDIS buffer/NDIS packets/shared memory
//
ASSERT(Adapter->nReadyRecv == Adapter->CurrNumRfd);
while (!IsListEmpty(&Adapter->RecvList)) { pMpRfd = (PMP_RFD)RemoveHeadList(&Adapter->RecvList); NICFreeRfd(Adapter, pMpRfd); }
// Free receive buffer pool
if (Adapter->RecvBufferPool) { NdisFreeBufferPool(Adapter->RecvBufferPool); Adapter->RecvBufferPool = NULL; }
// Free receive packet pool
if (Adapter->RecvPacketPool) { NdisFreePacketPool(Adapter->RecvPacketPool); Adapter->RecvPacketPool = NULL; } if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_RECV_LOOKASIDE)) { NdisDeleteNPagedLookasideList(&Adapter->RecvLookaside); MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_RECV_LOOKASIDE); } //
// Free SEND memory/NDIS buffer/NDIS packets/shared memory
//
while (!IsSListEmpty(&Adapter->SendBufList)) { pMpTxBuf = (PMP_TXBUF)PopEntryList(&Adapter->SendBufList); ASSERT(pMpTxBuf);
// Free the shared memory associated with each MP_TXBUF
if (pMpTxBuf->AllocVa) { NdisMFreeSharedMemory( Adapter->AdapterHandle, pMpTxBuf->AllocSize, TRUE, pMpTxBuf->AllocVa, pMpTxBuf->AllocPa); pMpTxBuf->AllocVa = NULL; }
// Free the NDIS buffer
if (pMpTxBuf->NdisBuffer) { NdisFreeBuffer(pMpTxBuf->NdisBuffer); pMpTxBuf->NdisBuffer = NULL; } }
// Free the send buffer pool
if (Adapter->SendBufferPool) { NdisFreeBufferPool(Adapter->SendBufferPool); Adapter->SendBufferPool = NULL; } // Free the memory for MP_TXBUF structures
if (Adapter->MpTxBufMem) { MP_FREEMEM(Adapter->MpTxBufMem, Adapter->MpTxBufMemSize, 0); Adapter->MpTxBufMem = NULL; }
// Free the shared memory for HW_TCB structures
if (Adapter->HwSendMemAllocVa) { NdisMFreeSharedMemory( Adapter->AdapterHandle, Adapter->HwSendMemAllocSize, FALSE, Adapter->HwSendMemAllocVa, Adapter->HwSendMemAllocPa); Adapter->HwSendMemAllocVa = NULL; }
// Free the shared memory for other command data structures
if (Adapter->HwMiscMemAllocVa) { NdisMFreeSharedMemory( Adapter->AdapterHandle, Adapter->HwMiscMemAllocSize, FALSE, Adapter->HwMiscMemAllocVa, Adapter->HwMiscMemAllocPa); Adapter->HwMiscMemAllocVa = NULL; }
// Free the memory for MP_TCB structures
if (Adapter->MpTcbMem) { MP_FREEMEM(Adapter->MpTcbMem, Adapter->MpTcbMemSize, 0); Adapter->MpTcbMem = NULL; }
// Free map registers. This must be after all the shared memory is freed
if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_MAP_REGISTER)) { NdisMFreeMapRegisters(Adapter->AdapterHandle); MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_MAP_REGISTER); }
//Free all the wake up patterns on this adapter
MPRemoveAllWakeUpPatterns(Adapter); NdisFreeSpinLock(&Adapter->Lock);
#if LBFO
if (Adapter->BundleId.MaximumLength) { MP_FREE_NDIS_STRING(&Adapter->BundleId); } #endif
#if OFFLOAD
// Free the shared memory for offload tasks
if (Adapter->OffloadSharedMem.StartVa) { NdisMFreeSharedMemory( Adapter->AdapterHandle, Adapter->OffloadSharedMemSize, FALSE, Adapter->OffloadSharedMem.StartVa, Adapter->OffloadSharedMem.PhyAddr); Adapter->OffloadSharedMem.StartVa = NULL; }
#endif
MP_FREEMEM(Adapter, sizeof(MP_ADAPTER), 0);
DBGPRINT(MP_TRACE, ("<-- NICFreeAdapter\n")); }
NDIS_STATUS NICReadRegParameters( IN PMP_ADAPTER Adapter, IN NDIS_HANDLE WrapperConfigurationContext) /*++
Routine Description:
Read the following from the registry 1. All the parameters 2. NetworkAddres 3. LBFO - BundleId
Arguments:
Adapter Pointer to our adapter WrapperConfigurationContext For use by NdisOpenConfiguration
Return Value:
NDIS_STATUS_SUCCESS NDIS_STATUS_FAILURE NDIS_STATUS_RESOURCES
--*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; NDIS_HANDLE ConfigurationHandle; PMP_REG_ENTRY pRegEntry; UINT i; UINT value; PUCHAR pointer; PNDIS_CONFIGURATION_PARAMETER ReturnedValue; PUCHAR NetworkAddress; UINT Length;
DBGPRINT(MP_TRACE, ("--> NICReadRegParameters\n"));
// Open the registry for this adapter
NdisOpenConfiguration( &Status, &ConfigurationHandle, WrapperConfigurationContext); if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT(MP_ERROR, ("NdisOpenConfiguration failed\n")); DBGPRINT_S(Status, ("<-- NICReadRegParameters, Status=%x\n", Status)); return Status; }
// read all the registry values
for (i = 0, pRegEntry = NICRegTable; i < NIC_NUM_REG_PARAMS; i++, pRegEntry++) { pointer = (PUCHAR) Adapter + pRegEntry->FieldOffset;
DBGPRINT_UNICODE(MP_INFO, &pRegEntry->RegName);
// Get the configuration value for a specific parameter. Under NT the
// parameters are all read in as DWORDs.
NdisReadConfiguration( &Status, &ReturnedValue, ConfigurationHandle, &pRegEntry->RegName, NdisParameterInteger);
// If the parameter was present, then check its value for validity.
if (Status == NDIS_STATUS_SUCCESS) { // Check that param value is not too small or too large
if (ReturnedValue->ParameterData.IntegerData < pRegEntry->Min || ReturnedValue->ParameterData.IntegerData > pRegEntry->Max) { value = pRegEntry->Default; } else { value = ReturnedValue->ParameterData.IntegerData; }
DBGPRINT_RAW(MP_INFO, ("= 0x%x\n", value)); } else if (pRegEntry->bRequired) { DBGPRINT_RAW(MP_ERROR, (" -- failed\n"));
ASSERT(FALSE);
Status = NDIS_STATUS_FAILURE; break; } else { value = pRegEntry->Default; DBGPRINT_RAW(MP_INFO, ("= 0x%x (default)\n", value)); Status = NDIS_STATUS_SUCCESS; }
// Store the value in the adapter structure.
switch(pRegEntry->FieldSize) { case 1: *((PUCHAR) pointer) = (UCHAR) value; break;
case 2: *((PUSHORT) pointer) = (USHORT) value; break;
case 4: *((PULONG) pointer) = (ULONG) value; break;
default: DBGPRINT(MP_ERROR, ("Bogus field size %d\n", pRegEntry->FieldSize)); break; } }
// Read NetworkAddress registry value
// Use it as the current address if any
if (Status == NDIS_STATUS_SUCCESS) { NdisReadNetworkAddress( &Status, &NetworkAddress, &Length, ConfigurationHandle);
// If there is a NetworkAddress override in registry, use it
if ((Status == NDIS_STATUS_SUCCESS) && (Length == ETH_LENGTH_OF_ADDRESS)) { if (ETH_IS_MULTICAST(NetworkAddress) || ETH_IS_BROADCAST(NetworkAddress)) { DBGPRINT(MP_ERROR, ("Overriding NetworkAddress is invalid - %02x-%02x-%02x-%02x-%02x-%02x\n", NetworkAddress[0], NetworkAddress[1], NetworkAddress[2], NetworkAddress[3], NetworkAddress[4], NetworkAddress[5])); } else { ETH_COPY_NETWORK_ADDRESS(Adapter->CurrentAddress, NetworkAddress); Adapter->bOverrideAddress = TRUE; } }
Status = NDIS_STATUS_SUCCESS; }
#if LBFO
if (Status == NDIS_STATUS_SUCCESS) { // Read BundleIdentifier string
NdisReadConfiguration( &Status, &ReturnedValue, ConfigurationHandle, &strBundleId, NdisParameterString);
if (Status == NDIS_STATUS_SUCCESS) { ASSERT(ReturnedValue->ParameterType == NdisParameterString);
if (ReturnedValue->ParameterData.StringData.Length !=0) { Status = MP_ALLOCMEMTAG(&Adapter->BundleId.Buffer, ReturnedValue->ParameterData.StringData.Length + sizeof(WCHAR)); if (Status == NDIS_STATUS_SUCCESS) { Adapter->BundleId.MaximumLength = ReturnedValue->ParameterData.StringData.Length + sizeof(WCHAR); NdisUpcaseUnicodeString( &Adapter->BundleId, &ReturnedValue->ParameterData.StringData); } else { DBGPRINT(MP_ERROR, ("Failed to allocate memory - BundleIdentifier\n")); } } } else { // This parameter is optional, set status to SUCCESS
Status = NDIS_STATUS_SUCCESS; } } #endif
// Close the registry
NdisCloseConfiguration(ConfigurationHandle); // Decode SpeedDuplex
if (Status == NDIS_STATUS_SUCCESS && Adapter->SpeedDuplex) { switch(Adapter->SpeedDuplex) { case 1: Adapter->AiTempSpeed = 10; Adapter->AiForceDpx = 1; break; case 2: Adapter->AiTempSpeed = 10; Adapter->AiForceDpx = 2; break; case 3: Adapter->AiTempSpeed = 100; Adapter->AiForceDpx = 1; break; case 4: Adapter->AiTempSpeed = 100; Adapter->AiForceDpx = 2; break; } }
DBGPRINT_S(Status, ("<-- NICReadRegParameters, Status=%x\n", Status));
return Status; }
NDIS_STATUS NICAllocAdapterMemory( IN PMP_ADAPTER Adapter) /*++
Routine Description:
Allocate all the memory blocks for send, receive and others
Arguments:
Adapter Pointer to our adapter
Return Value:
NDIS_STATUS_SUCCESS NDIS_STATUS_FAILURE NDIS_STATUS_RESOURCES
--*/ { NDIS_STATUS Status; PMP_TCB pMpTCB; PMP_TXBUF pMpTxbuf; PUCHAR pMem; ULONG MemPhys; LONG index; LONG MapRegisterCount; ULONG ErrorValue = 0; UINT MaxNumBuffers; #if OFFLOAD
BOOLEAN OffloadSharedMemSuccess = FALSE; UINT i; #endif
DBGPRINT(MP_TRACE, ("--> NICAllocMemory\n"));
DBGPRINT(MP_INFO, ("NumTcb=%d\n", Adapter->NumTcb)); Adapter->NumTbd = Adapter->NumTcb * NIC_MAX_PHYS_BUF_COUNT;
do { //
// Try to use the ScatterGather method first, this is the preferred way
// Only use map registers if we can't do scatter gather (e.g. on win9x)
#if OFFLOAD
Status = NdisMInitializeScatterGatherDma( Adapter->AdapterHandle, FALSE, LARGE_SEND_OFFLOAD_SIZE); #else
Status = NdisMInitializeScatterGatherDma( Adapter->AdapterHandle, FALSE, NIC_MAX_PACKET_SIZE); #endif
if (Status == NDIS_STATUS_SUCCESS) { MP_SET_FLAG(Adapter, fMP_ADAPTER_SCATTER_GATHER); } else { DBGPRINT(MP_WARN, ("Failed to init ScatterGather DMA, allocate map registers\n"));
// We should limit the totoal map registers needed to 32
Adapter->NumTcb = 32 / NIC_MAX_PHYS_BUF_COUNT; Adapter->NumTbd = Adapter->NumTcb * NIC_MAX_PHYS_BUF_COUNT; DBGPRINT(MP_WARN, ("NumTcb is reduced to %d", Adapter->NumTcb));
while (Adapter->NumTcb > 0) { Status = NdisMAllocateMapRegisters( Adapter->AdapterHandle, 0, NDIS_DMA_32BITS, Adapter->NumTbd, NIC_MAX_PACKET_SIZE);
if (Status == NDIS_STATUS_SUCCESS) { break; }
// Reduce NumTcb and try again
Adapter->NumTcb--; DBGPRINT(MP_WARN, ("NumTcb is reduced to %d", Adapter->NumTcb)); Adapter->NumTbd = Adapter->NumTcb * NIC_MAX_PHYS_BUF_COUNT; }
if (Status == NDIS_STATUS_SUCCESS) { MP_SET_FLAG(Adapter, fMP_ADAPTER_MAP_REGISTER); } else { ErrorValue = ERRLOG_OUT_OF_MAP_REGISTERS; DBGPRINT(MP_ERROR, ("Failed to allocate map registers\n")); break; } }
//
// Send + Misc
//
//
// Allocate MP_TCB's
//
Adapter->MpTcbMemSize = Adapter->NumTcb * sizeof(MP_TCB); Status = MP_ALLOCMEMTAG(&pMem, Adapter->MpTcbMemSize); if (Status != NDIS_STATUS_SUCCESS) { ErrorValue = ERRLOG_OUT_OF_MEMORY; DBGPRINT(MP_ERROR, ("Failed to allocate MP_TCB's\n")); break; } NdisZeroMemory(pMem, Adapter->MpTcbMemSize); Adapter->MpTcbMem = pMem; //
// Now the driver needs to allocate send buffer pool, the number
// of send buffers the driver needs is the larger one of Adapter->NumBuffer
// and Adapter->NumTcb.
//
MaxNumBuffers = Adapter->NumBuffers > Adapter->NumTcb ? Adapter->NumBuffers: Adapter->NumTcb; NdisAllocateBufferPool( &Status, &Adapter->SendBufferPool, MaxNumBuffers); if (Status != NDIS_STATUS_SUCCESS) { ErrorValue = ERRLOG_OUT_OF_BUFFER_POOL; DBGPRINT(MP_ERROR, ("Failed to allocate send buffer pool\n")); break; }
// Allocate send buffers
Adapter->MpTxBufMemSize = Adapter->NumBuffers * sizeof(MP_TXBUF); Status = MP_ALLOCMEMTAG(&pMem, Adapter->MpTxBufMemSize); if (Status != NDIS_STATUS_SUCCESS) { ErrorValue = ERRLOG_OUT_OF_MEMORY; DBGPRINT(MP_ERROR, ("Failed to allocate MP_TXBUF's\n")); break; } NdisZeroMemory(pMem, Adapter->MpTxBufMemSize); Adapter->MpTxBufMem = pMem;
pMpTxbuf = (PMP_TXBUF) pMem;
//
// NdisMGetDmaAlignment is provided in XP (WINVER=0x0501) and higher
// if you need to write a driver that runs on older versions of Windows
// you need to compile with older versions of DDK which have WINVER < 0x0501
// such as W2K DDK.
//
#if (WINVER < 0x0501)
Adapter->CacheFillSize = NdisGetCacheFillSize(); #else
Adapter->CacheFillSize = NdisMGetDmaAlignment(Adapter->AdapterHandle); #endif
DBGPRINT(MP_INFO, ("CacheFillSize=%d\n", Adapter->CacheFillSize));
for (index = 0; index < Adapter->NumBuffers; index++) { pMpTxbuf->AllocSize = NIC_MAX_PACKET_SIZE + Adapter->CacheFillSize; pMpTxbuf->BufferSize = NIC_MAX_PACKET_SIZE;
NdisMAllocateSharedMemory( Adapter->AdapterHandle, pMpTxbuf->AllocSize, TRUE, // CACHED
&pMpTxbuf->AllocVa, &pMpTxbuf->AllocPa);
if (!pMpTxbuf->AllocVa) { ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; DBGPRINT(MP_ERROR, ("Failed to allocate a big buffer\n")); Status = NDIS_STATUS_RESOURCES; break; }
// Align the buffer on the cache line boundary
pMpTxbuf->pBuffer = MP_ALIGNMEM(pMpTxbuf->AllocVa, Adapter->CacheFillSize); pMpTxbuf->BufferPa.QuadPart = MP_ALIGNMEM_PA(pMpTxbuf->AllocPa, Adapter->CacheFillSize);
NdisAllocateBuffer( &Status, &pMpTxbuf->NdisBuffer, Adapter->SendBufferPool, pMpTxbuf->pBuffer, pMpTxbuf->BufferSize);
if (Status != NDIS_STATUS_SUCCESS) { ErrorValue = ERRLOG_OUT_OF_NDIS_BUFFER; DBGPRINT(MP_ERROR, ("Failed to allocate NDIS buffer for a big buffer\n"));
NdisMFreeSharedMemory( Adapter->AdapterHandle, pMpTxbuf->AllocSize, TRUE, // CACHED
pMpTxbuf->AllocVa, pMpTxbuf->AllocPa);
break; }
PushEntryList(&Adapter->SendBufList, &pMpTxbuf->SList);
pMpTxbuf++; }
if (Status != NDIS_STATUS_SUCCESS) break;
// HW_START
// Allocate shared memory for send
Adapter->HwSendMemAllocSize = Adapter->NumTcb * (sizeof(TXCB_STRUC) + NIC_MAX_PHYS_BUF_COUNT * sizeof(TBD_STRUC));
NdisMAllocateSharedMemory( Adapter->AdapterHandle, Adapter->HwSendMemAllocSize, FALSE, (PVOID) &Adapter->HwSendMemAllocVa, &Adapter->HwSendMemAllocPa);
if (!Adapter->HwSendMemAllocVa) { ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; DBGPRINT(MP_ERROR, ("Failed to allocate send memory\n")); Status = NDIS_STATUS_RESOURCES; break; }
NdisZeroMemory(Adapter->HwSendMemAllocVa, Adapter->HwSendMemAllocSize);
// Allocate shared memory for other uses
Adapter->HwMiscMemAllocSize = sizeof(SELF_TEST_STRUC) + ALIGN_16 + sizeof(DUMP_AREA_STRUC) + ALIGN_16 + sizeof(NON_TRANSMIT_CB) + ALIGN_16 + sizeof(ERR_COUNT_STRUC) + ALIGN_16; // Allocate the shared memory for the command block data structures.
NdisMAllocateSharedMemory( Adapter->AdapterHandle, Adapter->HwMiscMemAllocSize, FALSE, (PVOID *) &Adapter->HwMiscMemAllocVa, &Adapter->HwMiscMemAllocPa); if (!Adapter->HwMiscMemAllocVa) { ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; DBGPRINT(MP_ERROR, ("Failed to allocate misc memory\n")); Status = NDIS_STATUS_RESOURCES; break; }
NdisZeroMemory(Adapter->HwMiscMemAllocVa, Adapter->HwMiscMemAllocSize);
pMem = Adapter->HwMiscMemAllocVa; MemPhys = NdisGetPhysicalAddressLow(Adapter->HwMiscMemAllocPa);
Adapter->SelfTest = (PSELF_TEST_STRUC)MP_ALIGNMEM(pMem, ALIGN_16); Adapter->SelfTestPhys = MP_ALIGNMEM_PHYS(MemPhys, ALIGN_16); pMem = (PUCHAR)Adapter->SelfTest + sizeof(SELF_TEST_STRUC); MemPhys = Adapter->SelfTestPhys + sizeof(SELF_TEST_STRUC);
Adapter->NonTxCmdBlock = (PNON_TRANSMIT_CB)MP_ALIGNMEM(pMem, ALIGN_16); Adapter->NonTxCmdBlockPhys = MP_ALIGNMEM_PHYS(MemPhys, ALIGN_16); pMem = (PUCHAR)Adapter->NonTxCmdBlock + sizeof(NON_TRANSMIT_CB); MemPhys = Adapter->NonTxCmdBlockPhys + sizeof(NON_TRANSMIT_CB);
Adapter->DumpSpace = (PDUMP_AREA_STRUC)MP_ALIGNMEM(pMem, ALIGN_16); Adapter->DumpSpacePhys = MP_ALIGNMEM_PHYS(MemPhys, ALIGN_16); pMem = (PUCHAR)Adapter->DumpSpace + sizeof(DUMP_AREA_STRUC); MemPhys = Adapter->DumpSpacePhys + sizeof(DUMP_AREA_STRUC);
Adapter->StatsCounters = (PERR_COUNT_STRUC)MP_ALIGNMEM(pMem, ALIGN_16); Adapter->StatsCounterPhys = MP_ALIGNMEM_PHYS(MemPhys, ALIGN_16);
// HW_END
//
// Recv
//
NdisInitializeNPagedLookasideList( &Adapter->RecvLookaside, NULL, NULL, 0, sizeof(MP_RFD), NIC_TAG, 0);
MP_SET_FLAG(Adapter, fMP_ADAPTER_RECV_LOOKASIDE);
// set the max number of RFDs
// disable the RFD grow/shrink scheme if user specifies a NumRfd value
// larger than NIC_MAX_GROW_RFDS
Adapter->MaxNumRfd = max(Adapter->NumRfd, NIC_MAX_GROW_RFDS); DBGPRINT(MP_INFO, ("NumRfd = %d\n", Adapter->NumRfd)); DBGPRINT(MP_INFO, ("MaxNumRfd = %d\n", Adapter->MaxNumRfd));
Adapter->HwRfdSize = sizeof(RFD_STRUC);
// alloc the recv packet pool
NdisAllocatePacketPoolEx( &Status, &Adapter->RecvPacketPool, Adapter->NumRfd, Adapter->MaxNumRfd, sizeof(PVOID) * 4); if (Status != NDIS_STATUS_SUCCESS) { ErrorValue = ERRLOG_OUT_OF_PACKET_POOL; break; }
// alloc the buffer pool
NdisAllocateBufferPool( &Status, &Adapter->RecvBufferPool, Adapter->MaxNumRfd); if (Status != NDIS_STATUS_SUCCESS) { ErrorValue = ERRLOG_OUT_OF_BUFFER_POOL; break; }
Status = NDIS_STATUS_SUCCESS;
} while (FALSE);
if (Status != NDIS_STATUS_SUCCESS) { NdisWriteErrorLogEntry( Adapter->AdapterHandle, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 1, ErrorValue); } #if OFFLOAD
// Allocate the shared memory for the offloading packet
// this miniport use this shared memory when OFFLAOD is on
for (i = 0; i < LARGE_SEND_MEM_SIZE_OPTION; i++) { NdisMAllocateSharedMemory( Adapter->AdapterHandle, LargeSendSharedMemArray[i], FALSE, (PVOID *)&(Adapter->OffloadSharedMem.StartVa), &(Adapter->OffloadSharedMem.PhyAddr)); if (Adapter->OffloadSharedMem.StartVa) { Adapter->OffloadSharedMemSize = LargeSendSharedMemArray[i]; OffloadSharedMemSuccess = TRUE; Adapter->OffloadEnable = TRUE;
break; } } if (OffloadSharedMemSuccess == FALSE) {
ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; DBGPRINT(MP_ERROR, ("Failed to allocate offload used memory\n")); Adapter->OffloadEnable = FALSE; } #endif
DBGPRINT_S(Status, ("<-- NICAllocMemory, Status=%x\n", Status));
return Status;
}
VOID NICInitSend( IN PMP_ADAPTER Adapter) /*++
Routine Description:
Initialize send data structures
Arguments:
Adapter Pointer to our adapter
Return Value:
None
--*/ { PMP_TCB pMpTcb; PHW_TCB pHwTcb; ULONG HwTcbPhys; LONG TcbCount;
PTBD_STRUC pHwTbd; ULONG HwTbdPhys;
DBGPRINT(MP_TRACE, ("--> NICInitSend\n"));
Adapter->TransmitIdle = TRUE; Adapter->ResumeWait = TRUE;
// Setup the initial pointers to the SW and HW TCB data space
pMpTcb = (PMP_TCB) Adapter->MpTcbMem; pHwTcb = (PHW_TCB) Adapter->HwSendMemAllocVa; HwTcbPhys = NdisGetPhysicalAddressLow(Adapter->HwSendMemAllocPa);
// Setup the initial pointers to the TBD data space.
// TBDs are located immediately following the TCBs
pHwTbd = (PTBD_STRUC) (Adapter->HwSendMemAllocVa + (sizeof(TXCB_STRUC) * Adapter->NumTcb)); HwTbdPhys = HwTcbPhys + (sizeof(TXCB_STRUC) * Adapter->NumTcb);
// Go through and set up each TCB
for (TcbCount = 0; TcbCount < Adapter->NumTcb; TcbCount++) { pMpTcb->HwTcb = pHwTcb; // save ptr to HW TCB
pMpTcb->HwTcbPhys = HwTcbPhys; // save HW TCB physical address
pMpTcb->HwTbd = pHwTbd; // save ptr to TBD array
pMpTcb->HwTbdPhys = HwTbdPhys; // save TBD array physical address
if (TcbCount) pMpTcb->PrevHwTcb = pHwTcb - 1; else pMpTcb->PrevHwTcb = (PHW_TCB)((PUCHAR)Adapter->HwSendMemAllocVa + ((Adapter->NumTcb - 1) * sizeof(HW_TCB)));
pHwTcb->TxCbHeader.CbStatus = 0; // clear the status
pHwTcb->TxCbHeader.CbCommand = CB_EL_BIT | CB_TX_SF_BIT | CB_TRANSMIT;
// Set the link pointer in HW TCB to the next TCB in the chain.
// If this is the last TCB in the chain, then set it to the first TCB.
if (TcbCount < Adapter->NumTcb - 1) { pMpTcb->Next = pMpTcb + 1; pHwTcb->TxCbHeader.CbLinkPointer = HwTcbPhys + sizeof(HW_TCB); } else { pMpTcb->Next = (PMP_TCB) Adapter->MpTcbMem; pHwTcb->TxCbHeader.CbLinkPointer = NdisGetPhysicalAddressLow(Adapter->HwSendMemAllocPa); }
pHwTcb->TxCbThreshold = (UCHAR) Adapter->AiThreshold; pHwTcb->TxCbTbdPointer = HwTbdPhys;
pMpTcb++; pHwTcb++; HwTcbPhys += sizeof(TXCB_STRUC); pHwTbd = (PTBD_STRUC)((PUCHAR)pHwTbd + sizeof(TBD_STRUC) * NIC_MAX_PHYS_BUF_COUNT); HwTbdPhys += sizeof(TBD_STRUC) * NIC_MAX_PHYS_BUF_COUNT; }
// set the TCB head/tail indexes
// head is the olded one to free, tail is the next one to use
Adapter->CurrSendHead = (PMP_TCB) Adapter->MpTcbMem; Adapter->CurrSendTail = (PMP_TCB) Adapter->MpTcbMem;
// set the map register head/tail indexes if used
if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_MAP_REGISTER)) { Adapter->CurrMapRegHead = 0; Adapter->CurrMapRegTail = 0; }
DBGPRINT(MP_TRACE, ("<-- NICInitSend, Status=%x\n")); }
NDIS_STATUS NICInitRecv( IN PMP_ADAPTER Adapter) /*++
Routine Description:
Initialize receive data structures
Arguments:
Adapter Pointer to our adapter
Return Value:
NDIS_STATUS_SUCCESS NDIS_STATUS_RESOURCES
--*/ { NDIS_STATUS Status = NDIS_STATUS_RESOURCES;
PMP_RFD pMpRfd; LONG RfdCount; ULONG ErrorValue = 0;
DBGPRINT(MP_TRACE, ("--> NICInitRecv\n"));
// Setup each RFD
for (RfdCount = 0; RfdCount < Adapter->NumRfd; RfdCount++) { pMpRfd = NdisAllocateFromNPagedLookasideList(&Adapter->RecvLookaside); if (!pMpRfd) { ErrorValue = ERRLOG_OUT_OF_LOOKASIDE_MEMORY; continue; }
// Allocate the shared memory for this RFD.
NdisMAllocateSharedMemory( Adapter->AdapterHandle, Adapter->HwRfdSize, FALSE, &pMpRfd->HwRfd, &pMpRfd->HwRfdPa);
if (!pMpRfd->HwRfd) { ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; NdisFreeToNPagedLookasideList(&Adapter->RecvLookaside, pMpRfd); continue; }
ErrorValue = NICAllocRfd(Adapter, pMpRfd); if (ErrorValue) { NdisFreeToNPagedLookasideList(&Adapter->RecvLookaside, pMpRfd); continue; }
// Add this RFD to the RecvList
Adapter->CurrNumRfd++; NICReturnRFD(Adapter, pMpRfd); }
if (Adapter->CurrNumRfd > NIC_MIN_RFDS) { Status = NDIS_STATUS_SUCCESS; }
if (Status != NDIS_STATUS_SUCCESS) { NdisWriteErrorLogEntry( Adapter->AdapterHandle, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 1, ErrorValue); NdisFreeToNPagedLookasideList(&Adapter->RecvLookaside, pMpRfd); }
DBGPRINT_S(Status, ("<-- NICInitRecv, Status=%x\n", Status));
return Status; }
ULONG NICAllocRfd( IN PMP_ADAPTER Adapter, IN PMP_RFD pMpRfd) /*++
Routine Description:
Allocate NDIS_PACKET and NDIS_BUFFER associated with a RFD
Arguments:
Adapter Pointer to our adapter pMpRfd pointer to a RFD
Return Value:
ERRLOG_OUT_OF_NDIS_PACKET ERRLOG_OUT_OF_NDIS_BUFFER
--*/ { NDIS_STATUS Status; PHW_RFD pHwRfd; ULONG HwRfdPhys; ULONG ErrorValue = 0;
do { pHwRfd = pMpRfd->HwRfd; pMpRfd->HwRfdPhys = NdisGetPhysicalAddressLow(pMpRfd->HwRfdPa);
pMpRfd->Flags = 0; pMpRfd->NdisPacket = NULL; pMpRfd->NdisBuffer = NULL;
NdisAllocatePacket( &Status, &pMpRfd->NdisPacket, Adapter->RecvPacketPool); if (Status != NDIS_STATUS_SUCCESS) { ASSERT(pMpRfd->NdisPacket == NULL); ErrorValue = ERRLOG_OUT_OF_NDIS_PACKET; break; }
// point our buffer for receives at this Rfd
NdisAllocateBuffer( &Status, &pMpRfd->NdisBuffer, Adapter->RecvBufferPool, (PVOID)&pHwRfd->RfdBuffer.RxMacHeader, NIC_MAX_PACKET_SIZE); if (Status != NDIS_STATUS_SUCCESS) { ASSERT(pMpRfd->NdisBuffer == NULL); ErrorValue = ERRLOG_OUT_OF_NDIS_BUFFER; break; }
// Init each RFD header
pHwRfd->RfdRbdPointer = DRIVER_NULL; pHwRfd->RfdSize = NIC_MAX_PACKET_SIZE;
NDIS_SET_PACKET_HEADER_SIZE(pMpRfd->NdisPacket, NIC_HEADER_SIZE);
NdisChainBufferAtFront(pMpRfd->NdisPacket, pMpRfd->NdisBuffer);
// Save ptr to MP_RFD in the packet, used in MPReturnPackets
MP_SET_PACKET_RFD(pMpRfd->NdisPacket, pMpRfd);
return ErrorValue;
} while (FALSE);
if (ErrorValue) { if (pMpRfd->NdisPacket) { NdisFreePacket(pMpRfd->NdisPacket); }
if (pMpRfd->HwRfd) { NdisMFreeSharedMemory( Adapter->AdapterHandle, Adapter->HwRfdSize, FALSE, pMpRfd->HwRfd, pMpRfd->HwRfdPa); } }
return ErrorValue;
}
VOID NICFreeRfd( IN PMP_ADAPTER Adapter, IN PMP_RFD pMpRfd) /*++
Routine Description:
Free a RFD and assocaited NDIS_PACKET and NDIS_BUFFER
Arguments:
Adapter Pointer to our adapter pMpRfd Pointer to a RFD
Return Value:
None
--*/ { ASSERT(pMpRfd->NdisBuffer); ASSERT(pMpRfd->NdisPacket); ASSERT(pMpRfd->HwRfd);
NdisFreeBuffer(pMpRfd->NdisBuffer); NdisFreePacket(pMpRfd->NdisPacket); pMpRfd->NdisBuffer = NULL; pMpRfd->NdisPacket = NULL;
NdisMFreeSharedMemory( Adapter->AdapterHandle, Adapter->HwRfdSize, FALSE, pMpRfd->HwRfd, pMpRfd->HwRfdPa); pMpRfd->HwRfd = NULL;
NdisFreeToNPagedLookasideList(&Adapter->RecvLookaside, pMpRfd); }
NDIS_STATUS NICSelfTest( IN PMP_ADAPTER Adapter) /*++
Routine Description:
Perform a NIC self-test
Arguments:
Adapter Pointer to our adapter
Return Value:
NDIS_STATUS_SUCCESS NDIS_STATUS_DEVICE_FAILED
--*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; ULONG SelfTestCommandCode;
DBGPRINT(MP_TRACE, ("--> NICSelfTest\n"));
DBGPRINT(MP_INFO, ("SelfTest=%x, SelfTestPhys=%x\n", Adapter->SelfTest, Adapter->SelfTestPhys));
// Issue a software reset to the adapter
HwSoftwareReset(Adapter);
// Execute The PORT Self Test Command On The 82558.
ASSERT(Adapter->SelfTestPhys != 0); SelfTestCommandCode = Adapter->SelfTestPhys;
// Setup SELF TEST Command Code in D3 - D0
SelfTestCommandCode |= PORT_SELFTEST;
// Initialize the self-test signature and results DWORDS
Adapter->SelfTest->StSignature = 0; Adapter->SelfTest->StResults = 0xffffffff;
// Do the port command
Adapter->CSRAddress->Port = SelfTestCommandCode;
MP_STALL_EXECUTION(NIC_DELAY_POST_SELF_TEST_MS);
// if The First Self Test DWORD Still Zero, We've timed out. If the second
// DWORD is not zero then we have an error.
if ((Adapter->SelfTest->StSignature == 0) || (Adapter->SelfTest->StResults != 0)) { DBGPRINT(MP_ERROR, ("StSignature=%x, StResults=%x\n", Adapter->SelfTest->StSignature, Adapter->SelfTest->StResults));
NdisWriteErrorLogEntry( Adapter->AdapterHandle, NDIS_ERROR_CODE_HARDWARE_FAILURE, 1, ERRLOG_SELFTEST_FAILED);
Status = NDIS_STATUS_DEVICE_FAILED; }
DBGPRINT_S(Status, ("<-- NICSelfTest, Status=%x\n", Status));
return Status; }
NDIS_STATUS NICInitializeAdapter( IN PMP_ADAPTER Adapter) /*++
Routine Description:
Initialize the adapter and set up everything
Arguments:
Adapter Pointer to our adapter
Return Value:
NDIS_STATUS_SUCCESS NDIS_STATUS_HARD_ERRORS
--*/ { NDIS_STATUS Status; USHORT EepromFlags;
DBGPRINT(MP_TRACE, ("--> NICInitializeAdapter\n"));
do {
// set up our link indication variable
// it doesn't matter what this is right now because it will be
// set correctly if link fails
Adapter->MediaState = NdisMediaStateConnected;
Adapter->CurrentPowerState = NdisDeviceStateD0; Adapter->NextPowerState = NdisDeviceStateD0;
// Issue a software reset to the D100
HwSoftwareReset(Adapter);
// Load the CU BASE (set to 0, because we use linear mode)
Adapter->CSRAddress->ScbGeneralPointer = 0; Status = D100IssueScbCommand(Adapter, SCB_CUC_LOAD_BASE, FALSE); if (Status != NDIS_STATUS_SUCCESS) { break; }
// Wait for the SCB command word to clear before we set the general pointer
if (!WaitScb(Adapter)) { Status = NDIS_STATUS_HARD_ERRORS; break; }
// Load the RU BASE (set to 0, because we use linear mode)
Adapter->CSRAddress->ScbGeneralPointer = 0; Status = D100IssueScbCommand(Adapter, SCB_RUC_LOAD_BASE, FALSE); if (Status != NDIS_STATUS_SUCCESS) { break; }
// Configure the adapter
Status = HwConfigure(Adapter); if (Status != NDIS_STATUS_SUCCESS) break;
Status = HwSetupIAAddress(Adapter); if (Status != NDIS_STATUS_SUCCESS) break;
// Clear the internal counters
HwClearAllCounters(Adapter);
} while (FALSE); if (Status != NDIS_STATUS_SUCCESS) { NdisWriteErrorLogEntry( Adapter->AdapterHandle, NDIS_ERROR_CODE_HARDWARE_FAILURE, 1, ERRLOG_INITIALIZE_ADAPTER); }
DBGPRINT_S(Status, ("<-- NICInitializeAdapter, Status=%x\n", Status));
return Status; }
VOID HwSoftwareReset( IN PMP_ADAPTER Adapter) /*++
Routine Description:
Issue a software reset to the hardware
Arguments:
Adapter Pointer to our adapter
Return Value:
None
--*/ { DBGPRINT(MP_TRACE, ("--> HwSoftwareReset\n"));
// Issue a PORT command with a data word of 0
Adapter->CSRAddress->Port = PORT_SOFTWARE_RESET;
// wait after the port reset command
NdisStallExecution(NIC_DELAY_POST_RESET);
// Mask off our interrupt line -- its unmasked after reset
NICDisableInterrupt(Adapter);
DBGPRINT(MP_TRACE, ("<-- HwSoftwareReset\n")); }
NDIS_STATUS HwConfigure( IN PMP_ADAPTER Adapter) /*++
Routine Description:
Configure the hardware
Arguments:
Adapter Pointer to our adapter
Return Value:
NDIS_STATUS_SUCCESS NDIS_STATUS_HARD_ERRORS
--*/ { NDIS_STATUS Status; PCB_HEADER_STRUC NonTxCmdBlockHdr = (PCB_HEADER_STRUC)Adapter->NonTxCmdBlock; UINT i;
DBGPRINT(MP_TRACE, ("--> HwConfigure\n"));
// Init the packet filter to nothing.
Adapter->PacketFilter = 0; //
// Store the current setting for BROADCAST/PROMISCUOS modes
Adapter->OldParameterField = CB_557_CFIG_DEFAULT_PARM15; // Setup the non-transmit command block header for the configure command.
NonTxCmdBlockHdr->CbStatus = 0; NonTxCmdBlockHdr->CbCommand = CB_CONFIGURE; NonTxCmdBlockHdr->CbLinkPointer = DRIVER_NULL;
// Fill in the configure command data.
// First fill in the static (end user can't change) config bytes
Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[0] = CB_557_CFIG_DEFAULT_PARM0; Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[2] = CB_557_CFIG_DEFAULT_PARM2; Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[3] = CB_557_CFIG_DEFAULT_PARM3; Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[6] = CB_557_CFIG_DEFAULT_PARM6; Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[9] = CB_557_CFIG_DEFAULT_PARM9; Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[10] = CB_557_CFIG_DEFAULT_PARM10; Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[11] = CB_557_CFIG_DEFAULT_PARM11; Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[12] = CB_557_CFIG_DEFAULT_PARM12; Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[13] = CB_557_CFIG_DEFAULT_PARM13; Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[14] = CB_557_CFIG_DEFAULT_PARM14; Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[16] = CB_557_CFIG_DEFAULT_PARM16; Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[17] = CB_557_CFIG_DEFAULT_PARM17; Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[18] = CB_557_CFIG_DEFAULT_PARM18; Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[20] = CB_557_CFIG_DEFAULT_PARM20; Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[21] = CB_557_CFIG_DEFAULT_PARM21;
// Now fill in the rest of the configuration bytes (the bytes that contain
// user configurable parameters).
// Set the Tx and Rx Fifo limits
Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[1] = (UCHAR) ((Adapter->AiTxFifo << 4) | Adapter->AiRxFifo);
if (Adapter->MWIEnable) { Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[3] |= CB_CFIG_B3_MWI_ENABLE; }
// Set the Tx and Rx DMA maximum byte count fields.
if ((Adapter->AiRxDmaCount) || (Adapter->AiTxDmaCount)) { Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[4] = Adapter->AiRxDmaCount; Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[5] = (UCHAR) (Adapter->AiTxDmaCount | CB_CFIG_DMBC_EN); } else { Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[4] = CB_557_CFIG_DEFAULT_PARM4; Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[5] = CB_557_CFIG_DEFAULT_PARM5; }
Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[7] = (UCHAR) ((CB_557_CFIG_DEFAULT_PARM7 & (~CB_CFIG_URUN_RETRY)) | (Adapter->AiUnderrunRetry << 1) );
// Setup for MII or 503 operation. The CRS+CDT bit should only be set
// when operating in 503 mode.
if (Adapter->PhyAddress == 32) { Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[8] = (CB_557_CFIG_DEFAULT_PARM8 & (~CB_CFIG_503_MII)); Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[15] = (CB_557_CFIG_DEFAULT_PARM15 | CB_CFIG_CRS_OR_CDT); } else { Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[8] = (CB_557_CFIG_DEFAULT_PARM8 | CB_CFIG_503_MII); Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[15] = ((CB_557_CFIG_DEFAULT_PARM15 & (~CB_CFIG_CRS_OR_CDT)) | CB_CFIG_BROADCAST_DIS); }
// Setup Full duplex stuff
// If forced to half duplex
if (Adapter->AiForceDpx == 1) Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[19] = (CB_557_CFIG_DEFAULT_PARM19 & (~(CB_CFIG_FORCE_FDX| CB_CFIG_FDX_ENABLE)));
// If forced to full duplex
else if (Adapter->AiForceDpx == 2) Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[19] = (CB_557_CFIG_DEFAULT_PARM19 | CB_CFIG_FORCE_FDX);
// If auto-duplex
else { // We must force full duplex on if we are using PHY 0, and we are
// supposed to run in FDX mode. We do this because the D100 has only
// one FDX# input pin, and that pin will be connected to PHY 1.
if ((Adapter->PhyAddress == 0) && (Adapter->usDuplexMode == 2)) Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[19] = (CB_557_CFIG_DEFAULT_PARM19 | CB_CFIG_FORCE_FDX); else Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[19] = CB_557_CFIG_DEFAULT_PARM19; }
// display the config info to the debugger
DBGPRINT(MP_INFO, (" Issuing Configure command\n")); DBGPRINT(MP_INFO, (" Config Block at virt addr "PTR_FORMAT", phys address %x\n", &NonTxCmdBlockHdr->CbStatus, Adapter->NonTxCmdBlockPhys));
for (i=0; i < CB_CFIG_BYTE_COUNT; i++) DBGPRINT(MP_INFO, (" Config byte %x = %.2x\n", i, Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[i]));
// Wait for the SCB command word to clear before we set the general pointer
if (!WaitScb(Adapter)) { Status = NDIS_STATUS_HARD_ERRORS; } else { ASSERT(Adapter->CSRAddress->ScbCommandLow == 0) Adapter->CSRAddress->ScbGeneralPointer = Adapter->NonTxCmdBlockPhys; // Submit the configure command to the chip, and wait for it to complete.
Status = D100SubmitCommandBlockAndWait(Adapter); }
DBGPRINT_S(Status, ("<-- HwConfigure, Status=%x\n", Status));
return Status; }
NDIS_STATUS HwSetupIAAddress( IN PMP_ADAPTER Adapter) /*++
Routine Description:
Set up the individual MAC address
Arguments:
Adapter Pointer to our adapter
Return Value:
NDIS_STATUS_SUCCESS NDIS_SUCCESS_HARD_ERRORS
--*/ { NDIS_STATUS Status; UINT i; PCB_HEADER_STRUC NonTxCmdBlockHdr = (PCB_HEADER_STRUC)Adapter->NonTxCmdBlock;
DBGPRINT(MP_TRACE, ("--> HwSetupIAAddress\n"));
// Individual Address Setup
NonTxCmdBlockHdr->CbStatus = 0; NonTxCmdBlockHdr->CbCommand = CB_IA_ADDRESS; NonTxCmdBlockHdr->CbLinkPointer = DRIVER_NULL;
// Copy in the station's individual address
for (i = 0; i < ETH_LENGTH_OF_ADDRESS; i++) Adapter->NonTxCmdBlock->NonTxCb.Setup.IaAddress[i] = Adapter->CurrentAddress[i];
// Update the command list pointer. We don't need to do a WaitSCB here
// because this command is either issued immediately after a reset, or
// after another command that runs in polled mode. This guarantees that
// the low byte of the SCB command word will be clear. The only commands
// that don't run in polled mode are transmit and RU-start commands.
ASSERT(Adapter->CSRAddress->ScbCommandLow == 0) Adapter->CSRAddress->ScbGeneralPointer = Adapter->NonTxCmdBlockPhys;
// Submit the IA configure command to the chip, and wait for it to complete.
Status = D100SubmitCommandBlockAndWait(Adapter);
DBGPRINT_S(Status, ("<-- HwSetupIAAddress, Status=%x\n", Status));
return Status; }
NDIS_STATUS HwClearAllCounters( IN PMP_ADAPTER Adapter) /*++
Routine Description:
This routine will clear the hardware error statistic counters Arguments:
Adapter Pointer to our adapter
Return Value:
NDIS_STATUS_SUCCESS NDIS_STATUS_HARD_ERRORS
--*/ { NDIS_STATUS Status; BOOLEAN bResult;
DBGPRINT(MP_TRACE, ("--> HwClearAllCounters\n"));
do { // Load the dump counters pointer. Since this command is generated only
// after the IA setup has complete, we don't need to wait for the SCB
// command word to clear
ASSERT(Adapter->CSRAddress->ScbCommandLow == 0) Adapter->CSRAddress->ScbGeneralPointer = Adapter->StatsCounterPhys;
// Issue the load dump counters address command
Status = D100IssueScbCommand(Adapter, SCB_CUC_DUMP_ADDR, FALSE); if (Status != NDIS_STATUS_SUCCESS) break;
// Now dump and reset all of the statistics
Status = D100IssueScbCommand(Adapter, SCB_CUC_DUMP_RST_STAT, TRUE); if (Status != NDIS_STATUS_SUCCESS) break;
// Now wait for the dump/reset to complete, timeout value 2 secs
MP_STALL_AND_WAIT(Adapter->StatsCounters->CommandComplete == 0xA007, 2000, bResult); if (!bResult) { MP_SET_HARDWARE_ERROR(Adapter); Status = NDIS_STATUS_HARD_ERRORS; break; }
// init packet counts
Adapter->GoodTransmits = 0; Adapter->GoodReceives = 0;
// init transmit error counts
Adapter->TxAbortExcessCollisions = 0; Adapter->TxLateCollisions = 0; Adapter->TxDmaUnderrun = 0; Adapter->TxLostCRS = 0; Adapter->TxOKButDeferred = 0; Adapter->OneRetry = 0; Adapter->MoreThanOneRetry = 0; Adapter->TotalRetries = 0;
// init receive error counts
Adapter->RcvCrcErrors = 0; Adapter->RcvAlignmentErrors = 0; Adapter->RcvResourceErrors = 0; Adapter->RcvDmaOverrunErrors = 0; Adapter->RcvCdtFrames = 0; Adapter->RcvRuntErrors = 0;
} while (FALSE);
DBGPRINT_S(Status, ("<-- HwClearAllCounters, Status=%x\n", Status));
return Status; }
|