2063 lines
62 KiB
C
2063 lines
62 KiB
C
/*++
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|