summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/ibmtok2i/interrup.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ndis/ibmtok2i/interrup.c')
-rw-r--r--private/ntos/ndis/ibmtok2i/interrup.c1376
1 files changed, 1376 insertions, 0 deletions
diff --git a/private/ntos/ndis/ibmtok2i/interrup.c b/private/ntos/ndis/ibmtok2i/interrup.c
new file mode 100644
index 000000000..8db43f373
--- /dev/null
+++ b/private/ntos/ndis/ibmtok2i/interrup.c
@@ -0,0 +1,1376 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ interrup.c
+
+Abstract:
+
+ This module contains the interrupt-processing code for the
+ TOK162 NDIS 3.0 driver.
+
+Author:
+
+ Kevin Martin (KevinMa) 26-Jan-1994
+
+Environment:
+
+ Kernel Mode.
+
+Revision History:
+
+--*/
+
+#include <tok162sw.h>
+
+VOID
+TOK162ProcessReceiveInterrupts(
+ IN PTOK162_ADAPTER Adapter
+ );
+
+VOID
+TOK162ProcessCommandInterrupts(
+ IN PTOK162_ADAPTER Adapter
+ );
+
+
+VOID
+TOK162Isr(
+ OUT PBOOLEAN InterruptRecognized,
+ OUT PBOOLEAN QueueDpc,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ Interrupt service routine for the TOK162. Used only during init.
+ The NdisMRegisterInterrupt() call (reset.c) specified not to call the
+ ISR for every interrupt. The DPC is called directly instead.
+
+Arguments:
+
+ Interrupt - Interrupt object for the TOK162.
+
+ Context - Really a pointer to the adapter.
+
+Return Value:
+
+ Returns true if the interrupt really was from the TOK162 and whether the
+ wrapper should queue a DPC.
+
+--*/
+
+{
+
+ //
+ // Holds the pointer to the adapter structure.
+ //
+ PTOK162_ADAPTER Adapter = Context;
+
+ //
+ // Holds IsrpHigh with some bits masked off.
+ //
+ USHORT Sif;
+
+ //
+ // Indicate that an interrupt has occurred (internal logging and
+ // debug print's).
+ //
+ VERY_LOUD_DEBUG(DbgPrint("TOK162!ISR\n");)
+ IF_LOG('o');
+
+ //
+ // Read the adapter interrupt register
+ //
+ READ_ADAPTER_USHORT(Adapter,PORT_OFFSET_STATUS,&Sif);
+
+ //
+ // Check if this is our interrupt. If it is, set flag indicating that the
+ // interrupt is recognized. Otherwise indicate that the interrupt is not
+ // ours.
+ //
+ if ((Sif & STATUS_SYSTEM_INTERRUPT) != 0) {
+
+ *InterruptRecognized = TRUE;
+
+ } else {
+
+ *InterruptRecognized = FALSE;
+
+ }
+
+ //
+ // Mask off the interrupt type portion of the register.
+ //
+ Sif = (UCHAR) (Sif & STATUS_INT_CODE_MASK);
+
+ //
+ // If this is a receive, go ahead and do the DPC. This allows us to keep
+ // in synch with the card concerning the receive list index. Also, for a
+ // a receive there is no need to allow the SSB to be updated as the DPC
+ // routine will do this for us. If it isn't a receive, we need to indicate
+ // that no DPC is necessary and we also allow the SSB to be updated.
+ //
+ if (Sif == STATUS_INT_CODE_RECEIVE_STATUS) {
+
+ IF_LOG('p');
+
+ *QueueDpc = TRUE;
+
+ //
+ // If we have a command, then it is the open or an error has occurred.
+ // Indicate that the Ssb can be cleared after the open info has been
+ // obtained.
+ //
+ } else if (Sif == STATUS_INT_CODE_CMD_STATUS) {
+
+ if (Adapter->Ssb->Command == CMD_DMA_OPEN) {
+
+ Adapter->SsbStatus1 = Adapter->Ssb->Status1;
+ Adapter->InitialOpenComplete = TRUE;
+
+ }
+
+ //
+ // Enable updating of the SSB
+ //
+ IF_LOG('z');
+
+ WRITE_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_STATUS,
+ ENABLE_SSB_UPDATE
+ );
+
+
+ *QueueDpc = FALSE;
+
+ //
+ // If we get the SCB clear interrupt, then we can do the receive command.
+ //
+ } else if (Sif == STATUS_INT_CODE_SCB_CLEAR) {
+
+ DoTheReceive(Adapter);
+ Adapter->InitialReceiveSent = TRUE;
+
+ } else {
+
+ //
+ // Enable updating of the SSB
+ //
+ IF_LOG('z');
+
+ WRITE_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_STATUS,
+ ENABLE_SSB_UPDATE
+ );
+
+ *QueueDpc = FALSE;
+
+ }
+
+ //
+ // Indicate the ISR routine has ended.
+ //
+ IF_LOG('O');
+}
+
+
+VOID
+TOK162DeferredTimer(
+ IN PVOID SystemSpecific1,
+ IN PTOK162_ADAPTER Adapter,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ )
+/*++
+
+Routine Description:
+
+ Just an entry point to distinguish between a timer call and the wrapper
+ calling the DPC directly.
+
+Arguments:
+
+ Adapter - pointer to current adapter
+
+ The rest are not used, but simply passed on
+
+Return Value:
+
+ None
+
+--*/
+{
+ //
+ // Indicate that a timer has expired.
+ //
+ VERY_LOUD_DEBUG(DbgPrint("TOK162!Deferred Timer called\n");)
+
+ //
+ // Call the standard DPC handler.
+ //
+ TOK162HandleInterrupt(Adapter);
+}
+
+
+VOID
+TOK162HandleInterrupt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+
+/*++
+
+Routine Description:
+
+ Main routine for processing interrupts.
+
+Arguments:
+
+ Adapter - The Adapter to process interrupts for.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Pointer to the TOK162 adapter structure.
+ //
+ PTOK162_ADAPTER Adapter = ((PTOK162_ADAPTER)MiniportAdapterContext);
+
+ //
+ // Holds the value of the interrupt type
+ //
+ USHORT IMask = 0;
+
+ //
+ // If any receive interrupts are processed, we have to indicate that
+ // the receive work has been completed after all interrupts have been
+ // processed.
+ //
+ BOOLEAN IndicateReceiveComplete = FALSE;
+
+ //
+ // Indicate that the DPC routine has been called.
+ //
+ EXTRA_LOUD_DEBUG(DbgPrint("TOK162!DPC was just called\n");)
+ IF_LOG('r');
+
+ //
+ // Loop through processing interrupts until we have processed them all.
+ //
+ while (TRUE) {
+
+ //
+ // Read the adapter interrupt register
+ //
+ READ_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_STATUS,
+ &IMask
+ );
+
+ //
+ // If this is not our interrupt, end DPC processing
+ //
+ if ((IMask & STATUS_SYSTEM_INTERRUPT) == 0) {
+
+ //
+ // Indicate that we received a bad interrupt and break
+ // out of the loop.
+ //
+ IF_LOG('a');
+
+ break;
+
+ } else {
+
+ //
+ // Indicatate that the interrupt was found to be ours.
+ //
+ IF_LOG('A');
+
+ //
+ // Record pertinent information about the interrupt as this
+ // card/chipset only allows one interrupt to be indicated by
+ // the card at a time.
+ //
+ Adapter->SsbCommand = Adapter->Ssb->Command;
+ Adapter->SsbStatus1 = Adapter->Ssb->Status1;
+ Adapter->SsbStatus2 = Adapter->Ssb->Status2;
+ Adapter->SsbStatus3 = Adapter->Ssb->Status3;
+
+ }
+
+ //
+ // Figure out the type of interrupt
+ //
+ IMask = (UCHAR) (IMask & STATUS_INT_CODE_MASK);
+
+ //
+ // Indicate the type of interrupt to the debugger.
+ //
+ EXTRA_LOUD_DEBUG(DbgPrint("TOK162!New IMask is %x\n",IMask);)
+
+ //
+ // Process the interrupt based on the type of interrupt.
+ //
+ switch(IMask) {
+
+ case STATUS_INT_CODE_RING:
+
+ //
+ // We have a ring status change. Log this fact.
+ //
+ IF_LOG('b');
+
+ //
+ // If we have a soft error, it is possible that the
+ // card has become overrun with receives. Therefore, the
+ // TOK162ProcessRingInterrupts will return TRUE in this
+ // case to allow us to call ProcessReceiveInterrupts().
+ // In all other cases, TOK162ProcessRingInterrupts() will
+ // return FALSE.
+ //
+ if (TOK162ProcessRingInterrupts(Adapter) == TRUE) {
+
+ TOK162ProcessReceiveInterrupts(Adapter);
+
+ //
+ // Indicate that we did process receives during this
+ // DPC.
+ //
+ IndicateReceiveComplete = TRUE;
+
+ }
+
+ break;
+
+ case STATUS_INT_CODE_RECEIVE_STATUS:
+
+ //
+ // We have a receive interrupt. Log this fact.
+ //
+ IF_LOG('c');
+
+ //
+ // Process the interrupt.
+ //
+ TOK162ProcessReceiveInterrupts(Adapter);
+
+ //
+ // Indicate that we did process a receive during this
+ // DPC.
+ //
+ IndicateReceiveComplete = TRUE;
+
+ break;
+
+ case STATUS_INT_CODE_XMIT_STATUS:
+
+ //
+ // We have a transmit interrupt. Log this fact.
+ //
+ IF_LOG('d');
+
+ //
+ // Process the transmit.
+ //
+ TOK162ProcessTransmitInterrupts(Adapter);
+
+ break;
+
+ case STATUS_INT_CODE_CMD_STATUS:
+
+ //
+ // We have a command interrupt to process. Log this fact.
+ //
+ IF_LOG('e');
+
+ //
+ // If there is a command structure that has been sent to the
+ // adapter, then we will process that command. Otherwise, we
+ // simply return.
+ //
+ if (Adapter->CommandOnCard != NULL) {
+
+ //
+ // Process the active command.
+ //
+ TOK162ProcessCommandInterrupts(Adapter);
+
+ }
+ break;
+
+ default:
+
+ //
+ // The interrupt type is not one that we know (illegal value).
+ // Indicate this to the debugger.
+ //
+ LOUD_DEBUG(DbgPrint("TOK162!Int Command %x, %x\n",Adapter->SsbCommand,
+ Adapter->SsbStatus1);)
+
+ break;
+
+ }
+
+ //
+ // Indicate that we are about to dismiss the interrupt.
+ //
+ IF_LOG('z');
+
+ //
+ // Dismiss the interrupt, allowing the SSB to be updated.
+ //
+ WRITE_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_STATUS,
+ ENABLE_SSB_UPDATE
+ );
+
+ }
+
+ //
+ // If we processed any receive interrupts, IndicateReceiveComplete() will
+ // be set to TRUE. In this case, we need to indicate that all receives
+ // are complete.
+ //
+ if (IndicateReceiveComplete) {
+
+ //
+ // Indicate to the debugger that we are doing the complete.
+ //
+ EXTRA_LOUD_DEBUG(DbgPrint("TOK162!Doing the indicate complete on the receive\n");)
+
+ //
+ // Call the Token Ring Filter to indicate the receive complete.
+ //
+ NdisMTrIndicateReceiveComplete(Adapter->MiniportAdapterHandle);
+
+ }
+
+ //
+ // Log and indicate to the debugger that we are ending DPC processing.
+ //
+ IF_LOG('R');
+ EXTRA_LOUD_DEBUG(DbgPrint("TOK162!Ending DPC processing\n");)
+
+}
+
+
+VOID
+TOK162ProcessReceiveInterrupts(
+ IN PTOK162_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ Process the packets that have finished receiving.
+
+ NOTE: This routine assumes that no other thread of execution
+ is processing receives!
+
+Arguments:
+
+ Adapter - The adapter to indicate to.
+
+Return Value:
+
+ Whether to clear interrupt or not
+
+--*/
+
+{
+
+ //
+ // We don't get here unless there was a receive. Loop through
+ // the receive blocks starting at the last known block owned by
+ // the hardware.
+ //
+ // After we find a packet we give the routine that process the
+ // packet through the filter, the buffers virtual address (which
+ // is always the lookahead size) and as the MAC Context the
+ // index to the receive block.
+ //
+
+ //
+ // Pointer to the receive block being examined.
+ //
+ PTOK162_SUPER_RECEIVE_LIST CurrentEntry = Adapter->ReceiveQueueCurrent;
+
+ //
+ // Used during receiveindicate to let the filter know the header size
+ // of the given buffer.
+ //
+ USHORT HeaderSize;
+
+ //
+ // Used to indicate the total size of the frame to the filter.
+ //
+ USHORT FrameSize;
+
+ //
+ // Points to the beginning of the received buffer. Used to determine the
+ // size of the frame header (source routing).
+ //
+ PUCHAR Temp;
+
+ //
+ // Log the fact that we are processing a receive.
+ //
+ IF_LOG('C');
+
+ //
+ // Continue processing receives until we have exhausted them.
+ //
+ while (TRUE) {
+
+ //
+ // Ensure that our Receive Entry is on an even boundary.
+ //
+ ASSERT(!(NdisGetPhysicalAddressLow(CurrentEntry->Self) & 1));
+
+ //
+ // Send the receive status byte to the debugger.
+ //
+ EXTRA_LOUD_DEBUG(DbgPrint(
+ "TOK162!Receive CSTAT == %x\n",CurrentEntry->Hardware.CSTAT);)
+
+ //
+ // Check to see if CSTAT has been changed indicating
+ // the receive entry has been modified
+ //
+ if (CurrentEntry->Hardware.CSTAT & RECEIVE_CSTAT_VALID) {
+
+ //
+ // Record the receive list entry following the last good
+ // entry as the starting point for the next time receives
+ // are processed.
+ //
+ Adapter->ReceiveQueueCurrent = CurrentEntry;
+
+ //
+ // Tell the adapter to allow more receives.
+ //
+ WRITE_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_COMMAND,
+ ENABLE_RECEIVE_VALID
+ );
+
+ return;
+
+ }
+
+ //
+ // Get a pointer to the first byte of the current receive buffer.
+ //
+ Temp = (PUCHAR)CurrentEntry->ReceiveBuffer;
+
+ //
+ // If the source routing bit is on, figure out the size of the
+ // MAC Frame header. Otherwise, the size is set to the default
+ // of 14 (decimal).
+ //
+ HeaderSize = 14;
+
+
+ if (Temp[8] & 0x80) {
+
+ //
+ // Source routing bit is on in source address, so calculate
+ // the frame header size.
+ //
+ HeaderSize = (Temp[14] & 0x1f) + 14;
+
+ }
+
+ //
+ // Save the received header size.
+ //
+ Adapter->SizeOfReceivedHeader = HeaderSize;
+
+ //
+ // Record the fact that we had a good receive.
+ //
+ Adapter->GoodReceives++;
+
+ //
+ // Make sure the adapter and the system are in synch.
+ //
+ NdisFlushBuffer(CurrentEntry->FlushBuffer, FALSE);
+
+ //
+ // Get the frame size of this buffer.
+ //
+ FrameSize = BYTE_SWAP(CurrentEntry->Hardware.FrameSize);
+
+ //
+ // Indicate the frame size to the debugger
+ //
+ EXTRA_LOUD_DEBUG(DbgPrint("TOK162!Frame size is %u\n",
+ FrameSize);)
+
+ //
+ // If the frame that we have been passed has an invalid length
+ // (less than the reported header size) then we need to check
+ // if the frame size is larger than the default address length.
+ //
+ if (FrameSize >= HeaderSize) {
+
+ //
+ // We have a 'normal' packet. Indicate this to the debugger
+ // and log it.
+ EXTRA_LOUD_DEBUG(DbgPrint("TOK162!Doing receive indicate\n");)
+ IF_LOG('q');
+
+ //
+ // Do the indication to the filter.
+ //
+ NdisMTrIndicateReceive(
+ Adapter->MiniportAdapterHandle,
+ (NDIS_HANDLE)(
+ ((PUCHAR)(CurrentEntry->ReceiveBuffer))+HeaderSize),
+ CurrentEntry->ReceiveBuffer,
+ (UINT)HeaderSize,
+ ((PUCHAR)CurrentEntry->ReceiveBuffer) + HeaderSize,
+ FrameSize - HeaderSize,
+ FrameSize - HeaderSize
+ );
+
+ } else {
+
+ //
+ // If the frame size is greater than or equal to the length
+ // of an address (network address, 12 bytes) then we can
+ // indicate it as a runt packet to the filter. Otherwise,
+ // we ignore the received buffer.
+ //
+ if (FrameSize >= TOK162_LENGTH_OF_ADDRESS) {
+
+ //
+ // Indicate this is a runt packet to the debugger
+ //
+ VERY_LOUD_DEBUG(DbgPrint(
+ "TOK162!Doing receive indicate for a runt\n");)
+
+ //
+ // Indicate the packet to the filter.
+ //
+ NdisMTrIndicateReceive(
+ Adapter->MiniportAdapterHandle,
+ (NDIS_HANDLE)(
+ ((PUCHAR)(CurrentEntry->ReceiveBuffer)) + HeaderSize),
+ (PUCHAR)Temp,
+ (UINT)FrameSize,
+ NULL,
+ 0,
+ 0
+ );
+
+ }
+
+ }
+
+ //
+ // Mark the receive list as processed and able to receive another
+ // buffer.
+ //
+ CurrentEntry->Hardware.CSTAT = RECEIVE_CSTAT_REQUEST_RESET;
+
+ //
+ // Move to the next entry to see if there are more to process.
+ //
+ CurrentEntry = CurrentEntry->NextEntry;
+
+ //
+ // Log the fact that we are telling the card to send us more receives.
+ //
+ IF_LOG('Q');
+
+ //
+ // Tell the card that we are ready to process more receives.
+ //
+ WRITE_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_COMMAND,
+ ENABLE_RECEIVE_VALID
+ );
+
+ }
+
+}
+
+
+VOID
+TOK162ProcessCommandInterrupts(
+ IN PTOK162_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ Process the Command Complete interrupts.
+
+ NOTE: This routine assumes that it is being executed in a
+ single thread of execution.
+
+Arguments:
+
+ Adapter - The adapter that was sent from.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Pointer to command block being processed.
+ //
+ PTOK162_SUPER_COMMAND_BLOCK CurrentCommandBlock = Adapter->CommandOnCard;
+
+ //
+ // Status variable
+ //
+ NDIS_STATUS Status;
+
+ //
+ // NetCard Address Block
+ //
+ PTOK162_ADDRESSBLOCK Addresses;
+ //
+ // Ensure that the Command Block is on an even boundary.
+ //
+ ASSERT(!(NdisGetPhysicalAddressLow(CurrentCommandBlock->Self) & 1));
+
+ //
+ // Log the fact that we are processing a command interrupt.
+ //
+ IF_LOG('E');
+
+ //
+ // Process the command based on the command code.
+ //
+ switch(CurrentCommandBlock->Hardware.CommandCode) {
+
+ case CMD_DMA_READ:
+
+ //
+ // We are processing a read command. The read command is
+ // generated by a query request.
+ //
+ // Indicate we are processing a read command to the
+ // debugger.
+ //
+ VERY_LOUD_DEBUG(DbgPrint("TOK162!DPC for read adapter called\n");)
+
+ // Get a pointer to the block of memory set aside for the
+ // read command.
+ //
+ Addresses = (PTOK162_ADDRESSBLOCK)Adapter->AdapterBuf;
+
+ //
+ // Check the Oid to see if we are after the permanent card
+ // address or the current addresses.
+ //
+ if (Adapter->Oid == OID_802_5_PERMANENT_ADDRESS) {
+ //
+ // Update the permanent node address
+ //
+ NdisMoveMemory(
+ Adapter->NetworkAddress,
+ Addresses->NodeAddress,
+ 6
+ );
+
+ } else {
+
+ //
+ // Update the current network address
+ //
+ NdisMoveMemory(
+ (UNALIGNED PUCHAR)Adapter->CurrentAddress,
+ Addresses->NodeAddress,
+ 6);
+ }
+
+ //
+ // Finish the query and relenquish the command block
+ //
+ TOK162FinishQueryInformation(Adapter);
+ TOK162RelinquishCommandBlock(Adapter, CurrentCommandBlock);
+
+ break;
+
+ case CMD_DMA_OPEN:
+
+ //
+ // An open command is generated during a reset command. The
+ // initial open is called during adapter initialization and
+ // no DPC is generated.
+ //
+ // Indicate we are processing an open to the debugger.
+ //
+ VERY_LOUD_DEBUG(DbgPrint("TOK162!Processing the open command.\n");)
+
+ //
+ // Relinquish the command block associcated with this open.
+ //
+ TOK162RelinquishCommandBlock(Adapter, CurrentCommandBlock);
+
+ //
+ // Check to see if the open succeeded.
+ //
+ if ((Adapter->SsbStatus1 & OPEN_COMPLETION_MASK_RESULT)
+ != OPEN_RESULT_ADAPTER_OPEN) {
+
+ //
+ // The open failed. Set the current ring state and set the
+ // return variable to NDIS_STATUS_FAILURE.
+ //
+ Adapter->CurrentRingState = NdisRingStateOpenFailure;
+ Adapter->OpenErrorCode = Adapter->SsbStatus1;
+ Status = NDIS_STATUS_FAILURE;
+
+ //
+ // Display the error code on the debugger.
+ //
+ VERY_LOUD_DEBUG(DbgPrint(
+ "TOK162!Error on the open - %x\n",Adapter->SsbStatus1);)
+
+ } else {
+
+ //
+ // The open succeeded. Set the current ring state and set the
+ // return variable to NDIS_STATUS_SUCCESS.
+ //
+ Adapter->CurrentRingState = NdisRingStateOpened;
+ Adapter->OpenErrorCode = 0;
+ Status = NDIS_STATUS_SUCCESS;
+
+ //
+ // Now send out the receive command. Display the fact that
+ // DoReceive is being called on the debugger.
+ //
+ VERY_LOUD_DEBUG(DbgPrint("Doing the receive\n");)
+
+ //
+ // Check if the receive command succeeded. If not, set the
+ // return variable to NDIS_STATUS_FAILURE. It is currently
+ // set to NDIS_STATUS_SUCCESS, so no change is necessary
+ // if the receive command succeeds.
+ //
+ if (DoTheReceive(Adapter) == FALSE) {
+
+ Status = NDIS_STATUS_FAILURE;
+
+ }
+
+ }
+
+ //
+ // Indicate to the wrapper the result of the open/receive for
+ // the original reset request.
+ //
+ TOK162DoResetIndications(Adapter, Status);
+ break;
+
+ case CMD_DMA_READ_ERRLOG:
+
+ LOUD_DEBUG(DbgPrint("TOK162!DPC for read errorlog called\n");)
+
+ //
+ // Record the values for the error counters
+ //
+ Adapter->ReceiveCongestionError +=
+ Adapter->ErrorLog->ReceiveCongestionError;
+
+ Adapter->LineError += Adapter->ErrorLog->LineError;
+
+ Adapter->LostFrameError += Adapter->ErrorLog->LostFrameError;
+
+ Adapter->BurstError += Adapter->ErrorLog->BurstError;
+
+ Adapter->FrameCopiedError += Adapter->ErrorLog->FrameCopiedError;
+
+ Adapter->TokenError += Adapter->ErrorLog->TokenError;
+
+ Adapter->InternalError += Adapter->ErrorLog->InternalError;
+
+ Adapter->ARIFCIError += Adapter->ErrorLog->ARIFCIError;
+
+ Adapter->AbortDelimeter += Adapter->ErrorLog->AbortDelimeter;
+
+ Adapter->DMABusError += Adapter->ErrorLog->DMABusError;
+
+ //
+ // Indicate the values to the debugger
+ //
+ VERY_LOUD_DEBUG(DbgPrint("TOK162!CongestionErrors = %u\n",
+ Adapter->ErrorLog->ReceiveCongestionError);)
+
+ VERY_LOUD_DEBUG(DbgPrint("TOK162!LineErrors = %u\n",
+ Adapter->ErrorLog->LineError);)
+
+ VERY_LOUD_DEBUG(DbgPrint("TOK162!LostFrameErrors = %u\n",
+ Adapter->ErrorLog->LostFrameError);)
+
+ VERY_LOUD_DEBUG(DbgPrint("TOK162!BurstErrors = %u\n",
+ Adapter->ErrorLog->BurstError);)
+
+ VERY_LOUD_DEBUG(DbgPrint("TOK162!FrameCopiedErrors = %u\n",
+ Adapter->ErrorLog->FrameCopiedError);)
+
+ VERY_LOUD_DEBUG(DbgPrint("TOK162!TokenErrors = %u\n",
+ Adapter->ErrorLog->TokenError);)
+
+ VERY_LOUD_DEBUG(DbgPrint("TOK162!InternalErrors = %u\n",
+ Adapter->ErrorLog->InternalError);)
+
+ VERY_LOUD_DEBUG(DbgPrint("TOK162!ARIFCIErrors = %u\n",
+ Adapter->ErrorLog->ARIFCIError);)
+
+ VERY_LOUD_DEBUG(DbgPrint("TOK162!AbortDelimeters = %u\n",
+ Adapter->ErrorLog->AbortDelimeter);)
+
+ VERY_LOUD_DEBUG(DbgPrint("TOK162!DMABusErrors = %u\n",
+ Adapter->ErrorLog->DMABusError);)
+
+ //
+ // If a query for information generated this interrupt, finish
+ // the query.
+ //
+ if (Adapter->RequestInProgress) {
+
+ TOK162FinishQueryInformation(Adapter);
+
+ }
+
+ //
+ // Relinquish the command block associated with this
+ // readadapterlog.
+ //
+ TOK162RelinquishCommandBlock(Adapter, CurrentCommandBlock);
+
+ break;
+
+
+ default:
+
+ //
+ // Did this command come from a set information request?
+ //
+ if (CurrentCommandBlock->Set) {
+
+ //
+ // Relinquish the command block.
+ //
+ TOK162RelinquishCommandBlock(Adapter, CurrentCommandBlock);
+
+ //
+ // Mark the current request state as complete.
+ //
+ Adapter->RequestInProgress = FALSE;
+
+ //
+ // Inform the wrapper the request has been completed.
+ //
+ NdisMSetInformationComplete(
+ Adapter->MiniportAdapterHandle,
+ NDIS_STATUS_SUCCESS);
+
+ //
+ // Not from a set. If this is the unique case of where a group
+ // address and a functional address had to be set to satisfy a
+ // packet filter change command (two commands for one), then we
+ // will only do an indication on the last one. The first one,
+ // however, still needs to have the command block associated
+ // with it relinquished.
+ //
+ } else if ((CurrentCommandBlock->Hardware.CommandCode == CMD_DMA_SET_GRP_ADDR) ||
+ (CurrentCommandBlock->Hardware.CommandCode == CMD_DMA_SET_FUNC_ADDR)) {
+
+ TOK162RelinquishCommandBlock(Adapter, CurrentCommandBlock);
+
+ }
+
+ break;
+ }
+
+}
+
+
+VOID
+TOK162ProcessTransmitInterrupts(
+ IN PTOK162_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ Process the Transmit Complete interrupts.
+
+ NOTE: This routine assumes that it is being executed in a
+ single thread of execution.
+
+Arguments:
+
+ Adapter - The adapter the transmit was sent from.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Pointer to command block being processed.
+ //
+ PTOK162_SUPER_COMMAND_BLOCK CurrentCommandBlock = Adapter->TransmitOnCard;
+
+ //
+ // Pointer to the packet that started this transmission.
+ //
+ PNDIS_PACKET OwningPacket;
+
+ //
+ // Points to the reserved part of the OwningPacket.
+ //
+ PTOK162_RESERVED Reserved;
+
+ //
+ // Holds CSTAT variable for transmit
+ //
+ USHORT Cstat;
+
+ //
+ // Status variable
+ //
+ NDIS_STATUS Status;
+
+ //
+ // Ensure that the Command Block is on an even boundary.
+ //
+ ASSERT(!(NdisGetPhysicalAddressLow(CurrentCommandBlock->Self) & 1));
+
+ //
+ // Log the fact that we are processing a transmit interrupt
+ //
+ IF_LOG('D');
+
+ //
+ // Check if there is any reason to continue with the process. It is
+ // possible during a reset that not all of the transmits had completed.
+ // The reset path takes care of aborting all sends that didn't complete
+ // so we don't want to process anything during a reset. In the general
+ // case we don't want to process any transmit that doesn't have an
+ // associated command block.
+ //
+ if ((CurrentCommandBlock == NULL) ||
+ (Adapter->ResetInProgress == TRUE)) {
+
+ //
+ // Log the fact that we received a possibly bogus transmit interrupt.
+ //
+ IF_LOG('p');
+ return;
+
+ }
+
+ //
+ // Get a pointer to the owning packet and the reserved part of
+ // the packet.
+ //
+ OwningPacket = CurrentCommandBlock->OwningPacket;
+ Reserved = PTOK162_RESERVED_FROM_PACKET(OwningPacket);
+
+ //
+ // Check if this packet was constrained.
+ //
+ if (CurrentCommandBlock->UsedTOK162Buffer == FALSE) {
+ //
+ // Pointer to the current NDIS_BUFFER that we need to do the
+ // completemapregister on.
+ //
+ PNDIS_BUFFER CurrentBuffer;
+
+ //
+ // Index to the map register being freed.
+ //
+ UINT CurMapRegister;
+
+ //
+ // The transmit is finished, so we can release
+ // the physical mapping used for it.
+ //
+ NdisQueryPacket(
+ OwningPacket,
+ NULL,
+ NULL,
+ &CurrentBuffer,
+ NULL
+ );
+
+ //
+ // Compute the first map register used by this transmit.
+ //
+ CurMapRegister = CurrentCommandBlock->CommandBlockIndex *
+ Adapter->TransmitThreshold;
+
+ //
+ // Loop through the NDIS_BUFFERs until there are no more.
+ //
+ while (CurrentBuffer != NULL) {
+
+ //
+ // Free the current map register.
+ //
+ NdisMCompleteBufferPhysicalMapping(
+ Adapter->MiniportAdapterHandle,
+ CurrentBuffer,
+ CurMapRegister
+ );
+
+ //
+ // Move to the next map register.
+ //
+ ++CurMapRegister;
+
+ //
+ // Get the next NDIS_BUFFER
+ //
+ NdisGetNextBuffer(
+ CurrentBuffer,
+ &CurrentBuffer
+ );
+
+ }
+
+ }
+
+ //
+ // If there was an error transmitting this
+ // packet, update our error counters.
+ //
+ Cstat = CurrentCommandBlock->Hardware.TransmitEntry.CSTAT;
+
+ //
+ // Display the completion status for the transmit entry on the debugger.
+ //
+ VERY_LOUD_DEBUG(DbgPrint(
+ "TOK162!Csat for the command block is %x\n",Cstat);)
+
+ //
+ // Check if there was an error on the transmit. Set Status and increment
+ // appropriate counter.
+ //
+ if ((Cstat & TRANSMIT_CSTAT_XMIT_ERROR) != 0) {
+
+ Adapter->BadTransmits++;
+ Status = NDIS_STATUS_FAILURE;
+
+ } else {
+
+ Adapter->GoodTransmits++;
+ Status = NDIS_STATUS_SUCCESS;
+
+ }
+
+ //
+ // Release the command block.
+ //
+ TOK162RelinquishTransmitBlock(Adapter, CurrentCommandBlock);
+
+ //
+ // Indicate to the filter than the send has been completed.
+ //
+ NdisMSendComplete(
+ Adapter->MiniportAdapterHandle,
+ OwningPacket,
+ Status
+ );
+
+}
+
+
+
+BOOLEAN
+TOK162ProcessRingInterrupts(
+ IN PTOK162_ADAPTER Adapter
+ )
+/*++
+
+Routine Description:
+
+ Process ring status interrupts.
+
+Arguments:
+
+ Adapter - The adapter registering the ring interrupt
+
+Return Value:
+
+ FALSE - Don't need to process receives as a result of the ring condition
+ TRUE - Need to process receives
+
+--*/
+{
+ //
+ // Holds the return status value
+ //
+ ULONG RingStatus;
+
+ //
+ // Command block variable used if we need to read the errorlog due to
+ // an overflow condition.
+ //
+ PTOK162_SUPER_COMMAND_BLOCK CommandBlock;
+
+ //
+ // Return value for the function. Assume we don't need to process
+ // receives.
+ //
+ BOOLEAN SoftError = FALSE;
+
+ //
+ // Log that we are processing a ring DPC. Display the ring interrupt
+ // information on the debugger.
+ //
+ IF_LOG('B');
+ VERY_LOUD_DEBUG(DbgPrint(
+ "TOK162!Doing ring processing -%04x\n",Adapter->SsbStatus1);)
+
+ //
+ // Initialize Ring Status to 0
+ //
+ RingStatus = 0;
+
+ //
+ // Determine the reason for the ring interrupt.
+ //
+ if (Adapter->SsbStatus1 & RING_STATUS_SIGNAL_LOSS) {
+
+ RingStatus |= NDIS_RING_SIGNAL_LOSS;
+
+ } else if (Adapter->SsbStatus1 & RING_STATUS_HARD_ERROR) {
+
+ RingStatus |= NDIS_RING_HARD_ERROR;
+
+ } else if (Adapter->SsbStatus1 & RING_STATUS_SOFT_ERROR) {
+
+ //
+ // If we have a soft error, we should check the receives.
+ //
+ RingStatus |= NDIS_RING_SOFT_ERROR;
+ SoftError = TRUE;
+
+ } else if (Adapter->SsbStatus1 & RING_STATUS_XMIT_BEACON) {
+
+ RingStatus |= NDIS_RING_TRANSMIT_BEACON;
+
+ } else if (Adapter->SsbStatus1 & RING_STATUS_LOBE_WIRE_FAULT) {
+
+ RingStatus |= NDIS_RING_LOBE_WIRE_FAULT;
+
+ } else if (Adapter->SsbStatus1 & RING_STATUS_AUTO_REMOVE_1) {
+
+ RingStatus |= NDIS_RING_AUTO_REMOVAL_ERROR;
+
+ } else if (Adapter->SsbStatus1 & RING_STATUS_REMOVE_RECEIVED) {
+
+ RingStatus |= NDIS_RING_REMOVE_RECEIVED;
+
+ } else if (Adapter->SsbStatus1 & RING_STATUS_OVERFLOW) {
+
+ RingStatus |= NDIS_RING_COUNTER_OVERFLOW;
+
+ } else if (Adapter->SsbStatus1 & RING_STATUS_SINGLESTATION) {
+
+ RingStatus |= NDIS_RING_SINGLE_STATION;
+
+ } else if (Adapter->SsbStatus1 & RING_STATUS_RINGRECOVERY) {
+
+ RingStatus |= NDIS_RING_RING_RECOVERY;
+
+ }
+
+ //
+ // Display the ring status that we will be indicating to the filter on
+ // the debugger.
+ //
+ VERY_LOUD_DEBUG(DbgPrint(
+ "TOK162!Indicating ring status - %lx\n",RingStatus);)
+
+ //
+ // Save the current status for query purposes.
+ //
+ Adapter->LastNotifyStatus = RingStatus;
+
+ //
+ // Indicate to the filter the ring status.
+ //
+ NdisMIndicateStatus(
+ Adapter->MiniportAdapterHandle,
+ NDIS_STATUS_RING_STATUS,
+ &RingStatus,
+ sizeof(ULONG)
+ );
+
+ //
+ // Tell the filter that we have completed the ring status.
+ //
+ NdisMIndicateStatusComplete(Adapter->MiniportAdapterHandle);
+
+ //
+ // If a counter has overflowed, we need to read the stats from
+ // the adapter to clear this condition.
+ //
+ if ((Adapter->SsbStatus1 & RING_STATUS_OVERFLOW) != 0) {
+
+
+ //
+ // Get a command block.
+ //
+ TOK162AcquireCommandBlock(Adapter,
+ &CommandBlock
+ );
+
+
+ //
+ // Set up the command block for a read_error_log command.
+ //
+ CommandBlock->Set = FALSE;
+ CommandBlock->NextCommand = NULL;
+ CommandBlock->Hardware.Status = 0;
+ CommandBlock->Hardware.NextPending = TOK162_NULL;
+ CommandBlock->Hardware.CommandCode = CMD_DMA_READ_ERRLOG;
+ CommandBlock->Hardware.ParmPointer =
+ NdisGetPhysicalAddressLow(Adapter->ErrorLogPhysical);
+
+ //
+ // Submit the command to the card.
+ //
+ TOK162SubmitCommandBlock(Adapter,
+ CommandBlock
+ );
+
+ }
+
+ //
+ // Return whether processreceiveinterrupts needs to be called.
+ //
+ return(SoftError);
+
+}
+