diff options
Diffstat (limited to 'private/ntos/ndis/ibmtok2i')
-rw-r--r-- | private/ntos/ndis/ibmtok2i/command.c | 715 | ||||
-rw-r--r-- | private/ntos/ndis/ibmtok2i/interrup.c | 1376 | ||||
-rw-r--r-- | private/ntos/ndis/ibmtok2i/log.txt | 77 | ||||
-rw-r--r-- | private/ntos/ndis/ibmtok2i/makefile | 6 | ||||
-rw-r--r-- | private/ntos/ndis/ibmtok2i/request.c | 1346 | ||||
-rw-r--r-- | private/ntos/ndis/ibmtok2i/reset.c | 1918 | ||||
-rw-r--r-- | private/ntos/ndis/ibmtok2i/send.c | 706 | ||||
-rw-r--r-- | private/ntos/ndis/ibmtok2i/sources | 48 | ||||
-rw-r--r-- | private/ntos/ndis/ibmtok2i/tok162.c | 2504 | ||||
-rw-r--r-- | private/ntos/ndis/ibmtok2i/tok162.rc | 38 | ||||
-rw-r--r-- | private/ntos/ndis/ibmtok2i/tok162hw.h | 1382 | ||||
-rw-r--r-- | private/ntos/ndis/ibmtok2i/tok162pr.h | 315 | ||||
-rw-r--r-- | private/ntos/ndis/ibmtok2i/tok162sw.h | 699 |
13 files changed, 11130 insertions, 0 deletions
diff --git a/private/ntos/ndis/ibmtok2i/command.c b/private/ntos/ndis/ibmtok2i/command.c new file mode 100644 index 000000000..7b139ed3d --- /dev/null +++ b/private/ntos/ndis/ibmtok2i/command.c @@ -0,0 +1,715 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + command.c + +Abstract: + + This file contains the code for managing command and transmit blocks on + the TOK162's queues. It is based loosely on the NE3200 driver. + +Author: + + Kevin Martin(KevinMa) 04-Jan-1993 + +Environment: + + Kernel Mode - Or whatever is the equivalent on OS/2 and DOS. + +Revision History: + + +--*/ + +#include <tok162sw.h> + +VOID +TOK162SendCommandBlock( + PTOK162_ADAPTER Adapter, + PTOK162_SUPER_COMMAND_BLOCK CommandBlock + ); + + +VOID +TOK162SubmitCommandBlock( + IN PTOK162_ADAPTER Adapter, + IN PTOK162_SUPER_COMMAND_BLOCK CommandBlock + ) + +/*++ + +Routine Description: + + Submit a complete Command Block for execution by the TOK162. + +Arguments: + + Adapter - The adapter that points to the ring entry structures. + + CommandBlock - Holds the pointer to the Command Block to be + submitted. + +Return Value: + + None. + +--*/ +{ + // + // Pointer to the most recently submitted Command Block. + // + PTOK162_SUPER_COMMAND_BLOCK PreviousCommandBlock; + + // Ensure that our command block is on an even boundary. + // + ASSERT(!(NdisGetPhysicalAddressLow(CommandBlock->Self) & 1)); + + // + // Timestamp the command block. + // + CommandBlock->Timeout = FALSE; + CommandBlock->Hardware.State = TOK162_STATE_WAIT_FOR_ADAPTER; + + // + // If the adapter is currently executing a command add this to + // the end of the waiting list. Otherwise submit this command to the card. + // + if (Adapter->CommandOnCard != NULL) { + + // + // Pend this command + // + IF_LOG('i'); + + PreviousCommandBlock = Adapter->WaitingCommandTail; + Adapter->WaitingCommandTail = CommandBlock; + + // + // Check if there are any other pendings. If not, we are + // the first pending. If there are others, tack this one on + // the end. + // + if (PreviousCommandBlock == NULL) { + + Adapter->WaitingCommandHead = CommandBlock; + + } else { + + PreviousCommandBlock->NextCommand = CommandBlock; + + } + + } else { + + // + // Set this command as the active one + // + Adapter->CommandOnCard = CommandBlock; + + // + // Log that we are sending the command to the card + // + IF_LOG('I'); + + // + // send the command out to the card + // + TOK162SendCommandBlock(Adapter,CommandBlock); + + } + +} + +VOID +TOK162SubmitTransmitBlock( + IN PTOK162_ADAPTER Adapter, + IN PTOK162_SUPER_COMMAND_BLOCK CommandBlock + ) + +/*++ + +Routine Description: + + Submit a complete Command Block for execution by the TOK162. + +Arguments: + + Adapter - The adapter that points to the ring entry structures. + + CommandBlock - Holds the pointer to the transmit block to be + submitted. + +Return Value: + + None. + +--*/ +{ + // + // Pointer to the most recently submitted Transmit Block. + // + PTOK162_SUPER_COMMAND_BLOCK PreviousCommandBlock; + + // Ensure that our command block is on an even boundary. + // + ASSERT(!(NdisGetPhysicalAddressLow(CommandBlock->Self) & 1)); + + // + // Timestamp the transmit block. + // + CommandBlock->Timeout = FALSE; + CommandBlock->Hardware.State = TOK162_STATE_WAIT_FOR_ADAPTER; + + // + // If the adapter is currently executing a transmit add this to + // the end of the waiting list. Otherwise submit this transmit to + // the card. + // + if (Adapter->TransmitOnCard != NULL) { + + // + // Log that we have to pend the transmit + IF_LOG('w'); + + // + // Pend this transmit + // + PreviousCommandBlock = Adapter->WaitingTransmitTail; + Adapter->WaitingTransmitTail = CommandBlock; + + // + // Check if there are any other pendings + // + if (PreviousCommandBlock == NULL) { + + Adapter->WaitingTransmitHead = CommandBlock; + + } else { + + PreviousCommandBlock->NextCommand = CommandBlock; + + } + + } else { + + // + // Mark this transmit as the active one. + // + Adapter->TransmitOnCard = CommandBlock; + + // + // Log that we are sending the transmit over the wire + // + IF_LOG('W'); + + // + // send the transmit to the card + // + TOK162SendCommandBlock(Adapter,CommandBlock); + + } + +} + +BOOLEAN +TOK162AcquireTransmitBlock( + IN PTOK162_ADAPTER Adapter, + OUT PTOK162_SUPER_COMMAND_BLOCK * CommandBlock + ) + +/*++ + +Routine Description: + + Sees if a Transmit Block is available and if so returns its index. + +Arguments: + + Adapter - The adapter that has the transmit queue + + CommandBlock - Will receive a pointer to a Command Block if one is + available. + +Return Value: + + Returns FALSE if there are no free Command Blocks. + +--*/ + +{ + + // + // Pointer to the available transmit block + // + PTOK162_SUPER_COMMAND_BLOCK temp; + + // + // Get a pointer to the Transmit Block. + // + temp = Adapter->TransmitQueue + Adapter->NextTransmitBlock; + + // + // If there aren't any available transmits, we return FALSE + // + if (Adapter->NumberOfAvailableTransmitBlocks == 0) { + + // + // Log that there weren't any available + // + IF_LOG('x'); + + return FALSE; + + } + + // + // Decrement the number of available transit blocks. + // + Adapter->NumberOfAvailableTransmitBlocks--; + + // + // Initialize the Transmit Command Block. + // + temp->Hardware.NextPending = TOK162_NULL; + temp->CommandBlock = FALSE; + + // + // Increment to next transmit command block + // + if (Adapter->NextTransmitBlock == (Adapter->NumberOfTransmitLists - 1)) { + + Adapter->NextTransmitBlock = 0; + + } else { + + Adapter->NextTransmitBlock++; + } + + // + // Return the transmit block pointer. + // + *CommandBlock = temp; + + // + // Log that we returned a transmit block. + // + IF_LOG('X'); + + return(TRUE); + +} + +VOID +TOK162AcquireCommandBlock( + IN PTOK162_ADAPTER Adapter, + OUT PTOK162_SUPER_COMMAND_BLOCK * CommandBlock + ) + +/*++ + +Routine Description: + + Gets the command block. + +Arguments: + + Adapter - The adapter that points to the ring entry structures. + + CommandBlock - Will receive a pointer to a Command Block. + +Return Value: + + None. + +--*/ + +{ + // + // Pointer to the command block to be returned. + // + PTOK162_SUPER_COMMAND_BLOCK temp; + + // + // This is a pointer to the Command Block. + // + temp = Adapter->CommandQueue + Adapter->NextCommandBlock; + + ASSERT(Adapter->NumberOfAvailableCommandBlocks > 0); + + IF_LOG('l'); + + // + // Decrement the number of available command blocks + // + Adapter->NumberOfAvailableCommandBlocks--; + + // + // Initialize the Command Block. + // + NdisZeroMemory( + temp, + sizeof(TOK162_SUPER_COMMAND_BLOCK) + ); + + // + // There aren't any linked command blocks right now. + // + temp->Hardware.NextPending = TOK162_NULL; + + // + // This is a command block and not a transmit block + // + temp->CommandBlock = TRUE; + + // + // Set the self-referential pointer. + // + NdisSetPhysicalAddressLow( + temp->Self, + NdisGetPhysicalAddressLow(Adapter->CommandQueuePhysical) + + Adapter->NextCommandBlock * sizeof(TOK162_SUPER_COMMAND_BLOCK) + ); + + // + // Increment to next command block + // + if (Adapter->NextCommandBlock == (TOK162_NUMBER_OF_CMD_BLOCKS - 1)) { + + Adapter->NextCommandBlock = 0; + + } else { + + Adapter->NextCommandBlock++; + + } + + // + // Return the Command Block pointer. + // + *CommandBlock = temp; + + // + // Log that we returned a command block + // + IF_LOG('L'); + +} + + +VOID +TOK162RelinquishCommandBlock( + IN PTOK162_ADAPTER Adapter, + IN PTOK162_SUPER_COMMAND_BLOCK CommandBlock + ) + +/*++ + +Routine Description: + + Relinquish the Command Block resource. + +Arguments: + + Adapter - The adapter that owns the Command Block. + + CommandBlock - The Command Block to relinquish. + +Return Value: + + None. + +--*/ + +{ + // + // If there is a waiting chain of commands -- submit the first one + // + if (Adapter->WaitingCommandHead != NULL) { + + // + // Log that we found pending commands + // + IF_LOG('j'); + + // + // Mark the next one as the active one. + // + Adapter->CommandOnCard = Adapter->WaitingCommandHead; + + // + // Update the waiting command head. + // + Adapter->WaitingCommandHead = + Adapter->WaitingCommandHead->NextCommand; + + // + // Update the waiting command tail pointer + // + if (Adapter->WaitingCommandHead == NULL) { + + Adapter->WaitingCommandTail = NULL; + + } + + // + // Send out the new command + // + TOK162SendCommandBlock(Adapter,Adapter->CommandOnCard); + + } else { + + // + // Indicate that the queue was empty. + // + IF_LOG('J'); + + // + // No commands on the card. We're done for now. + // + Adapter->CommandOnCard = NULL; + + } + + // + // Free the command block + // + CommandBlock->Hardware.State = TOK162_STATE_FREE; + CommandBlock->NextCommand = NULL; + + // + // Increment the number of available command blocks + // + Adapter->NumberOfAvailableCommandBlocks++; + +} + + +VOID +TOK162RelinquishTransmitBlock( + IN PTOK162_ADAPTER Adapter, + IN PTOK162_SUPER_COMMAND_BLOCK CommandBlock + ) + +/*++ + +Routine Description: + + Relinquish the Transmit Command Block resource. + +Arguments: + + Adapter - The adapter that owns the Command Block. + + CommandBlock - The transmit block to relinquish. + +Return Value: + + None. + +--*/ + +{ + // + // If there is a waiting chain of commands -- submit the first one + // + if (Adapter->WaitingTransmitHead != NULL) { + + // + // Log that there is a waiting send. + // + IF_LOG('y'); + + // + // Update the queue pointers + // + Adapter->TransmitOnCard = Adapter->WaitingTransmitHead; + + Adapter->WaitingTransmitHead = + Adapter->WaitingTransmitHead->NextCommand; + + if (Adapter->WaitingTransmitHead == NULL) { + + Adapter->WaitingTransmitTail = NULL; + + } + + // + // Submit this command to the card. + // + TOK162SendCommandBlock(Adapter,Adapter->TransmitOnCard); + + } else { + + // + // Log that the waiting queue was empty. + // + IF_LOG('Y'); + + // + // We are done with submits + // + Adapter->TransmitOnCard = NULL; + + } + + // + // Free the transmit block + // + CommandBlock->Hardware.State = TOK162_STATE_FREE; + CommandBlock->NextCommand = NULL; + + // + // Increment the number of available transmit blocks + // + Adapter->NumberOfAvailableTransmitBlocks++; + + // + // Decrement the number of queued transmit blocks + // + Adapter->TransmitsQueued--; + +} + + +void +TOK162SendCommandBlock( + IN PTOK162_ADAPTER Adapter, + IN PTOK162_SUPER_COMMAND_BLOCK CommandBlock + ) +{ +/*++ + +Routine Description: + + Submits the command block passed in to the card. + +Arguments: + + Adapter - The adapter that owns the Command Block. + + CommandBlock - The command/transmit block to submit. + +Return Value: + + None. + +--*/ + + // + // This is the "execution" variable for the SCB. The standard is to just + // send the interrupt adapter, execute, and don't reset the + // adapter-to-system interrupt bits. The initial init open command will + // add in the scb clear bit. + ULONG ScbExecute = EXECUTE_SCB_COMMAND; + + // + // First figure out the SCB, based on the command + // + Adapter->Scb->Command = CommandBlock->Hardware.CommandCode; + + switch(Adapter->Scb->Command) { + + // + // We have a transmit. + // + case CMD_DMA_XMIT: + + // + // Point the Scb to the transmit list + // + Adapter->Scb->Parm1 = + BYTE_SWAP(HIGH_WORD(CommandBlock->PhysicalTransmitEntry)); + + Adapter->Scb->Parm2 = + BYTE_SWAP(LOW_WORD(CommandBlock->PhysicalTransmitEntry)); + + break; + + // + // These are the Immediate Data commands. Close doesn't care what + // is passed, however. + // + case CMD_DMA_CLOSE: + case CMD_DMA_SET_GRP_ADDR: + case CMD_DMA_SET_FUNC_ADDR: + + // + // The parameter is set according to the ImmediateData field of + // the command block. + // + Adapter->Scb->Parm1 = + BYTE_SWAP(HIGH_WORD(CommandBlock->Hardware.ImmediateData)); + + Adapter->Scb->Parm2 = + BYTE_SWAP(LOW_WORD(CommandBlock->Hardware.ImmediateData)); + + break; + + // + // The rest use a pointer. + // + + // + // In the case of an open, we have to check to see if this is part + // of the initial init. If so, we need to get the SCB Clear bit + // set so we have proper timing for the receieve command. After + // that decision has been made, the open command is treated like + // any other pointer command. + // + case CMD_DMA_OPEN: + + if (Adapter->InitialInit == TRUE) { + + ScbExecute |= CMD_PIO_SCB_REQUEST; + + } + + case CMD_DMA_READ_ERRLOG: + case CMD_DMA_READ: + case CMD_DMA_RCV: + case CMD_DMA_IMPL_ENABLE: + + // + // The parameter is set according to the ParmPointer field of + // the command block. + // + Adapter->Scb->Parm1 = + BYTE_SWAP(HIGH_WORD(CommandBlock->Hardware.ParmPointer)); + + Adapter->Scb->Parm2 = + BYTE_SWAP(LOW_WORD(CommandBlock->Hardware.ParmPointer)); + + break; + + } + + // + // Mark the command block as executing + // + CommandBlock->Hardware.State = TOK162_STATE_EXECUTING; + + // + // Log that we are sending an SCB to the card. + // + IF_LOG('Z'); + + // + // Display the SCB on the debugger + // + EXTRA_LOUD_DEBUG(DbgPrint("SCB going out is %x,%x,%x\n", + Adapter->Scb->Command, + Adapter->Scb->Parm1, + Adapter->Scb->Parm2);) + + // + // Finally, send the command out to the card + // + WRITE_ADAPTER_USHORT(Adapter, + PORT_OFFSET_COMMAND, + ScbExecute + ); + +} 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); + +} + diff --git a/private/ntos/ndis/ibmtok2i/log.txt b/private/ntos/ndis/ibmtok2i/log.txt new file mode 100644 index 000000000..b56b48d52 --- /dev/null +++ b/private/ntos/ndis/ibmtok2i/log.txt @@ -0,0 +1,77 @@ +a - Not our Interrupt interrup.c +A - Our Interrupt interrup.c + +b - Ring Status Interrupt interrup.c +B - Ring Status DPC interrup.c + +c - Receive Interrupt interrup.c +C - Receive DPC interrup.c + +d - Transmit Interrupt interrup.c +D - Transmit DPC interrup.c + +e - Command Interrupt interrup.c +E - Command DPC interrup.c + +f - +F - Receive Command Failed reset.c + +g - DoTheOpen Entered reset.c +G - DoTheOpen Exited reset.c + +h - Open succeeded reset.c +H - Open failed reset.c + +i - Command Block Pended command.c +I - Command Block Sent command.c + +j - Command Block Relinquished, queue not empty command.c +J - Command Block Relinquished, queue empty command.c + +k - +K - + +l - Acquire Command Block Entered command.c +L - Acquire Command Block Exited command.c + +m - +M - + +n - TransferData Entered tok162.c +N - TransferData Exited tok162.c + +o - ISR called interrup.c +O - ISR leaving interrup.c + +p - ISR is for Receive interrup.c +P - + +q - Indicate Receive interrup.c +Q - Receive Valid Interrupt Issued interrup.c + +r - Entering DPC interrup.c +R - Leaving DPC interrup.c + +s - Send Entered send.c +S - Send Exited send.c + +t - Tramsmit Packet Entered send.c +T - Transmit Packet Exited send.c + +u - Transmit Packet Exited Resources send.c +U - Transmit Packet Exited Error send.c + +v - Transmit Constrain Entered send.c +V - Transmit Constrain Exited send.c + +w - Transmit Command Pended command.c +W - Transmit Command Sent command.c + +x - No Transmit Blocks Available command.c +X - Transmit Block allocated command.c + +y - Transmit Block Relinquished, queue not empty command.c +Y - Transmit Block Relinquished, queue empty command.c + +z - SSB Update interrup.c, reset.c +Z - Execute SCB command.c, reset.c diff --git a/private/ntos/ndis/ibmtok2i/makefile b/private/ntos/ndis/ibmtok2i/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/ndis/ibmtok2i/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/ndis/ibmtok2i/request.c b/private/ntos/ndis/ibmtok2i/request.c new file mode 100644 index 000000000..a5dcbfd7d --- /dev/null +++ b/private/ntos/ndis/ibmtok2i/request.c @@ -0,0 +1,1346 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + request.c + +Abstract: + + This file contains code to implement MiniportQueryInformation and + MiniportSetInformation. This driver conforms to the + NDIS 3.0 Miniport interface. + +Author: + + Kevin Martin (KevinMa) 27-Jan-1994 + +Environment: + + Kernel Mode - Or whatever is the equivalent on OS/2 and DOS. + +Revision History: + + +--*/ + +#include <tok162sw.h> + +extern +NDIS_STATUS +TOK162ChangeAddress( + OUT PTOK162_ADAPTER Adapter, + IN ULONG Address, + IN NDIS_OID Oid, + IN USHORT Command, + IN BOOLEAN Set + ); + +extern +NDIS_STATUS +TOK162SetInformation( + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_OID Oid, + IN PVOID InformationBuffer, + IN ULONG InformationBufferLength, + OUT PULONG BytesRead, + OUT PULONG BytesNeeded + ) + +/*++ + +Routine Description: + + TOK162SetInformation handles a set operation for a + single OID. + +Arguments: + + MiniportAdapterContext - The adapter that the set is for. + + BytesNeeded - If there is not enough data in OvbBuffer + to satisfy the OID, returns the amount of storage needed. + +Return Value: + + NDIS_STATUS_SUCCESS + NDIS_STATUS_PENDING + NDIS_STATUS_INVALID_LENGTH + NDIS_STATUS_INVALID_OID + +--*/ + +{ + // + // Pointer to the TOK162 adapter structure. + // + PTOK162_ADAPTER Adapter = + PTOK162_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext); + + // + // Return value from NDIS calls + // + NDIS_STATUS Status; + + // + // Temporary storage for the packet filter + // + ULONG TempFilter; + + // + // If we are in the middle of a reset, return this fact + // + if (Adapter->ResetInProgress == TRUE) { + + return(NDIS_STATUS_RESET_IN_PROGRESS); + + } + + // + // Process request based on the OID + // + switch (Oid) { + + case OID_802_5_CURRENT_FUNCTIONAL: + + if (InformationBufferLength != TR_LENGTH_OF_FUNCTIONAL) { + + // + // The data must be a multiple of the functional + // address size. + // + + Status = NDIS_STATUS_INVALID_DATA; + + } + + // + // Save the address away + // + NdisMoveMemory(&Adapter->FunctionalAddress, + InformationBuffer, + InformationBufferLength + ); + + // + // Need to reverse it + // + Adapter->FunctionalAddress = + BYTE_SWAP_ULONG(Adapter->FunctionalAddress); + + VERY_LOUD_DEBUG(DbgPrint("Functional Address is now %08x\n", + Adapter->FunctionalAddress);) + + // + // Now call the filter package to set up the address if the + // functional address has been set in the packet filter. + // + if (!(Adapter->CurrentPacketFilter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL) && + (Adapter->CurrentPacketFilter & NDIS_PACKET_TYPE_FUNCTIONAL) + ) + { + Status = TOK162ChangeAddress( + Adapter, + Adapter->FunctionalAddress, + Oid, + CMD_DMA_SET_FUNC_ADDR, + TRUE + ); + + // + // Nothing changed with the card, so return SUCCESS + // + } else { + + Status = NDIS_STATUS_SUCCESS; + + } + + // + // Set number of bytes read + // + *BytesRead = TR_LENGTH_OF_FUNCTIONAL; + + break; + + case OID_802_5_CURRENT_GROUP: + + // + // Group addresses and Functional addresses are the same length. + // + if (InformationBufferLength != TR_LENGTH_OF_FUNCTIONAL) { + + // + // The data must be a multiple of the group + // address size. + // + Status = NDIS_STATUS_INVALID_DATA; + + } + + // + // Save the address away + // + NdisMoveMemory(&Adapter->GroupAddress, + InformationBuffer, + InformationBufferLength + ); + + + // + // Need to reverse it + // + Adapter->GroupAddress = + BYTE_SWAP_ULONG(Adapter->GroupAddress); + + // + // Now call the filter package to set up the address if group + // addresses have been set in the packet filter. + // + if ((Adapter->CurrentPacketFilter & NDIS_PACKET_TYPE_GROUP) != 0) { + + Status = TOK162ChangeAddress( + Adapter, + Adapter->GroupAddress, + Oid, + CMD_DMA_SET_GRP_ADDR, + TRUE + ); + } else { + + Status = NDIS_STATUS_SUCCESS; + + } + + // + // Set number of bytes read + // + *BytesRead = TR_LENGTH_OF_FUNCTIONAL; + + break; + + case OID_GEN_CURRENT_PACKET_FILTER: + + // + // Make sure the new packet filter is the correct size (length) + // + if (InformationBufferLength != 4) { + + Status = NDIS_STATUS_INVALID_DATA; + + } + + // + // + TempFilter = *(PULONG)(InformationBuffer); + LOUD_DEBUG(DbgPrint("GEN_CURRENT_PACKET_FILTER = %x\n",TempFilter);) + + // + // Make sure the new filter is not something we don't support + // + if (TempFilter & (NDIS_PACKET_TYPE_MULTICAST | + NDIS_PACKET_TYPE_ALL_MULTICAST | + NDIS_PACKET_TYPE_SMT | + NDIS_PACKET_TYPE_PROMISCUOUS | + NDIS_PACKET_TYPE_MAC_FRAME + )) { + + Status = NDIS_STATUS_NOT_SUPPORTED; + + *BytesRead = 4; + *BytesNeeded = 0; + + break; + } + + if (Adapter->CurrentPacketFilter != TempFilter) { + + Adapter->CurrentPacketFilter = TempFilter; + + // + // This is a filter we can deal with. Go change the functional + // and group addresses based on the filter. + // + Status = TOK162ChangeFuncGroup(Adapter); + + } else { + + Status = NDIS_STATUS_SUCCESS; + + *BytesRead = 4; + *BytesNeeded = 0; + + } + + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + + // + // We don't change anything, but we accept any value. + // + *BytesRead = 4; + + Status = NDIS_STATUS_SUCCESS; + + break; + + // + // We got an OID that is not settable. + // + default: + + Status = NDIS_STATUS_INVALID_OID; + break; + } + + // + // If we have a request pending as a result of any work we've done, + // mark it. + // + if (Status == NDIS_STATUS_PENDING) { + + Adapter->RequestInProgress = TRUE; + + } + + return Status; +} + +extern +NDIS_STATUS +TOK162ChangeAddress( + OUT PTOK162_ADAPTER Adapter, + IN ULONG Address, + IN NDIS_OID Oid, + IN USHORT Command, + IN BOOLEAN Set + ) +/*++ + +Routine Description: + + TOK162ChangeAddress will submit a command for either a group or + functional address, based on what is passed in. + +Arguments: + + Adapter - Structure representing the current adapter + + Address - The ULONG address to send to the card + + Oid - Current Oid (Either functional or group) + + Command - Command to send to card + + Set - Whether to mark the command as a set. If we need to change two + addresses (ChangeFuncGroup) as the result of one Oid, we will + only do a completion for the one with the set. In the normal + case of one address being set, Set will always be TRUE. + +Return Value: + + NDIS_STATUS_PENDING + +--*/ +{ + // + // Command block pointer + // + PTOK162_SUPER_COMMAND_BLOCK CommandBlock; + + // + // Set the adapter Oid to the current Oid + // + Adapter->Oid = Oid; + + // + // Get a command block + // + TOK162AcquireCommandBlock(Adapter, + &CommandBlock + ); + + // + // Set the command block based on the parameters passed in + // + CommandBlock->Set = Set; + CommandBlock->NextCommand = NULL; + CommandBlock->Hardware.Status = 0; + CommandBlock->Hardware.NextPending = TOK162_NULL; + CommandBlock->Hardware.CommandCode = Command; + CommandBlock->Hardware.ImmediateData = Address; + + // + // Display the address about to be set on the debugger. + // + LOUD_DEBUG(DbgPrint("Address being set is %08x\n", + CommandBlock->Hardware.ImmediateData);) + + // + // Indicate that a request is in progress + // + Adapter->RequestInProgress = TRUE; + + // + // Make this request be in progress. + // + TOK162SubmitCommandBlock(Adapter, CommandBlock); + + // + // Complete the request when the interrupt comes in. + // + return NDIS_STATUS_PENDING; +} + + +NDIS_STATUS +TOK162QueryInformation( + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_OID Oid, + IN PVOID InformationBuffer, + IN ULONG InformationBufferLength, + OUT PULONG BytesWritten, + OUT PULONG BytesNeeded +) + +/*++ + +Routine Description: + + The TOK162QueryInformation process a Query request for specific + NDIS_OIDs + +Arguments: + + MiniportAdapterContext - a pointer to the adapter. + + Oid - the NDIS_OID to process. + + InformationBuffer - a pointer into the + NdisRequest->InformationBuffer into which + we store the result of the query + + InformationBufferLength - a pointer to the number of bytes left in the + InformationBuffer. + + BytesWritten - a pointer to the number of bytes written into + the InformationBuffer. + + BytesNeeded - If there is not enough room in the information + buffer this will contain the number of bytes + needed to complete the request. + +Return Value: + + The function value is the status of the operation.(NDIS_STATUS_PENDING) + +--*/ + +{ + // + // Command block used for the request. + // + PTOK162_SUPER_COMMAND_BLOCK CommandBlock; + + // + // Adapter structure for the current card + // + PTOK162_ADAPTER Adapter = + PTOK162_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext); + + NDIS_STATUS Status = NDIS_STATUS_PENDING; + + // + // If we are in the middle of a reset, return this fact + // + if (Adapter->ResetInProgress == TRUE) + { + return(NDIS_STATUS_RESET_IN_PROGRESS); + } + + // + // Save the information passed in + // + Adapter->BytesWritten = BytesWritten; + + Adapter->BytesNeeded = BytesNeeded; + + Adapter->Oid = Oid; + + Adapter->InformationBuffer = InformationBuffer; + + Adapter->InformationBufferLength = InformationBufferLength; + + // + // Figure out the specific command based on the OID + // + switch(Oid) + { + case OID_802_5_CURRENT_FUNCTIONAL: + + if (InformationBufferLength != TR_LENGTH_OF_FUNCTIONAL) + { + // + // The data must be a multiple of the functional + // address size. + // + Status = NDIS_STATUS_INVALID_DATA; + } + else + { + // + // Save the address away + // + NdisMoveMemory( + InformationBuffer, + &Adapter->FunctionalAddress, + InformationBufferLength); + + Status = NDIS_STATUS_SUCCESS; + } + + break; + + case OID_802_5_CURRENT_GROUP: + + if (InformationBufferLength != TR_LENGTH_OF_FUNCTIONAL) + { + // + // The data must be a multiple of the group + // address size. + // + Status = NDIS_STATUS_INVALID_DATA; + } + else + { + // + // Save the address away + // + NdisMoveMemory( + InformationBuffer, + &Adapter->GroupAddress, + InformationBufferLength); + + Status = NDIS_STATUS_SUCCESS; + } + + break; + + // + // If the permanent address is requested, we need to read from + // the adapter at the permanent address offset. + // + case OID_802_5_PERMANENT_ADDRESS: + + // + // Get a command block + // + TOK162AcquireCommandBlock(Adapter, &CommandBlock); + + // + // Notify that this is from a set + // + CommandBlock->Set = TRUE; + + // + // Setup the common fields of the command block. + // + CommandBlock->NextCommand = NULL; + CommandBlock->Hardware.Status = 0; + CommandBlock->Hardware.NextPending = TOK162_NULL; + + // + // Fill in the adapter buffer area with the information to + // obtain the permanent address. + // + Adapter->AdapterBuf->DataCount = BYTE_SWAP(0x0006); + + Adapter->AdapterBuf->DataAddress = + BYTE_SWAP(Adapter->UniversalAddress); + + // + // Set the command block for the read adapter command. + // + CommandBlock->Hardware.CommandCode = CMD_DMA_READ; + + CommandBlock->Hardware.ParmPointer = + NdisGetPhysicalAddressLow(Adapter->AdapterBufPhysical); + + break; + + // + // For any of the current addresses (functional, group, network) + // we will want to read the current addresses as the adapter has + // them recorded. + // + case OID_802_5_CURRENT_ADDRESS: + + // + // Get a command block + // + TOK162AcquireCommandBlock(Adapter, &CommandBlock); + + // + // Notify that this is from a set + // + CommandBlock->Set = TRUE; + + // + // Setup the common fields of the command block. + // + CommandBlock->NextCommand = NULL; + CommandBlock->Hardware.Status = 0; + CommandBlock->Hardware.NextPending = TOK162_NULL; + + // + // Set up the adapter buffer to get the current addresses. + // + Adapter->AdapterBuf->DataCount = BYTE_SWAP(0x000e); + + Adapter->AdapterBuf->DataAddress = + BYTE_SWAP(Adapter->AdapterAddresses); + + // + // Set the command block for the read adapter command. + // + CommandBlock->Hardware.CommandCode = CMD_DMA_READ; + + CommandBlock->Hardware.ParmPointer = + NdisGetPhysicalAddressLow(Adapter->AdapterBufPhysical); + + break; + + // + // For any other OID, we read the errorlog to help make sure we + // don't get a counter overflow and lose information. + // + default: + + // + // Get a command block + // + TOK162AcquireCommandBlock(Adapter, &CommandBlock); + + // + // Notify that this is from a set + // + CommandBlock->Set = TRUE; + + // + // Setup the common fields of the command block. + // + CommandBlock->NextCommand = NULL; + CommandBlock->Hardware.Status = 0; + CommandBlock->Hardware.NextPending = TOK162_NULL; + + // + // Set the command block for a read error log command. + // + CommandBlock->Hardware.CommandCode = CMD_DMA_READ_ERRLOG; + + CommandBlock->Hardware.ParmPointer = + NdisGetPhysicalAddressLow(Adapter->ErrorLogPhysical); + + break; + } + + // + // If we need to process the command block... + // + if (NDIS_STATUS_PENDING == Status) + { + // + // Now that we're set up, let's do it! + // + Adapter->RequestInProgress = TRUE; + + // + // Submit the command to the card + // + TOK162SubmitCommandBlock(Adapter, CommandBlock); + } + + return(Status); +} + +VOID +TOK162FinishQueryInformation( + IN PTOK162_ADAPTER Adapter +) + +/*++ + +Routine Description: + + The TOK162FinishQueryInformation finish processing a Query request for + NDIS_OIDs that are specific about the Driver. + +Arguments: + + Adapter - a pointer to the adapter. + +Return Value: + + The function value is the status of the operation. + +--*/ + +{ +// +// The list of Oid's that we support with this driver. +// +static +NDIS_OID TOK162GlobalSupportedOids[] = { + OID_GEN_SUPPORTED_LIST, + OID_GEN_HARDWARE_STATUS, + OID_GEN_MEDIA_SUPPORTED, + OID_GEN_MEDIA_IN_USE, + OID_GEN_MAXIMUM_LOOKAHEAD, + OID_GEN_MAXIMUM_FRAME_SIZE, + OID_GEN_MAXIMUM_TOTAL_SIZE, + OID_GEN_MAC_OPTIONS, + OID_GEN_PROTOCOL_OPTIONS, + OID_GEN_LINK_SPEED, + OID_GEN_TRANSMIT_BUFFER_SPACE, + OID_GEN_RECEIVE_BUFFER_SPACE, + OID_GEN_TRANSMIT_BLOCK_SIZE, + OID_GEN_RECEIVE_BLOCK_SIZE, + OID_GEN_VENDOR_ID, + OID_GEN_VENDOR_DESCRIPTION, + OID_GEN_DRIVER_VERSION, + OID_GEN_CURRENT_PACKET_FILTER, + OID_GEN_CURRENT_LOOKAHEAD, + OID_GEN_XMIT_OK, + OID_GEN_RCV_OK, + OID_GEN_XMIT_ERROR, + OID_GEN_RCV_ERROR, + OID_GEN_RCV_NO_BUFFER, + OID_GEN_RCV_CRC_ERROR, + OID_GEN_TRANSMIT_QUEUE_LENGTH, + OID_802_5_PERMANENT_ADDRESS, + OID_802_5_CURRENT_ADDRESS, + OID_802_5_CURRENT_FUNCTIONAL, + OID_802_5_CURRENT_GROUP, + OID_802_5_LAST_OPEN_STATUS, + OID_802_5_CURRENT_RING_STATUS, + OID_802_5_CURRENT_RING_STATE, + OID_802_5_LINE_ERRORS, + OID_802_5_LOST_FRAMES, + OID_802_5_BURST_ERRORS, + OID_802_5_FRAME_COPIED_ERRORS, + OID_802_5_TOKEN_ERRORS + }; + + // + // Variable to keep track of the bytes written out. + // + PUINT BytesWritten = Adapter->BytesWritten; + + // + // Variable to keep track of the bytes needed + // + PUINT BytesNeeded = Adapter->BytesNeeded; + + // + // The actual Oid that just finished. + // + NDIS_OID Oid = Adapter->Oid; + + // + // Result buffer. + // + PVOID InformationBuffer = Adapter->InformationBuffer; + + // + // Length of result buffer. + // + UINT InformationBufferLength = Adapter->InformationBufferLength; + + // + // The medium supported by this driver. + // + NDIS_MEDIUM Medium = NdisMedium802_5; + + // + // Generic repository for ULONG results + // + UINT GenericUlong; + + // + // Generic repository for USHORT results + // + USHORT GenericUShort; + + // + // Generic repository for character array results + // + UCHAR GenericArray[6]; + + // + // Pointer to source of result Common variables for pointing to result of query + // + PVOID MoveSource = (PVOID)(&GenericUlong); + + // + // Number of bytes to be moved, defaulting to the size of a ULONG. + // + ULONG MoveBytes = sizeof(ULONG); + + // + // Hardware Status + // + NDIS_HARDWARE_STATUS HardwareStatus; + + // + // Return value of NDIS calls + // + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + // + // Initialize bytes written and bytes needed + // + *BytesWritten = 0; + *BytesNeeded = 0; + + // + // Switch on the Oid + // + switch(Oid){ + + // + // The MAC options represents the options our driver supports/needs. + // + case OID_GEN_MAC_OPTIONS: + + // + // We don't pend transfers. + // we copy lookahead data, and we have serialized receives. + // + GenericUlong = (ULONG)(NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | + NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | + NDIS_MAC_OPTION_RECEIVE_SERIALIZED + ); + + break; + + // + // We return the list of Oid's we support (list above) + // + case OID_GEN_SUPPORTED_LIST: + + // + // Point to the beginning of the list. + // + MoveSource = (PVOID)(TOK162GlobalSupportedOids); + + // + // We have to move the whole list. + // + MoveBytes = sizeof(TOK162GlobalSupportedOids); + + break; + + case OID_GEN_HARDWARE_STATUS: + + // + // If we have a reset in progress, the hardware status is + // set to reset. Otherwise, we return that we are ready. + // + if (Adapter->ResetInProgress) { + + HardwareStatus = NdisHardwareStatusReset; + + } else { + + HardwareStatus = NdisHardwareStatusReady; + + } + + // + // Set the pointer to the HardwareStatus variable + // + MoveSource = (PVOID)(&HardwareStatus); + + // + // Move the size of hardware status bytes + // + MoveBytes = sizeof(NDIS_HARDWARE_STATUS); + + break; + + // + // Simply indicate that we support TokenRing. + // + case OID_GEN_MEDIA_SUPPORTED: + case OID_GEN_MEDIA_IN_USE: + + MoveSource = (PVOID) (&Medium); + MoveBytes = sizeof(NDIS_MEDIUM); + break; + + // + // The maximum lookahead, current lookahead, and frame size are + // static and are equal to the maximum frame size minus the header + // size. + // + case OID_GEN_MAXIMUM_LOOKAHEAD: + case OID_GEN_CURRENT_LOOKAHEAD: + + GenericUlong = Adapter->ReceiveBufferSize - TOK162_HEADER_SIZE; + break; + + case OID_GEN_MAXIMUM_FRAME_SIZE: + + GenericUlong = Adapter->ReceiveBufferSize - 14; + break; + + // + // Total sizes are easier because we don't have to subtract out the + // header size. + // + case OID_GEN_MAXIMUM_TOTAL_SIZE: + case OID_GEN_TRANSMIT_BLOCK_SIZE: + case OID_GEN_RECEIVE_BLOCK_SIZE: + GenericUlong = Adapter->ReceiveBufferSize; + break; + + + // + // Link speed is either 4MBPS or 16MBPS depending on which we're + // running on. + // + case OID_GEN_LINK_SPEED: + + GenericUlong = (Adapter->Running16Mbps == TRUE) ? (ULONG)160000 : + (ULONG)40000; + + break; + + + // + // Transmit buffer space is found by multiplying the size of the + // transmit buffers (same as receive buffer size) by the number + // of transmit lists. + // + case OID_GEN_TRANSMIT_BUFFER_SPACE: + + GenericUlong = (ULONG)Adapter->ReceiveBufferSize * + Adapter->NumberOfTransmitLists; + + break; + + // + // Receive buffer space is equal to multiplying the size of receive + // buffers by the number of receive lists. + // + case OID_GEN_RECEIVE_BUFFER_SPACE: + + GenericUlong = (ULONG)Adapter->ReceiveBufferSize * + RECEIVE_LIST_COUNT; + + break; + + + // + // The vendor ID is calculated by ANDing the current network address + // with 0xFFFFFF00. + // + case OID_GEN_VENDOR_ID: + + // + // Get the current network address. + // + GenericUlong = 0; + NdisMoveMemory( + (PVOID)&GenericUlong, + Adapter->CurrentAddress, + 3 + ); + GenericUlong &= 0xFFFFFF00; + + MoveSource = (PVOID)(&GenericUlong); + + MoveBytes = sizeof(GenericUlong); + + break; + + // + // Return our vendor string + // + case OID_GEN_VENDOR_DESCRIPTION: + + MoveSource = (PVOID)"IBM TokenRing 16/4 II Adapter "; + + MoveBytes = 30; + + break; + + // + // Return our version (3.10) number + // + case OID_GEN_DRIVER_VERSION: + + GenericUShort = (USHORT)0x0300; + + MoveSource = (PVOID)(&GenericUShort); + + MoveBytes = sizeof(GenericUShort); + + break; + + // + // Return the permanent address + // + case OID_802_5_PERMANENT_ADDRESS: + + TR_COPY_NETWORK_ADDRESS( + (PCHAR)GenericArray, + Adapter->NetworkAddress + ); + + MoveSource = (PVOID)(GenericArray); + + MoveBytes = TR_LENGTH_OF_ADDRESS; + + break; + + // + // Return the current address. + // + case OID_802_5_CURRENT_ADDRESS: + + TR_COPY_NETWORK_ADDRESS( + (PCHAR)GenericArray, + Adapter->CurrentAddress + ); + + MoveSource = (PVOID)(GenericArray); + + MoveBytes = TR_LENGTH_OF_ADDRESS; + + break; + + // + // Return the current functional address. + // + case OID_802_5_CURRENT_FUNCTIONAL: + + // + // Get the address stored in the adapter structure + // + GenericUlong = (ULONG)Adapter->FunctionalAddress; + + // + // Now we need to reverse the crazy thing. + // + GenericUlong = BYTE_SWAP_ULONG(GenericUlong); + + break; + + // + // Return the current group address. + // + case OID_802_5_CURRENT_GROUP: + + // + // Get the address stored in the adapter structure + // + GenericUlong = (ULONG)Adapter->GroupAddress; + + // + // Now we need to reverse the crazy thing. + // + GenericUlong = BYTE_SWAP_ULONG(GenericUlong); + + break; + + // + // Return the number of good transmits + // + case OID_GEN_XMIT_OK: + + GenericUlong = (ULONG) Adapter->GoodTransmits; + + break; + + // + // Return the number of good receives + // + case OID_GEN_RCV_OK: + + GenericUlong = (ULONG) Adapter->GoodReceives; + + break; + + // + // Return the number of transmit errors + // + case OID_GEN_XMIT_ERROR: + + GenericUlong = (ULONG) Adapter->BadTransmits; + + break; + + // + // Return the number of receive errors + // + case OID_GEN_RCV_ERROR: + + GenericUlong = (ULONG) 0; + + break; + + // + // Return the number of congestion errors that have occurred + // + case OID_GEN_RCV_NO_BUFFER: + + GenericUlong = (ULONG) Adapter->ReceiveCongestionError; + + break; + + // + // Return the number of CRC errors (receives) + // + case OID_GEN_RCV_CRC_ERROR: + + GenericUlong = (ULONG) 0; + + break; + + // + // Return the current transmit queue length + // + case OID_GEN_TRANSMIT_QUEUE_LENGTH: + + GenericUlong = (ULONG) Adapter->TransmitsQueued; + + break; + + // + // Return the number of Line errors + // + case OID_802_5_LINE_ERRORS: + + GenericUlong = (ULONG) Adapter->LineError; + + break; + + // + // Return the last ring status. + // + case OID_802_5_CURRENT_RING_STATUS: + + GenericUlong = (ULONG)Adapter->LastNotifyStatus; + + break; + + // + // Return the current ring state. + // + case OID_802_5_CURRENT_RING_STATE: + + GenericUlong = (ULONG)Adapter->CurrentRingState; + + break; + + // + // Last open error code. + // + case OID_802_5_LAST_OPEN_STATUS: + + GenericUlong = (ULONG)(NDIS_STATUS_TOKEN_RING_OPEN_ERROR | + (NDIS_STATUS)Adapter->OpenErrorCode); + + break; + + // + // Return the number of Lost Frames + // + case OID_802_5_LOST_FRAMES: + + GenericUlong = (ULONG) Adapter->LostFrameError; + + break; + + // + // Return the number of Burst errors + // + case OID_802_5_BURST_ERRORS: + + GenericUlong = (ULONG) Adapter->BurstError; + + break; + + // + // Return the number of Frame Copied Errors + // + case OID_802_5_FRAME_COPIED_ERRORS: + + GenericUlong = (ULONG) Adapter->FrameCopiedError; + + break; + + // + // Return the number of Token errors + // + case OID_802_5_TOKEN_ERRORS: + + GenericUlong = (ULONG) Adapter->TokenError; + + break; + // + // Must be an unsupported Oid + // + default: + + Status = NDIS_STATUS_INVALID_OID; + + break; + } + + + // + // If there weren't any errors, copy the bytes indicated above. + // + if (Status == NDIS_STATUS_SUCCESS) { + + // + // Make sure we don't have too much to move. If so, return an error. + // + if (MoveBytes > InformationBufferLength) { + + // + // Not enough room in InformationBuffer. Punt + // + + *BytesNeeded = MoveBytes; + + Status = NDIS_STATUS_INVALID_LENGTH; + + // + // Do the copy + // + } else { + + *BytesWritten = MoveBytes; + + if (MoveBytes > 0) { + + NdisMoveMemory( + InformationBuffer, + MoveSource, + MoveBytes + ); + } + } + } + + // + // We're finished with the request. + // + Adapter->RequestInProgress = FALSE; + + // + // Indicate the result to the protocol(s) + // + NdisMQueryInformationComplete( + Adapter->MiniportAdapterHandle, + Status + ); + + return; +} + + +NDIS_STATUS +TOK162ChangeFuncGroup( + IN PTOK162_ADAPTER Adapter +) +/*++ + +Routine Description: + + The TOK162ChangeFuncGroup modifies the appropriate adapter + address (functional, group, or both). This routine submits two command + blocks representing one call to the system. Therefore, only the group + address change performs a status indication (the Set variable). + +Arguments: + + Adapter - a pointer to the adapter. + +Return Value: + + The function value is the status of the operation. + +--*/ + +{ + // + // Address to be set. Used for both functional and group addresses. + // + ULONG Address; + + // + // Variable to hold the return value of NDIS calls + // + NDIS_STATUS Status; + + // + // First check the functional address status, including the all + // functional address. + // + if ((Adapter->CurrentPacketFilter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL) != 0) { + + Address = 0x7FFFFFFF; + + } else if ((Adapter->CurrentPacketFilter & NDIS_PACKET_TYPE_FUNCTIONAL) != 0) { + + Address = Adapter->FunctionalAddress; + + } else { + + Address = 0; + + } + + // + // Change the functional address on the card. + // + Status = TOK162ChangeAddress( + Adapter, + Address, + OID_802_5_CURRENT_FUNCTIONAL, + CMD_DMA_SET_FUNC_ADDR, + FALSE + ); + + // + // Now check the group address status + // + if ((Adapter->CurrentPacketFilter & NDIS_PACKET_TYPE_GROUP) != 0) { + + Address = Adapter->GroupAddress; + + } else { + + Address = 0; + + } + + // + // Change the group address on the card. + // + Status = TOK162ChangeAddress( + Adapter, + Address, + OID_802_5_CURRENT_GROUP, + CMD_DMA_SET_GRP_ADDR, + TRUE + ); + + return(Status); +} diff --git a/private/ntos/ndis/ibmtok2i/reset.c b/private/ntos/ndis/ibmtok2i/reset.c new file mode 100644 index 000000000..ca967de06 --- /dev/null +++ b/private/ntos/ndis/ibmtok2i/reset.c @@ -0,0 +1,1918 @@ +/*++ + +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 + ); + + } + + } +} diff --git a/private/ntos/ndis/ibmtok2i/send.c b/private/ntos/ndis/ibmtok2i/send.c new file mode 100644 index 000000000..d360bc596 --- /dev/null +++ b/private/ntos/ndis/ibmtok2i/send.c @@ -0,0 +1,706 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + send.c + +Abstract: + + This file contains the code for putting a packet through the + staged allocation for transmission. + +Author: + + Kevin Martin(KevinMa) 20-Dec-1993 + +Environment: + + Kernel Mode - Or whatever is the equivalent on OS/2 and DOS. + +Revision History: + + +--*/ + +#include <tok162sw.h> + + +NDIS_STATUS +TOK162ConstrainPacket( + IN PTOK162_ADAPTER Adapter, + IN PNDIS_PACKET Packet, + OUT PTOK162_SUPER_COMMAND_BLOCK CommandBlock + ); + +NDIS_STATUS +TOK162TransmitPacket( + IN PTOK162_ADAPTER Adapter, + PNDIS_PACKET FirstPacket + ); + +#if DBG +VOID +PrintTransmitEntry( + IN PTOK162_SUPER_COMMAND_BLOCK TransmitBlock + ); +#endif + +NDIS_STATUS +TOK162Send( + IN NDIS_HANDLE MiniportAdapterContext, + IN PNDIS_PACKET Packet, + IN UINT Flags + ) + +/*++ + +Routine Description: + + The TOK162Send request instructs a Miniport to transmit a packet through + the adapter onto the medium. + +Arguments: + + MiniportAdapterContext - The context value returned by the Miniport when + the adapter was initialized. In reality, it is + a pointer to TOK162_ADAPTER. + + Packet - A pointer to a descriptor for the packet that is + to be transmitted. + +Return Value: + + The function value is the status of the operation. + +--*/ + +{ + // + // Pointer to the adapter. + // + PTOK162_ADAPTER Adapter = + PTOK162_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext); + + // + // Status returned from TOK162TransmitPacket. + // + NDIS_STATUS Status; + + // + // Points to the MAC reserved portion of this packet. This + // interpretation of the reserved section is only valid during + // the allocation phase of the packet. + // + PTOK162_RESERVED Reserved = PTOK162_RESERVED_FROM_PACKET(Packet); + + // + // The number of ndis buffers in the packet. + // + UINT NdisBufferCount; + + // + // The number of physical buffers in the entire packet. + // + UINT PhysicalBufferCount; + + // + // The total amount of data contained within the ndis packet. + // + UINT TotalVirtualLength; + + // + // Log the fact that we are entering TOK162Send. + // + IF_LOG('s'); + + ASSERT(sizeof(TOK162_RESERVED) <= sizeof(Packet->MiniportReserved)); + + // + // If we are in the middle of a reset, return this fact + // + if (Adapter->ResetInProgress == TRUE) { + + return(NDIS_STATUS_RESET_IN_PROGRESS); + + } + + // + // Determine if and how much adapter space would need to be allocated + // to meet hardware constraints. + // + NdisQueryPacket( + Packet, + &PhysicalBufferCount, + &NdisBufferCount, + NULL, + &TotalVirtualLength + ); + + // + // See if the packet exceeds TOK162_MAXIMUM_BLOCKS_PER_PACKET. + // Keep in mind that if the total virtual packet length is less than + // MINIMUM_TOKENRING_PACKET_SIZE then we'll have to chain on an + // additional buffer to pad the packet out to the minimum size. + // + if ((PhysicalBufferCount > Adapter->TransmitThreshold) || + (TotalVirtualLength < MINIMUM_TOKENRING_PACKET_SIZE)) { + + Reserved->NdisBuffersToMove = NdisBufferCount; + + } else { + + Reserved->NdisBuffersToMove = 0; + } + + // + // See if we can send it now. + // + Status = TOK162TransmitPacket(Adapter, Packet); + + // + // Log the fact that we are leaving TOK162Send + // + IF_LOG('S'); + + return Status; +} + + +NDIS_STATUS +TOK162TransmitPacket( + IN PTOK162_ADAPTER Adapter, + PNDIS_PACKET FirstPacket + ) + +/*++ + +Routine Description: + + This routine attempts to take a packet through a stage of allocation. + +Arguments: + + Adapter - The adapter that the packets are coming through. + + FirstPacket - Packet to be sent. + +Return Value: + + NDIS_STATUS_RESOURCES - if there are not enough resources + NDIS_STATUS_PENDING - if sending. + +--*/ + +{ + // + // Status + // + NDIS_STATUS Status; + + // + // If we successfully acquire a command block, this + // is a pointer to it. + // + PTOK162_SUPER_COMMAND_BLOCK CommandBlock; + + // + // Points to the reserved portion of the packet. + // + PTOK162_RESERVED Reserved = PTOK162_RESERVED_FROM_PACKET(FirstPacket); + + // + // Pointer to the TOK162 data block descriptor being filled. + // + UNALIGNED PTOK162_DATA_BLOCK DataBlock; + + // + // The total amount of data in the ndis packet. + // + UINT TotalDataLength; + + // + // The number of ndis buffers in the packet. + // + UINT NdisBufferCount; + + // + // Points to the current ndis buffer being walked. + // + PNDIS_BUFFER CurrentBuffer; + + + // + // Log the fact we are in TOK162TransmitPacket. + // + IF_LOG('t'); + + // + // See if there is a free transmit block + // + if (TOK162AcquireTransmitBlock( + Adapter, + &CommandBlock + )) { + + // We have a command block. + // Initialize the general fields of the Command Block. + // + CommandBlock->OwningPacket = FirstPacket; + CommandBlock->NextCommand = NULL; + CommandBlock->Hardware.Status = 0; + CommandBlock->Hardware.NextPending = TOK162_NULL; + CommandBlock->Hardware.CommandCode = CMD_DMA_XMIT; + + // + // Check to see if we need to constrain the packet + // + if (PTOK162_RESERVED_FROM_PACKET( + FirstPacket)->NdisBuffersToMove != 0) { + + // + // Now we merge the packet into a buffer + // + Status = TOK162ConstrainPacket(Adapter, + FirstPacket, + CommandBlock + ); + + // + // Otherwise, we will use the map registers and send the packet out + // as is. + // + } else { + + // + // Array to hold the physical segments + // + NDIS_PHYSICAL_ADDRESS_UNIT PhysicalSegmentArray[TOK162_MAX_SG]; + + // + // Number of physical segments in the buffer + // + UINT BufferPhysicalSegments; + + // + // map register to use for this buffer + // + UINT CurMapRegister; + + // + // Iteration variable + // + UINT i; + + // + // Assume we will be successful + // + Status = NDIS_STATUS_SUCCESS; + + // + // Get the first buffer as well as the number of ndis buffers in + // the packet. + // + NdisQueryPacket( + FirstPacket, + NULL, + &NdisBufferCount, + &CurrentBuffer, + &TotalDataLength + ); + + // + // Each packet is sent out complete and is not chained. + // + CommandBlock->Hardware.TransmitEntry.ForwardPointer = 0xFFFFFFFF; + + // + // Let the card know this buffer is ready to send. + // + CommandBlock->Hardware.TransmitEntry.CSTAT = + TRANSMIT_CSTAT_REQUEST; + + // + // We didn't have to constrain. + // + CommandBlock->UsedTOK162Buffer = FALSE; + + // + // Store the frame size. + // + CommandBlock->Hardware.TransmitEntry.FrameSize = + BYTE_SWAP((USHORT)TotalDataLength); + + // + // Get the first map register to use + // + CurMapRegister = CommandBlock->CommandBlockIndex * + Adapter->TransmitThreshold; + + // + // Go through all of the buffers in the packet getting + // the actual physical buffers from each MDL. + // + DataBlock = (UNALIGNED PTOK162_DATA_BLOCK) + &(CommandBlock->Hardware.TransmitEntry.DataCount1); + + while (CurrentBuffer != NULL) { + + NdisMStartBufferPhysicalMapping( + Adapter->MiniportAdapterHandle, + CurrentBuffer, + CurMapRegister, + TRUE, + PhysicalSegmentArray, + &BufferPhysicalSegments + ); + + CurMapRegister++; + + // + // Store segments into command block + // + for (i = 0; i < BufferPhysicalSegments ; i++) { + DataBlock->Size = + BYTE_SWAP((USHORT)PhysicalSegmentArray[i].Length + 0x8000); + + DataBlock->IBMPhysicalAddress = BYTE_SWAP_ULONG( + NdisGetPhysicalAddressLow(PhysicalSegmentArray[i].PhysicalAddress)); + + LOUD_DEBUG(DbgPrint("Address set is %08x\n",DataBlock->IBMPhysicalAddress);) + + DataBlock++; + } + + // + // Make sure the buffer, if cached, is updated in memory + // + NdisFlushBuffer(CurrentBuffer, TRUE); + + // + // Get the next buffer + // + NdisGetNextBuffer( + CurrentBuffer, + &CurrentBuffer + ); + + + } + + // + // We'll be one past the last entry, so move back + // + DataBlock--; + + // + // Strip off the high bit (already byte_swapped) to let the card + // know this is the last entry. + // + DataBlock->Size &= 0xFF7F; + } + + if (Status == NDIS_STATUS_SUCCESS) { + + // + // Indicate that we have one more transmit queued + // + Adapter->TransmitsQueued++; + + // + // Display the send structure on the debugger + // + EXTRA_LOUD_DEBUG(PrintTransmitEntry(CommandBlock);) + + // + // Submit the transmit block to be sent out + // + TOK162SubmitTransmitBlock( + Adapter, + CommandBlock + ); + + } else { + + // + // Log the fact that we have an unsuccessful transmit setup + // and return the error code. + // + IF_LOG('U'); + return(Status); + + } + + // + // No transmit block was available. + // + } else { + + // + // Log the fact that we couldn't get a transmit block and return + // RESOURCES error. + // + IF_LOG('u'); + return(NDIS_STATUS_RESOURCES); + + } + + // + // Log that we are leaving TOK162TransmitPacket + // + IF_LOG('T'); + LOUD_DEBUG(DbgPrint("Transmit is now set to pending\n");) + + // + // Indicate the send has pended. + // + return(NDIS_STATUS_PENDING); + +} + +NDIS_STATUS +TOK162ConstrainPacket( + IN PTOK162_ADAPTER Adapter, + IN PNDIS_PACKET Packet, + OUT PTOK162_SUPER_COMMAND_BLOCK CommandBlock + ) + +/*++ + +Routine Description: + + Given a packet and if necessary attempt to acquire adapter + buffer resources so that the packet meets TOK162 hardware/MAC.BIN + contraints. + +Arguments: + + Adapter - The adapter the packet is coming through. + + Packet - The packet whose buffers are to be constrained. + The packet reserved section is filled with information + detailing how the packet needs to be adjusted. + + CommandBlock - Command block describing the packet to be sent. + +Return Value: + + Status - SUCCESS. + +--*/ + +{ + + // + // Pointer to the reserved section of the packet to be contrained. + // + PTOK162_RESERVED Reserved = PTOK162_RESERVED_FROM_PACKET(Packet); + + // + // Will point into the virtual address space addressed + // by the adapter buffer if one was successfully allocated. + // + PCHAR CurrentDestination; + + // + // Will hold the total amount of data copied to the + // adapter buffer. + // + UINT TotalDataMoved = 0; + + // + // Will point to the current source buffer. + // + PNDIS_BUFFER SourceBuffer; + + // + // Points to the virtual address of the source buffers data. + // + PVOID SourceData; + + // + // Will point to the number of bytes of data in the source + // buffer. + // + UINT SourceLength; + + // + // The total amount of data contained within the ndis packet. + // + UINT TotalVirtualLength; + + // + // Simple iteration variable. + // + INT i; + + // + // Log that we entered TOK162ConstrainPacket + // + IF_LOG('v'); + + // + // Indicate that we are using this buffer + // + CommandBlock->UsedTOK162Buffer = TRUE; + + // + // Get info on the data to be transmitted. + // + NdisQueryPacket( + Packet, + NULL, + NULL, + &SourceBuffer, + &TotalVirtualLength + ); + + NdisQueryBuffer( + SourceBuffer, + &SourceData, + &SourceLength + ); + + // + // There is no link to this transmit list, and + // this list is ready to send. + // + CommandBlock->Hardware.TransmitEntry.ForwardPointer = 0xFFFFFFFF; + CommandBlock->Hardware.TransmitEntry.CSTAT = TRANSMIT_CSTAT_REQUEST; + + // + // Set frame size to total virtual length of the packet. + // + CommandBlock->Hardware.TransmitEntry.FrameSize = + BYTE_SWAP(TotalVirtualLength); + + // + // Set data count to frame size + // + CommandBlock->Hardware.TransmitEntry.DataCount1 = + CommandBlock->Hardware.TransmitEntry.FrameSize; + + // + // Set the address to the buffer associated with this transmit block + // + CommandBlock->Hardware.TransmitEntry.PhysicalAddress1=BYTE_SWAP_ULONG( + NdisGetPhysicalAddressLow(CommandBlock->TOK162BufferPhysicalAddress)); + + // + // Make sure count fields for the second and third entries are 0. + // + CommandBlock->Hardware.TransmitEntry.DataCount2 = 0x00000000; + CommandBlock->Hardware.TransmitEntry.DataCount3 = 0x00000000; + + // + // Fill in the buffer with the data from the users buffers. + // + CurrentDestination = (PVOID)CommandBlock->TOK162BufferAddress; + + for ( + i = Reserved->NdisBuffersToMove; + i; + i-- + ) { + + NdisMoveMemory( + CurrentDestination, + SourceData, + SourceLength + ); + + CurrentDestination = (PCHAR)CurrentDestination + SourceLength; + + TotalDataMoved += SourceLength; + + if (i > 1) { + + NdisGetNextBuffer( + SourceBuffer, + &SourceBuffer + ); + + NdisQueryBuffer( + SourceBuffer, + &SourceData, + &SourceLength + ); + + } + + } + + // + // If the packet is less than the minimum TokenRing + // packet size, then clear the remaining part of + // the buffer up to the minimum packet size. + // + if (TotalVirtualLength < MINIMUM_TOKENRING_PACKET_SIZE) { + + NdisZeroMemory( + CurrentDestination, + MINIMUM_TOKENRING_PACKET_SIZE - TotalVirtualLength + ); + + } + + + // + // Make sure the card and the system are in sync. + // + // The following was removed on 1/26/95 because it causes a hang + // on MIPs machines. + // + // NdisFlushBuffer(CommandBlock->FlushBuffer,TRUE); + + // + // Log that we are leaving TOK162ConstrainPacket + // + IF_LOG('V'); + + return(NDIS_STATUS_SUCCESS); +} + +#if DBG +VOID +PrintTransmitEntry( + IN PTOK162_SUPER_COMMAND_BLOCK TransmitBlock + ) +/*++ + +Routine Description: + + This routine displays a transmit list on the debug screen + +Arguments: + + CommandBlock - Pointer to the command block with the transmit list + +Return Value: + + None. +--*/ + +{ + + // + // Pointer to the transmit list portion of the transmit block. + // + TOK162_TRANSMIT_LIST Transmit = TransmitBlock->Hardware.TransmitEntry; + + // + // Display all of the information about the send on the debugger. + // + DbgPrint("Forward Pointer = %08lx\n",Transmit.ForwardPointer); + DbgPrint("CSTAT = %x\n" ,Transmit.CSTAT); + DbgPrint("Frame Size = %04x\n" ,Transmit.FrameSize); + DbgPrint("DataCount1 = %04x\n" ,Transmit.DataCount1); + DbgPrint("DataAddress1 = %08lx\n",Transmit.PhysicalAddress1); + DbgPrint("DataCount2 = %04x\n" ,Transmit.DataCount2); + DbgPrint("DataAddress2 = %08lx\n",Transmit.PhysicalAddress2); + DbgPrint("DataCount3 = %04x\n" ,Transmit.DataCount3); + DbgPrint("DataAddress3 = %08lx\n",Transmit.PhysicalAddress3); + +} +#endif diff --git a/private/ntos/ndis/ibmtok2i/sources b/private/ntos/ndis/ibmtok2i/sources new file mode 100644 index 000000000..9e402e3a4 --- /dev/null +++ b/private/ntos/ndis/ibmtok2i/sources @@ -0,0 +1,48 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=ntos +MINORCOMP=ndis + +TARGETNAME=ibmtok2i +TARGETPATH=\nt\public\sdk\lib +TARGETTYPE=DRIVER + +TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\ndis.lib + +C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER + +INCLUDES=inc;..\..\inc;..\..\..\inc + +SOURCES=command.c \ + interrup.c \ + tok162.c \ + request.c \ + reset.c \ + send.c \ + tok162.rc + +RELATIVE_DEPTH=..\.. + +MSC_WARNING_LEVEL=/W3 /WX diff --git a/private/ntos/ndis/ibmtok2i/tok162.c b/private/ntos/ndis/ibmtok2i/tok162.c new file mode 100644 index 000000000..dce952707 --- /dev/null +++ b/private/ntos/ndis/ibmtok2i/tok162.c @@ -0,0 +1,2504 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + TOK162.c + +Abstract: + + This is the main file for the IBM Token-Ring 16/4 Adapter II. + This driver conforms to the NDIS 3.0 Miniport interface. + +Author: + + Kevin Martin (KevinMa) 27-Jan-1994 + +Environment: + + Kernel Mode. + +Revision History: + +--*/ + + +#include <TOK162sw.h> + +#pragma NDIS_INIT_FUNCTION(TOK162Initialize) + +// +// If debug messages and logging is wanted, set the DBG environment variable. +// +#if DBG + +// +// Variable which indicates the level of debugging messages. Values are +// defined below. +// +UCHAR Tok162Debug = 0; + +// +// Pointer to the logging table. The table is allocated when the adapter +// memory is allocated. +// +PUCHAR Tok162Log; + +// +// Index pointer for the logging macro. +// +USHORT Tok162LogPlace = 0; + +#endif + +// +// Function declarations for functions private to this file. +// +BOOLEAN +TOK162AllocateAdapterMemory( + IN PTOK162_ADAPTER Adapter + ); + + +NTSTATUS +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ) +/*++ + +Routine Description: + + This is the primary initialization routine for the TOK162 driver. + It is simply responsible for the intializing the wrapper and registering + the MAC. It then calls a system and architecture specific routine that + will initialize and register each adapter. + +Arguments: + + DriverObject - Pointer to driver object created by the system. + +Return Value: + + The status of the operation. + +--*/ + +{ + // + // Receives the status of the NdisMRegisterMiniport operation. + // + NDIS_STATUS Status; + + // + // Handle for our driver given to us by the wrapper. + // + NDIS_HANDLE NdisWrapperHandle; + + // + // Miniport driver characteristics + // + char Tmp[sizeof(NDIS_MINIPORT_CHARACTERISTICS)]; + + PNDIS_MINIPORT_CHARACTERISTICS TOK162Char = + (PNDIS_MINIPORT_CHARACTERISTICS)(PVOID)Tmp; + + // + // Initialize the wrapper. + // + NdisMInitializeWrapper( + &NdisWrapperHandle, + DriverObject, + RegistryPath, + NULL + ); + + // + // Initialize the Miniport characteristics for the call to + // NdisRegisterMac. + // + TOK162Char->MajorNdisVersion = TOK162_NDIS_MAJOR_VERSION; + TOK162Char->MinorNdisVersion = TOK162_NDIS_MINOR_VERSION; + + // + // Define the entry points into this driver for the wrapper. + // + TOK162Char->CheckForHangHandler = TOK162CheckForHang; + TOK162Char->DisableInterruptHandler = TOK162DisableInterrupt; + TOK162Char->EnableInterruptHandler = TOK162EnableInterrupt; + TOK162Char->HaltHandler = TOK162Halt; + TOK162Char->HandleInterruptHandler = TOK162HandleInterrupt; + TOK162Char->InitializeHandler = TOK162Initialize; + TOK162Char->ISRHandler = TOK162Isr; + TOK162Char->QueryInformationHandler = TOK162QueryInformation; + + // + // We don't support reconfigure so we pass a null. + // + TOK162Char->ReconfigureHandler = NULL; + TOK162Char->ResetHandler = TOK162Reset; + TOK162Char->SendHandler = TOK162Send; + TOK162Char->SetInformationHandler = TOK162SetInformation; + TOK162Char->TransferDataHandler = TOK162TransferData; + + // + // Register the driver. + // + Status = NdisMRegisterMiniport( + NdisWrapperHandle, + TOK162Char, + sizeof(*TOK162Char) + ); + + // + // If everything went ok, return STATUS_SUCCESS + // + if (Status == NDIS_STATUS_SUCCESS) { + + return STATUS_SUCCESS; + + } + + // + // We can only get here if something went wrong with registering + // the miniport or *all* of the adapters. + // + NdisTerminateWrapper(NdisWrapperHandle, NULL); + return STATUS_UNSUCCESSFUL; + +} + + +NDIS_STATUS +TOK162RegisterAdapter( + IN NDIS_HANDLE ConfigurationHandle, + IN NDIS_HANDLE MiniportAdapterHandle, + IN PUCHAR CurrentAddress, + IN UINT PortAddress, + IN ULONG MaxFrameSize + ) + +/*++ + +Routine Description: + + This routine (and its interface) are not portable. They are + defined by the OS, the architecture, and the particular TOK162 + implementation. + + This routine is responsible for the allocation of the datastructures + for the driver as well as any hardware specific details necessary + to talk with the device. + +Arguments: + + ConfigurationHandle - Handle passed to NdisRegisterAdapter. + MiniportAdapterHandle - Handle received from + CurrentAddress - The network address found in the registry + PortAddress - The starting i/o port address found in the + registry + +Return Value: + + Returns NDIS_STATUS_SUCCESS if everything goes ok, else + if anything occurred that prevents the initialization + of the adapter it returns an appropriate NDIS error. + +--*/ + +{ + + // + // Holds the value returned by NDIS calls. + // + NDIS_STATUS Status; + + // + // Holds information needed when registering the adapter. + // + PTOK162_ADAPTER Adapter; + + // We put in this assertion to make sure that ushort are 2 bytes. + // if they aren't then the initialization block definition needs + // to be changed. + // + ASSERT(sizeof(TOK162_PHYSICAL_ADDRESS) == 4); + + // + // Allocate the Adapter memory + // + TOK162_ALLOC_PHYS(&Status, &Adapter, sizeof(TOK162_ADAPTER)); + + // + // If everything went ok (Status == NDIS_STATUS_SUCCESS), zero the + // memory, and then assign values that we know to the adapter structure. + // + if (Status != NDIS_STATUS_SUCCESS) { + + // + // The allocation didn't work, so return an error indicating resource + // problems. + // + return NDIS_STATUS_RESOURCES; + } + + NdisZeroMemory( + Adapter, + sizeof(TOK162_ADAPTER) + ); + + // + // Assign the handle and io port address base + // + Adapter->MiniportAdapterHandle = MiniportAdapterHandle; + Adapter->PortIOBase = PortAddress; + + // + // Set the receive, transmit, and command buffer and block + // information. + // + Adapter->NumberOfReceiveBuffers = RECEIVE_LIST_COUNT; + Adapter->NumberOfTransmitLists = TRANSMIT_LIST_COUNT; + + Adapter->NumberOfAvailableCommandBlocks = + TOK162_NUMBER_OF_CMD_BLOCKS; + + // + // Set the address the adapter should enter the ring with. + // + NdisMoveMemory( + Adapter->CurrentAddress, + CurrentAddress, + TOK162_LENGTH_OF_ADDRESS + ); + + // + // Notify the wrapper of our attributes + // + NdisMSetAttributes( + MiniportAdapterHandle, + (NDIS_HANDLE)Adapter, + TRUE, + NdisInterfaceIsa + ); + + // + // Register our shutdown handler. + // + + NdisMRegisterAdapterShutdownHandler( + Adapter->MiniportAdapterHandle, // miniport handle. + Adapter, // shutdown context. + TOK162Shutdown // shutdown handler. + ); + + // + // Register our port usage + // + Status = NdisMRegisterIoPortRange( + (PVOID *)(&(Adapter->PortIOAddress)), + MiniportAdapterHandle, + Adapter->PortIOBase, + 0x10 + ); + + // + // If there was a problem with the registration, free the memory + // associated with the adapter and return resource error + // + if (Status != NDIS_STATUS_SUCCESS) { + + goto Error1Exit; + + } + + // + // Obtain all of the other adapter parameters + // + Status = TOK162GetAdapterConfiguration(Adapter); + + if (Status != NDIS_STATUS_SUCCESS) { + + goto Error1Exit; + + } + + if (MaxFrameSize != 0) { + + Adapter->ReceiveBufferSize = (USHORT)MaxFrameSize; + + } + + + // + // Allocate the map registers + // + Status = NdisMAllocateMapRegisters( + Adapter->MiniportAdapterHandle, + Adapter->ConfigurationBlock.DMAChannel, + FALSE, + Adapter->NumberOfTransmitLists * + Adapter->TransmitThreshold, + Adapter->ReceiveBufferSize + ); + + // + // If there were any problems, return resources error. + // + if (Status != NDIS_STATUS_SUCCESS) { + + goto Error2Exit; + + } + + // + // Allocate memory for all of the adapter structures + // + if (TOK162AllocateAdapterMemory(Adapter) == FALSE) { + + // + // We get here if the allocateadaptermemory call fails. All we + // can do is log the resource problem, display the fact that the + // register failed, and return resources. + // + + goto Error3Exit; + + } + + // + // The allocation succeeded. + // Reset the variables associated with the adapter + // + TOK162ResetVariables(Adapter); + + // + // Initialize deferred and reset timers + // + NdisMInitializeTimer( + &Adapter->DeferredTimer, + Adapter->MiniportAdapterHandle, + (PVOID) TOK162DeferredTimer, + (PVOID) Adapter + ); + + NdisMInitializeTimer( + &Adapter->ResetTimer, + Adapter->MiniportAdapterHandle, + (PVOID) TOK162ResetHandler, + (PVOID) Adapter + ); + + // + // Initialize the adapter + // + VERY_LOUD_DEBUG(DbgPrint("TOK162!Calling InitialInit\n");) + + if (TOK162InitialInit(Adapter) == FALSE) { + + // + // If there was an error (FALSE), write the log entry, and + // free up all of the resources. + // + NdisWriteErrorLogEntry( + MiniportAdapterHandle, + NDIS_ERROR_CODE_ADAPTER_NOT_FOUND, + 0 + ); + + // + // Return resources to the wrapper + // + if (Adapter->InterruptLevel != 0) { + + NdisMDeregisterInterrupt(&Adapter->Interrupt); + + } + + goto Error3Exit; + + } + + // + // Display success to the debugger. + // + VERY_LOUD_DEBUG(DbgPrint( + "TOK162!Returning TRUE from RegisterAdapter\n");) + + return NDIS_STATUS_SUCCESS; + +// +// Error3Exit level indicates that we need to deregister the map registers +// and deallocate the adapter-related allocated memory. +// +Error3Exit: + + NdisMFreeMapRegisters(Adapter->MiniportAdapterHandle); + TOK162DeleteAdapterMemory(Adapter); + +// +// Error2Exit level indicates that we need to deregister the IO Port Range. +// +Error2Exit: + + NdisMDeregisterIoPortRange(Adapter->MiniportAdapterHandle, + Adapter->PortIOBase, + 0x30, + Adapter->PortIOAddress + ); + + +// +// Error1Exit level indicates that we need to free the memory allocated +// for the adapter structure. Log that register adapter failed. +// +Error1Exit: + + NdisWriteErrorLogEntry( + MiniportAdapterHandle, + NDIS_ERROR_CODE_OUT_OF_RESOURCES, + 0 + ); + + VERY_LOUD_DEBUG(DbgPrint( + "TOK162!Returning FALSE from RegisterAdapter\n");) + + TOK162_FREE_PHYS(Adapter); + return NDIS_STATUS_RESOURCES; + +} + + +extern +NDIS_STATUS +TOK162GetAdapterConfiguration( + IN PTOK162_ADAPTER Adapter + ) +/*++ + +Routine Description: + + This routine obtains all of the settings from the adapter + +Arguments: + + Adapter - Current Adapter structure + +Return Value: + + NDIS_STATUS_SUCCESS if allocation of structure is successful. + NDIS_STATUS_RESOURCES if not. + +--*/ +{ + // + // Holds value of the switches registers + // + PADAPTERSWITCHES Switches; + + // + // Variable used to obtain the switches. + // + USHORT temp; + + // + // Read in the switches registers from the adapter + // + READ_ADAPTER_USHORT(Adapter, + PORT_OFFSET_SWITCH_INT_DISABLE, + &temp + ); + + Switches = (PADAPTERSWITCHES)&temp; + + // + // Display the value of the switches on the debugger. + // + VERY_LOUD_DEBUG(DbgPrint("TOK162!Switches are: %X\n",temp);) + + // + // Display the individual values of the switches. These values are + // the values of the switches, not actual values that the switches + // represent (i.e. - interrupt 9 will be seen as 00, the switch + // positions representing interrupt 9). + // + VERY_LOUD_DEBUG(DbgPrint( + "TOK162!Reserved - %x\n", Switches->Reserved);) + VERY_LOUD_DEBUG(DbgPrint( + "TOK162!Setting AdapterMode - %x\n", Switches->AdapterMode);) + VERY_LOUD_DEBUG(DbgPrint( + "TOK162!Setting Waitstate - %x\n", Switches->WaitState);) + VERY_LOUD_DEBUG(DbgPrint( + "TOK162!Setting RPL - %x\n", Switches->RPL);) + VERY_LOUD_DEBUG(DbgPrint( + "TOK162!Setting RPL/IO Address - %x\n",Switches->RPL_PIO_Address);) + VERY_LOUD_DEBUG(DbgPrint( + "TOK162!Setting RingSpeed - %02x\n", Switches->RingSpeed);) + VERY_LOUD_DEBUG(DbgPrint( + "TOK162!Setting UTP/STP - %x\n", Switches->UTP_STP);) + VERY_LOUD_DEBUG(DbgPrint( + "TOK162!Setting DMA - %u\n", Switches->DMA);) + VERY_LOUD_DEBUG(DbgPrint( + "TOK162!Setting Interrupt - %u\n", Switches->IntRequest);) + + // + // Get the adapter mode + // + if (Switches->AdapterMode == SW_ADAPTERMODE_NORMAL) { + + Adapter->ConfigurationBlock.AdapterMode = CFG_ADAPTERMODE_NORMAL; + + } else { + + Adapter->ConfigurationBlock.AdapterMode = CFG_ADAPTERMODE_TEST; + + } + + // + // Get the adatper wait state setting. + // + if (Switches->WaitState == SW_WAITSTATE_NORMAL) { + + Adapter->ConfigurationBlock.WaitState = CFG_WAITSTATE_NORMAL; + + } else { + + Adapter->ConfigurationBlock.WaitState = CFG_WAITSTATE_FAST; + + } + + // + // Check if Remote Program Load (RPL) is set. If it is, get the + // RPL Address. + // + if (Switches->RPL == SW_RPL_ENABLE) { + + Adapter->ConfigurationBlock.RPL = TRUE; + + switch(Switches->RPL_PIO_Address) { + + case SW_PIO_ADDR_8: + + Adapter->ConfigurationBlock.RPLAddress = CFG_RPLADDR_C0000; + break; + + case SW_PIO_ADDR_C: + + Adapter->ConfigurationBlock.RPLAddress = CFG_RPLADDR_C4000; + break; + + case SW_PIO_ADDR_A: + + Adapter->ConfigurationBlock.RPLAddress = CFG_RPLADDR_C8000; + break; + + case SW_PIO_ADDR_E: + + Adapter->ConfigurationBlock.RPLAddress = CFG_RPLADDR_CC000; + break; + + case SW_PIO_ADDR_9: + + Adapter->ConfigurationBlock.RPLAddress = CFG_RPLADDR_D0000; + break; + + case SW_PIO_ADDR_D: + + Adapter->ConfigurationBlock.RPLAddress = CFG_RPLADDR_D4000; + break; + + case SW_PIO_ADDR_B: + + Adapter->ConfigurationBlock.RPLAddress = CFG_RPLADDR_D8000; + break; + + case SW_PIO_ADDR_F: + + Adapter->ConfigurationBlock.RPLAddress = CFG_RPLADDR_DC000; + break; + + } + + } else { + + // + // RPL is not enabled. Record this fact and zero out the RPL address. + // + Adapter->ConfigurationBlock.RPL = FALSE; + Adapter->ConfigurationBlock.RPLAddress = 0x0000; + + } + + + // + // Get the ring speed. + // + if (Switches->RingSpeed == SW_RINGSPEED_4) { + + // + // If the adapter is running at 4MBPS, set the ring speed + // value, allow up to 3 scatter-gathers per transmit, and + // set the receive buffer size (the max for the ring at this + // speed). + // + Adapter->ConfigurationBlock.RingSpeed = CFG_RINGSPEED_4; + + Adapter->TransmitThreshold = 3; + + Adapter->Running16Mbps = FALSE; + + Adapter->ReceiveBufferSize = RECEIVE_LIST_BUFFER_SIZE_4; + + } else { + + // + // If the adapter is running at 16MBPS, set the ring speed + // value, allow up to 2 scatter-gathers per transmit, and + // set the receive buffer size (the max for the ring at this + // speed). + // + Adapter->ConfigurationBlock.RingSpeed = CFG_RINGSPEED_16; + + Adapter->TransmitThreshold = 1; + + Adapter->Running16Mbps = TRUE; + + Adapter->ReceiveBufferSize = RECEIVE_LIST_BUFFER_SIZE_16; + } + + + // + // Get the connector type + // + if (Switches->UTP_STP == SW_UTP) { + + Adapter->ConfigurationBlock.UTPorSTP = CFG_MEDIATYPE_UTP; + + } else { + + Adapter->ConfigurationBlock.UTPorSTP = CFG_MEDIATYPE_STP; + + } + + // + // Get the DMA channel in use. + // + switch(Switches->DMA) { + + case SW_DMA_5: + + Adapter->ConfigurationBlock.DMAChannel = CFG_DMACHANNEL_5; + break; + + case SW_DMA_6: + + Adapter->ConfigurationBlock.DMAChannel = CFG_DMACHANNEL_6; + break; + + case SW_DMA_7: + + Adapter->ConfigurationBlock.DMAChannel = CFG_DMACHANNEL_7; + break; + + } + + // + // Get the interrupt level. + // + switch(Switches->IntRequest) { + + case SW_INT_9: + + Adapter->InterruptLevel = CFG_INT_9; + break; + + case SW_INT_10: + + Adapter->InterruptLevel = CFG_INT_10; + break; + + case SW_INT_11: + + Adapter->InterruptLevel = CFG_INT_11; + break; + + case SW_INT_15: + + Adapter->InterruptLevel = CFG_INT_15; + break; + + } + + // + // Return that we succeeded. + // + return(NDIS_STATUS_SUCCESS); +} + + +extern +NDIS_STATUS +TOK162Initialize( + OUT PNDIS_STATUS OpenErrorStatus, + OUT PUINT SelectedMediumIndex, + IN PNDIS_MEDIUM MediumArray, + IN UINT MediumArraySize, + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE ConfigurationHandle + ) + +/*++ + +Routine Description: + + This routine is used to initialize each adapter card/chip. + +Arguments: + + OpenErrorStatus - Token Ring Adapter Open Status + SelectedMediumIndex - Medium used for transmission (Token Ring) + MediumArray - Array of mediums supported by wrapper + MiniportAdapterHandle - Adapter Handle + ConfigurationHandle - Configuration Handle + +Return Value: + + Result of registering this adapter. + +--*/ + +{ + // + // Handle returned by NdisOpenConfiguration + // + NDIS_HANDLE ConfigHandle; + + // + // Simple indexing variable + // + ULONG i; + + // + // Buffer to copy the passed in network address. + // + UCHAR NetworkAddress[TOK162_LENGTH_OF_ADDRESS]; + + // + // Receives address of the network address string in the registry + // + PVOID NetAddress; + + // + // Length of above network address string + // + ULONG Length; + + // + // Beginning port address for this adapter + // + ULONG PortAddress; + + // + // Variable holding value returned by NdisReadConfiguration + // + PNDIS_CONFIGURATION_PARAMETER ReturnedValue; + + // + // Description string constants found in registry + // + NDIS_STRING IOAddressStr = NDIS_STRING_CONST("IOBaseAddress"); + NDIS_STRING MaxFrameStr = NDIS_STRING_CONST("MAXFRAMESIZE"); + + // + // Return value from NDIS calls + // + NDIS_STATUS Status; + + // + // Value to be passed along as MaxFrameSize + // + ULONG MaxFrameSize; + + // + // Cache-Alignment variable + // + ULONG Alignment; + + // + // Search for the medium type (802.5) + // + for (i = 0; i < MediumArraySize; i++){ + + + if (MediumArray[i] == NdisMedium802_5){ + break; + + } + + } + + // + // See if Token Ring is supported by the wrapper + // + if (i == MediumArraySize) { + + return NDIS_STATUS_UNSUPPORTED_MEDIA; + + } + + // + // Tell wrapper the index in the medium array we're using + // + *SelectedMediumIndex = i; + + // + // Get access to the configuration information + // + NdisOpenConfiguration( + &Status, + &ConfigHandle, + ConfigurationHandle + ); + + // + // If there was an error, return with the error code. + // + if (Status != NDIS_STATUS_SUCCESS) { + + return Status; + + } + + // + // Read net address from the configuration info. + // + NdisReadNetworkAddress( + &Status, + &NetAddress, + &Length, + ConfigHandle + ); + + // + // Make sure the call worked and the address returned is of valid length + // + if ((Length == TOK162_LENGTH_OF_ADDRESS) && + (Status == NDIS_STATUS_SUCCESS)) { + + NdisMoveMemory( + NetworkAddress, + NetAddress, + TOK162_LENGTH_OF_ADDRESS + ); + + // + // If not, set the current address to all 0's, forcing the adapter + // to use the permanent address as the current address. + // + } else { + + NdisZeroMemory( + NetworkAddress, + TOK162_LENGTH_OF_ADDRESS + ); + + } + + // + // Get the port address from the configuration info. + // + NdisReadConfiguration( + &Status, + &ReturnedValue, + ConfigHandle, + &IOAddressStr, + NdisParameterHexInteger + ); + + PortAddress = ReturnedValue->ParameterData.IntegerData; + + // + // Get the max frame size if indicated by user + // + NdisReadConfiguration( + &Status, + &ReturnedValue, + ConfigHandle, + &MaxFrameStr, + NdisParameterInteger + ); + + if (Status == NDIS_STATUS_SUCCESS) { + + MaxFrameSize = (ULONG)(ReturnedValue->ParameterData.IntegerData); + + Alignment = NdisGetCacheFillSize(); + + if ( Alignment < sizeof(ULONG) ) { + + Alignment = sizeof(ULONG); + } + + MaxFrameSize = (MaxFrameSize + (Alignment - 1)) & ~(Alignment - 1); + + if ((MaxFrameSize > RECEIVE_LIST_BUFFER_SIZE_16) || + (MaxFrameSize < RECEIVE_LIST_BUFFER_SIZE_4)) { + + MaxFrameSize = 0; + + } + + } else { + + MaxFrameSize = 0; + + } + + // + // We're done with the configuration info. + // + NdisCloseConfiguration(ConfigHandle); + + // + // Go register this adapter. + // + Status = TOK162RegisterAdapter( + ConfigurationHandle, + MiniportAdapterHandle, + NetworkAddress, + PortAddress, + MaxFrameSize + ); + + // + // Return the value TOK162RegisterAdapter returned + // + return Status; + +} + + +BOOLEAN +TOK162AllocateAdapterMemory( + IN PTOK162_ADAPTER Adapter + ) +/*++ + +Routine Description: + + This routine allocates memory for: + + - SCB + + - SSB + + - ErrorLog Block + + - ReadAdapter Block + + - Initialization Block + + - Open Command Block + + - Command Queue + + - Transmit Command Queue + + - Transmit Buffers + + - Flush Buffer Pool + + - Receive Queue + + - Receive Buffers + + - Receive Flush Buffers + +Arguments: + + Adapter - The adapter to allocate memory for. + +Return Value: + + Returns FALSE if some memory needed for the adapter could not + be allocated. + +--*/ + +{ + // + // Pointer to a Super Receive List. Used while initializing + // the Receive Queue. + // + PTOK162_SUPER_RECEIVE_LIST CurrentReceiveEntry; + + // + // Pointer to a Command Block. Used while initializing + // the Command Queue. + // + PTOK162_SUPER_COMMAND_BLOCK CurrentCommandBlock; + + // + // Simple iteration variable. + // + UINT i; + + // + // Status of allocation + // + NDIS_STATUS Status; + +#if DBG + + // + // If debugging is specified, we need to allocate the trace log + // buffer. + // + + NDIS_PHYSICAL_ADDRESS ndp; + + NdisMAllocateSharedMemory( + Adapter->MiniportAdapterHandle, + LOG_SIZE, + FALSE, + (PVOID *)&Tok162Log, + &ndp); +#endif + // + // Allocate the SCB + // + + VERY_LOUD_DEBUG(DbgPrint("Allocating SCB\n");) + + NdisMAllocateSharedMemory( + Adapter->MiniportAdapterHandle, + sizeof(SCB) + 8, + FALSE, + (PVOID *) &Adapter->Scb, + &Adapter->ScbPhysical + ); + + VERY_LOUD_DEBUG(DbgPrint("Address of SCB is %lx\n",(ULONG)Adapter->Scb);) + + // + // If the Scb could not be allocated, a NULL pointer will have been + // returned. + // + if (Adapter->Scb == NULL) { + + return FALSE; + + } + + // + // Allocate the SSB + // + VERY_LOUD_DEBUG(DbgPrint("Allocating SSB\n");) + + NdisMAllocateSharedMemory( + Adapter->MiniportAdapterHandle, + sizeof(SSB) + 8, + FALSE, + (PVOID *) &Adapter->Ssb, + &Adapter->SsbPhysical + ); + + VERY_LOUD_DEBUG(DbgPrint("Address of SSB is %lx\n",(ULONG)Adapter->Ssb);) + + // + // If the Ssb could not be allocated, a NULL pointer will have been + // returned. + // + if (Adapter->Ssb == NULL) { + + return FALSE; + + } + + // + // Allocate the ErrorLog Block + // + VERY_LOUD_DEBUG(DbgPrint("Allocating ErrorLog Block\n");) + + NdisMAllocateSharedMemory( + Adapter->MiniportAdapterHandle, + sizeof(TOK162_ERRORLOG) + 8, + FALSE, + (PVOID *) &Adapter->ErrorLog, + &Adapter->ErrorLogPhysical + ); + + // + // If the ErrorLog could not be allocated, a NULL pointer will have been + // returned. + // + if (Adapter->ErrorLog == NULL) { + + return FALSE; + + } + + // + // Allocate the ReadAdapter Buffer + // + VERY_LOUD_DEBUG(DbgPrint("Allocating ReadAdapterBuffer\n");) + + NdisMAllocateSharedMemory( + Adapter->MiniportAdapterHandle, + 4096, + FALSE, + (PVOID *) &Adapter->AdapterBuf, + &Adapter->AdapterBufPhysical + ); + + VERY_LOUD_DEBUG(DbgPrint("Address of ReadAdapterBuf is %lx\n",(ULONG)Adapter->AdapterBuf);) + + // + // If the ReadAdapter Buffer could not be allocated, a NULL + // pointer will have been returned. + // + if (Adapter->AdapterBuf == NULL) { + + return FALSE; + + } + + // + // Allocate the Initialization Block + // + VERY_LOUD_DEBUG(DbgPrint("Allocating Initialization Block\n");) + + NdisMAllocateSharedMemory( + Adapter->MiniportAdapterHandle, + sizeof(ADAPTER_INITIALIZATION) + 8, + FALSE, + (PVOID *) &Adapter->InitializationBlock, + &Adapter->InitializationBlockPhysical + ); + + // + // If the Initialization Block could not be allocated, a NULL pointer + // will have been returned. + // + if (Adapter->InitializationBlock == NULL) { + + return FALSE; + + } + + // + // Allocate the Open Command Block + // + + VERY_LOUD_DEBUG(DbgPrint("Allocating Open Command\n");) + + NdisMAllocateSharedMemory( + Adapter->MiniportAdapterHandle, + sizeof(OPEN_COMMAND) + 8, + FALSE, + (PVOID *) &Adapter->Open, + &Adapter->OpenPhysical + ); + + VERY_LOUD_DEBUG(DbgPrint( + "Address of Open Command is %lx\n",(ULONG)Adapter->Open);) + + // + // If the Open Command Block could not be allocated, a NULL pointer + // will have been returned. + // + if (Adapter->Open == NULL) { + + return FALSE; + + } + + // + // Allocate the command block queue + // + VERY_LOUD_DEBUG(DbgPrint("Allocating Command Block Queue\n");) + + NdisMAllocateSharedMemory( + Adapter->MiniportAdapterHandle, + sizeof(TOK162_SUPER_COMMAND_BLOCK) * (TOK162_NUMBER_OF_CMD_BLOCKS+1), + FALSE, + (PVOID *) &Adapter->CommandQueue, + &Adapter->CommandQueuePhysical + ); + + // + // If the Command Block Queue could not be allocated, a NULL pointer + // will have been returned. + // + if (Adapter->CommandQueue == NULL) { + + return FALSE; + + } + + // + // Initialize the command block queue command blocks + // + for (i = 0, CurrentCommandBlock = Adapter->CommandQueue; + i < TOK162_NUMBER_OF_CMD_BLOCKS; + i++, CurrentCommandBlock++ + ) { + + // + // Set the state of this command block to free, the + // NextPending pointer and Next pointer to null, and + // the command timeout state to FALSE + // + CurrentCommandBlock->Hardware.State = TOK162_STATE_FREE; + CurrentCommandBlock->Hardware.NextPending = TOK162_NULL; + CurrentCommandBlock->NextCommand = NULL; + CurrentCommandBlock->Timeout = FALSE; + + // + // Set the Self pointer of the command block + // + NdisSetPhysicalAddressHigh (CurrentCommandBlock->Self, 0); + NdisSetPhysicalAddressLow( + CurrentCommandBlock->Self, + NdisGetPhysicalAddressLow(Adapter->CommandQueuePhysical) + + i * sizeof(TOK162_SUPER_COMMAND_BLOCK)); + + // + // This is a command block and not a transmit command block + // + CurrentCommandBlock->CommandBlock = TRUE; + + // + // Set the index of this command block + // + CurrentCommandBlock->CommandBlockIndex = (USHORT)i; + + } + + // + // Allocate Flush Buffer Pool + // + VERY_LOUD_DEBUG(DbgPrint("Allocating Flush Buffer Pool\n");) + + NdisAllocateBufferPool( + &Status, + (PVOID*)&Adapter->FlushBufferPoolHandle, + Adapter->NumberOfReceiveBuffers + Adapter->NumberOfTransmitLists + ); + + // + // If there was a problem allocating the flush buffer pool, + // write out an errorlog entry, delete the allocated adapter memory, + // and return FALSE + // + if (Status != NDIS_STATUS_SUCCESS) { + + return FALSE; + + } + + // + // Allocate the Transmit Command Queue. + // + VERY_LOUD_DEBUG(DbgPrint("Allocating Transmit Command Block Queue\n");) + + NdisMAllocateSharedMemory( + Adapter->MiniportAdapterHandle, + sizeof(TOK162_SUPER_COMMAND_BLOCK) * + (Adapter->NumberOfTransmitLists+1), + FALSE, + (PVOID*)&Adapter->TransmitQueue, + &Adapter->TransmitQueuePhysical + ); + + + // + // If the Transmit Block Queue could not be allocated, a NULL pointer + // will have been returned. + // + if (Adapter->TransmitQueue == NULL) { + + return FALSE; + + } + + // + // Initialize the transmit command queue + // + if (TOK162InitializeTransmitQueue(Adapter) == FALSE) { + + return FALSE; + } + + // + // Allocate the Receive Queue. + // + VERY_LOUD_DEBUG(DbgPrint("Allocating Receive Queue\n");) + + NdisMAllocateSharedMemory( + Adapter->MiniportAdapterHandle, + sizeof(TOK162_SUPER_RECEIVE_LIST) * + (Adapter->NumberOfReceiveBuffers+1), + FALSE, + (PVOID*)&Adapter->ReceiveQueue, + &Adapter->ReceiveQueuePhysical + ); + + // + // If the Receive Queue could not be allocated, a NULL pointer will + // have been returned. + // + if (Adapter->ReceiveQueue == NULL) { + + return FALSE; + + } + + // + // Initialize the receieve queue entries. First zero out the entire + // queue memory. + // + NdisZeroMemory( + Adapter->ReceiveQueue, + sizeof(TOK162_SUPER_RECEIVE_LIST) * Adapter->NumberOfReceiveBuffers + ); + + // + // Allocate the receive buffers and attach them to the Receive + // Queue entries. + // + VERY_LOUD_DEBUG(DbgPrint("Allocating Receive Buffers\n");) + + for (i = 0, CurrentReceiveEntry = Adapter->ReceiveQueue; + i < Adapter->NumberOfReceiveBuffers; + i++, CurrentReceiveEntry++ + ) { + + VERY_LOUD_DEBUG(DbgPrint("ReceiveEntry[%d] = %08x\n",i, + CurrentReceiveEntry);) + + NdisMAllocateSharedMemory( + Adapter->MiniportAdapterHandle, + Adapter->ReceiveBufferSize+8, + TRUE, + &CurrentReceiveEntry->ReceiveBuffer, + &CurrentReceiveEntry->ReceiveBufferPhysical + ); + + VERY_LOUD_DEBUG(DbgPrint("Receive Buffer is %08x\n",CurrentReceiveEntry->ReceiveBuffer);) + + // + // If the current buffer could not be allocated, write the errorlog + // entry, delete allocated adapter memory, and return FALSE + // + if (!CurrentReceiveEntry->ReceiveBuffer) { + + return FALSE; + + } + + // + // Build flush buffers + // + NdisAllocateBuffer( + &Status, + &CurrentReceiveEntry->FlushBuffer, + Adapter->FlushBufferPoolHandle, + CurrentReceiveEntry->ReceiveBuffer, + Adapter->ReceiveBufferSize + ); + + if (Status != NDIS_STATUS_SUCCESS) { + + return FALSE; + + } + + // + // Initialize receive lists + // + NdisFlushBuffer(CurrentReceiveEntry->FlushBuffer, FALSE); + + // + // Set the CSTAT to indicate this buffer is free + // + CurrentReceiveEntry->Hardware.CSTAT = RECEIVE_CSTAT_REQUEST_RESET; + + // + // Set the size of the buffer + // + CurrentReceiveEntry->Hardware.DataCount1 = + BYTE_SWAP(Adapter->ReceiveBufferSize); + + // + // Set the address of the buffer + // + CurrentReceiveEntry->Hardware.PhysicalAddress1 = BYTE_SWAP_ULONG( + NdisGetPhysicalAddressLow( + CurrentReceiveEntry->ReceiveBufferPhysical)); + + // + // Set the self-referencing pointer + // + NdisSetPhysicalAddressHigh (CurrentReceiveEntry->Self, 0); + NdisSetPhysicalAddressLow( + CurrentReceiveEntry->Self, + NdisGetPhysicalAddressLow(Adapter->ReceiveQueuePhysical) + + i * sizeof(TOK162_SUPER_RECEIVE_LIST)); + + // + // Create a circular list of receive buffers. For every one but the + // last, set the forward pointer to the next entry. The last entry + // has to point to the first entry (queue head). + // + if (i != (Adapter->NumberOfReceiveBuffers - 1)) { + + CurrentReceiveEntry->Hardware.ForwardPointer = BYTE_SWAP_ULONG( + NdisGetPhysicalAddressLow(Adapter->ReceiveQueuePhysical) + + (i + 1) * sizeof(TOK162_SUPER_RECEIVE_LIST)); + + CurrentReceiveEntry->NextEntry = (PTOK162_SUPER_RECEIVE_LIST)( + (PUCHAR)(Adapter->ReceiveQueue) + + (i+1) * (sizeof(TOK162_SUPER_RECEIVE_LIST))); + + } else { + + CurrentReceiveEntry->Hardware.ForwardPointer = BYTE_SWAP_ULONG( + NdisGetPhysicalAddressLow(Adapter->ReceiveQueuePhysical) + ); + + CurrentReceiveEntry->NextEntry = Adapter->ReceiveQueue; + + } + + } + + // + // If we made it this far, everything is ok. Return TRUE. + // + return TRUE; + +} + + +VOID +TOK162DeleteAdapterMemory( + IN PTOK162_ADAPTER Adapter + ) + +/*++ + +Routine Description: + + This routine deallocates memory for: + + - SCB + + - SSB + + - ErrorLog Block + + - ReadAdapter Block + + - Initialization Block + + - Open Command Block + + - Command Queue + + - Transmit Command Queue + + - Transmit Buffers + + - Flush Buffer Pool + + - Receive Queue + + - Receive Buffers + + - Receive Flush Buffers + +Arguments: + + Adapter - The adapter to deallocate memory for. + +Return Value: + + None. + +--*/ + +{ + + // + // Pointer to a command block used to initialize the command blocks + // and the transmit command blocks. + // + PTOK162_SUPER_COMMAND_BLOCK CommandBlock; + + // + // Iteration variable + // + USHORT i; + + // + // Display to the debugger where we are + // + VERY_LOUD_DEBUG(DbgPrint("In delete adapter memory\n");) + + // + // Free the SCB + // + if (Adapter->Scb != NULL) { + + VERY_LOUD_DEBUG(DbgPrint("Freeing SCB\n");) + + NdisMFreeSharedMemory( + Adapter->MiniportAdapterHandle, + sizeof(SCB) + 8, + FALSE, + Adapter->Scb, + Adapter->ScbPhysical + ); + + } + + // + // Free the SSB + // + if (Adapter->Ssb != NULL) { + + VERY_LOUD_DEBUG(DbgPrint("Freeing SSB - %x %x\n",Adapter->Ssb, + Adapter->SsbPhysical);) + + NdisMFreeSharedMemory( + Adapter->MiniportAdapterHandle, + sizeof(SSB) + 8, + FALSE, + Adapter->Ssb, + Adapter->SsbPhysical + ); + + } + + // + // Free the errorlog block + // + if (Adapter->ErrorLog != NULL) { + + VERY_LOUD_DEBUG(DbgPrint("Freeing ErrorLog - %x\n", + Adapter->ErrorLog);) + + NdisMFreeSharedMemory( + Adapter->MiniportAdapterHandle, + sizeof(TOK162_ERRORLOG) + 8, + FALSE, + Adapter->ErrorLog, + Adapter->ErrorLogPhysical + ); + + } + + // + // Free the read adapter block + // + if (Adapter->AdapterBuf != NULL) { + + VERY_LOUD_DEBUG(DbgPrint("Freeing Read Adapter Block\n");) + + NdisMFreeSharedMemory( + Adapter->MiniportAdapterHandle, + 4096, + FALSE, + Adapter->AdapterBuf, + Adapter->AdapterBufPhysical + ); + + } + + // + // Free the initialization block + // + if (Adapter->InitializationBlock != NULL) { + + VERY_LOUD_DEBUG(DbgPrint("Freeing Initialization Block\n");) + + NdisMFreeSharedMemory( + Adapter->MiniportAdapterHandle, + sizeof(ADAPTER_INITIALIZATION) + 8, + FALSE, + Adapter->InitializationBlock, + Adapter->InitializationBlockPhysical + ); + + } + + // + // Free the open command block + // + if (Adapter->Open != NULL) { + + VERY_LOUD_DEBUG(DbgPrint("Freeing Open Block - %x\n",Adapter->Open);) + + NdisMFreeSharedMemory( + Adapter->MiniportAdapterHandle, + sizeof(OPEN_COMMAND) + 8, + FALSE, + Adapter->Open, + Adapter->OpenPhysical + ); + + } + + // + // Free the command queue + // + if (Adapter->CommandQueue != NULL) { + + VERY_LOUD_DEBUG(DbgPrint("Freeing CommandQueue\n");) + + NdisMFreeSharedMemory( + Adapter->MiniportAdapterHandle, + sizeof(TOK162_SUPER_COMMAND_BLOCK) * + (TOK162_NUMBER_OF_CMD_BLOCKS + 1), + FALSE, + Adapter->CommandQueue, + Adapter->CommandQueuePhysical + ); + + } + + // + // Free the transmit command queue, transmit buffers, and flush buffers + // + if (Adapter->TransmitQueue != NULL) { + + VERY_LOUD_DEBUG(DbgPrint("Freeing TransmitQueue\n");) + + // + // First the buffers + // + for (i = 0, CommandBlock = Adapter->TransmitQueue; + i < Adapter->NumberOfTransmitLists; + i++,CommandBlock++ + ) { + + if (CommandBlock->TOK162BufferAddress != ((ULONG)NULL)) { + + NdisMFreeSharedMemory( + Adapter->MiniportAdapterHandle, + Adapter->ReceiveBufferSize, + FALSE, + (PVOID)(CommandBlock->TOK162BufferAddress), + CommandBlock->TOK162BufferPhysicalAddress + ); + + } + + if (CommandBlock->FlushBuffer != NULL) { + + NdisFreeBuffer( + CommandBlock->FlushBuffer + ); + + } + + } + + // + // Now the queue itself + // + NdisMFreeSharedMemory( + Adapter->MiniportAdapterHandle, + sizeof(TOK162_SUPER_COMMAND_BLOCK) * + Adapter->NumberOfTransmitLists, + FALSE, + Adapter->TransmitQueue, + Adapter->TransmitQueuePhysical + ); + + } + + // + // Free the receive queue, receive buffers, and flush buffers + // + if (Adapter->ReceiveQueue != NULL) { + + // + // Pointer to current Receive Entry being deallocated. + // + PTOK162_SUPER_RECEIVE_LIST CurrentReceiveEntry; + + // + // Simple iteration counter. + // + UINT i; + + VERY_LOUD_DEBUG(DbgPrint("Freeing ReceiveCommandQueue\n");) + + for (i = 0, CurrentReceiveEntry = Adapter->ReceiveQueue; + i < Adapter->NumberOfReceiveBuffers; + i++, CurrentReceiveEntry++ + ) { + + if (CurrentReceiveEntry->ReceiveBuffer) { + NdisMFreeSharedMemory( + Adapter->MiniportAdapterHandle, + Adapter->ReceiveBufferSize, + TRUE, + CurrentReceiveEntry->ReceiveBuffer, + CurrentReceiveEntry->ReceiveBufferPhysical + ); + + + if (CurrentReceiveEntry->FlushBuffer != NULL) { + + NdisFreeBuffer( + CurrentReceiveEntry->FlushBuffer + ); + + } + } + + } + + NdisMFreeSharedMemory( + Adapter->MiniportAdapterHandle, + sizeof(TOK162_SUPER_RECEIVE_LIST) * + Adapter->NumberOfReceiveBuffers, + FALSE, + Adapter->ReceiveQueue, + Adapter->ReceiveQueuePhysical + ); + + } + + // + // Free the flush buffer pool handle + // + if (Adapter->FlushBufferPoolHandle) { + + VERY_LOUD_DEBUG(DbgPrint("Freeing BufferPool\n");) + + NdisFreeBufferPool( + Adapter->FlushBufferPoolHandle + ); + + } + +} + + +extern +VOID +TOK162Halt( + IN NDIS_HANDLE MiniportAdapterContext + ) + +/*++ + +Routine Description: + + TOK162Halt removes an adapter previously initialized. + +Arguments: + + MiniportAdapterContext - The context value that the Miniport returned + from Tok162Initialize; actually is pointer to + a TOK162_ADAPTER. + +Return Value: + + None. + +--*/ + +{ + // + // Pointer to an adapter structure. Makes Context (passed in value) + // a structure we can deal with. + // + PTOK162_ADAPTER Adapter = + PTOK162_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext); + + // + // Shut down the chip. + // + TOK162DisableInterrupt(Adapter); + + // + // Return resources to the wrapper + // + NdisMDeregisterInterrupt(&Adapter->Interrupt); + + NdisMDeregisterIoPortRange(Adapter->MiniportAdapterHandle, + Adapter->PortIOBase, + 0x30, + Adapter->PortIOAddress + ); + + NdisMFreeMapRegisters(Adapter->MiniportAdapterHandle); + + // + // Free the allocated memory for the adapter-related structures + // + TOK162DeleteAdapterMemory(Adapter); + + // + // Finally, free the allocated memory for the adapter structure itself + // + TOK162_FREE_PHYS(Adapter); + +} + + +extern +VOID +TOK162Shutdown( + IN NDIS_HANDLE MiniportAdapterContext + ) + +/*++ + +Routine Description: + + TOK162Shutdown-- removes an adapter previously initialized. + +Arguments: + + MiniportAdapterContext - The context value that the Miniport returned + from Tok162Initialize; actually is pointer to + a TOK162_ADAPTER. + +Return Value: + + None. + +--*/ + +{ + // + // Pointer to an adapter structure. Makes Context (passed in value) + // a structure we can deal with. + // + + PTOK162_ADAPTER Adapter = + PTOK162_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext); + + // + // Simply remove ourselves from the ring by doing a reset of the + // adapter. + // + TOK162ResetAdapter(Adapter); + +} + + +NDIS_STATUS +TOK162Reset( + OUT PBOOLEAN AddressingReset, + IN NDIS_HANDLE MiniportAdapterContext + ) +/*++ + +Routine Description: + + The TOK162Reset request instructs the Miniport to issue a hardware reset + to the network adapter. The driver also resets its software state. See + the description of NdisMReset for a detailed description of this request. + +Arguments: + + MiniportAdapterContext - Pointer to the adapter structure. + +Return Value: + + The function value is the status of the operation. +--*/ + +{ + // + // Pointer to an adapter structure. Makes Context (passed in value) + // a structure we can deal with. + // + PTOK162_ADAPTER Adapter = + PTOK162_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext); + +#if DBG + Tok162Debug = 0x08; +#endif + + VERY_LOUD_DEBUG(DbgPrint("Reset called\n");) + + // + // Make sure we aren't already doing a reset. + // + if (Adapter->ResetInProgress == FALSE) { + + Adapter->ResetInProgress = TRUE; + + Adapter->ResetState = CheckReset; + + TOK162SetupForReset( + Adapter + ); + + return NDIS_STATUS_PENDING; + + } else { + + // + // If we are doing a reset currently, return this fact. + // + return NDIS_STATUS_RESET_IN_PROGRESS; + + } + +} + + +BOOLEAN +TOK162CheckForHang( + IN NDIS_HANDLE MiniportAdapterContext + ) + +/*++ + +Routine Description: + + This routine is called by the wrapper to determine if the adapter + is hung. + +Arguments: + + Context - Really a pointer to the adapter. + +Return Value: + + None. + +--*/ +{ + + // + // Pointer to an adapter structure. Makes Context (passed in value) + // a structure we can deal with. + // + PTOK162_ADAPTER Adapter = + PTOK162_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext); + + // + // Variable pointing to the outstanding command. Used to make the + // code easier to read (could use Adapter->CommandOnCard). + // + PTOK162_SUPER_COMMAND_BLOCK FirstPendingCommand = Adapter->CommandOnCard; + + // + // Variable pointing to the outstanding transmit. Used to make the + // code easier to read (could use Adapter->TransmitOnCard). + // + PTOK162_SUPER_COMMAND_BLOCK FirstPendingTransmit = + Adapter->TransmitOnCard; + + // + // If we're in the middle of a reset, just return false + // + if (Adapter->ResetInProgress == TRUE) { + + return FALSE; + + } + + // + // First see if there is a command outstanding + // + if (FirstPendingCommand != NULL) { + + // + // See if the command block has timed-out. + // + if (FirstPendingCommand->Timeout) { + + // + // See if we have given it enough time + // + if ( FirstPendingCommand->TimeoutCount >= 40) { + + LOUD_DEBUG(DbgPrint("Returning True from checkforhang\n");) + return TRUE; + + } else { + + FirstPendingCommand->TimeoutCount++; + + } + + } else { + + // + // Mark the current command as timed out and get the clock + // rolling. + // + FirstPendingCommand->Timeout = TRUE; + FirstPendingCommand->TimeoutCount = 0; + + } + + } + + // + // Check if there is an outstanding transmit + // + if (FirstPendingTransmit != NULL) { + + // + // See if the transmit has timed-out. + // + if (FirstPendingTransmit->Timeout) { + + // + // See if we have given it enough time + // + if ( FirstPendingTransmit->TimeoutCount >= 40) { + + // + // Give up, the card appears dead. + // + return TRUE; + + } else { + + FirstPendingTransmit->TimeoutCount++; + + } + + } else { + + // + // Set outstanding transmit to timeout and start the clock + // rolling. + // + FirstPendingTransmit->Timeout = TRUE; + FirstPendingTransmit->TimeoutCount = 0; + + } + + } + + // + // If we got here, we aren't hung. + // + return FALSE; +} + + +NDIS_STATUS +TOK162TransferData( + OUT PNDIS_PACKET Packet, + OUT PUINT BytesTransferred, + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_HANDLE MiniportReceiveContext, + IN UINT ByteOffset, + IN UINT BytesToTransfer + ) + +/*++ + +Routine Description: + + A protocol calls the TOK162TransferData request (indirectly via + NdisTransferData) from within its Receive event handler + to instruct the Miniport to copy the contents of the received packet + a specified packet buffer. + +Arguments: + + MiniportAdapterContext - The context value returned by the driver when the + adapter was initialized. In reality this is a + pointer to TOK162_ADAPTER. + + MiniportReceiveContext - The context value passed by the driver on its + call to NdisMIndicateReceive. The driver can + use this value to determine which packet, on + which adapter, is being received. + + ByteOffset - An unsigned integer specifying the offset within + the received packet at which the copy is to begin. + If the entire packet is to be copied, + ByteOffset must be zero. + + BytesToTransfer - An unsigned integer specifying the number of + bytes to copy. It is legal to transfer zero + bytes; this has no effect. If the sum of + ByteOffset and BytesToTransfer is greater than + the size of the received packet, then the + remainder of the packet (starting from + ByteOffset) is transferred, and the trailing + portion of the receive buffer is not modified. + + Packet - A pointer to a descriptor for the packet storage + into which the MAC is to copy the received packet. + + BytesTransfered - A pointer to an unsigned integer. The miniport + writes the actual number of bytes transferred + into this location. This value is not valid if + the return status is STATUS_PENDING. + +Return Value: + + The function value is the status of the operation. + +--*/ +{ + + // + // Pointer to an adapter structure. Makes Context (passed in value) + // a structure we can deal with. + // + PTOK162_ADAPTER Adapter = + PTOK162_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext); + + // + // Holds the count of the number of ndis buffers comprising the + // destination packet. + // + UINT DestinationBufferCount; + + // + // Points to the buffer into which we are putting data. + // + PNDIS_BUFFER DestinationCurrentBuffer; + + // + // Points to the location in Buffer from which we are extracting data. + // + PUCHAR SourceCurrentAddress; + + // + // Holds the virtual address of the current destination buffer. + // + PVOID DestinationVirtualAddress; + + // + // Holds the length of the current destination buffer. + // + UINT DestinationCurrentLength; + + // + // Keep a local variable of BytesTransferred so we aren't referencing + // through a pointer. + // + UINT LocalBytesTransferred = 0; + + // + // Display where we are on the debugger and log where we are. + // + LOUD_DEBUG(DbgPrint("TOK162!Transfer Data called\n");) + IF_LOG('n'); + + // + // Display number of bytes to transfer on the debugger + // + VERY_LOUD_DEBUG(DbgPrint("Copying %u bytes\n",BytesToTransfer);) + + // + // Initialize the number of bytes transferred to 0 + // + *BytesTransferred = 0; + + // + // If we don't have any more to transfer, we're done + // + if (BytesToTransfer == 0) { + + return NDIS_STATUS_SUCCESS; + + } + + // + // Get the first buffer of the destination. + // + NdisQueryPacket( + Packet, + NULL, + &DestinationBufferCount, + &DestinationCurrentBuffer, + NULL + ); + + // + // Could have a null packet. If so, we are done. + // + if (DestinationBufferCount == 0) { + + return NDIS_STATUS_SUCCESS; + + } + + // + // Get information on the buffer. + // + NdisQueryBuffer( + DestinationCurrentBuffer, + &DestinationVirtualAddress, + &DestinationCurrentLength + ); + + // + // Set up the source address. + // + SourceCurrentAddress = (PCHAR)(MiniportReceiveContext) + ByteOffset; + + // + // Do the actual transfer from source to destination + // + while (LocalBytesTransferred < BytesToTransfer) { + + // + // Check to see whether we've exhausted the current destination + // buffer. If so, move onto the next one. + // + if (!DestinationCurrentLength) { + + NdisGetNextBuffer( + DestinationCurrentBuffer, + &DestinationCurrentBuffer + ); + + if (!DestinationCurrentBuffer) { + + // + // We've reached the end of the packet. We return + // with what we've done so far. (Which must be shorter + // than requested.) + // + + break; + + } + + NdisQueryBuffer( + DestinationCurrentBuffer, + &DestinationVirtualAddress, + &DestinationCurrentLength + ); + + continue; + + } + + // + // Copy the data. + // + { + // + // Holds the amount of data to move. + // + UINT AmountToMove; + + // + // Holds the amount desired remaining. + // + UINT Remaining = BytesToTransfer - LocalBytesTransferred; + + + AmountToMove = DestinationCurrentLength; + + AmountToMove = ((Remaining < AmountToMove)? + (Remaining):(AmountToMove)); + + NdisMoveMemory( + DestinationVirtualAddress, + SourceCurrentAddress, + AmountToMove + ); + + // + // Update pointers and counters + // + SourceCurrentAddress += AmountToMove; + LocalBytesTransferred += AmountToMove; + DestinationCurrentLength -= AmountToMove; + + } + + } + + // + // Indicate how many bytes were transferred + // + *BytesTransferred = LocalBytesTransferred; + + // + // Display total bytes transferred on debugger + // + VERY_LOUD_DEBUG(DbgPrint("Total bytes transferred = %x\n", + *BytesTransferred);) + + + // + // Log the fact that we are leaving transferdata + // + IF_LOG('N'); + + return NDIS_STATUS_SUCCESS; + +} + + +BOOLEAN +TOK162InitializeTransmitQueue( + IN PTOK162_ADAPTER Adapter + ) +/*++ + +Routine Description: + + This routine initializes the transmit queue + +Arguments: + + Adapter - Current Adapter structure + +Return Value: + + None. + +--*/ +{ + // + // Local pointer to command blocks + // + PTOK162_SUPER_COMMAND_BLOCK CurrentCommandBlock; + + // + // Counter variable + // + USHORT i; + + // + // Status variable + // + NDIS_STATUS Status; + + // + // Initialize the Adapter structure fields associate with transmit lists + // + Adapter->NextTransmitBlock = 0; + Adapter->NumberOfAvailableTransmitBlocks = + Adapter->NumberOfTransmitLists; + + // + // Zero the memory of the transmit queue + // + NdisZeroMemory( + Adapter->TransmitQueue, + sizeof(TOK162_SUPER_COMMAND_BLOCK) * Adapter->NumberOfTransmitLists + ); + + // + // Put the Transmit Command Blocks into a known state. + // + for (i = 0, CurrentCommandBlock = Adapter->TransmitQueue; + i < Adapter->NumberOfTransmitLists; + i++, CurrentCommandBlock++ + ) { + + // + // Set the next command pointer to NULL + // + CurrentCommandBlock->NextCommand = NULL; + + // + // Set the self-referential pointer + // + NdisSetPhysicalAddressHigh (CurrentCommandBlock->Self, 0); + NdisSetPhysicalAddressLow( + CurrentCommandBlock->Self, + NdisGetPhysicalAddressLow(Adapter->TransmitQueuePhysical) + + i * sizeof(TOK162_SUPER_COMMAND_BLOCK)); + + CurrentCommandBlock->PhysicalTransmitEntry = + NdisGetPhysicalAddressLow(CurrentCommandBlock->Self); + + // + // This is a transmit block, not a command block + // + CurrentCommandBlock->CommandBlock = FALSE; + + // + // Set the index and the timeout values + // + CurrentCommandBlock->CommandBlockIndex = i; + CurrentCommandBlock->Timeout = FALSE; + + // + // Initialize the hardware portion of the command block. + // Set the state to free and next pending to NULL. + // + CurrentCommandBlock->Hardware.State = TOK162_STATE_FREE; + CurrentCommandBlock->Hardware.NextPending = TOK162_NULL; + + // + // Allocate the transmit buffer associated with this transmit + // list entry + // + NdisMAllocateSharedMemory( + Adapter->MiniportAdapterHandle, + Adapter->ReceiveBufferSize + 8, + FALSE, + &((PVOID)CurrentCommandBlock->TOK162BufferAddress), + &CurrentCommandBlock->TOK162BufferPhysicalAddress + ); + + LOUD_DEBUG(DbgPrint("XMITBuffer %u = %lx %lx\n",i, + CurrentCommandBlock->TOK162BufferAddress, + NdisGetPhysicalAddressLow( + CurrentCommandBlock->TOK162BufferPhysicalAddress));) + + // + // If the allocation failed, write the errorlog and return FALSE + // + if (CurrentCommandBlock->TOK162BufferAddress == (ULONG)NULL) { + + NdisWriteErrorLogEntry( + Adapter->MiniportAdapterHandle, + NDIS_ERROR_CODE_OUT_OF_RESOURCES, + 0 + ); + + return FALSE; + + } + +// +// Remove the following section because it isn't needed. Flush buffers on +// transmits appear to be causing hangs on mips machines. +// +#if 0 + // + // Build flush buffers + // + NdisAllocateBuffer( + &Status, + &CurrentCommandBlock->FlushBuffer, + Adapter->FlushBufferPoolHandle, + (PVOID)CurrentCommandBlock->TOK162BufferAddress, + Adapter->ReceiveBufferSize + ); + + if (Status != NDIS_STATUS_SUCCESS) { + + return FALSE; + + } +#endif + } + + // + // If we got here, everything is ok. Return TRUE. + // + return TRUE; + +} diff --git a/private/ntos/ndis/ibmtok2i/tok162.rc b/private/ntos/ndis/ibmtok2i/tok162.rc new file mode 100644 index 000000000..f211525d9 --- /dev/null +++ b/private/ntos/ndis/ibmtok2i/tok162.rc @@ -0,0 +1,38 @@ +#include <windows.h> +#include <ntverp.h> + +/*-----------------------------------------------*/ +/* the following lines are specific to this file */ +/*-----------------------------------------------*/ + +/* VER_FILETYPE, VER_FILESUBTYPE, VER_FILEDESCRIPTION_STR + * and VER_INTERNALNAME_STR must be defined before including COMMON.VER + * The strings don't need a '\0', since common.ver has them. + */ +#define VER_FILETYPE VFT_DRV +/* possible values: VFT_UNKNOWN + VFT_APP + VFT_DLL + VFT_DRV + VFT_FONT + VFT_VXD + VFT_STATIC_LIB +*/ +#define VER_FILESUBTYPE VFT2_DRV_NETWORK +/* possible values VFT2_UNKNOWN + VFT2_DRV_PRINTER + VFT2_DRV_KEYBOARD + VFT2_DRV_LANGUAGE + VFT2_DRV_DISPLAY + VFT2_DRV_MOUSE + VFT2_DRV_NETWORK + VFT2_DRV_SYSTEM + VFT2_DRV_INSTALLABLE + VFT2_DRV_SOUND + VFT2_DRV_COMM +*/ +#define VER_FILEDESCRIPTION_STR "IBM Token Ring 16/4 Adapter II ISA Network Driver" +#define VER_INTERNALNAME_STR "IBMTOK2I.SYS" +#define VER_ORIGINALFILENAME_STR "IBMTOK2I.SYS" + +#include "common.ver" diff --git a/private/ntos/ndis/ibmtok2i/tok162hw.h b/private/ntos/ndis/ibmtok2i/tok162hw.h new file mode 100644 index 000000000..d0cf26ab3 --- /dev/null +++ b/private/ntos/ndis/ibmtok2i/tok162hw.h @@ -0,0 +1,1382 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + tokhrd.h + +Abstract: + + The hardware-related definitions for the IBM Token-Ring 16/4 II + ISA driver. + +Author: + + Kevin Martin (kevinma) 1-Feb-1994 + +Environment: + + Architecturally, there is an assumption in this driver that we are + on a little endian machine. + +Notes: + + References to "IBM Spec" refer to the IBM "Supplement to the LAN + Technical Reference (Token-Ring Network 16/4 Adapter II)" Specification. + The document number is - SD21-052-00. + + References to "TI Spec" refer to the Texas Instruments "TMS380 Second- + Generation Token Ring" User's Guide. The document number is - SPWU005. + +Revision History: + +--*/ + +// +// Pack everything on word boundaries +// +#include <pshpack2.h> + +// +// Define "Physical Addresses" which are ULONG in size. The card +// wants physical addresses. +// +typedef ULONG TOK162_PHYSICAL_ADDRESS, *PTOK162_PHYSICAL_ADDRESS; + + +// +// The length of an address (network) is 6 bytes +// +#define TOK162_LENGTH_OF_ADDRESS 6 + +// +// Define a NULL pointer +// +#define TOK162_NULL ((TOK162_PHYSICAL_ADDRESS)(-1L)) + +// +// Default number of command blocks +// +#define TOK162_NUMBER_OF_CMD_BLOCKS 4 + +// +// Burst size for transmit and receive DMA. A zero tells the adapter to +// use the size of the transfer as the burst size. +// +// IBM Spec, Page 21 + +#define TOK162_BURST_SIZE 0 + +// +// Number of retries to attempt after a DMA error +// +#define TOK162_DMA_RETRIES 0x0303 + +// +// Minimum packet size for a valid transfer/receive +// +#define MINIMUM_TOKENRING_PACKET_SIZE 32 + +// +// Default packet header size +// +#define TOK162_HEADER_SIZE 32 + +// +// TOK162 Receive/Command Block States +// +#define TOK162_STATE_FREE ((USHORT)0x0000) +#define TOK162_STATE_EXECUTING ((USHORT)0x0001) +#define TOK162_STATE_WAIT_FOR_ADAPTER ((USHORT)0x0002) + +// +// Start of I/O ports based on switch settings. +// +// IBM Spec, Page 9. +// +#define BASE_OPTION_ZERO 0x86A0 +#define BASE_OPTION_ONE 0xC6A0 +#define BASE_OPTION_TWO 0xA6A0 +#define BASE_OPTION_THREE 0xE6A0 +#define BASE_OPTION_FOUR 0x96A0 +#define BASE_OPTION_FIVE 0xD6A0 +#define BASE_OPTION_SIX 0xB6A0 +#define BASE_OPTION_SEVEN 0xF6A0 + +// +// Offsets from above of the actual ports used. +// +// IBM Spec, Page 4. +// +#define PORT_OFFSET_DATA 0x0000 +#define PORT_OFFSET_DATA_AUTO_INC 0x0002 +#define PORT_OFFSET_ADDRESS 0x0004 +#define PORT_OFFSET_STATUS 0x0006 +#define PORT_OFFSET_COMMAND 0x0006 +#define PORT_OFFSET_ADAPTER_RESET 0x0008 +#define PORT_OFFSET_ADAPTER_ENABLE 0x000A +#define PORT_OFFSET_SWITCH_INT_DISABLE 0x000C +#define PORT_OFFSET_SWITCH_INT_ENABLE 0x000E + +// +// Macro to write a ULONG variable to a register on the adapter +// +#define WRITE_ADAPTER_ULONG(a, p, v) \ + NdisRawWritePortUshort((ULONG) (a)->PortIOAddress + (p), \ + (ULONG) (v)) + +// +// Macro to read a ULONG variable from a register on the adapter +// +#define READ_ADAPTER_ULONG(a, p, v) \ + NdisRawReadPortUshort((ULONG) (a)->PortIOAddress + (p), \ + (PULONG) (v)) + +// +// Macro to write a USHORT variable to a register on the adapter +// +#define WRITE_ADAPTER_USHORT(a, p, v) \ + NdisRawWritePortUshort((ULONG) (a)->PortIOAddress + (p), \ + (USHORT) (v)) + +// +// Macro to read a USHORT variable from a register on the adapter +// +#define READ_ADAPTER_USHORT(a, p, v) \ + NdisRawReadPortUshort((ULONG) (a)->PortIOAddress + (p), \ + (PUSHORT) (v)) + +// +// Macro to write a CHAR variable to a register on the adapter +// +#define WRITE_ADAPTER_UCHAR(a, p, v) \ + NdisRawWritePortUchar((ULONG)(a)->PortIOAddress + (p), \ + (UCHAR)(v)) + +// +// Macro to read a ULONG variable from a register on the adapter +// +#define READ_ADAPTER_UCHAR(a, p, v) \ + NdisRawReadPortUchar((ULONG)(a)->PortIOAddress + (p), \ + (PUCHAR)(v)) + +// +// Masks for the command register +// +// IBM Spec, Pages 5-6. +// +#define CMD_PIO_INTERRUPT 0x8000 +#define CMD_PIO_RESET 0x4000 +#define CMD_PIO_SSB_CLEAR 0x2000 +#define CMD_PIO_EXECUTE 0x1000 +#define CMD_PIO_SCB_REQUEST 0x0800 +#define CMD_PIO_RCV_CONTINUE 0x0400 +#define CMD_PIO_RCV_VALID 0x0200 +#define CMD_PIO_XMIT_VALID 0x0100 +#define CMD_PIO_RESET_SYSTEM 0x0080 + +// +// Common mask combinations +// +#define EXECUTE_SCB_COMMAND 0x9080 // int+exec+resetsysint +#define ENABLE_SSB_UPDATE 0xA000 // int+ssbclear +#define ENABLE_RECEIVE_VALID 0x8200 // int+rcvvalid + +// +// Masks for the status register. +// +// IBM Spec, Pages 6-7. +// +#define STATUS_ADAPTER_INTERRUPT 0x8000 +#define STATUS_SYSTEM_INTERRUPT 0x0080 + +// +// Masks for adapter interrupts. +// +// IBM Spec, Page 7. +// +#define STATUS_INT_CODE_MASK 0x000F +#define STATUS_INT_CODE_CHECK 0x0000 +#define STATUS_INT_CODE_IMPL 0x0002 +#define STATUS_INT_CODE_RING 0x0004 +#define STATUS_INT_CODE_SCB_CLEAR 0x0006 +#define STATUS_INT_CODE_CMD_STATUS 0x0008 +#define STATUS_INT_CODE_RECEIVE_STATUS 0x000A +#define STATUS_INT_CODE_XMIT_STATUS 0x000C + +// +// My Mask for System Interrupts +// +#define MASK_ADAPTER_CHECK 0x0001 +#define MASK_RING_STATUS 0x0002 +#define MASK_SCB_CLEAR 0x0004 +#define MASK_COMMAND_STATUS 0x0008 +#define MASK_RECEIVE_STATUS 0x0010 +#define MASK_TRANSMIT_STATUS 0x0020 + + +// +// Adapter switch structure. The switches determine the configuration of the +// card. +// +// IBM Spec, Page 8. +// +typedef struct _ADAPTERSWITCHES { + + // + // Connector Type. + // + USHORT UTP_STP:1; + + // + // Token Ring Speed + // + USHORT RingSpeed:1; + + // + // DMA Channel + // + USHORT DMA:2; + + // + // Is Remote Program Load enabled? + // + USHORT RPL:1; + + // + // Adapter mode, test or normal + // + USHORT AdapterMode:1; + + // + // Adapter wait state + // + USHORT WaitState:1; + + // + // Interrupt Request Level + // + USHORT IntRequest:2; + + // + // RPL address (if RPL enabled) or adapter I/O base address + // + USHORT RPL_PIO_Address:3; + + // + // Not used. + // + USHORT Reserved:4; +} ADAPTERSWITCHES,*PADAPTERSWITCHES; + +// +// #defines for the I/O Address switches +// +// IBM Spec, Page 9. +// +#define SW_PIO_ADDR_8 0x00 +#define SW_PIO_ADDR_C 0x01 +#define SW_PIO_ADDR_A 0x02 +#define SW_PIO_ADDR_E 0x03 +#define SW_PIO_ADDR_9 0x04 +#define SW_PIO_ADDR_D 0x05 +#define SW_PIO_ADDR_B 0x06 +#define SW_PIO_ADDR_F 0x07 + +// +// #defines for the interrupt request level +// +// IBM Spec, Page 9. +// +#define SW_INT_9 0x00 +#define SW_INT_11 0x01 +#define SW_INT_10 0x02 +#define SW_INT_15 0x03 + +// +// #defines for the wait state. +// +// IBM Spec, Page 9. +// +#define SW_WAITSTATE_NORMAL 0x00 +#define SW_WAITSTATE_FAST 0x01 + +// +// #defines for the adapter mode. +// +// IBM Spec, Page 10. +// +#define SW_ADAPTERMODE_NORMAL 0x00 +#define SW_ADAPTERMODE_TEST 0x01 + +// +// #defines for RPL +// +// IBM Spec, Page 10. +// +#define SW_RPL_DISABLE 0x00 +#define SW_RPL_ENABLE 0x01 + +// +// #defines for the DMA channel +// +// IBM Spec, Page 10. +// +#define SW_DMA_5 0x00 +#define SW_DMA_7 0x01 +#define SW_DMA_6 0x02 + +// +// #defines for the ring speed. +// +// IBM Spec, Page 10. +// +#define SW_RINGSPEED_4 0x00 +#define SW_RINGSPEED_16 0x01 + +// +// #defines for the connector interface. +// +// IBM Spec, Page 10. +// +#define SW_STP 0x00 +#define SW_UTP 0x01 + +// +// DMA Command Values +// +// IBM Spec, Page 25. +// +#define CMD_DMA_OPEN 0x0300 +#define CMD_DMA_XMIT 0x0400 +#define CMD_DMA_XMIT_HALT 0x0500 +#define CMD_DMA_RCV 0x0600 +#define CMD_DMA_CLOSE 0x0700 +#define CMD_DMA_SET_GRP_ADDR 0x0800 +#define CMD_DMA_SET_FUNC_ADDR 0x0900 +#define CMD_DMA_READ_ERRLOG 0x0A00 +#define CMD_DMA_READ 0x0B00 +#define CMD_DMA_IMPL_ENABLE 0x0C00 +#define CMD_DMA_START_STOP_TRACE 0x0D00 + +// +// System Command Block structure. +// +// IBM Spec, Pages 13-14. +// +typedef struct _SCB { + + // + // Command to be submitted to the card. + // + USHORT Command; + + // + // Parameter USHORTs, different for different commands. + // + USHORT Parm1; + USHORT Parm2; + +} SCB, *PSCB; + +// +// Generic System Status Block Structure. +// +// IBM Spec, Page 15. +// +typedef struct _SSB { + + // + // Command for which status is returned. + // + USHORT Command; + + // + // Status USHORTs, different for different commands + // + USHORT Status1; + USHORT Status2; + USHORT Status3; + +} SSB, *PSSB; + +// +// Ring Status SSB #defines and structure +// +// IBM Spec, Page 15-16. +// +typedef struct _SSB_RING_STATUS { + + // + // Command code, will be SSB_CMD_RING_STATUS + // + USHORT Command; + + // + // Ring Status code, as defined below. + // + USHORT RingStatus; + + // + // Last two not used. + // + USHORT Reserved1; + USHORT Reserved2; + +} SSB_RING_STATUS,*PSSB_RING_STATUS; + +#define SSB_CMD_RING_STATUS 0x0100 + +#define RING_STATUS_OVERFLOW 0x8000 +#define RING_STATUS_SINGLESTATION 0x4000 +#define RING_STATUS_RINGRECOVERY 0x2000 +#define RING_STATUS_SIGNAL_LOSS 0x0080 +#define RING_STATUS_HARD_ERROR 0x0040 +#define RING_STATUS_SOFT_ERROR 0x0020 +#define RING_STATUS_XMIT_BEACON 0x0010 +#define RING_STATUS_LOBE_WIRE_FAULT 0x0008 +#define RING_STATUS_AUTO_REMOVE_1 0x0004 +#define RING_STATUS_REMOVE_RECEIVED 0x0001 + +// +// Command Reject Status SSB #defines and structure +// +typedef struct _SSB_CMD_REJECT_STATUS { + + // + // Command code, will be SSB_CMD_COMMAND_REJECT_STATUS + // + USHORT Command; + + // + // Reason for rejection, as defined below. + // + USHORT Reason; + + // + // Command that was rejected. + // + USHORT SCBCommand; + + // + // Not used. + // + USHORT Reserved; + +} SSB_CMD_REJECT_STATUS, *PSSB_CMD_REJECT_STATUS; + +#define SSB_CMD_COMMAND_REJECT_STATUS 0x0200 + +#define CMD_REJECT_STATUS_BAD_CMD 0x0080 +#define CMD_REJECT_STATUS_BAD_ADDR 0x0040 +#define CMD_REJECT_STATUS_BAD_OPEN 0x0020 +#define CMD_REJECT_STATUS_BAD_CLOSED 0x0010 +#define CMD_REJECT_STATUS_BAD_SAME 0x0008 + +// +// Adapter Check Port information, structure and defines +// +// IBM Spec, Pages 18-19. +// + +// +// Offsets within the adapter memory where the values for the check can +// be obtained. +// +// IBM Spec, Page 18. +// +#define ADAPTER_CHECK_PORT_OFFSET_BASE 0x05E0 +#define ADAPTER_CHECK_PORT_OFFSET_PARM0 0x05E2 +#define ADAPTER_CHECK_PORT_OFFSET_PARM1 0x05E4 +#define ADAPTER_CHECK_PORT_OFFSET_PARM2 0x05E6 + +// +// Structure that can be used to gather all of the adapter check information. +// +typedef struct _ADAPTER_CHECK { + + // + // USHORT indicating why the adapter check occurred. Reasons are defined + // below. + // + USHORT Check; + + // + // The parameters are used based on the reason above. Please see the spec + // as to what the different parameters are for the given reason. + // + USHORT Parm0; + USHORT Parm1; + USHORT Parm2; + +} ADAPTER_CHECK, *PADAPTER_CHECK; + +#define ADAPTER_CHECK_DMA_ABORT_READ 0x4000 +#define ADAPTER_CHECK_DMA_ABORT_WRITE 0x2000 +#define ADAPTER_CHECK_ILLEGAL_OPCODE 0x1000 +#define ADAPTER_CHECK_PARITY_ERR 0x0800 +#define ADAPTER_CHECK_PARITY_ERR_EXT 0x0400 +#define ADAPTER_CHECK_PARITY_ERR_SIM 0x0200 // System Interface Master +#define ADAPTER_CHECK_PARITY_ERR_PHM 0x0100 // Protocol Handler Master +#define ADAPTER_CHECK_PARITY_ERR_RR 0x0080 // Ring Receive +#define ADAPTER_CHECK_PARITY_ERR_RXMT 0x0040 // Ring Transmit +#define ADAPTER_CHECK_RING_UNDERRUN 0x0020 +#define ADAPTER_CHECK_RING_OVERRUN 0x0010 +#define ADAPTER_CHECK_INVALID_INT 0x0008 +#define ADAPTER_CHECK_INVALID_ERR_INT 0x0004 +#define ADAPTER_CHECK_INVALID_XOP 0x0002 +#define ADAPTER_CHECK_PROGRAM_CHECK 0x0001 + +// +// Initialization Structure. +// +// IBM Spec, Pages 19-25. +// + +// +// This structure needs to be packed on a two-byte boundary or the +// SCB pointer will be off during the loop that sends the initialization +// bytes to the card. +// + +typedef struct _ADAPTER_INITIALIZATION { + + // + // Initialization options as defined below + // + USHORT Options; + + // + // Reserved USHORTs + // + USHORT Reserved1; + USHORT Reserved2; + USHORT Reserved3; + + // + // Size of DMA bursts on receives + // + USHORT ReceiveBurstSize; + + // + // Size of DMA bursts on transmits + // + USHORT TransmitBurstSize; + + // + // Number of retries on DMA errors before giving up + // + USHORT DMAAbortThresholds; + + // + // Pointer to the SCB (physical pointer), split into two words + // because we are writing them to the adaper in words + // + USHORT SCBHigh; + USHORT SCBLow; + + // + // Pointer to the SSB (physical pointer), split into words because + // we are writing them to the adapter in words + // + USHORT SSBHigh; + USHORT SSBLow; + +} ADAPTER_INITIALIZATION, *PADAPTER_INITIALIZATION; + +// +// Initialization options +// +#define INIT_OPTIONS_RESERVED 0x8000 +#define INIT_OPTIONS_SCBSSB_BURST 0x1000 +#define INIT_OPTIONS_SCBSSB_CYCLE 0x0000 +#define INIT_OPTIONS_LIST_BURST 0x0800 +#define INIT_OPTIONS_LIST_CYCLE 0x0000 +#define INIT_OPTIONS_LIST_STATUS_BURST 0x0400 +#define INIT_OPTIONS_LIST_STATUS_CYCLE 0x0000 +#define INIT_OPTIONS_RECEIVE_BURST 0x0200 +#define INIT_OPTIONS_RECEIVE_CYCLE 0x0000 +#define INIT_OPTIONS_XMIT_BURST 0x0100 +#define INIT_OPTIONS_XMIT_CYCLE 0x0000 +#define INIT_OPTIONS_SPEED_16 0x0040 +#define INIT_OPTIONS_SPEED_4 0x0000 +#define INIT_OPTIONS_DISABLE_ETR 0x0020 +#define INIT_OPTIONS_ENABLE_ETR 0x0000 + +// +// Starting address on card of where to write the init block +// +// IBM Spec, Page 22. +// +#define INIT_ADAPTER_PORT_OFFSET 0x0200 + +// +// Value to write to the command register after the init block has been +// downloaded. +// +#define INIT_ADAPTER_INTERRUPT 0x9080 + +// +// Bit masks for initialization results. +// +// IBM Spec, Page 23. +// +#define STATUS_INIT_INITIALIZE 0x0040 +#define STATUS_INIT_TEST 0x0020 +#define STATUS_INIT_ERROR 0x0010 + +// +// Bring-Up Error Codes +// +// IBM Spec, Pages 23-24 +// +#define BRING_UP_ERR_INIT_TEST 0x0000 +#define BRING_UP_ERR_CRC 0x0001 +#define BRING_UP_ERR_RAM 0x0002 +#define BRING_UP_ERR_INSTRUCTION_TEST 0x0003 +#define BRING_UP_ERR_INT_TEST 0x0004 +#define BRING_UP_ERR_PROTOCOL_HANDLER 0x0005 +#define BRING_UP_ERR_SYSTEM_INTERFACE_REG 0x0006 + +// +// Initialize Error Codes +// +// IBM Spec, Page 24. +// +#define INITIALIZE_ERR_PARM_LEN 0x0001 +#define INITIALIZE_ERR_INV_OPTIONS 0x0002 +#define INITIALIZE_ERR_INV_RCV_BURST 0x0003 +#define INITIALIZE_ERR_INV_XMIT_BURST 0x0004 +#define INITIALIZE_ERR_INV_DMA_ABORT 0x0005 +#define INITIALIZE_ERR_INV_SCB 0x0006 +#define INITIALIZE_ERR_INV_SSB 0x0007 +#define INITIALIZE_ERR_DMA_TIMEOUT 0x0009 +#define INITIALIZE_ERR_DMA_BUS 0x000B +#define INITIALIZE_ERR_DMA_DATA 0x000C +#define INITIALIZE_ERR_ADAPTER_CHECK 0x000D + +// +// Recommended burst sizes. +// +// IBM Spec, Page 25. +// +#define DEFAULT_BURST_SIZE_FAST 0x004C +#define DEFAULT_BURST_SIZE_NORMAL 0x0040 + +// +// TOK162 ErrorLog structure. +// +// IBM Spec, Page 35. +// +typedef struct _TOK162_ERRORLOG { + + // + // These are error count fields. The adapter resets the internal + // counters after they are read into this structure. + // + UCHAR LineError; + UCHAR InternalError; + UCHAR BurstError; + UCHAR ARIFCIError; + UCHAR AbortDelimeter; + UCHAR Reserved1; + UCHAR LostFrameError; + UCHAR ReceiveCongestionError; + UCHAR FrameCopiedError; + UCHAR Reserved2; + UCHAR TokenError; + UCHAR Reserved3; + UCHAR DMABusError; + UCHAR Reserved4; + +} TOK162_ERRORLOG, *PTOK162_ERRORLOG; + +// +// TOK162 Read Adapter Log structure. Used to get permanent address, current +// addresses (network, group, functional), the microcode level, and the MAC +// buffer. +// +// IBM Spec, Pages 32-33. +// +typedef struct _TOK162_READADAPTERBUF { + + // + // Number of bytes to be read from the adapter + // + USHORT DataCount; + + // + // Offset for buffer + // + USHORT DataAddress; + + // + // Buffer space + // + UCHAR BufferSpace[68-6]; + +} TOK162_READADAPTERBUF, *PTOK162_READADAPTERBUF; + +// +// TOK162 Address Block +// +// IBM Spec, Page 33. +// +typedef struct _TOK162_ADDRESSBLOCK { + + // + // The node address. Used for both the current address and the permanent + // address (depending on the read call). + // + UCHAR NodeAddress[6]; + + // + // The current group address. + // + UCHAR GroupAddress[4]; + + // + // The current functional address. + // + UCHAR FunctionalAddress[4]; + +} TOK162_ADDRESSBLOCK, *PTOK162_ADDRESSBLOCK; + +// +// TOK162 Receive List +// +// IBM Spec, Pages 36-40. +// +typedef struct _TOK162_RECEIVE_LIST { + + // + // This is the physical address of the next entry + // in the Receive Ring. + // + TOK162_PHYSICAL_ADDRESS ForwardPointer; + + // + // List entry characteristics + // + USHORT CSTAT; + + // + // This is the total size of the received frame. + // + USHORT FrameSize; + + // + // This is the length (in bytes) of the buffer associated. IBM Format. + // + USHORT DataCount1; + + // + // This is the address of the buffer associated. IBM Format. + // + ULONG PhysicalAddress1; + + // + // This is the length (in bytes) of this block. Stored in IBM format + // + USHORT DataCount2; + + // + // This is the physical address of this block. Stored in IBM Format + // + ULONG PhysicalAddress2; + + // + // This is the length (in bytes) of this block. Stored in IBM format + // + USHORT DataCount3; + + // + // This is the physical address of this block. Stored in IBM Format + // + ULONG PhysicalAddress3; + + // + // This is the length (in bytes) of this block. Stored in IBM format + // + USHORT DataCount4; + + // + // This is the physical address of this block. Stored in IBM Format + // + ULONG PhysicalAddress4; + + // + // This is the length (in bytes) of this block. Stored in IBM format + // + USHORT DataCoun5; + + // + // This is the physical address of this block. Stored in IBM Format + // + ULONG PhysicalAddress5; + + // + // This is the length (in bytes) of this block. Stored in IBM format + // + USHORT DataCount6; + + // + // This is the physical address of this block. Stored in IBM Format + // + ULONG PhysicalAddress6; + + // + // This is the length (in bytes) of this block. Stored in IBM format + // + USHORT DataCount7; + + // + // This is the physical address of this block. Stored in IBM Format + // + ULONG PhysicalAddress7; + + // + // This is the length (in bytes) of this block. Stored in IBM format + // + USHORT DataCount8; + + // + // This is the physical address of this block. Stored in IBM Format + // + ULONG PhysicalAddress8; + + // + // This is the length (in bytes) of this block. Stored in IBM format + // + USHORT DataCount9; + + // + // This is the physical address of this block. Stored in IBM Format + // + ULONG PhysicalAddress9; + +} TOK162_RECEIVE_LIST, *PTOK162_RECEIVE_LIST; + +// +// Receive and Transmit buffer sizes, depending on the ring speed. +// +// IBM Spec, Page 13. +// +#define RECEIVE_LIST_BUFFER_SIZE_4 4500 +#define RECEIVE_LIST_BUFFER_SIZE_16 17986 + +// +// The number of receive lists/buffers +// +#define RECEIVE_LIST_COUNT 3 + +// +// Receive CSTAT bit masks +// +// IBM Spec, Pages 38-39. +// +#define RECEIVE_CSTAT_REQUEST_RESET 0x0088 // Valid bit + frame int +#define RECEIVE_CSTAT_VALID 0x0080 // Valid bit + +// +// Transmit list entry. This is exactly like the receive list entry. +// +// IBM Spec, Pages 46-55. +// +typedef struct _TOK162_TRANSMIT_LIST { + + // + // This is the physical address of the next entry + // in the Transmit Chain. + // + TOK162_PHYSICAL_ADDRESS ForwardPointer; + + // + // List entry characteristics. IBM Format. + // + USHORT CSTAT; + + // + // This is the total size of the received frame. IBM Format. + // + USHORT FrameSize; + + // + // This is the length (in bytes) of this block. Stored in IBM format + // + USHORT DataCount1; + + // + // This is the physical address of this block. Stored in IBM Format + // + TOK162_PHYSICAL_ADDRESS PhysicalAddress1; + + // + // This is the length (in bytes) of this block. Stored in IBM format + // + USHORT DataCount2; + + // + // This is the physical address of this block. Stored in IBM Format + // + TOK162_PHYSICAL_ADDRESS PhysicalAddress2; + + // + // This is the length (in bytes) of this block. Stored in IBM format + // + USHORT DataCount3; + + // + // This is the physical address of this block. Stored in IBM Format + // + TOK162_PHYSICAL_ADDRESS PhysicalAddress3; + + // + // This is the length (in bytes) of this block. Stored in IBM format + // + USHORT DataCount4; + + // + // This is the physical address of this block. Stored in IBM Format + // + TOK162_PHYSICAL_ADDRESS PhysicalAddress4; + + // + // This is the length (in bytes) of this block. Stored in IBM format + // + USHORT DataCoun5; + + // + // This is the physical address of this block. Stored in IBM Format + // + TOK162_PHYSICAL_ADDRESS PhysicalAddress5; + + // + // This is the length (in bytes) of this block. Stored in IBM format + // + USHORT DataCount6; + + // + // This is the physical address of this block. Stored in IBM Format + // + TOK162_PHYSICAL_ADDRESS PhysicalAddress6; + + // + // This is the length (in bytes) of this block. Stored in IBM format + // + USHORT DataCount7; + + // + // This is the physical address of this block. Stored in IBM Format + // + TOK162_PHYSICAL_ADDRESS PhysicalAddress7; + + // + // This is the length (in bytes) of this block. Stored in IBM format + // + USHORT DataCount8; + + // + // This is the physical address of this block. Stored in IBM Format + // + TOK162_PHYSICAL_ADDRESS PhysicalAddress8; + + // + // This is the length (in bytes) of this block. Stored in IBM format + // + USHORT DataCount9; + + // + // This is the physical address of this block. Stored in IBM Format + // + TOK162_PHYSICAL_ADDRESS PhysicalAddress9; + +} TOK162_TRANSMIT_LIST, *PTOK162_TRANSMIT_LIST; + +// +// The number of transmit lists +// +#define TRANSMIT_LIST_COUNT 0x0002 + +// +// The maximum number of transmit list scatter-gathers +// +#define TOK162_MAX_SG 0x0003 + +// +// Transmit CSTAT bit masks +// +#define TRANSMIT_CSTAT_REQUEST 0x00B0 +#define TRANSMIT_CSTAT_XMIT_ERROR 0x0004 + +// +// TOK162 Command Block. Contains all of the fields necessary to support +// both commands and transmits. +// +typedef struct _TOK162_COMMAND_BLOCK { + + // + // Transmit List Entry + // + TOK162_TRANSMIT_LIST TransmitEntry; + + // + // This is the state of this Command Block. + // + USHORT State; + + // + // This is the status of this Command Block. + // + USHORT Status; + + // + // This is the physical address of the next Command Block + // to be executed. If this address == -1, then there are + // no more commands to be executed. + // + UNALIGNED TOK162_PHYSICAL_ADDRESS NextPending; + + // + // This is the TOK162 Command Code. + // + USHORT CommandCode; + + // + // Pointer used by different commands + // + ULONG ParmPointer; + + // + // This is the immediate data to be used by all commands + // other than transmit. + // + ULONG ImmediateData; + +} TOK162_COMMAND_BLOCK, *PTOK162_COMMAND_BLOCK; + + +// +// Data block pointer +// Used only to reference the different fields of the transmit list entry. +// Allows code to access the transmit list entries in a for loop rather than +// having code for each specific entry. +// +// Must be packed on a 2 byte boundary. +// +typedef struct _TOK162_DATA_BLOCK { + + // + // size of the block. IBM format. + // + USHORT Size; + + // + // physical pointer to the buffer. IBM format. + // + TOK162_PHYSICAL_ADDRESS IBMPhysicalAddress; + +} TOK162_DATA_BLOCK,*PTOK162_DATA_BLOCK; + +// +// Numerical values for switches +// (e.g. - Interrupt 5 instead of 00 [switch value]) +// +// IBM Spec, Pages 8-10. +// + +// +// Adapter mode values +// +#define CFG_ADAPTERMODE_NORMAL 0x0000 +#define CFG_ADAPTERMODE_TEST 0x0001 + +// +// Wait state values +// +#define CFG_WAITSTATE_NORMAL 0x0000 +#define CFG_WAITSTATE_FAST 0x0001 + +// +// DMA channel values +// +#define CFG_DMACHANNEL_5 0x0005 +#define CFG_DMACHANNEL_6 0x0006 +#define CFG_DMACHANNEL_7 0x0007 + +// +// Connector type values +// +#define CFG_MEDIATYPE_STP 0x0000 +#define CFG_MEDIATYPE_UTP 0x0001 + +// +// Adapter interrupt values +// +#define CFG_INT_9 0x0009 +#define CFG_INT_10 0x000A +#define CFG_INT_11 0x000B +#define CFG_INT_15 0x000F + +// +// RPL address values +// +#define CFG_RPLADDR_C0000 0xC0000 +#define CFG_RPLADDR_C4000 0xC4000 +#define CFG_RPLADDR_C8000 0xC8000 +#define CFG_RPLADDR_CC000 0xCC000 +#define CFG_RPLADDR_D0000 0xD0000 +#define CFG_RPLADDR_D4000 0xD4000 +#define CFG_RPLADDR_D8000 0xD8000 +#define CFG_RPLADDR_DC000 0xDC000 + +// +// Ring speed values +// +#define CFG_RINGSPEED_4 0x0004 +#define CFG_RINGSPEED_16 0x0010 + +// +// command and result structures +// + +// +// Open command structure. Submitted to the card to insert the system in +// the Token Ring. +// +// IBM Spec, Pages 27-32. +// +typedef struct _OPEN_COMMAND { + + // + // Open options. Defined below. + // + USHORT Options; + + // + // Address to insert ourselves into the ring under. + // + UCHAR NodeAddress[6]; + + // + // Group address adapter should respond to. + // + ULONG GroupAddress; + + // + // Functional address adapter should respond to. + // + ULONG FunctionalAddress; + + // + // Size of the receive list structure + // + USHORT ReceiveListSize; + // + // Size of the transmit list structure + // + USHORT TransmitListSize; + + // + // Adapter buffer size. + // + USHORT BufferSize; + + // + // Unused. + // + USHORT Reserved1; + USHORT Reserved2; + + // + // Minimum number of buffers to reserve for transmits + // + UCHAR TransmitBufCountMin; + + // + // Maximum number of buffers to reserve for transmits + // + UCHAR TransmitBufCountMax; + + // + // Pointer to the system product ID + // + ULONG ProdIDAddress; + +} OPEN_COMMAND, *POPEN_COMMAND; + +#define OPEN_OPTION_PASS_BEACON_FRAMES 0x8000 +#define OPEN_OPTION_DISABLE_DMA_TIMEOUT 0x4000 +#define OPEN_OPTION_ENABLE_DMA_TIMEOUT 0x0000 +#define OPEN_OPTION_WRAP_INTERFACE 0x0080 +#define OPEN_OPTION_DISABLE_HARD_ERROR 0x0040 +#define OPEN_OPTION_ENABLE_HARD_ERROR 0x0000 +#define OPEN_OPTION_DISABLE_SOFT_ERROR 0x0020 +#define OPEN_OPTION_ENABLE_SOFT_ERROR 0x0000 +#define OPEN_OPTION_PASS_ADAPTER_FRAMES 0x0010 +#define OPEN_OPTION_PASS_ATTENTION_FRAMES 0x0008 +#define OPEN_OPTION_PAD_ROUTING_FIELD 0x0004 +#define OPEN_OPTION_FRAME_HOLD 0x0002 +#define OPEN_OPTION_CONTENDER 0x0001 + +// +// Values to set the open parameters to +// +#define OPEN_RECEIVE_LIST_SIZE 0x000e +#define OPEN_TRANSMIT_LIST_SIZE 0x001A +#define OPEN_BUFFER_SIZE 512 + +// +// Open completion structure (SSB) +// +// IBM Spec, Pages 31-32. +// +typedef struct _OPEN_COMPLETION { + + // + // Better be CMD_DMA_OPEN. + // + USHORT Command; + + // + // Completion code. Bitmasks defined below. + // + USHORT Completion; + + // + // Not used. + // + USHORT Reserved1; + USHORT Reserved2; + +} OPEN_COMPLETION, *POPEN_COMPLETION; + +#define OPEN_COMPLETION_MASK_PHASE 0xF000 +#define OPEN_COMPLETION_MASK_ERROR 0x0F00 +#define OPEN_COMPLETION_MASK_RESULT 0x00FF + +#define OPEN_COMPLETION_PHASE_LOBE 0x1000 +#define OPEN_COMPLETION_PHASE_INSERTION 0x2000 +#define OPEN_COMPLETION_PHASE_VERIFY 0x3000 +#define OPEN_COMPLETION_PHASE_RING 0x4000 +#define OPEN_COMPLETION_PHASE_PARMS 0x5000 + +#define OPEN_COMPLETION_ERROR_FUNCTION 0x0100 +#define OPEN_COMPLETION_ERROR_SIGLOSS 0x0200 +#define OPEN_COMPLETION_ERROR_TIMEOUT 0x0500 +#define OPEN_COMPLETION_ERROR_RINGFAIL 0x0600 +#define OPEN_COMPLETION_ERROR_RINGBEACON 0x0700 +#define OPEN_COMPLETION_ERROR_DUPLICATE 0x0800 +#define OPEN_COMPLETION_ERROR_REQPARMS 0x0900 +#define OPEN_COMPLETION_ERROR_REMOVE_REC 0x0A00 +#define OPEN_COMPLETION_ERROR_IMPL_REC 0x0B00 +#define OPEN_COMPLETION_ERROR_DUPMOD 0x0C00 + +#define OPEN_RESULT_ADAPTER_OPEN 0x0080 +#define OPEN_RESULT_NODE_ADDR_ERROR 0x0040 +#define OPEN_RESULT_LIST_SIZE_ERROR 0x0020 +#define OPEN_RESULT_BUF_SIZE_ERROR 0x0010 +#define OPEN_RESULT_EXT_RAM_ERROR 0x0008 +#define OPEN_RESULT_XMIT_CNT_ERROR 0x0004 +#define OPEN_RESULT_OPEN_ERROR 0x0002 + +// +// The adapter requires many of the WORD values and almost all of the +// DWORD values to be in IBM format, versus Intel Format. The difference +// between the two is as follows: +// +// If you are storing the value 0x1234, a word value, memory would look like: +// +// --------- --------- +// | | | | +// Intel | 34 | | 12 | +// | | | | +// --------- --------- +// Address 100 101 +// +// +// --------- --------- +// | | | | +// IBM | 12 | | 34 | +// | | | | +// --------- --------- +// Address 100 101 +// +// +// If you are storing the value 0x12345678, a dword value, memory would look +// like: +// +// --------- --------- --------- --------- +// | | | | | | | | +// Intel | 78 | | 56 | | 34 | | 12 | +// | | | | | | | | +// --------- --------- --------- --------- +// Address 100 101 +// +// +// --------- --------- --------- --------- +// | | | | | | | | +// IBM | 12 | | 34 | | 56 | | 78 | +// | | | | | | | | +// --------- --------- --------- --------- +// Address 100 101 +// +// +// To convert "Intel" WORDs and DWORDs to "IBM" format, the following macros +// are used. +// + +// +// Macro to byte swap a word. +// +#define BYTE_SWAP(_word) (\ + (USHORT) (((_word) >> 8) | ((_word) << 8)) ) + +// +// Macro to byte swap a word. +// +#define WORD_SWAP(_dword) (\ + (ULONG) (((_dword) >> 16) | ((_dword) << 16)) ) + +// +// Macro to get low byte of a word. +// +#define LOW_BYTE(_word) (\ + (UCHAR) ((_word) & 0x00FF) ) + +// +// Macro to get high byte of a word. +// +#define HIGH_BYTE(_word) (\ + (UCHAR) (((_word) >> 8) & 0x00FF) ) + +// +// Macro to get low word of a dword. +// +#define LOW_WORD(_dword) (\ + (USHORT) ((_dword) & 0x0000FFFF) ) + +// +// Macro to get high word of a dword. +// +#define HIGH_WORD(_dword) (\ + (USHORT) (((_dword) >> 16) & 0x0000FFFF) ) + +// +// Macro to create a dword from two words. +// +#define MAKE_LONG(_highword,_lowword) (\ + (ULONG) ((((ULONG)_highword) << 16) + _lowword)) + +// +// Macro to byte swap a dword. +// +#define BYTE_SWAP_ULONG(_ulong) (\ + (ULONG)((ULONG)(BYTE_SWAP(LOW_WORD(_ulong)) << 16) + \ + BYTE_SWAP(HIGH_WORD(_ulong)))) + +// +// End the packing +// +#include <poppack.h> diff --git a/private/ntos/ndis/ibmtok2i/tok162pr.h b/private/ntos/ndis/ibmtok2i/tok162pr.h new file mode 100644 index 000000000..1875cdd23 --- /dev/null +++ b/private/ntos/ndis/ibmtok2i/tok162pr.h @@ -0,0 +1,315 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + tok162pr.h + +Abstract: + + The procedure declarations for the IBM Token-Ring 16/4 II + ISA driver. + +Author: + + Kevin Martin (kevinma) 1-Feb-1994 + +Environment: + + Architecturally, there is an assumption in this driver that we are + on a little endian machine. + +Notes: + + optional-notes + +Revision History: + + +--*/ + +#ifndef _TOK162PROC_ +#define _TOK162PROC_ + +// +// We define the external interfaces to the TOK162 driver. +// These routines are only external to permit separate +// compilation. Given a truely fast compiler they could +// all reside in a single file and be static. +// + +extern +VOID +TOK162DisableInterrupt( + IN NDIS_HANDLE MiniportAdapterContext + ); + +extern +VOID +TOK162EnableInterrupt( + IN NDIS_HANDLE MiniportAdapterContext + ); + +extern +VOID +TOK162Halt( + IN NDIS_HANDLE MiniportAdapterContext + ); + +extern +VOID +TOK162Shutdown( + IN NDIS_HANDLE MiniportAdapterContext + ); + +extern +VOID +TOK162HandleInterrupt( + IN NDIS_HANDLE MiniportAdapterContext + ); + +extern +BOOLEAN +TOK162InitialInit( + IN PTOK162_ADAPTER Adapter + ); +extern +NDIS_STATUS +TOK162Initialize( + OUT PNDIS_STATUS OpenErrorStatus, + OUT PUINT SelectedMediumIndex, + IN PNDIS_MEDIUM MediumArray, + IN UINT MediumArraySize, + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE WrapperConfigurationContext + ); + +extern +NDIS_STATUS +TOK162QueryInformation( + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_OID Oid, + IN PVOID InformationBuffer, + IN ULONG InformationBufferLength, + OUT PULONG BytesWritten, + OUT PULONG BytesNeeded + ); + +extern +NDIS_STATUS +TOK162SetInformation( + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_OID Oid, + IN PVOID InformationBuffer, + IN ULONG InformationBufferLength, + OUT PULONG BytesRead, + OUT PULONG BytesNeeded + ); + +extern +VOID +TOK162Isr( + OUT PBOOLEAN InterruptRecognized, + OUT PBOOLEAN QueueDpc, + IN NDIS_HANDLE MiniportAdapterContext + ); + +extern +NDIS_STATUS +TOK162Reset( + OUT PBOOLEAN AddressingReset, + IN NDIS_HANDLE MiniportAdapterContext + ); + +extern +NDIS_STATUS +TOK162TransferData( + OUT PNDIS_PACKET Packet, + OUT PUINT BytesTransferred, + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_HANDLE MiniportReceiveContext, + IN UINT ByteOffset, + IN UINT BytesToTransfer + ); + +extern +NDIS_STATUS +TOK162Send( + IN NDIS_HANDLE MiniportAdapterContext, + IN PNDIS_PACKET Packet, + IN UINT Flags + ); + +extern +VOID +TOK162CopyFromBufferToPacket( + IN PCHAR Buffer, + IN UINT BytesToCopy, + IN PNDIS_PACKET Packet, + IN UINT Offset, + OUT PUINT BytesCopied + ); + + +VOID +TOK162FinishQueryInformation( + IN PTOK162_ADAPTER Adapter +); + +extern +NDIS_STATUS +TOK162RegisterAdapter( + IN NDIS_HANDLE ConfigurationHandle, + IN NDIS_HANDLE MiniportAdapterHandle, + IN PUCHAR CurrentAddress, + IN UINT PortAddress, + IN ULONG MaxFrameSize + ); + +extern +VOID +TOK162AcquireCommandBlock( + IN PTOK162_ADAPTER Adapter, + OUT PTOK162_SUPER_COMMAND_BLOCK * CommandBlock + ); + +extern +BOOLEAN +TOK162AcquireTransmitBlock( + IN PTOK162_ADAPTER Adapter, + OUT PTOK162_SUPER_COMMAND_BLOCK * CommandBlock + ); + +extern +VOID +TOK162RelinquishCommandBlock( + IN PTOK162_ADAPTER Adapter, + IN PTOK162_SUPER_COMMAND_BLOCK CommandBlock + ); + +extern +VOID +TOK162SubmitCommandBlock( + IN PTOK162_ADAPTER Adapter, + IN PTOK162_SUPER_COMMAND_BLOCK CommandBlock + ); + +extern +VOID +TOK162DoAdapterReset( + IN PTOK162_ADAPTER Adapter + ); + +extern +NDIS_STATUS +TOK162SetupForReset( + IN PTOK162_ADAPTER Adapter + ); + +BOOLEAN +TOK162CheckForHang( + IN NDIS_HANDLE MiniportAdapterContext + ); + +VOID +TOK162ResetVariables( + IN PTOK162_ADAPTER Adapter + ); + +VOID +TOK162ResetHandler( + IN PVOID SystemSpecific1, + IN PTOK162_ADAPTER Adapter, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3 + ); + +VOID +TOK162DeferredTimer( + IN PVOID SystemSpecific1, + IN PTOK162_ADAPTER Adapter, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3 + ); + + +extern +NDIS_STATUS +TOK162GetAdapterConfiguration( + IN PTOK162_ADAPTER Adapter + ); +extern +VOID +TOK162ResetAdapter( + IN PTOK162_ADAPTER Adapter + ); + +BOOLEAN +DoTheOpen( + PTOK162_ADAPTER Adapter + ); + +BOOLEAN +DoTheReceive( + PTOK162_ADAPTER Adapter + ); + +extern +NDIS_STATUS +TOK162ChangeFuncGroup( + IN PTOK162_ADAPTER Adapter +); + + +BOOLEAN +TOK162InitializeTransmitQueue( + IN PTOK162_ADAPTER Adapter + ); +VOID +TOK162ResetTimer( + IN PVOID SystemSpecific1, + IN PTOK162_ADAPTER Adapter, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3 + ); +VOID +TOK162DoResetIndications( + IN PTOK162_ADAPTER Adapter, + IN NDIS_STATUS Status + ); + +BOOLEAN +TOK162AcquireTransmitBlock( + IN PTOK162_ADAPTER Adapter, + OUT PTOK162_SUPER_COMMAND_BLOCK * CommandBlock + ); + +VOID +TOK162RelinquishTransmitBlock( + IN PTOK162_ADAPTER Adapter, + IN PTOK162_SUPER_COMMAND_BLOCK CommandBlock + ); + +VOID +TOK162SubmitTransmitBlock( + IN PTOK162_ADAPTER Adapter, + IN PTOK162_SUPER_COMMAND_BLOCK CommandBlock + ); +VOID +TOK162ProcessTransmitInterrupts( + IN PTOK162_ADAPTER Adapter + ); +extern +BOOLEAN +TOK162ProcessRingInterrupts( + IN PTOK162_ADAPTER Adapter + ); + +extern +VOID +TOK162DeleteAdapterMemory( + IN PTOK162_ADAPTER Adapter + ); + +#endif //_TOK162PROC_ diff --git a/private/ntos/ndis/ibmtok2i/tok162sw.h b/private/ntos/ndis/ibmtok2i/tok162sw.h new file mode 100644 index 000000000..8f431b6b1 --- /dev/null +++ b/private/ntos/ndis/ibmtok2i/tok162sw.h @@ -0,0 +1,699 @@ +/*++ + +Copyright (c) 1992 Microsoft Corporation + +Module Name: + + tok162sw.h + +Abstract: + + The hardware-related definitions for the IBM Token-Ring 16/4 II + ISA driver. + +Author: + + Kevin Martin (kevinma) 1-Feb-1994 + +Environment: + + Architecturally, there is an assumption in this driver that we are + on a little endian machine. + +Notes: + + optional-notes + +Revision History: + + +--*/ + +#include <ndis.h> +#include <tok162hw.h> + +// +// Temporary #define for debugging regardless of DBG flag +// +#define MYDBGPRINT DbgPrint; + +// +// Debugging flags. +// +#if DBG + +// +// Degrees of debugging output. Can be OR'd in any combination. +// +#define TOK162_DEBUG_LOUD 0x1 +#define TOK162_DEBUG_VERY_LOUD 0x2 +#define TOK162_DEBUG_EXTRA_LOUD 0x4 + +// +// The degree of debugging output being displayed on the debugger currently. +// Defined in TOK162.C. +// +extern UCHAR Tok162Debug; + +// +// Macros that decide on the debugging based on Tok162Debug. +// +#define LOUD_DEBUG(A) if (Tok162Debug & TOK162_DEBUG_LOUD) { A ; } +#define VERY_LOUD_DEBUG(A) if (Tok162Debug & TOK162_DEBUG_VERY_LOUD) { A ; } +#define EXTRA_LOUD_DEBUG(A) if (Tok162Debug & TOK162_DEBUG_EXTRA_LOUD) { A ; } +#define CURRENT_DEBUG(A) if (Tok162Debug & 8) { A ; } + +// +// The size of the logging array +// +#define LOG_SIZE 256 + +// +// Pointer for the logging array. Allocated in TOK162.C +// (AllocateAdapterMemory) +// +extern PUCHAR Tok162Log; + +// +// The current index into the logging array. +// +extern USHORT Tok162LogPlace; + +// +// Logging macro. +// +#define IF_LOG(ch) { Tok162Log[Tok162LogPlace] = (ch); \ + Tok162LogPlace = (Tok162LogPlace + 1) % LOG_SIZE; } + +#else // if dbg + +// +// Make sure all of the debugging and logging calls resolve to NULL +// +#define LOUD_DEBUG(A) +#define VERY_LOUD_DEBUG(A) +#define EXTRA_LOUD_DEBUG(A) + +#define IF_LOG(ch) { } + +#endif // if dbg + +// +// Version constants for this driver +// +#define TOK162_NDIS_MAJOR_VERSION 3 +#define TOK162_NDIS_MINOR_VERSION 0 + +// +// Macro to allocate physical memory. +// +#define TOK162_ALLOC_PHYS(_Status, _pBuffer, _Length) \ +{ \ + NDIS_PHYSICAL_ADDRESS MinusOne = NDIS_PHYSICAL_ADDRESS_CONST (-1, -1); \ + *(_Status) = NdisAllocateMemory( \ + (PVOID*)(_pBuffer), \ + (_Length), \ + 0, \ + MinusOne); \ +} + +// +// Macro to free physical memory previously allocated. +// +#define TOK162_FREE_PHYS(_Buffer) NdisFreeMemory((_Buffer), 0, 0) + +// +// Enumeration for the reset stages. +// +enum ResetStates{InitialInit, + CheckReset, + CheckResetRetry, + DoTheInit, + CheckInit, + CheckInitRetry + }; + +// +// Adapter structure is defined further down. +// +struct _TOK162_ADAPTER; + + +// +// TOK162 Configuration Block +// +// This structure contains configuration data for the TOK162. This +// structure is filled in based on the switches. +// +typedef struct _TOK162_CONFIGURATION_BLOCK { + + // + // This is the adapter mode; + // + USHORT AdapterMode; + + // + // This field contains the wait state + // + USHORT WaitState; + + // + // This field contains the RPL + // + BOOLEAN RPL; + + // + // This field contains the RPL Address + // + UINT RPLAddress; + + // + // This field contains the DMA Channel + // + USHORT DMAChannel; + + // + // This field contains the Ring Speed + // + USHORT RingSpeed; + + // + // Interrupt level + // + USHORT InterruptLevel; + + // + // This field contains the connector type + // + USHORT UTPorSTP; + +} TOK162_CONFIGURATION_BLOCK, *PTOK162_CONFIGURATION_BLOCK; + +// +// In addition to the Command Block fields which the TOK162HW.H +// defines, we need some additional fields for our own purposes. +// To ensure that these fields are properly aligned (and to +// ensure that the actual Command Block is properly aligned) +// we'll defined a Super Command Block. This structure will +// contain a "normal" TOK162 Command Block plus some additional +// fields. This structure is used for both commands and transmits. +// +typedef struct _TOK162_SUPER_COMMAND_BLOCK { + + // + // The actual TOK162 Command Block. + // + TOK162_COMMAND_BLOCK Hardware; + + // + // This contains the physical address of the above Command Block. + // + NDIS_PHYSICAL_ADDRESS Self; + TOK162_PHYSICAL_ADDRESS PhysicalTransmitEntry; + + // + // Constrain Buffer addresses + // + NDIS_PHYSICAL_ADDRESS TOK162BufferPhysicalAddress; + TOK162_PHYSICAL_ADDRESS TOK162BufferAddress; + + // + // This contains the virtual address of the next pending command. + // + struct _TOK162_SUPER_COMMAND_BLOCK *NextCommand; + + // + // Points to the packet from which data is being transmitted + // through this Command Block. + // + PNDIS_PACKET OwningPacket; + + // + // When a packet is submitted to the hardware we record + // here whether it used adapter buffers and if so, the buffer + // index. + // + BOOLEAN UsedTOK162Buffer; + + // + // Is this from a set + // + BOOLEAN Set; + + // + // If this is a public (adapter-wide) command block, then + // this will contain this block's index into the adapter's + // command queue. + // + USHORT CommandBlockIndex; + + // + // This tells if the command block is a regular or transmit command block. + // + BOOLEAN CommandBlock; + + // + // This field is used to timestamp the command blocks + // as they are placed into the command queue. If a + // block fails to execute, the adapter will get a kick in the ass to + // start it up again. + // + BOOLEAN Timeout; + + // + // Count of the number of times we have retried a command. + // + UCHAR TimeoutCount; + + // + // Points to an Mdl which points to this buffer + // + PNDIS_BUFFER FlushBuffer; + +} TOK162_SUPER_COMMAND_BLOCK, *PTOK162_SUPER_COMMAND_BLOCK; + +// +// In addition to the Receive Entry fields which the TOK162HW.H +// defines, we need some additional fields for our own purposes. +// To ensure that these fields are properly aligned (and to +// ensure that the actual Receive Entry is properly aligned) +// we'll defined a Super Receive Entry. This structure will +// contain a "normal" TOK162 Receive Entry plus some additional +// fields. +// +typedef struct _TOK162_SUPER_RECEIVE_LIST { + + // + // The actual TOK162 Receive List. + // + TOK162_RECEIVE_LIST Hardware; + + // + // This contains the physical address of the above Receive List. + // + NDIS_PHYSICAL_ADDRESS Self; + + // + // This contains the virtual address of this Receive List's + // frame buffer. + // + PVOID ReceiveBuffer; + NDIS_PHYSICAL_ADDRESS ReceiveBufferPhysical; + + // + // This contains the virtual address of the next + // Receive List in the Receive Queue. + // + struct _TOK162_SUPER_RECEIVE_LIST *NextEntry; + + // + // Points to an Mdl which points to this buffer + // + PNDIS_BUFFER FlushBuffer; + +} TOK162_SUPER_RECEIVE_LIST, *PTOK162_SUPER_RECEIVE_LIST; + +// +// Adapter Structure +// + +typedef struct _TOK162_ADAPTER { + + // + // Handle given by NDIS when the miniport was initialized. + // + NDIS_HANDLE MiniportAdapterHandle; + + // + // Interrupt pointers and variables for the adapter + // + NDIS_MINIPORT_INTERRUPT Interrupt; + USHORT InterruptLevel; + + // + // Are we running at 16Mbps? + // + BOOLEAN Running16Mbps; + + // + // Pointers for the System Command Block for the adapter + // + PSCB Scb; + NDIS_PHYSICAL_ADDRESS ScbPhysical; + + // + // Pointers for the System Status Block for the adapter + // + PSSB Ssb; + NDIS_PHYSICAL_ADDRESS SsbPhysical; + + // + // Command queue and related variables + // + PTOK162_SUPER_COMMAND_BLOCK CommandQueue; + NDIS_PHYSICAL_ADDRESS CommandQueuePhysical; + + // + // Index to next command block + // + UINT NextCommandBlock; + + // + // Number of command blocks available for use + // + UINT NumberOfAvailableCommandBlocks; + + // + // Active command. + // + PTOK162_SUPER_COMMAND_BLOCK CommandOnCard; + + // + // First pending command. + // + PTOK162_SUPER_COMMAND_BLOCK WaitingCommandHead; + + // + // Last pending command. + // + PTOK162_SUPER_COMMAND_BLOCK WaitingCommandTail; + + // + // Current packet filter on adapter + // + UINT CurrentPacketFilter; + + // + // Is there an outstanding request + // + BOOLEAN RequestInProgress; + + // + // Number of bytes needed and written. + // + PUINT BytesWritten; + PUINT BytesNeeded; + + // + // Current Oid processing. + // + NDIS_OID Oid; + + // + // Buffer and length of buffer used for doing query/set info calls. + // + PVOID InformationBuffer; + UINT InformationBufferLength; + + // + // Current interrupt value + // + USHORT InterruptMask; + + // + // Command that caused the interrupt + // + USHORT SsbCommand; + + // + // The status variables that are saved as the result of an interrupt + // + USHORT SsbStatus1; + USHORT SsbStatus2; + USHORT SsbStatus3; + + // + // The I/O Base address of the adapter. + // + ULONG PortIOBase; + PVOID PortIOAddress; + + // + // Pointers and variables for the Open block for the adapter + // + POPEN_COMMAND Open; + NDIS_PHYSICAL_ADDRESS OpenPhysical; + + // + // The network address for the adapter and the current one being used. + // + CHAR NetworkAddress[TOK162_LENGTH_OF_ADDRESS]; + CHAR CurrentAddress[TOK162_LENGTH_OF_ADDRESS]; + + // + // Functional and Group Addresses for the adapter + // + ULONG FunctionalAddress; + ULONG GroupAddress; + + // + // Pointer to the Receive Queue. + // + PTOK162_SUPER_RECEIVE_LIST ReceiveQueue; + NDIS_PHYSICAL_ADDRESS ReceiveQueuePhysical; + + // + // Pointer to the current receive list + // + PTOK162_SUPER_RECEIVE_LIST ReceiveQueueCurrent; + + // + // Number of frame header bytes in the buffer. + // + USHORT SizeOfReceivedHeader; + + // + // Count of the receive buffers + // + UINT NumberOfReceiveBuffers; + + // + // Size of the receive buffer, based on the ring speed. + // + USHORT ReceiveBufferSize; + + // + // The receive flush buffer pool handle + // + PNDIS_HANDLE FlushBufferPoolHandle; + + // + // Pointer to the Transmit Command Queue. + // + PTOK162_SUPER_COMMAND_BLOCK TransmitQueue; + NDIS_PHYSICAL_ADDRESS TransmitQueuePhysical; + + // + // Index of next available transmit block + // + UINT NextTransmitBlock; + + // + // Pointer to active transmit. + // + PTOK162_SUPER_COMMAND_BLOCK TransmitOnCard; + + // + // Pointer to head of waiting queue. + // + PTOK162_SUPER_COMMAND_BLOCK WaitingTransmitHead; + + // + // Pointer to tail of waiting queue + // + PTOK162_SUPER_COMMAND_BLOCK WaitingTransmitTail; + + // + // Number of transmit blocks currently free + // + UINT NumberOfAvailableTransmitBlocks; + + // + // Total number of transmit blocks/lists + // + UINT NumberOfTransmitLists; + + // + // Maximum number of physical buffers that we can handle and still not + // have to merge the packet + // + USHORT TransmitThreshold; + + // + // Flag that when enabled lets routines know that a reset + // is in progress. + // + BOOLEAN ResetInProgress; + + // + // Are we doing the initial initialization? + // + BOOLEAN InitialInit; + + // + // Has the initial open completed? + // + BOOLEAN InitialOpenComplete; + + // + // Has the initial receive command been sent + // + BOOLEAN InitialReceiveSent; + + // + // Last open error code. + // + USHORT OpenErrorCode; + + // + // Reset State + // + USHORT ResetState; + + // + // Variables to keep track of the number of retries attempted during + // a reset + // + USHORT ResetRetries; + USHORT InitRetries; + + // + // Result of Reset command + // + NDIS_STATUS ResetResult; + + // + // Offsets into adapter memory for different structures. + // These are obtained at initialization time and the values + // are read using the READ.ADAPTER DMA command. + // + USHORT UniversalAddress; + USHORT MicrocodeLevel; + USHORT AdapterAddresses; + USHORT AdapterParms; + USHORT MacBuffer; + + // + // Buffer for READ.ERROR.LOG + // + PTOK162_ERRORLOG ErrorLog; + NDIS_PHYSICAL_ADDRESS ErrorLogPhysical; + + // + // Buffer for READ.ADAPTER for node addresses. If more info is needed + // in the future, this will have to be changed as the current addresses + // are being stored here (func,node,group) + // + PTOK162_READADAPTERBUF AdapterBuf; + NDIS_PHYSICAL_ADDRESS AdapterBufPhysical; + + // + // Counters to hold the various number of errors/statistics for both + // reception and transmission. + // + UINT ReceiveCongestionError; + UINT LineError; + UINT LostFrameError; + UINT BurstError; + UINT FrameCopiedError; + UINT TokenError; + UINT InternalError; + UINT ARIFCIError; + UINT AbortDelimeter; + UINT DMABusError; + + // + // Packet counts + // + UINT GoodTransmits; + UINT GoodReceives; + UINT TransmitsQueued; + UINT BadTransmits; + UINT BadReceives; + + // + // Timer objects for TOK162InterruptHandler and TOK162ResetHandler + // + NDIS_MINIPORT_TIMER DeferredTimer; + NDIS_MINIPORT_TIMER ResetTimer; + + // + // Holds number of different types of RING.STATUS.CHANGE + // indications. + // + UINT SignalLoss; + UINT HardError; + UINT SoftError; + UINT TransmitBeacon; + UINT LobeWireFault; + UINT AutoRemovalError; + UINT RemoveReceived; + UINT CounterOverflow; + UINT SingleStation; + UINT RingRecovery; + + // + // Current state of the ring. + // + NDIS_802_5_RING_STATE CurrentRingState; + + // + // Last ring status indicated to protocols. + // + NDIS_STATUS LastNotifyStatus; + + // + // This is a pointer to the Configuration Block for this + // adapter. The Configuration Block will be modified during + // changes to the packet filter. + // + TOK162_CONFIGURATION_BLOCK ConfigurationBlock; + + // + // Pointer to the initialization block + // + PADAPTER_INITIALIZATION InitializationBlock; + NDIS_PHYSICAL_ADDRESS InitializationBlockPhysical; + + // + // This points to the next adapter registered for the same Miniport + // + LIST_ENTRY AdapterList; + +} TOK162_ADAPTER,*PTOK162_ADAPTER; + +// +// Given a MiniportContextHandle return the PTOK162_ADAPTER +// it represents. +// +#define PTOK162_ADAPTER_FROM_CONTEXT_HANDLE(Handle) \ + ((PTOK162_ADAPTER)(Handle)) + +// +// This record type is inserted into the MiniportReserved portion +// of the packet header when the packet is going through the +// staged allocation of buffer space prior to the actual send. +// +typedef struct _TOK162_RESERVED { + + // + // Number of Buffers to move + // + UINT NdisBuffersToMove; + + // + // Don't need this part. Reserve it. + // + UINT Reserved; + + +} TOK162_RESERVED,*PTOK162_RESERVED; + +// +// This macro will return a pointer to the TOK162 reserved portion +// of a packet given a pointer to a packet. +// +#define PTOK162_RESERVED_FROM_PACKET(Packet) \ + ((PTOK162_RESERVED)((Packet)->MiniportReserved)) + +#include <tok162pr.h> |