summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/ibmtok2e/command.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ndis/ibmtok2e/command.c')
-rw-r--r--private/ntos/ndis/ibmtok2e/command.c1811
1 files changed, 1811 insertions, 0 deletions
diff --git a/private/ntos/ndis/ibmtok2e/command.c b/private/ntos/ndis/ibmtok2e/command.c
new file mode 100644
index 000000000..3705e163d
--- /dev/null
+++ b/private/ntos/ndis/ibmtok2e/command.c
@@ -0,0 +1,1811 @@
+/*++
+
+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
+ );
+
+extern
+NDIS_STATUS
+TOK162ChangeAddress(
+ OUT PTOK162_ADAPTER Adapter,
+ IN ULONG Address,
+ IN NDIS_OID Oid,
+ IN USHORT Command,
+ IN BOOLEAN Set
+ );
+
+
+VOID
+TOK162SubmitCommandBlock(
+ IN PTOK162_ADAPTER Adapter,
+ IN PTOK162_SUPER_COMMAND_BLOCK CommandBlock
+ )
+
+/*++
+
+Routine Description:
+
+ Submit a complete Command Block for execution by the TOK162.
+
+ NOTE: This routine assumes that it is called with the lock held.
+
+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;
+
+ //
+ // 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
+ //
+ 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;
+
+ //
+ // send the command out to the card
+ //
+ TOK162SendCommandBlock(Adapter,CommandBlock);
+
+ }
+
+}
+
+VOID
+TOK162AcquireCommandBlock(
+ IN PTOK162_ADAPTER Adapter,
+ OUT PTOK162_SUPER_COMMAND_BLOCK * CommandBlock
+ )
+
+/*++
+
+Routine Description:
+
+ Gets the command block.
+
+ NOTE: This routine assumes that the lock is held.
+
+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);
+
+ //
+ // 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;
+
+ //
+ // 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;
+
+}
+
+
+VOID
+TOK162RelinquishCommandBlock(
+ IN PTOK162_ADAPTER Adapter,
+ IN PTOK162_SUPER_COMMAND_BLOCK CommandBlock
+ )
+
+/*++
+
+Routine Description:
+
+ Relinquish the Command Block resource.
+
+ NOTE: This routine assumes that the lock is held.
+
+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) {
+
+ //
+ // 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 {
+
+ //
+ // 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
+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.
+
+--*/
+
+ //
+ // First figure out the SCB, based on the command
+ //
+ Adapter->Scb->Command = CommandBlock->Hardware.CommandCode;
+
+ switch(Adapter->Scb->Command) {
+
+ //
+ // 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 =
+ HIGH_WORD(CommandBlock->Hardware.ImmediateData);
+
+ Adapter->Scb->Parm2 =
+ LOW_WORD(CommandBlock->Hardware.ImmediateData);
+
+ break;
+
+ //
+ // The rest use a pointer.
+ //
+ case CMD_DMA_OPEN:
+ case CMD_DMA_READ_ERRLOG:
+ case CMD_DMA_READ:
+ case CMD_DMA_IMPL_ENABLE:
+
+ //
+ // The parameter is set according to the ParmPointer field of
+ // the command block.
+ //
+ Adapter->Scb->Parm1 =
+ HIGH_WORD(CommandBlock->Hardware.ParmPointer);
+
+ Adapter->Scb->Parm2 =
+ LOW_WORD(CommandBlock->Hardware.ParmPointer);
+
+ break;
+
+ }
+
+ //
+ // Mark the command block as executing
+ //
+ CommandBlock->Hardware.State = TOK162_STATE_EXECUTING;
+
+ //
+ // Display the SCB on the debugger
+ //
+ EXTRA_LOUD_DEBUG(DbgPrint("IBMTOK2E!SCB going out is %x,%x,%x\n",
+ Adapter->Scb->Command,
+ Adapter->Scb->Parm1,
+ Adapter->Scb->Parm2);)
+
+ //
+ // Download the SCB to the card
+ //
+ TOK162DownLoadScb(Adapter);
+
+ //
+ // Finally, send the command out to the card
+ //
+ WRITE_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_COMMAND,
+ EXECUTE_SCB_COMMAND
+ );
+
+}
+
+
+void
+TOK162UpLoadSsb(
+ IN PTOK162_ADAPTER Adapter
+ )
+/*++
+
+Routine Description:
+
+ Reads the Ssb from the card and stores it in the Adapter structure
+
+Arguments:
+
+ Adapter - The adapter that has info in the Ssb.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // First set the address register on the card to point to the Ssb
+ //
+ WRITE_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_ADDRESS,
+ Adapter->CommunicationOffset + COMMUNICATION_SSB_OFFSET
+ );
+
+ //
+ // Now read the Ssb from the card starting with the command
+ //
+ READ_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_DATA_AUTO_INC,
+ &Adapter->Ssb->Command
+ );
+
+ //
+ // Now read the first parameter of the Ssb
+ //
+ READ_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_DATA_AUTO_INC,
+ &Adapter->Ssb->Status1
+ );
+
+ //
+ // Now read the second parameter of the Ssb
+ //
+ READ_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_DATA_AUTO_INC,
+ &Adapter->Ssb->Status2
+ );
+
+ //
+ // Now read the second parameter of the Ssb
+ //
+ READ_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_DATA_AUTO_INC,
+ &Adapter->Ssb->Status3
+ );
+}
+
+
+void
+TOK162DownLoadScb(
+ IN PTOK162_ADAPTER Adapter
+ )
+/*++
+
+Routine Description:
+
+ Sends the readied SCB to the card
+
+Arguments:
+
+ Adapter - The adapter that owns the Command Block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // First set the address register on the card to point to the SCB
+ //
+ WRITE_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_ADDRESS,
+ Adapter->CommunicationOffset
+ );
+
+ //
+ // Now write the SCB to the card starting with the command
+ //
+ WRITE_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_DATA_AUTO_INC,
+ Adapter->Scb->Command
+ );
+
+ //
+ // Now write the first parameter of the SCB
+ //
+ WRITE_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_DATA_AUTO_INC,
+ Adapter->Scb->Parm1
+ );
+
+ //
+ // Now write the first parameter of the SCB
+ //
+ WRITE_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_DATA_AUTO_INC,
+ Adapter->Scb->Parm2
+ );
+
+}
+
+
+void
+TOK162DownLoadReceiveList(
+ IN PTOK162_ADAPTER Adapter,
+ IN PTOK162_SUPER_RECEIVE_LIST RcvList
+ )
+/*++
+
+Routine Description:
+
+ Writes a receive list to the adapter
+
+Arguments:
+
+ Adapter - The adapter that owns the Command Block.
+ RcvList - Receive List to be written to the adapter
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // First set the address register on the card to point to correct
+ // receive list.
+ //
+ WRITE_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_ADDRESS,
+ RcvList->AdapterOffset
+ );
+
+ //
+ // Write the size of the buffer
+ //
+ WRITE_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_DATA_AUTO_INC,
+ Adapter->ReceiveBufferSize
+ );
+
+ //
+ // Now write high part of the buffer address
+ //
+ WRITE_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_DATA_AUTO_INC,
+ HIGH_WORD(NdisGetPhysicalAddressLow(RcvList->ReceiveBufferPhysical))
+ );
+
+ //
+ // Now write the low part of the buffer address
+ //
+ WRITE_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_DATA_AUTO_INC,
+ LOW_WORD(NdisGetPhysicalAddressLow(RcvList->ReceiveBufferPhysical))
+ );
+
+ //
+ // Now write the Receive List CSTAT to the card
+ //
+ WRITE_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_DATA_AUTO_INC,
+ RcvList->Hardware.CSTAT
+ );
+
+}
+
+
+void
+TOK162UpLoadReceiveList(
+ IN PTOK162_ADAPTER Adapter,
+ OUT PTOK162_SUPER_RECEIVE_LIST RcvList
+ )
+/*++
+
+Routine Description:
+
+ Reads a receive list from the adapter
+
+Arguments:
+
+ Adapter - The adapter that owns the Command Block.
+ RcvList - Receive List to be read
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Dummy variable to hold the address of the buffer, which won't change
+ //
+ USHORT Dummy;
+
+ //
+ // First set the address register on the card to point to correct
+ // receive list.
+ //
+ WRITE_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_ADDRESS,
+ RcvList->AdapterOffset
+ );
+
+ //
+ // Read the size of the buffer
+ //
+ READ_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_DATA_AUTO_INC,
+ &(RcvList->Hardware.FrameSize)
+ );
+
+ //
+ // Read the high part of the buffer address
+ //
+ READ_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_DATA_AUTO_INC,
+ &Dummy
+ );
+
+ //
+ // Read the low part of the buffer address
+ //
+ READ_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_DATA_AUTO_INC,
+ &Dummy
+ );
+
+ //
+ // Now read the Receive List CSTAT
+ //
+ READ_ADAPTER_USHORT(Adapter,
+ PORT_OFFSET_DATA_AUTO_INC,
+ &RcvList->Hardware.CSTAT
+ );
+
+}
+
+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;
+
+ //
+ // 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("IBMTOK2E!Functional Address is now %x\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_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;
+
+ }
+
+ //
+ // Make sure packet filter is valid
+ //
+ TempFilter = *(PULONG)(InformationBuffer);
+ VERY_LOUD_DEBUG(DbgPrint("IBMTOK2E!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;
+ }
+
+ //
+ // We have a good packet filter, so save it.
+ //
+ 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);
+
+ 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.
+ //
+ VERY_LOUD_DEBUG(DbgPrint("IBMTOK2E!Address being set is %lx\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);
+
+ //
+ // 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;
+
+ //
+ // 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;
+
+ //
+ // Figure out the specific command based on the OID
+ //
+ switch(Oid) {
+
+ //
+ // If the permanent address is requested, we need to read from
+ // the adapter at the permanent address offset.
+ //
+ case OID_802_5_PERMANENT_ADDRESS:
+
+ //
+ // Fill in the adapter buffer area with the information to
+ // obtain the permanent address.
+ //
+ Adapter->AdapterBuf->DataCount = 0x0006;
+
+ Adapter->AdapterBuf->DataAddress = 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_FUNCTIONAL:
+ case OID_802_5_CURRENT_GROUP:
+ case OID_802_5_CURRENT_ADDRESS:
+
+ //
+ // Set up the adapter buffer to get the current addresses.
+ //
+ Adapter->AdapterBuf->DataCount = 0x000e;
+
+ Adapter->AdapterBuf->DataAddress = 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:
+
+ //
+ // Set the command block for a read error log command.
+ //
+ CommandBlock->Hardware.CommandCode = CMD_DMA_READ_ERRLOG;
+
+ CommandBlock->Hardware.ParmPointer =
+ NdisGetPhysicalAddressLow(Adapter->ErrorLogPhysical);
+
+ break;
+ }
+
+ //
+ // Now that we're set up, let's do it!
+ //
+ Adapter->RequestInProgress = TRUE;
+
+ //
+ // Submit the command to the card
+ //
+ TOK162SubmitCommandBlock(Adapter,
+ CommandBlock
+ );
+
+ //
+ // Complete the request when the interrupt comes in.
+ //
+
+ return NDIS_STATUS_PENDING;
+}
+
+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_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 need help on loopback,
+ // we copy lookahead data, and we have serialized receives.
+ //
+ GenericUlong = (ULONG)(NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
+ //NDIS_MAC_OPTION_NO_LOOPBACK |
+ 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:
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+
+ GenericUlong = Adapter->ReceiveBufferSize - TOK162_HEADER_SIZE;
+ 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 *
+ TRANSMIT_LIST_COUNT;
+
+ 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.
+ //
+ NdisMoveMemory(
+ (PVOID)&GenericUlong,
+ Adapter->NetworkAddress,
+ 3
+ );
+ GenericUlong &= 0xFFFFFF00;
+
+ MoveSource = (PVOID)(&GenericUlong);
+
+ MoveBytes = sizeof(GenericUlong);
+
+ break;
+
+ //
+ // Return our vendor string
+ //
+ case OID_GEN_VENDOR_DESCRIPTION:
+
+ MoveSource = (PVOID)"IBM Busmaster EISA TokenRing Adapter ";
+
+ MoveBytes = 30;
+
+ break;
+
+ //
+ // Return our version (3.00) 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 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);
+}