📄 d100.c
字号:
// Allocate the Adapter Object, exit if error occurs
Status = D100_ALLOC_MEM(&Adapter, sizeof(D100_ADAPTER));
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGSTR(("ADAPTER Allocate Memory failed (Status = 0x%x)\n", Status));
return Status;
}
//Zero out the adapter object space
NdisZeroMemory(Adapter, sizeof(D100_ADAPTER));
Adapter->D100AdapterHandle = MiniportAdapterHandle;
INITSTR(("Adapter structure pointer is %08x\n", Adapter));
// Open Registry, exit if error occurs.
NdisOpenConfiguration(&Status,
&ConfigHandle,
WrapperConfigurationContext);
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGSTR(("NdisOpenConfiguration failed (Status = 0x%x)\n", Status));
FreeAdapterObject(Adapter);
return NDIS_STATUS_FAILURE;
}
// Parse all of our configuration parameters.
Status = ParseRegistryParameters(Adapter, ConfigHandle);
// If a required configuration parameter was not present, then error out
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGSTR(("ParseRegistryParameters failed (Status = 0x%x)\n", Status));
NdisCloseConfiguration(ConfigHandle);
FreeAdapterObject(Adapter);
return Status;
}
// initialize the number of Tcbs we will have in our queue
// this is to work around limitations of the hardware and the S-bit
Adapter->NumTcb = Adapter->RegNumTcb + 1;
DEBUGSTR(("ParseRegistryParameters Completed successfully\n"));
// Look for a Node Address (IA) override
// this is where the registry parameter NodeAddress in
// HKLM\System\CCS\Services\E100BX\Parameters
NdisReadNetworkAddress(&Status,
&OverrideNetAddress,
(UINT *) &i,
ConfigHandle);
// If there is an IA override save it to the adapter object
if ((i == ETH_LENGTH_OF_ADDRESS) && (Status == NDIS_STATUS_SUCCESS))
NdisMoveMemory(Adapter->AiNodeAddress,
OverrideNetAddress,
ETH_LENGTH_OF_ADDRESS);
// We read out all of our config info, so close the gateway to the registry
NdisCloseConfiguration(ConfigHandle);
// register our adapter object with the OS as a PCI adapter
IfType = NdisInterfacePci;
// call NdisMSetAttributesEx in order to let NDIS know
// what kind of driver and features we support
NdisMSetAttributesEx(
Adapter->D100AdapterHandle,
(NDIS_HANDLE) Adapter,
0,
(ULONG)
NDIS_ATTRIBUTE_DESERIALIZE |
NDIS_ATTRIBUTE_BUS_MASTER,
IfType
);
// Assign (Claim) a physical Adapter for this Adapter object
// In this function is where we find our adapter on the PCI bus and
// call NdisMPciAssignResources
if (ClaimAdapter(Adapter) != NDIS_STATUS_SUCCESS)
{
DEBUGSTR(("No adapter detected\n"));
FreeAdapterObject(Adapter);
return NDIS_STATUS_FAILURE;
}
// set up our Command Register's I/O mapping (the CSR)
Status = SetupAdapterInfo(Adapter);
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGSTR(("I/O Space allocation failed (Status = 0x%X)\n",Status));
FreeAdapterObject(Adapter);
return(NDIS_STATUS_FAILURE);
}
// allocate & Initialize the required 82557 (D100) Shared Memory areas
Status = SetupSharedAdapterMemory(Adapter);
// Check the status returned from SetupSharedAdapterMemory
if (Status != NDIS_STATUS_SUCCESS)
{
// Since we couldn't allocate enough shared memory, free any resources
// that we previously allocated and error out.
D100LogError(Adapter, EVENT_10, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 0);
DEBUGSTR(("Shared Memory Allocation failed (Status = 0x%x)\n", Status));
// Free our adapter object
FreeAdapterObject(Adapter);
return NDIS_STATUS_FAILURE;
}
// Disable interrupts while we finish with the initialization
// Must SetupSharedAdapterMemory() before you can do this
// (fixed bug) must check for success of alloc sharedmem before
// calling D100DisableInterrupt.
D100DisableInterrupt(Adapter);
// Next we'll register our interrupt with the NDIS wrapper.
// Hook our interrupt vector. We used level-triggered, shared interrupts
// with our PCI adapters
DEBUGSTR(("RegisterIrq: handl=%x, irq=%x, mode=%x\n",
Adapter->D100AdapterHandle, Adapter->AiInterrupt,
Adapter->InterruptMode));
Status = NdisMRegisterInterrupt(&Adapter->Interrupt,
Adapter->D100AdapterHandle,
Adapter->AiInterrupt,
Adapter->AiInterrupt,
FALSE,
TRUE, /* shared irq */
Adapter->InterruptMode);
if (Status != NDIS_STATUS_SUCCESS)
{
TRACESTR(Adapter,("Interrupt conflict, Status %08x, IRQ %d, %s Sensitive\n",
Status,
Adapter->AiInterrupt,
(Adapter->InterruptMode==NdisInterruptLevelSensitive)?"Level":"Edge")
);
D100LogError(Adapter,
EVENT_0,
NDIS_ERROR_CODE_INTERRUPT_CONNECT,
(ULONG) Adapter -> AiInterrupt);
// Free the entire adapter object and error out
FreeAdapterObject(Adapter);
return NDIS_STATUS_FAILURE;
}
// Test our adapter hardware. If the adapter is not seated in a bus
// mastering slot, or if the master enable bit is not set in the adapter's
// PCI configuration space, the self-test will fail.
Status = SelfTestHardware(Adapter);
if(Status != NDIS_STATUS_SUCCESS)
{
// Since the adapter failed the self-test, free any resources that
// we previously allocated and error out.
DEBUGSTR(("Adapter Self Test Failure.\n"));
NdisMDeregisterInterrupt(&Adapter->Interrupt);
FreeAdapterObject(Adapter);
return NDIS_STATUS_FAILURE;
}
// Setup and initialize the transmit structures.
SetupTransmitQueues(Adapter, TRUE);
// configure the 82557 (D100) chip.
if (!InitializeAdapter(Adapter))
{
// Since the adapter failed to initialize, free any resources that
// we previously allocated and error out.
DEBUGSTR(("InitializeAdapter Failed.\n"));
NdisMDeregisterInterrupt(&Adapter->Interrupt);
FreeAdapterObject(Adapter);
return NDIS_STATUS_FAILURE;
}
// allocate a spin lock for locking at all our entry points
NdisAllocateSpinLock(&Adapter->Lock);
// DbgPrint ("E100B: Adapter->Lock address is %8X\n", (char *) &Adapter->Lock);
// DbgPrint ("E100B: Adapter->SendQueueListHead address is 0x%8X\n", (char *) &(Adapter->FirstTxQueue));
// Setup and initialize the receive structures
SetupReceiveQueues(Adapter);
// Start the receive unit -- we can now receive packets off the wire
StartReceiveUnit(Adapter);
// register a shutdown handler...
NdisMRegisterAdapterShutdownHandler(Adapter->D100AdapterHandle,
(PVOID) Adapter,
(ADAPTER_SHUTDOWN_HANDLER) D100ShutdownHandler);
// Init a timer for use with our reset routine...
NdisMInitializeTimer(&Adapter->D100AsyncResetTimer,
Adapter->D100AdapterHandle,
(PNDIS_TIMER_FUNCTION) D100ResetComplete,
(PVOID) Adapter);
// Enable board interrupts
D100EnableInterrupt(Adapter);
DEBUGSTR(("D100Initialize: Completed Init Successfully\n"));
return NDIS_STATUS_SUCCESS;
}
//-----------------------------------------------------------------------------
// Procedure: D100Reset
//
// Description: Instructs the Miniport to issue a hardware reset to the
// network adapter. The driver also resets its software state.
// this function also resets the transmit queues.
//
// Arguments:
// AddressingReset - TRUE if the wrapper needs to call
// MiniportSetInformation to restore the addressing
// information to the current values
// MiniportAdapterContext - pointer to the adapter object data area.
//
// Returns:
// NDIS_STATUS_PENDING - This function sets a timer to complete, so
// pending is always returned
//-----------------------------------------------------------------------------
NDIS_STATUS
D100Reset(PBOOLEAN AddressingReset,
NDIS_HANDLE MiniportAdapterContext)
{
PD100_ADAPTER Adapter;
DEBUGFUNC("D100Reset");
INITSTR(("\n"));
Adapter = PD100_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
NdisAcquireSpinLock(&Adapter->Lock);
DEBUGCHAR(Adapter,'$');
*AddressingReset = TRUE;
// *** possible temporary code
// *** NDIS may actually handle this
Adapter->ResetInProgress = TRUE;
// Disable interrupts while we re-init the transmit structures
D100DisableInterrupt(Adapter);
// The NDIS 5 support for deserialized miniports requires that
// when reset is called, the driver de-queue and fail all uncompleted
// sends, and complete any uncompleted sends. Essentially we must have
// no pending send requests left when we leave this routine.
// we will fail all sends that we have left right now.
DEBUGSTR(("DeQing: "));
while(Adapter->FirstTxQueue)
{
PNDIS_PACKET QueuePacket = Adapter->FirstTxQueue;
Adapter->NumPacketsQueued--;
DequeuePacket(Adapter->FirstTxQueue, Adapter->LastTxQueue);
// we must release the lock here before returning control to ndis
// (even temporarily like this)
NdisReleaseSpinLock(&Adapter->Lock);
NdisMSendComplete(
Adapter->D100AdapterHandle,
QueuePacket,
NDIS_STATUS_FAILURE);
NdisAcquireSpinLock(&Adapter->Lock);
}
DEBUGSTR(("\nDone!\n"));
// clean up all the packets we have successfully TX'd
ProcessTXInterrupt(Adapter);
while (!(QueueEmpty(&Adapter->ActiveChainList)))
{
// here we have to fail any sends that haven't completed yet
PD100SwTcb pSwTcb = (PD100SwTcb) QueuePopHead(&Adapter->ActiveChainList);
// If this wasn't a multicast command, then we need to check to see
// if we need to issue send complete
if ((pSwTcb->Tcb->TxCbHeader.CbCommand & CB_CMD_MASK) != CB_MULTICAST)
{
DEBUGCHAR(Adapter,'-');
NdisReleaseSpinLock(&Adapter->Lock);
// Do a send Complete for this frame
NdisMSendComplete(
Adapter->D100AdapterHandle,
pSwTcb->Packet,
NDIS_STATUS_FAILURE);
NdisAcquireSpinLock(&Adapter->Lock);
}
}
// Issue a selective reset to make the CU idle. This will also abort
// the RU, and make the receive unit go idle.
D100IssueSelectiveReset(Adapter);
// since the d100/d101 both assert the interrupt line after reset,
// lets try disabling ints here, because we don't handle
// anything on a reset interrupt anyway.
D100DisableInterrupt(Adapter);
// Clear out our software transmit structures
NdisZeroMemory((PVOID) Adapter->XmitCached, Adapter->XmitCachedSize);
// re-init the map register related variables
Adapter->NextFreeMapReg = 0;
Adapter->OldestUsedMapReg = 0;
// re-initialize the transmit structures
DEBUGSTR(("D100Reset: Calling SetupTransmitQueues\n"));
SetupTransmitQueues(Adapter, FALSE);
// set a timer to call us back so
// that we don't try to hold a spinlock too long
// delay 500 ms
NdisMSetTimer(&Adapter->D100AsyncResetTimer,500);
NdisReleaseSpinLock(&Adapter->Lock);
// return status_pending so that we can finish this later
return(NDIS_STATUS_PENDING);
}
//-----------------------------------------------------------------------------
// D100ResetComplete
//
// PARAMETERS: NDIS_HANDLE MiniportAdapterContext
//
// DESCRIPTION: This function is called by a timer indicating our
// reset is done (by way of .5 seconds expiring)
//
// RETURNS: nothing, but sets NdisMResetComplete, enables ints
// and starts the receive unit
//
//-----------------------------------------------------------------------------
VOID
D100ResetComplete(PVOID sysspiff1,
NDIS_HANDLE MiniportAdapterContext,
PVOID sysspiff2, PVOID sysspiff3)
{
PD100_ADAPTER Adapter;
DEBUGFUNC("D100ResetComplete");
INITSTR(("\n"));
Adapter = PD100_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
DEBUGCHAR(Adapter,'@');
NdisMResetComplete(Adapter->D100AdapterHandle,
(NDIS_STATUS) NDIS_STATUS_SUCCESS,
FALSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -