📄 init.c
字号:
else
HwTcbPtr->TxCbHeader.CbLinkPointer = HwTcbPhys + sizeof(TXCB_STRUC);
// Set the D100's early transmit threshold
HwTcbPtr->TxCbThreshold = (UCHAR) Adapter->AiThreshold;
// Pointer this TCB's TBD array
HwTcbPtr->TxCbTbdPointer = HwTbdPhys;
// Store a pointer to the previous TCB in the SwTcb structure. This
// pointer will be used later when we have to clear the S-bit in the
// previous TCB
if (TcbCount == 0)
SwTcbPtr->PreviousTcb = (PTXCB_STRUC) (Adapter->XmitUnCached +
((Adapter->NumTcb -1) * sizeof(TXCB_STRUC)));
else
SwTcbPtr->PreviousTcb = (HwTcbPtr -1);
// add this TCB to the free list
QueuePutTail(&Adapter->TxCBList, &SwTcbPtr->Link);
}
// Setup pointers to the first coalesce buffer. The SW coalesce structures
// will be located immediately after the last SwTcb, and the HW coalesce
// structures will located after the last TBD on a 2k boundary.
Coalesce = (PCOALESCE) SwTcbPtr;
CoalesceBufVirtPtr = (PUCHAR) HwTbdPtr;
CoalesceBufPhysPtr = (ULONG) HwTbdPhys;
CoalesceBufPhysPtr += 0x000007FF;
CoalesceBufPhysPtr &= (~0x000007FF);
CoalesceBufVirtPtr = (PUCHAR) (((ULONG_PTR) HwTbdPtr) +
(CoalesceBufPhysPtr - (ULONG) HwTbdPhys));
// Go through each coalesce buffer
for (CoalesceCount = 0; CoalesceCount < Adapter->NumCoalesce; CoalesceCount++, Coalesce++)
{
INITSTRTX(DebugPrint, ("Coalesce struct %d @ %08x, buffer %08x %08x\n",
CoalesceCount, Coalesce, CoalesceBufVirtPtr, CoalesceBufPhysPtr));
QueuePutTail(&Adapter->CoalesceBufferList, &Coalesce->Link);
// Set the phys and virtual pointers for each coalesce buffer
Coalesce->CoalesceBufferPtr = CoalesceBufVirtPtr;
Coalesce->CoalesceBufferPhys = CoalesceBufPhysPtr;
CoalesceBufPhysPtr += COALESCE_BUFFER_SIZE;
CoalesceBufVirtPtr += COALESCE_BUFFER_SIZE;
}
// Initialize the Transmit queueing pointers to NULL
Adapter->FirstTxQueue = (PNDIS_PACKET) NULL;
Adapter->LastTxQueue = (PNDIS_PACKET) NULL;
Adapter->NumPacketsQueued = 0;
}
//-----------------------------------------------------------------------------
// Procedure: SetupReceiveQueues
//
// Description: Setup the Receive Frame Area (RFA) at INIT time. This
// includes setting up each RFD in the RFA, and linking all of the
// RFDs together.
// Also set up our buffers for NDIS 5 and multiple receive indications
// through a packet array.
//
// Arguments:
// Adapter - ptr to Adapter object instance
//
// Returns: (none)
//-----------------------------------------------------------------------------
VOID
SetupReceiveQueues(
IN PD100_ADAPTER Adapter
)
{
// RFD local variables
D100SwRfd *SwRfdPtr, *SwRfdNext; // cached RFD list logical pointers
RFD_STRUC *HwRfdPtr, *HwRfdNext; // uncached RFD list logical pointers
ULONG HwRfdPhys; // uncached RFD list physical pointer
UINT RfdCount;
NDIS_STATUS AllocationStatus;
PD100SwRfd *TempPtr;
DEBUGFUNC("SetupReceiveQueues");
INITSTR(("\n"));
// save the old number of Rfds to make cleaning up easier
Adapter->OriginalNumRfd = Adapter->NumRfd;
/*************************************************/
/* initialize the logical and physical RFD lists */
/*************************************************/
// init the lists
QueueInitList(&Adapter->RfdList);
SwRfdNext = (D100SwRfd *)Adapter->RecvCached; // cached RFDs logical
HwRfdNext = (RFD_STRUC *)Adapter->RecvUnCached; // uncached RFDs logical
// uncached RFD physical address
HwRfdPhys = NdisGetPhysicalAddressLow(Adapter->RecvUnCachedPhys);
INITSTR(("sizeof(SwRfd)=%x\n", sizeof(D100SwRfd)));
INITSTR(("sizeof(HwRfd)=%x\n", sizeof(RFD_STRUC)));
INITSTR(("Adapter->NumRfd=%d\n", Adapter->NumRfd));
// Set up a pool of data for us to build our packet array out of
// for indicating groups of packets to NDIS
// this could be quite the memory hog, but makes management
// of the pointers associated with Asynchronous memory allocation
// easier
NdisAllocatePacketPool(&AllocationStatus,
&Adapter->ReceivePacketPool,
MAX_RECEIVE_DESCRIPTORS,
NUM_BYTES_PROTOCOL_RESERVED_SECTION);
ASSERT(AllocationStatus == NDIS_STATUS_SUCCESS);
// Set up our pool of buffer descriptors...
// we will at most have 1 per packet, so just allocate as
// many buffers as we have packets.
NdisAllocateBufferPool(&AllocationStatus,
&Adapter->ReceiveBufferPool,
MAX_RECEIVE_DESCRIPTORS);
// AllocateBufferPool suppossedly always returns success...
ASSERT(AllocationStatus == NDIS_STATUS_SUCCESS);
// Setup each RFD
for (RfdCount = 0; RfdCount < Adapter->NumRfd; RfdCount++)
{
// point to the next RFD (after the first time through)
SwRfdPtr = SwRfdNext;
HwRfdPtr = HwRfdNext;
INITSTR((" RfdCount=%d\n", RfdCount));
INITSTR((" SwRfdPtr=%lx\n", SwRfdPtr));
INITSTR((" HwRfdPtr=%lx\n", HwRfdPtr));
INITSTR((" HwRfdPhys=%lx\n", HwRfdPhys));
#if DBG
SwRfdPtr->RfdNum = RfdCount;
#endif
// point the logical RFD to the pointer of the physical one
SwRfdPtr->Rfd = HwRfdPtr;
// store the physical address in the Software RFD Structure
SwRfdPtr->RfdPhys = HwRfdPhys;
// point to the next RFD (add sizeof RFD struc)
// The compiler takes care of translating +1 into a +sizeof(RFD_STRUC)
SwRfdNext = SwRfdPtr + 1;
HwRfdNext = HwRfdPtr + 1;
HwRfdPhys += sizeof(RFD_STRUC);
// initialize the physical RFD contents
if (RfdCount < (Adapter->NumRfd - 1))
{
// if not the last RFD...
HwRfdPtr->RfdCbHeader.CbCommand =0;
HwRfdPtr->RfdCbHeader.CbLinkPointer = HwRfdPhys;
}
else
{
// if this is the last RFD...
HwRfdPtr->RfdCbHeader.CbCommand = RFD_EL_BIT;
HwRfdPtr->RfdCbHeader.CbLinkPointer = DRIVER_NULL;
}
// Init each RFD header
HwRfdPtr->RfdCbHeader.CbStatus = 0;
HwRfdPtr->RfdRbdPointer = DRIVER_NULL;
HwRfdPtr->RfdActualCount= 0;
HwRfdPtr->RfdSize = sizeof(ETH_RX_BUFFER_STRUC);
// set up the packet structure for passing up this Rfd
// with NdisMIndicateReceivePacket
NdisAllocatePacket(&AllocationStatus,
&SwRfdPtr->ReceivePacket,
Adapter->ReceivePacketPool);
// probably should do some error handling here
ASSERT(AllocationStatus == NDIS_STATUS_SUCCESS);
NDIS_SET_PACKET_HEADER_SIZE(SwRfdPtr->ReceivePacket,
ETHERNET_HEADER_SIZE);
// point our buffer for receives at this Rfd
NdisAllocateBuffer(&AllocationStatus,
&SwRfdPtr->ReceiveBuffer,
Adapter->ReceiveBufferPool,
(PVOID)&HwRfdPtr->RfdBuffer.RxMacHeader,
MAXIMUM_ETHERNET_PACKET_SIZE);
// probably should do some error handling here
ASSERT(AllocationStatus == NDIS_STATUS_SUCCESS);
NdisChainBufferAtFront(SwRfdPtr->ReceivePacket,
SwRfdPtr->ReceiveBuffer);
// set up the reverse path from Packet to SwRfd
// this is so when D100GetReturnedPackets is called we
// can find our software superstructure that owns this receive area.
TempPtr = (PD100SwRfd *) &SwRfdPtr->ReceivePacket->MiniportReserved;
*TempPtr = SwRfdPtr;
// Add this RFD to the free list
QueuePutTail(&Adapter->RfdList, &SwRfdPtr->Link);
}
}
//-----------------------------------------------------------------------------
// Procedure: InitializeAdapter
//
// Description: This routine performs a reset on the adapter, and configures
// the adapter. This includes configuring the 82557 LAN
// controller, validating and setting the node address, detecting
// and configuring the Phy chip on the adapter, and initializing
// all of the on chip counters.
//
// Arguments:
// Adapter - ptr to Adapter object instance
//
// Returns:
// TRUE - If the adapter was initialized
// FALSE - If the adapter failed initialization
//-----------------------------------------------------------------------------
BOOLEAN
InitializeAdapter(
IN PD100_ADAPTER Adapter
)
{
USHORT EepromFlags;
DEBUGFUNC("InitializeAdapter");
INITSTR(("\n"));
// Check if there was a node address over-ride. If there isn't then we'll
// use our adapter's permanent node address as our "current" node address.
// If a node address over-ride is present in the registry, then we'll use
// that override address as our node address instead of the permanent
// address in the adapter's EEPROM
if ((Adapter->AiNodeAddress[0]==0) &&
(Adapter->AiNodeAddress[1]==0) &&
(Adapter->AiNodeAddress[2]==0) &&
(Adapter->AiNodeAddress[3]==0) &&
(Adapter->AiNodeAddress[4]==0) &&
(Adapter->AiNodeAddress[5]==0))
{
// No node address override so use the permanent address
INITSTR(("InitializeAdapter: No node address over-ride, using permanent address\n"));
NdisMoveMemory(Adapter->AiNodeAddress,
Adapter->AiPermanentNodeAddress,
ETH_LENGTH_OF_ADDRESS);
}
INITSTR(("InitializeAdapter: Node Address is %.2x %.2x %.2x %.2x %.2x %.2x\n",
Adapter->AiNodeAddress[0],
Adapter->AiNodeAddress[1],
Adapter->AiNodeAddress[2],
Adapter->AiNodeAddress[3],
Adapter->AiNodeAddress[4],
Adapter->AiNodeAddress[5]
));
// Validate our current node address (make sure its not a mulicast)
if ((UCHAR) Adapter->AiNodeAddress[0] & 1)
{
INITSTR(("InitializeAdapter: Node address invalid -- its a MC address\n"));
D100LogError(Adapter, EVENT_2, NDIS_ERROR_CODE_NETWORK_ADDRESS, 0);
return (FALSE);
}
// Detect the serial component, and set up the Phy if necessary
if (!PhyDetect(Adapter))
return (FALSE);
// Set the McTimeoutFlag variable. This flag will determine whether the
// driver issues a periodic multicast command or not. Issuing a periodic
// multicast command will reset the 82557's internal receive state machine,
// and bring the 82557 out of a "Receive-lockup" state. This is a documented
// errata in the 82557 software developement manual.
// If the end user didn't over-ride the McTimeout flag, then it should be
// enabled only for 10mb operation, and only if the EEPROM indicates that
// this adapter has a potential rcv-lockup problem
if (Adapter->McTimeoutFlag == 2)
{
// Read the EEPROM flags register
EepromFlags = ReadEEprom(Adapter, EEPROM_FLAGS_WORD_3, Adapter->AiBaseIo);
if (((Adapter->AiLineSpeedCur == 10) && (!(EepromFlags & EEPROM_FLAG_10MC))) ||
((Adapter->AiLineSpeedCur == 100) && (!(EepromFlags & EEPROM_FLAG_100MC))))
Adapter->McTimeoutFlag = 1;
else
Adapter->McTimeoutFlag = 0;
}
INITSTR(("MC Timeout Flag = %x\n", Adapter->McTimeoutFlag));
// 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->LinkIsActive = NdisMediaStateConnected;
Adapter->CurrentPowerState = NdisDeviceStateD0;
Adapter->NextPowerState = NdisDeviceStateD0;
// Now Initialize the D100
return (InitializeD100(Adapter));
}
//-----------------------------------------------------------------------------
// Procedure: InitializeD100
//
// Description: This routine will perform the initial configuration on the
// the 82557 (D100) chip. This will include loading the CU and
// RU base values (0 in both cases), and calling other routines
// that will issue a configure command to the 82257, notify the
// 82557 of its node address, and clear all of the on-chip
// counters.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -