mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1918 lines
38 KiB
1918 lines
38 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
reset.c
|
|
|
|
Abstract:
|
|
|
|
This is the file containing the reset code for the IBM Token Ring 16/4 II
|
|
ISA adapter. This driver conforms to the NDIS 3.0 Miniport interface.
|
|
|
|
Author:
|
|
|
|
Kevin Martin (KevinMa) 1-Feb-1994
|
|
|
|
Environment:
|
|
|
|
Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <tok162sw.h>
|
|
|
|
#pragma NDIS_INIT_FUNCTION(TOK162InitialInit)
|
|
|
|
//
|
|
// Declarations for functions private to this file.
|
|
//
|
|
extern
|
|
VOID
|
|
TOK162ProcessRequestQueue(
|
|
IN PTOK162_ADAPTER Adapter,
|
|
IN BOOLEAN StatisticsUpdated
|
|
);
|
|
|
|
VOID
|
|
TOK162WriteInitializationBlock(
|
|
IN PTOK162_ADAPTER Adapter
|
|
);
|
|
|
|
VOID
|
|
TOK162SetInitializationBlock(
|
|
IN PTOK162_ADAPTER Adapter
|
|
);
|
|
|
|
VOID
|
|
TOK162SetInitializationBlockAndInit(
|
|
IN PTOK162_ADAPTER Adapter,
|
|
OUT PNDIS_STATUS Status
|
|
);
|
|
|
|
NDIS_STATUS
|
|
TOK162ChangeCurrentAddress(
|
|
IN PTOK162_ADAPTER Adapter
|
|
);
|
|
|
|
VOID
|
|
TOK162ResetCommandBlocks(
|
|
IN PTOK162_ADAPTER Adapter
|
|
);
|
|
|
|
BOOLEAN
|
|
CheckResetResults(
|
|
IN PTOK162_ADAPTER Adapter
|
|
);
|
|
|
|
NDIS_STATUS
|
|
CheckInitResults(
|
|
IN PTOK162_ADAPTER Adapter
|
|
);
|
|
|
|
VOID
|
|
TOK162GetAdapterOffsets(
|
|
IN PTOK162_ADAPTER Adapter
|
|
);
|
|
VOID
|
|
TOK162ResetReceiveQueue(
|
|
IN PTOK162_ADAPTER Adapter
|
|
);
|
|
|
|
VOID
|
|
TOK162AbortSend(
|
|
IN PTOK162_ADAPTER Adapter,
|
|
IN PTOK162_SUPER_COMMAND_BLOCK CurrentCommandBlock
|
|
);
|
|
|
|
extern
|
|
void
|
|
TOK162SendCommandBlock(
|
|
IN PTOK162_ADAPTER Adapter,
|
|
IN PTOK162_SUPER_COMMAND_BLOCK CommandBlock
|
|
);
|
|
|
|
|
|
|
|
|
|
BOOLEAN
|
|
TOK162InitialInit(
|
|
IN PTOK162_ADAPTER Adapter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets up the initial init of the driver.
|
|
|
|
Arguments:
|
|
|
|
Adapter - The adapter structure for the hardware.
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE if not.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Holds status returned from NDIS calls.
|
|
//
|
|
NDIS_STATUS Status;
|
|
|
|
//
|
|
// First we make sure that the device is stopped.
|
|
//
|
|
TOK162DisableInterrupt(Adapter);
|
|
|
|
//
|
|
// Set flags indicating we are doing the initial init
|
|
//
|
|
Adapter->InitialInit = TRUE;
|
|
Adapter->ResetState = InitialInit;
|
|
Adapter->InitialOpenComplete = FALSE;
|
|
Adapter->InitialReceiveSent = FALSE;
|
|
Adapter->ResetInProgress = TRUE;
|
|
|
|
//
|
|
// Initialize the interrupt.
|
|
//
|
|
Status = NdisMRegisterInterrupt(
|
|
&Adapter->Interrupt,
|
|
Adapter->MiniportAdapterHandle,
|
|
Adapter->InterruptLevel,
|
|
Adapter->InterruptLevel,
|
|
FALSE,
|
|
FALSE,
|
|
NdisInterruptLatched
|
|
);
|
|
|
|
//
|
|
// Report the status of the interrupt registering to the debugger
|
|
//
|
|
VERY_LOUD_DEBUG(DbgPrint(
|
|
"IBMTOK2I!Status from Registering Interrupt -%u was %u\n",
|
|
Adapter->InterruptLevel,
|
|
Status);)
|
|
|
|
//
|
|
// If the interrupt register failed, mark the interrupt level at 0 so
|
|
// we know not to do a deregister.
|
|
//
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
|
|
Adapter->InterruptLevel = 0;
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
//
|
|
// Initialize the open command to zeros
|
|
//
|
|
NdisZeroMemory(Adapter->Open,sizeof(OPEN_COMMAND));
|
|
|
|
//
|
|
// Set up the Open command block
|
|
//
|
|
|
|
//
|
|
// Set the options
|
|
//
|
|
Adapter->Open->Options = OPEN_OPTION_CONTENDER;
|
|
|
|
//
|
|
// Set the receive and transmit list sizes as well as the buffer size
|
|
//
|
|
Adapter->Open->ReceiveListSize = BYTE_SWAP(OPEN_RECEIVE_LIST_SIZE);
|
|
Adapter->Open->TransmitListSize = BYTE_SWAP(OPEN_TRANSMIT_LIST_SIZE);
|
|
Adapter->Open->BufferSize = BYTE_SWAP(OPEN_BUFFER_SIZE);
|
|
|
|
//
|
|
// Make sure the adapter can handle one entire frame
|
|
//
|
|
Adapter->Open->TransmitBufCountMin =
|
|
(Adapter->ReceiveBufferSize / OPEN_BUFFER_SIZE) + 1;
|
|
|
|
Adapter->Open->TransmitBufCountMax = Adapter->Open->TransmitBufCountMin;
|
|
|
|
//
|
|
// Reset the adapter
|
|
//
|
|
TOK162ResetAdapter(Adapter);
|
|
|
|
//
|
|
// Reenable interrupts
|
|
//
|
|
TOK162EnableInterrupt(Adapter);
|
|
|
|
//
|
|
// Go through the reset stages
|
|
//
|
|
VERY_LOUD_DEBUG(DbgPrint("IBMTOK2I!Calling TOK162ResetHandler\n");)
|
|
|
|
TOK162ResetHandler(NULL,Adapter,NULL,NULL);
|
|
|
|
VERY_LOUD_DEBUG(DbgPrint("IBMTOK2I!Back from TOK162ResetHandler\n");)
|
|
|
|
//
|
|
// The Initial init is done.
|
|
//
|
|
Adapter->InitialInit = FALSE;
|
|
|
|
//
|
|
// Check the reset status and return TRUE if successful, FALSE if not.
|
|
//
|
|
if (Adapter->ResetResult == NDIS_STATUS_SUCCESS) {
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
TOK162EnableAdapter(
|
|
IN NDIS_HANDLE Context
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to start an already initialized TOK162.
|
|
|
|
Arguments:
|
|
|
|
Context - The adapter for the TOK162.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Pointer to an adapter structure. Makes Context (passed in value)
|
|
// a structure we can deal with.
|
|
//
|
|
PTOK162_ADAPTER Adapter = (PTOK162_ADAPTER)Context;
|
|
|
|
//
|
|
// Enable the adapter
|
|
//
|
|
WRITE_ADAPTER_USHORT(Adapter,
|
|
PORT_OFFSET_ADAPTER_ENABLE,
|
|
0x2525
|
|
);
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
TOK162EnableInterrupt(
|
|
IN NDIS_HANDLE Context
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to turn on the interrupt mask.
|
|
|
|
Arguments:
|
|
|
|
Context - The adapter for the TOK162.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Pointer to an adapter structure. Makes Context (passed in value)
|
|
// a structure we can deal with.
|
|
//
|
|
PTOK162_ADAPTER Adapter = (PTOK162_ADAPTER)Context;
|
|
|
|
//
|
|
// Enable further interrupts.
|
|
//
|
|
WRITE_ADAPTER_USHORT(Adapter,
|
|
PORT_OFFSET_SWITCH_INT_ENABLE,
|
|
0x2525
|
|
);
|
|
|
|
}
|
|
|
|
VOID
|
|
TOK162DisableInterrupt(
|
|
IN NDIS_HANDLE Context
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to turn off the interrupt mask.
|
|
|
|
Arguments:
|
|
|
|
Context - The adapter for the TOK162.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Pointer to an adapter structure. Makes Context (passed in value)
|
|
// a structure we can deal with.
|
|
//
|
|
PTOK162_ADAPTER Adapter = (PTOK162_ADAPTER)Context;
|
|
|
|
//
|
|
// Disable the adapter interrupt.
|
|
//
|
|
WRITE_ADAPTER_USHORT(
|
|
Adapter,
|
|
PORT_OFFSET_SWITCH_INT_DISABLE,
|
|
0x2525
|
|
);
|
|
|
|
}
|
|
|
|
VOID
|
|
TOK162ResetAdapter(
|
|
IN PTOK162_ADAPTER Adapter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to reset the adapter.
|
|
|
|
Arguments:
|
|
|
|
Adapter - The TOK162 adapter to reset.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Mark the current ring state as closed (we are going to be removed
|
|
// from the ring by doing the reset).
|
|
//
|
|
|
|
Adapter->CurrentRingState = NdisRingStateClosed;
|
|
|
|
//
|
|
// This is very simple with this adapter. We simply issue a reset
|
|
// command right here and this will stop the chip.
|
|
//
|
|
WRITE_ADAPTER_USHORT(Adapter,
|
|
PORT_OFFSET_ADAPTER_RESET,
|
|
0x2525
|
|
);
|
|
|
|
//
|
|
// Allow the adapter to finish completing the reset
|
|
//
|
|
NdisStallExecution(50);
|
|
|
|
//
|
|
// Enable the adapter to allow us to access the adapter's registers.
|
|
//
|
|
TOK162EnableAdapter(Adapter);
|
|
|
|
//
|
|
// Allow the adapter to finish completing the reset
|
|
//
|
|
NdisStallExecution(50);
|
|
|
|
}
|
|
|
|
VOID
|
|
TOK162SetInitializationBlock(
|
|
IN PTOK162_ADAPTER Adapter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine simply fills the Initialization block
|
|
with the information necessary for initialization.
|
|
|
|
NOTE: this routine assumes a single thread of execution is accessing
|
|
the particular adapter.
|
|
|
|
Arguments:
|
|
|
|
Adapter - The adapter which holds the initialization block
|
|
to initialize.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Pointer to the initialization block
|
|
//
|
|
PADAPTER_INITIALIZATION Initialization = Adapter->InitializationBlock;
|
|
|
|
//
|
|
// Initialize the init block to zeros
|
|
//
|
|
NdisZeroMemory(
|
|
Initialization,
|
|
sizeof(ADAPTER_INITIALIZATION)
|
|
);
|
|
|
|
//
|
|
// Set the initializtion options as follows:
|
|
// Reserved bit must be on
|
|
// DMA Burst mode (versus cyclical) for the SSB/SCB
|
|
// DMA Burst mode (versus cyclical) for the xmit/rcv lists
|
|
// DMA Burst mode (versus cyclical) for the xmit/rcv status
|
|
// DMA Burst mode (versus cyclical) for the receive buffers
|
|
// DMA Burst mode (versus cyclical) for the transmit buffers
|
|
// Don't allow Early Token Release
|
|
//
|
|
Initialization->Options = INIT_OPTIONS_RESERVED |
|
|
INIT_OPTIONS_SCBSSB_BURST |
|
|
INIT_OPTIONS_LIST_BURST |
|
|
INIT_OPTIONS_LIST_STATUS_BURST |
|
|
INIT_OPTIONS_RECEIVE_BURST |
|
|
INIT_OPTIONS_XMIT_BURST |
|
|
INIT_OPTIONS_DISABLE_ETR;
|
|
|
|
//
|
|
// If we are running at 16MBPS, OR in this fact.
|
|
//
|
|
if (Adapter->Running16Mbps == TRUE) {
|
|
|
|
Initialization->Options |= INIT_OPTIONS_SPEED_16;
|
|
|
|
}
|
|
|
|
//
|
|
// Set the receive and transmit burst sizes to the max.
|
|
//
|
|
Initialization->ReceiveBurstSize = TOK162_BURST_SIZE;
|
|
Initialization->TransmitBurstSize = TOK162_BURST_SIZE;
|
|
|
|
//
|
|
// Set the DMA retries (values found in TOK162HW.H)
|
|
//
|
|
Initialization->DMAAbortThresholds = TOK162_DMA_RETRIES;
|
|
|
|
//
|
|
// Set the pointers to the SCB and SSB blocks.
|
|
//
|
|
Initialization->SCBHigh = HIGH_WORD(
|
|
NdisGetPhysicalAddressLow(Adapter->ScbPhysical));
|
|
|
|
Initialization->SCBLow = LOW_WORD(
|
|
NdisGetPhysicalAddressLow(Adapter->ScbPhysical));
|
|
|
|
Initialization->SSBHigh = HIGH_WORD(
|
|
NdisGetPhysicalAddressLow(Adapter->SsbPhysical));
|
|
|
|
Initialization->SSBLow = LOW_WORD(
|
|
NdisGetPhysicalAddressLow(Adapter->SsbPhysical));
|
|
}
|
|
|
|
|
|
VOID
|
|
TOK162SetInitializationBlockAndInit(
|
|
IN PTOK162_ADAPTER Adapter,
|
|
OUT PNDIS_STATUS Status
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
It is this routine's responsibility to make sure that the
|
|
Initialization block is filled and the adapter is initialized
|
|
and started.
|
|
|
|
Arguments:
|
|
|
|
Adapter - The adapter whose hardware is to be initialized.
|
|
Status - Result of the Init
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
|
|
//
|
|
// Simple iterative variable to keep track of the number of retries.
|
|
//
|
|
USHORT Retries;
|
|
|
|
//
|
|
// Check to make sure Reset went OK
|
|
//
|
|
if (Adapter->InitialInit == TRUE) {
|
|
|
|
Retries = 0;
|
|
|
|
while ((CheckResetResults(Adapter) == FALSE) && (Retries++ < 3)) {
|
|
|
|
TOK162ResetAdapter(Adapter);
|
|
|
|
}
|
|
|
|
if (Retries == 3) {
|
|
|
|
*Status = NDIS_STATUS_DEVICE_FAILED;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Reset the receive queue, the command block queue, and the transmit
|
|
// queue.
|
|
//
|
|
TOK162ResetReceiveQueue(Adapter);
|
|
TOK162ResetCommandBlocks(Adapter);
|
|
TOK162ResetVariables(Adapter);
|
|
|
|
//
|
|
// Fill in the adapter's initialization block.
|
|
//
|
|
VERY_LOUD_DEBUG(DbgPrint("TOK162!Setting init block\n");)
|
|
|
|
TOK162SetInitializationBlock(Adapter);
|
|
|
|
//
|
|
// Write the initialization sequence to the adapter
|
|
//
|
|
VERY_LOUD_DEBUG(DbgPrint("TOK162!Writing Init block to adapter\n");)
|
|
|
|
TOK162WriteInitializationBlock(Adapter);
|
|
|
|
//
|
|
// Check the results
|
|
//
|
|
if (Adapter->InitialInit == TRUE) {
|
|
|
|
VERY_LOUD_DEBUG(DbgPrint("TOK162!Checking init results\n");)
|
|
|
|
*Status = CheckInitResults(Adapter);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
TOK162ResetHandler(
|
|
IN PVOID SystemSpecific1,
|
|
IN PTOK162_ADAPTER Adapter,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Continue the reset given the current reset state (Adapter->ResetState).
|
|
|
|
Arguments:
|
|
SystemSpecific1 - Not used.
|
|
Adapter - The adapter whose hardware is being reset.
|
|
SystemSpecific2 - Not used.
|
|
SystemSpecific3 - Not used.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Holds the return value from NDIS calls.
|
|
//
|
|
NDIS_STATUS Status;
|
|
|
|
//
|
|
// Variable for the number of retries.
|
|
//
|
|
USHORT Retries;
|
|
|
|
//
|
|
// Holds the result of the receive command.
|
|
//
|
|
BOOLEAN ReceiveResult;
|
|
|
|
//
|
|
// Initialize retries to 0.
|
|
//
|
|
Retries = 0;
|
|
|
|
//
|
|
// Cancel the reset timer
|
|
//
|
|
NdisMCancelTimer(&(Adapter->ResetTimer),&ReceiveResult);
|
|
|
|
//
|
|
// Based on the current Adapter->ResetState, proceed with the reset.
|
|
//
|
|
switch(Adapter->ResetState) {
|
|
|
|
//
|
|
// The initialinit case means we are at the beginning and do not
|
|
// run off of interrupts. Everything is polled and we continue until
|
|
// we are finished with the reset, successful or not.
|
|
//
|
|
case InitialInit:
|
|
|
|
//
|
|
// For up to 3 times, try to init the chipset.
|
|
//
|
|
do {
|
|
|
|
TOK162SetInitializationBlockAndInit(Adapter,&Status);
|
|
Retries++;
|
|
|
|
} while ((Status != NDIS_STATUS_SUCCESS) && (Retries < 3));
|
|
|
|
//
|
|
// If everything went ok, get the adapter information offsets
|
|
// and do the open/receive combo.
|
|
//
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS) {
|
|
|
|
TOK162GetAdapterOffsets(Adapter);
|
|
|
|
//
|
|
// Do the open and if successful wait for the receive to
|
|
// complete (Status is already set to successful). If
|
|
// there was a problem, though, we need to set the error
|
|
// code.
|
|
//
|
|
if (DoTheOpen(Adapter) != TRUE) {
|
|
|
|
Status = NDIS_STATUS_FAILURE;
|
|
|
|
} else {
|
|
|
|
while (Adapter->InitialReceiveSent == FALSE) {
|
|
|
|
NdisStallExecution(500);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Do the reset indications
|
|
//
|
|
TOK162DoResetIndications(Adapter,Status);
|
|
|
|
break;
|
|
|
|
//
|
|
// CheckReset is the first stage of a non-init reset. Because of
|
|
// the retry mechanism, CheckReset and CheckResetRetry have the same
|
|
// entry point logically with the exception of the resetting of the
|
|
// retry variable.
|
|
//
|
|
|
|
case CheckReset:
|
|
|
|
Adapter->ResetRetries = 0;
|
|
|
|
case CheckResetRetry:
|
|
|
|
//
|
|
// Increment the retry count
|
|
//
|
|
Adapter->ResetRetries++;
|
|
|
|
//
|
|
// See if we have gone too long.
|
|
// If we have gone for 5 seconds without the reset
|
|
// going true, reset the adapter again. Ten seconds is
|
|
// the breaking point to actually return an error condition.
|
|
//
|
|
if (Adapter->ResetRetries == 200) {
|
|
|
|
TOK162ResetAdapter(Adapter);
|
|
|
|
NdisMSetTimer(&(Adapter->ResetTimer),
|
|
100
|
|
);
|
|
|
|
return;
|
|
|
|
} else if (Adapter->ResetRetries > 400) {
|
|
|
|
//
|
|
// Do the reset indications.
|
|
//
|
|
TOK162DoResetIndications(Adapter,NDIS_STATUS_FAILURE);
|
|
return;
|
|
|
|
}
|
|
|
|
//
|
|
// Check the result of the reset command. If it fails,
|
|
// set the state to CheckResetRetry.
|
|
//
|
|
if (CheckResetResults(Adapter) == FALSE) {
|
|
|
|
Adapter->ResetState = CheckResetRetry;
|
|
|
|
//
|
|
// If success, move to the next state (DoTheInit)
|
|
//
|
|
} else {
|
|
|
|
//
|
|
// We haven't had any retries of the init yet.
|
|
//
|
|
Adapter->InitRetries = 0;
|
|
|
|
VERY_LOUD_DEBUG(DbgPrint(
|
|
"TOK162!Moving to the init stage - %u\n",Adapter->ResetRetries);)
|
|
|
|
Adapter->ResetState = DoTheInit;
|
|
|
|
}
|
|
|
|
//
|
|
// Set the timer for the reset and leave this timer routine.
|
|
//
|
|
NdisMSetTimer(&(Adapter->ResetTimer),
|
|
50
|
|
);
|
|
|
|
return;
|
|
break;
|
|
|
|
//
|
|
// DoTheInit sends the initialization block out to the card, and
|
|
// sets the next state to CheckInit.
|
|
//
|
|
case DoTheInit:
|
|
|
|
Adapter->ResetState = CheckInit;
|
|
|
|
//
|
|
// Send the init block out to the adapter
|
|
//
|
|
TOK162SetInitializationBlockAndInit(Adapter,
|
|
&Adapter->ResetResult);
|
|
|
|
//
|
|
// Set the timer for the reset and leave this timer routine.
|
|
//
|
|
NdisMSetTimer(&(Adapter->ResetTimer),
|
|
200
|
|
);
|
|
|
|
return;
|
|
break;
|
|
|
|
//
|
|
// The CheckInit stage looks at the init results. If successful,
|
|
// the open command is issued and the regular interrupt handler
|
|
// will take care of the rest. If unsuccessful, the retry count
|
|
// is incremented and we wait until either the init results return
|
|
// successful or the retry count expires.
|
|
//
|
|
case CheckInit:
|
|
|
|
//
|
|
// Increment the retry count
|
|
//
|
|
Adapter->InitRetries++;
|
|
|
|
//
|
|
// If we have expired the retry count, do the indications
|
|
//
|
|
if (Adapter->InitRetries > 400) {
|
|
|
|
VERY_LOUD_DEBUG(DbgPrint("TOK162!Initialization failed\n");)
|
|
TOK162DoResetIndications(Adapter,NDIS_STATUS_FAILURE);
|
|
return;
|
|
|
|
}
|
|
|
|
//
|
|
// Check the result of the init.
|
|
//
|
|
Adapter->ResetResult = CheckInitResults(Adapter);
|
|
|
|
//
|
|
// If we were successful, issue the open command.
|
|
//
|
|
if (Adapter->ResetResult == NDIS_STATUS_SUCCESS) {
|
|
|
|
VERY_LOUD_DEBUG(DbgPrint("TOK162!Calling do the open\n");)
|
|
DoTheOpen(Adapter);
|
|
|
|
return;
|
|
|
|
//
|
|
// If not successful, start the timer and end this timer routine.
|
|
//
|
|
} else {
|
|
|
|
NdisMSetTimer(&(Adapter->ResetTimer),
|
|
50
|
|
);
|
|
|
|
}
|
|
|
|
return;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
VOID
|
|
TOK162DoResetIndications(
|
|
IN PTOK162_ADAPTER Adapter,
|
|
IN NDIS_STATUS Status
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by TOK162ResetDpc to perform any
|
|
indications which need to be done after a reset. Note that
|
|
this routine will be called after either a successful reset
|
|
or a failed reset.
|
|
|
|
Arguments:
|
|
|
|
Adapter - The adapter whose hardware has been initialized.
|
|
|
|
Status - The status of the reset to send to the protocol(s).
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
|
|
//
|
|
// Although it should never happen, if we get called when there
|
|
// isn't a reset in progress, just return.
|
|
//
|
|
if (Adapter->ResetInProgress == FALSE) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
//
|
|
// If we have a bad result, we stop the chip and do the indication
|
|
// back to the protocol(s).
|
|
//
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
|
|
LOUD_DEBUG(DbgPrint("TOK162!Reset failed\n");)
|
|
|
|
//
|
|
// Stop the chip
|
|
//
|
|
TOK162ResetAdapter(Adapter);
|
|
|
|
//
|
|
// Reset has failed, errorlog an entry.
|
|
//
|
|
NdisWriteErrorLogEntry(
|
|
Adapter->MiniportAdapterHandle,
|
|
NDIS_ERROR_CODE_HARDWARE_FAILURE,
|
|
0
|
|
);
|
|
|
|
}
|
|
|
|
//
|
|
// We are no longer resetting the adapter.
|
|
//
|
|
Adapter->ResetInProgress = FALSE;
|
|
|
|
//
|
|
// If this is during the initial init, just set the adapter variable.
|
|
//
|
|
if (Adapter->InitialInit == TRUE) {
|
|
|
|
Adapter->ResetResult = Status;
|
|
|
|
//
|
|
// Otherwise, send the status back to the protocol(s).
|
|
//
|
|
} else {
|
|
|
|
NdisMResetComplete(
|
|
Adapter->MiniportAdapterHandle,
|
|
Status,
|
|
TRUE
|
|
);
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
extern
|
|
NDIS_STATUS
|
|
TOK162SetupForReset(
|
|
IN PTOK162_ADAPTER Adapter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to write the resetting interrupt to the
|
|
token ring card, and then set up a timer to do the initialization
|
|
sequence under DPC.
|
|
|
|
Arguments:
|
|
|
|
Adapter - The adapter whose hardware is to be initialized.
|
|
|
|
Return Value:
|
|
|
|
Status of the reset process (always PENDING).
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// The reset is now in progres.
|
|
//
|
|
Adapter->ResetInProgress = TRUE;
|
|
|
|
//
|
|
// Shut down the chip. We won't be doing any more work until
|
|
// the reset is complete.
|
|
//
|
|
TOK162ResetAdapter(Adapter);
|
|
|
|
//
|
|
// Set the timer for the dpc routine. The wait is for 100 milliseconds.
|
|
//
|
|
NdisMSetTimer(&(Adapter->ResetTimer),
|
|
500
|
|
);
|
|
|
|
|
|
//
|
|
// Indicate the reset is pending
|
|
//
|
|
return NDIS_STATUS_PENDING;
|
|
}
|
|
|
|
|
|
VOID
|
|
TOK162ResetVariables(
|
|
IN PTOK162_ADAPTER Adapter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets variables to their proper value after a reset.
|
|
|
|
Arguments:
|
|
|
|
Adapter - Adapter we are resetting.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Reset the command queue and block variables
|
|
//
|
|
Adapter->CommandOnCard = NULL;
|
|
Adapter->WaitingCommandHead = NULL;
|
|
Adapter->WaitingCommandTail = NULL;
|
|
Adapter->NumberOfAvailableCommandBlocks = TOK162_NUMBER_OF_CMD_BLOCKS;
|
|
Adapter->NextCommandBlock = 0;
|
|
|
|
//
|
|
// Reset the transmit queue and block variables
|
|
//
|
|
Adapter->TransmitOnCard = NULL;
|
|
Adapter->WaitingTransmitHead = NULL;
|
|
Adapter->WaitingTransmitTail = NULL;
|
|
Adapter->NumberOfAvailableTransmitBlocks =
|
|
Adapter->NumberOfTransmitLists;
|
|
Adapter->NextTransmitBlock = 0;
|
|
Adapter->TransmitsQueued = 0;
|
|
}
|
|
|
|
|
|
VOID
|
|
TOK162ResetCommandBlocks(
|
|
IN PTOK162_ADAPTER Adapter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets command block elements to their proper value after
|
|
a reset.
|
|
|
|
Arguments:
|
|
|
|
Adapter - Adapter we are resetting.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Pointer to a Command Block. Used while initializing
|
|
// the Command Queue.
|
|
//
|
|
PTOK162_SUPER_COMMAND_BLOCK CurrentCommandBlock;
|
|
|
|
//
|
|
// Simple iteration variable.
|
|
//
|
|
UINT i;
|
|
|
|
//
|
|
// Abort all pending transmits
|
|
//
|
|
CurrentCommandBlock = Adapter->TransmitOnCard;
|
|
|
|
while (CurrentCommandBlock != NULL) {
|
|
|
|
TOK162AbortSend(Adapter,CurrentCommandBlock);
|
|
CurrentCommandBlock = CurrentCommandBlock->NextCommand;
|
|
|
|
}
|
|
|
|
//
|
|
// Put the Transmit Blocks into a known state.
|
|
//
|
|
for (i = 0, CurrentCommandBlock = Adapter->TransmitQueue;
|
|
i < Adapter->NumberOfTransmitLists;
|
|
i++, CurrentCommandBlock++
|
|
) {
|
|
|
|
CurrentCommandBlock->Hardware.State = TOK162_STATE_FREE;
|
|
CurrentCommandBlock->NextCommand = NULL;
|
|
CurrentCommandBlock->CommandBlock = FALSE;
|
|
CurrentCommandBlock->CommandBlockIndex = (USHORT)i;
|
|
CurrentCommandBlock->Timeout = FALSE;
|
|
}
|
|
|
|
//
|
|
// Now do the same for the command queue.
|
|
//
|
|
for (i = 0, CurrentCommandBlock = Adapter->CommandQueue;
|
|
i < TOK162_NUMBER_OF_CMD_BLOCKS;
|
|
i++, CurrentCommandBlock++
|
|
) {
|
|
|
|
CurrentCommandBlock->Hardware.State = TOK162_STATE_FREE;
|
|
CurrentCommandBlock->NextCommand = NULL;
|
|
CurrentCommandBlock->CommandBlock = TRUE;
|
|
CurrentCommandBlock->CommandBlockIndex = (USHORT)i;
|
|
CurrentCommandBlock->Timeout = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
CheckResetResults(PTOK162_ADAPTER Adapter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine checks the current state of the reset command and returns
|
|
whether the reset was successful.
|
|
|
|
Arguments:
|
|
|
|
Adapter - Adapter we are resetting.
|
|
|
|
Return Value:
|
|
|
|
TRUE if reset is successful, FALSE if not.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Count of the total delay waiting for the chip to give results
|
|
//
|
|
UINT TotalDelay;
|
|
|
|
//
|
|
// Indicating if we can break out of a loop by having definitive results.
|
|
//
|
|
BOOLEAN Complete;
|
|
|
|
//
|
|
// Variable holding value of the status.
|
|
//
|
|
USHORT Value;
|
|
|
|
//
|
|
// Return value, TRUE or FALSE.
|
|
//
|
|
BOOLEAN Success;
|
|
|
|
//
|
|
// Initialize the variables.
|
|
//
|
|
Complete = FALSE;
|
|
TotalDelay = 0;
|
|
Success = FALSE;
|
|
|
|
//
|
|
// If we are running in a DPC, we don't want to check more than once
|
|
//
|
|
if (Adapter->InitialInit == FALSE) {
|
|
|
|
Complete = TRUE;
|
|
|
|
}
|
|
|
|
//
|
|
// Loop until Complete is TRUE.
|
|
//
|
|
do {
|
|
|
|
//
|
|
// First get the status
|
|
//
|
|
READ_ADAPTER_USHORT(Adapter,
|
|
PORT_OFFSET_STATUS,
|
|
&Value
|
|
);
|
|
|
|
|
|
//
|
|
// Check for Initialize
|
|
//
|
|
if ((Value & STATUS_INIT_INITIALIZE) != 0) {
|
|
|
|
//
|
|
// Mask off the Test and Error Bits
|
|
//
|
|
Value = Value & 0x00FF;
|
|
Value = Value & ~STATUS_INIT_INITIALIZE;
|
|
|
|
|
|
//
|
|
// Check test and error to see if they are zero. If so,
|
|
// we are done and successful.
|
|
//
|
|
if ((Value & (STATUS_INIT_TEST | STATUS_INIT_ERROR)) == 0) {
|
|
|
|
Complete = TRUE;
|
|
Success = TRUE;
|
|
VERY_LOUD_DEBUG(DbgPrint("TOK162!Returning True\n");)
|
|
|
|
}
|
|
|
|
//
|
|
// If init isn't set but test and error are, we are done but
|
|
// have failed.
|
|
//
|
|
} else if ((Value & (STATUS_INIT_TEST | STATUS_INIT_ERROR)) ==
|
|
(STATUS_INIT_TEST | STATUS_INIT_ERROR)) {
|
|
|
|
Complete = TRUE;
|
|
Success = FALSE;
|
|
|
|
}
|
|
|
|
//
|
|
// If we aren't done yet, then we need to sleep for a while and
|
|
// try again.
|
|
//
|
|
if (Complete == FALSE) {
|
|
|
|
NdisStallExecution(500000);
|
|
TotalDelay += 500000;
|
|
|
|
}
|
|
|
|
//
|
|
// If we have gone past the total time allowed or we have completed,
|
|
// then we end. Otherwise we loop again.
|
|
//
|
|
} while ((TotalDelay < 5000000) && (Complete == FALSE));
|
|
|
|
//
|
|
// Return success/failure.
|
|
//
|
|
return(Success);
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
CheckInitResults(PTOK162_ADAPTER Adapter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine checks the current state of the init command and returns
|
|
whether the init was successful.
|
|
|
|
Arguments:
|
|
|
|
Adapter - Adapter we are resetting.
|
|
|
|
Return Value:
|
|
|
|
TRUE if init is successful, FALSE if not.
|
|
|
|
--*/
|
|
{
|
|
|
|
//
|
|
// Count of the total delay waiting for the chip to give results
|
|
//
|
|
UINT TotalDelay;
|
|
|
|
//
|
|
// Indicating if we can break out of a loop by having definitive results.
|
|
//
|
|
BOOLEAN Complete;
|
|
|
|
//
|
|
// Variable holding value of the status.
|
|
//
|
|
USHORT Value;
|
|
|
|
//
|
|
// Return value, TRUE or FALSE.
|
|
//
|
|
BOOLEAN Success;
|
|
|
|
//
|
|
// Initialize the variables.
|
|
//
|
|
Complete = FALSE;
|
|
TotalDelay = 0;
|
|
Success = FALSE;
|
|
|
|
//
|
|
// If we are running in a DPC, we don't want to check more than once
|
|
//
|
|
if (Adapter->InitialInit == FALSE) {
|
|
|
|
Complete = TRUE;
|
|
|
|
}
|
|
|
|
//
|
|
// Loop until Complete == TRUE
|
|
//
|
|
do {
|
|
|
|
//
|
|
// First get the status
|
|
//
|
|
READ_ADAPTER_USHORT(Adapter,
|
|
PORT_OFFSET_STATUS,
|
|
&Value
|
|
);
|
|
|
|
//
|
|
// Check for Initialize, Test, and Error to be correct
|
|
//
|
|
if ((Value & (STATUS_INIT_INITIALIZE | STATUS_INIT_TEST)) == 0) {
|
|
|
|
//
|
|
// Check Error Bit
|
|
//
|
|
Complete = TRUE;
|
|
|
|
if ((Value & STATUS_INIT_ERROR) != 0) {
|
|
|
|
Success = FALSE;
|
|
|
|
} else {
|
|
|
|
Success = TRUE;
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we aren't finished (Complete), Stall and try again.
|
|
//
|
|
if (Complete == FALSE) {
|
|
|
|
NdisStallExecution(100000);
|
|
TotalDelay += 100000;
|
|
|
|
}
|
|
|
|
} while ((TotalDelay < 10000000) && (Complete == FALSE));
|
|
|
|
//
|
|
// Display the values of the SCB and SSB to the debugger. After init
|
|
// the SCB should be 0000E2C18BD4 and the SSB should be FFFFD7D1D9C5D4C3.
|
|
//
|
|
LOUD_DEBUG(DbgPrint("TOK162!SCB Value after init = %04x%04x%04x\n",
|
|
Adapter->Scb->Command,
|
|
Adapter->Scb->Parm1,
|
|
Adapter->Scb->Parm2);)
|
|
|
|
//
|
|
// If we are successful, return STATUS_SUCCESS
|
|
//
|
|
if (Success == TRUE) {
|
|
|
|
VERY_LOUD_DEBUG(DbgPrint("TOK162!Returning Success\n");)
|
|
return(NDIS_STATUS_SUCCESS);
|
|
|
|
} else {
|
|
|
|
VERY_LOUD_DEBUG(DbgPrint("TOK162!Returning Failure\n");)
|
|
return(NDIS_STATUS_FAILURE);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
DoTheOpen(
|
|
PTOK162_ADAPTER Adapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine acquires and submits the open command. If called during the
|
|
initial init, the result of the open command is polled.
|
|
|
|
Arguments:
|
|
|
|
Adapter - Adapter we are opening.
|
|
|
|
Return Value:
|
|
|
|
TRUE if open is successful, FALSE if not.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Result of open for polling (initialinit) mode
|
|
//
|
|
USHORT Result;
|
|
|
|
//
|
|
// Command block used for the open.
|
|
//
|
|
PTOK162_SUPER_COMMAND_BLOCK Command;
|
|
|
|
//
|
|
// Log DoTheOpen entered
|
|
//
|
|
IF_LOG('g');
|
|
|
|
//
|
|
// Change the ring state
|
|
//
|
|
Adapter->CurrentRingState = NdisRingStateOpening;
|
|
|
|
//
|
|
// Initialize the group and functional addresses. These will be set
|
|
// after the reset has finished.
|
|
//
|
|
Adapter->Open->GroupAddress = 0;
|
|
Adapter->Open->FunctionalAddress = 0;
|
|
|
|
//
|
|
// Set the address the adapter should enter the ring with.
|
|
//
|
|
NdisMoveMemory(
|
|
Adapter->Open->NodeAddress,
|
|
Adapter->CurrentAddress,
|
|
TOK162_LENGTH_OF_ADDRESS
|
|
);
|
|
|
|
//
|
|
// Acquire a command block
|
|
//
|
|
TOK162AcquireCommandBlock(Adapter,
|
|
&Command
|
|
);
|
|
|
|
//
|
|
// Set up the command block for the open
|
|
//
|
|
Command->Hardware.CommandCode = CMD_DMA_OPEN;
|
|
Command->Hardware.ParmPointer =
|
|
NdisGetPhysicalAddressLow(Adapter->OpenPhysical);
|
|
|
|
//
|
|
// Issue the command to the controller
|
|
//
|
|
TOK162SubmitCommandBlock(Adapter,
|
|
Command
|
|
);
|
|
|
|
//
|
|
// During initialinit we have to poll for completion of the open. This
|
|
// is because there is no way to pend the initial init.
|
|
//
|
|
if (Adapter->InitialInit == TRUE) {
|
|
|
|
//
|
|
// Poll until the SSB contains an open.
|
|
//
|
|
while (Adapter->InitialOpenComplete == FALSE) {
|
|
|
|
NdisStallExecution(5000);
|
|
|
|
}
|
|
|
|
//
|
|
// Get the result of the open.
|
|
//
|
|
Result = Adapter->SsbStatus1 & OPEN_COMPLETION_MASK_RESULT;
|
|
|
|
//
|
|
// Return the command block
|
|
//
|
|
TOK162RelinquishCommandBlock(Adapter,
|
|
Command
|
|
);
|
|
|
|
//
|
|
// Figure out the error code
|
|
//
|
|
if (Result == OPEN_RESULT_ADAPTER_OPEN) {
|
|
|
|
//
|
|
// Log open successful
|
|
//
|
|
IF_LOG('h');
|
|
|
|
//
|
|
// Set the current ring state
|
|
//
|
|
Adapter->CurrentRingState = NdisRingStateOpened;
|
|
|
|
//
|
|
// Return TRUE
|
|
//
|
|
return(TRUE);
|
|
|
|
} else {
|
|
|
|
//
|
|
// Log open unsuccessful
|
|
//
|
|
IF_LOG('H');
|
|
|
|
//
|
|
// Set the current ring state
|
|
//
|
|
Adapter->CurrentRingState = NdisRingStateOpenFailure;
|
|
|
|
//
|
|
// Return FALSE
|
|
//
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Log DoTheOpen exited.
|
|
//
|
|
IF_LOG('G');
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
DoTheReceive(
|
|
PTOK162_ADAPTER Adapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine submits the receive command to the current adapter.
|
|
|
|
Arguments:
|
|
|
|
Adapter - Adapter we are submitting the receive.
|
|
|
|
Return Value:
|
|
|
|
TRUE
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Command block used for the open.
|
|
//
|
|
PTOK162_SUPER_COMMAND_BLOCK Command;
|
|
|
|
//
|
|
// Dismiss the interrupt, allowing the SSB to be updated.
|
|
//
|
|
WRITE_ADAPTER_USHORT(Adapter,
|
|
PORT_OFFSET_STATUS,
|
|
ENABLE_SSB_UPDATE
|
|
);
|
|
|
|
//
|
|
// Acquire a command block
|
|
//
|
|
TOK162AcquireCommandBlock(Adapter,
|
|
&Command
|
|
);
|
|
|
|
//
|
|
// Set up the command block for the receive
|
|
//
|
|
Command->Hardware.CommandCode = CMD_DMA_RCV;
|
|
|
|
Command->Hardware.ParmPointer =
|
|
NdisGetPhysicalAddressLow(Adapter->ReceiveQueuePhysical);
|
|
|
|
//
|
|
// Issue the command to the controller
|
|
//
|
|
TOK162SubmitCommandBlock(Adapter,
|
|
Command
|
|
);
|
|
|
|
//
|
|
// Return the command block
|
|
//
|
|
TOK162RelinquishCommandBlock(Adapter,
|
|
Command
|
|
);
|
|
|
|
VERY_LOUD_DEBUG(DbgPrint("TOK162!Returning from DoTheReceive\n");)
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
TOK162WriteInitializationBlock(
|
|
PTOK162_ADAPTER Adapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine writes the initialization block to the adapter
|
|
|
|
Arguments:
|
|
|
|
Adapter - Adapter we are initializing
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Simple index variable.
|
|
//
|
|
USHORT i;
|
|
|
|
//
|
|
// Pointer to the current value in the initialization block
|
|
//
|
|
PUSHORT val;
|
|
|
|
//
|
|
// Set the address of the adapter to 0x0200.
|
|
//
|
|
WRITE_ADAPTER_USHORT(Adapter,PORT_OFFSET_ADDRESS,0x0200);
|
|
|
|
//
|
|
// Write out the initialization bytes
|
|
//
|
|
val = (PUSHORT)Adapter->InitializationBlock;
|
|
|
|
for (i = 0;
|
|
i < (sizeof(ADAPTER_INITIALIZATION)/2);
|
|
i++,val++) {
|
|
|
|
WRITE_ADAPTER_USHORT(Adapter,
|
|
PORT_OFFSET_DATA_AUTO_INC,
|
|
*val
|
|
);
|
|
|
|
NdisStallExecution(10);
|
|
|
|
}
|
|
|
|
//
|
|
// Issue the command to the adapter
|
|
//
|
|
WRITE_ADAPTER_USHORT(Adapter,
|
|
PORT_OFFSET_COMMAND,
|
|
EXECUTE_SCB_COMMAND
|
|
);
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
TOK162GetAdapterOffsets(
|
|
IN PTOK162_ADAPTER Adapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine gets the offsets into adapter memory of adapter
|
|
parameter lists.
|
|
|
|
Arguments:
|
|
|
|
Adapter - Adapter we are obtaining info from
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Get the pointers for READ.ADAPTER
|
|
//
|
|
|
|
WRITE_ADAPTER_USHORT(Adapter,
|
|
PORT_OFFSET_ADDRESS,
|
|
0x0A00
|
|
);
|
|
|
|
//
|
|
// Get the universal address offset
|
|
//
|
|
READ_ADAPTER_USHORT(Adapter,
|
|
PORT_OFFSET_DATA_AUTO_INC,
|
|
&Adapter->UniversalAddress
|
|
);
|
|
|
|
VERY_LOUD_DEBUG(DbgPrint("TOK162!Universal address offset is %x\n",
|
|
Adapter->UniversalAddress);)
|
|
|
|
//
|
|
// Get the microcode level offset
|
|
//
|
|
READ_ADAPTER_USHORT(Adapter,
|
|
PORT_OFFSET_DATA_AUTO_INC,
|
|
&Adapter->MicrocodeLevel
|
|
);
|
|
|
|
//
|
|
// Get the current addresses (network, functional, group) offset
|
|
//
|
|
READ_ADAPTER_USHORT(Adapter,
|
|
PORT_OFFSET_DATA_AUTO_INC,
|
|
&Adapter->AdapterAddresses
|
|
);
|
|
|
|
VERY_LOUD_DEBUG(DbgPrint("TOK162!Adapter addresses offset is %x\n",
|
|
Adapter->AdapterAddresses);)
|
|
|
|
//
|
|
// Get the adapter parameters offset
|
|
//
|
|
READ_ADAPTER_USHORT(Adapter,
|
|
PORT_OFFSET_DATA_AUTO_INC,
|
|
&Adapter->AdapterParms
|
|
);
|
|
|
|
|
|
//
|
|
// Get the adapter Mac Buffer offset
|
|
//
|
|
READ_ADAPTER_USHORT(Adapter,
|
|
PORT_OFFSET_DATA_AUTO_INC,
|
|
&Adapter->MacBuffer
|
|
);
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
TOK162ResetReceiveQueue(
|
|
IN PTOK162_ADAPTER Adapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine resets the receive queue structures to their initialized
|
|
state. Most fields don't change and don't need to be updated, otherwise
|
|
the initreceivequeue function would be called.
|
|
|
|
Arguments:
|
|
|
|
Adapter - Adapter whose receive queue is being reset
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Simple iterative variable.
|
|
//
|
|
USHORT i;
|
|
|
|
//
|
|
// Pointer to the current receive entry.
|
|
//
|
|
PTOK162_SUPER_RECEIVE_LIST CurrentReceiveEntry;
|
|
|
|
//
|
|
// Set pointer to current receive list to queue head
|
|
//
|
|
Adapter->ReceiveQueueCurrent = Adapter->ReceiveQueue;
|
|
|
|
//
|
|
// For each receive list, reset the cstat and flush buffers
|
|
//
|
|
for (i = 0, CurrentReceiveEntry = Adapter->ReceiveQueue;
|
|
i < Adapter->NumberOfReceiveBuffers;
|
|
i++, CurrentReceiveEntry++
|
|
) {
|
|
|
|
//
|
|
// Flush the flush buffers
|
|
//
|
|
NdisFlushBuffer(CurrentReceiveEntry->FlushBuffer, FALSE);
|
|
|
|
//
|
|
// Reset the CSTAT to allow this receive buffer to be re-used.
|
|
//
|
|
CurrentReceiveEntry->Hardware.CSTAT = RECEIVE_CSTAT_REQUEST_RESET;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
TOK162AbortSend(
|
|
IN PTOK162_ADAPTER Adapter,
|
|
OUT PTOK162_SUPER_COMMAND_BLOCK CurrentCommandBlock
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine aborts the transmit block that was passed in.
|
|
|
|
Arguments:
|
|
|
|
Adapter - Adapter whose receive queue is being reset
|
|
CurrentCommandBlock - Transmit to be aborted.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Pointer to the packet that started this transmission.
|
|
//
|
|
PNDIS_PACKET OwningPacket = CurrentCommandBlock->OwningPacket;
|
|
|
|
//
|
|
// If we used map registers we need to do the completion on them.
|
|
//
|
|
if (CurrentCommandBlock->UsedTOK162Buffer == FALSE) {
|
|
|
|
//
|
|
// Pointer to the current buffer we are looking at.
|
|
//
|
|
PNDIS_BUFFER CurrentBuffer;
|
|
|
|
//
|
|
// Map register to complete
|
|
//
|
|
UINT CurMapRegister;
|
|
|
|
//
|
|
// The transmit is being aborted, so we can release
|
|
// the physical mapping used for it.
|
|
//
|
|
|
|
NdisQueryPacket(
|
|
OwningPacket,
|
|
NULL,
|
|
NULL,
|
|
&CurrentBuffer,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// Get the starting map register for this buffer.
|
|
//
|
|
CurMapRegister = CurrentCommandBlock->CommandBlockIndex *
|
|
Adapter->TransmitThreshold;
|
|
|
|
//
|
|
// Loop until there aren't any more buffers.
|
|
//
|
|
while (CurrentBuffer) {
|
|
|
|
//
|
|
// Release the current map register.
|
|
//
|
|
NdisMCompleteBufferPhysicalMapping(
|
|
Adapter->MiniportAdapterHandle,
|
|
CurrentBuffer,
|
|
CurMapRegister
|
|
);
|
|
|
|
//
|
|
// Move to the next map register.
|
|
//
|
|
++CurMapRegister;
|
|
|
|
//
|
|
// Move to the next buffer
|
|
//
|
|
NdisGetNextBuffer(
|
|
CurrentBuffer,
|
|
&CurrentBuffer
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
}
|