From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/ndis/ne3200/command.c | 272 +++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 private/ntos/ndis/ne3200/command.c (limited to 'private/ntos/ndis/ne3200/command.c') diff --git a/private/ntos/ndis/ne3200/command.c b/private/ntos/ndis/ne3200/command.c new file mode 100644 index 000000000..1e3bee680 --- /dev/null +++ b/private/ntos/ndis/ne3200/command.c @@ -0,0 +1,272 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + command.c + +Abstract: + + This file contains the code for managing Command Blocks on the + NE3200's Command Queue. + +Author: + + Keith Moore (KeithMo) 07-Feb-1991 + +Environment: + +Revision History: + + +--*/ + +#include + + +VOID +FASTCALL +Ne3200Stall( + PULONG Dummy + ) +/*++ + +Routine Description: + + This routine is used to cause the processor to spin momentarily, + without actually having to stall for a full microsecond, as in + NdisStallExecution. + +Arguments: + + Dummy - A variable to increment. + +Return Value: + + None. + +--*/ + +{ + (*Dummy)++; +} + + +VOID +NE3200AcquirePublicCommandBlock( + IN PNE3200_ADAPTER Adapter, + OUT PNE3200_SUPER_COMMAND_BLOCK * CommandBlock + ) + +/*++ + +Routine Description: + + Gets a public 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. + +--*/ + +{ + + // + // This is a pointer to the "public" Command Block. + // + PNE3200_SUPER_COMMAND_BLOCK PublicCommandBlock = + Adapter->PublicCommandQueue + Adapter->NextPublicCommandBlock; + + + ASSERT(Adapter->NumberOfPublicCommandBlocks > 0); + + // + // Remove a command block count. + // + Adapter->NumberOfPublicCommandBlocks--; + + // + // Initialize the Command Block. + // + NdisZeroMemory( + PublicCommandBlock, + sizeof(NE3200_SUPER_COMMAND_BLOCK) + ); + + PublicCommandBlock->Hardware.NextPending = NE3200_NULL; + PublicCommandBlock->AvailableCommandBlockCounter = + &Adapter->NumberOfPublicCommandBlocks; + NdisSetPhysicalAddressLow( + PublicCommandBlock->Self, + NdisGetPhysicalAddressLow(Adapter->PublicCommandQueuePhysical) + + Adapter->NextPublicCommandBlock * sizeof(NE3200_SUPER_COMMAND_BLOCK)); + + // + // Increment to next command block + // + Adapter->NextPublicCommandBlock++; + if (Adapter->NextPublicCommandBlock == NE3200_NUMBER_OF_PUBLIC_CMD_BLOCKS) { + Adapter->NextPublicCommandBlock = 0; + } + + IF_LOG('q'); + + // + // Return the Command Block pointer. + // + *CommandBlock = PublicCommandBlock; + + IF_NE3200DBG(ACQUIRE) { + + DPrint2( + "Acquired public command block @ %08lX\n", + (ULONG)PublicCommandBlock + ); + + } + +} + + +VOID +FASTCALL +NE3200RelinquishCommandBlock( + IN PNE3200_ADAPTER Adapter, + IN PNE3200_SUPER_COMMAND_BLOCK CommandBlock + ) + +/*++ + +Routine Description: + + Relinquish the Command Block resource. If this is a "public" + Command Block, then update the CommandQueue. If this is a + "private" Command Block, then free to the private command queue. + +Arguments: + + Adapter - The adapter that owns the Command Block. + + CommandBlock - The Command Block to relinquish. + +Return Value: + + None. + +--*/ + +{ + IF_NE3200DBG(SUBMIT) { + + DPrint2( + "Relinquishing command @ %08lX\n", + (ULONG)NdisGetPhysicalAddressLow(CommandBlock->Self) + ); + + } + + // + // If this is the last pending command block, then we + // can remove the adapter's last pending command pointer. + // + if (CommandBlock == Adapter->LastCommandOnCard) { + + // + // If there is another waiting chain of commands -- submit those + // + if (Adapter->FirstWaitingCommand != NULL) { + + // + // Move the chain to the on card queue. + // + Adapter->FirstCommandOnCard = Adapter->FirstWaitingCommand; + Adapter->LastCommandOnCard = Adapter->LastWaitingCommand; + Adapter->FirstWaitingCommand = NULL; + + IF_NE3200DBG(SUBMIT) { + + DPrint2( + "Starting command @ %08lX\n", + (ULONG)NdisGetPhysicalAddressLow(Adapter->FirstCommandOnCard->Self) + ); + + } + + // + // Submit this command chain to the card. + // + NE3200_WRITE_COMMAND_POINTER( + Adapter, + NdisGetPhysicalAddressLow(Adapter->FirstCommandOnCard->Self) + ); + + // + // Stall momentarily for the adapter to get the command. + // + { + ULONG i; + Ne3200Stall(&i); + } + + // + // Inform the card of the command + // + NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT( + Adapter, + NE3200_LOCAL_DOORBELL_NEW_COMMAND + ); + + } else { + + // + // No commands are pending, clear the on card queue + // + Adapter->FirstCommandOnCard = NULL; + + } + + } else { + + // + // Point the adapter's first pending command to the + // next command on the command queue. + // + Adapter->FirstCommandOnCard = CommandBlock->NextCommand; + + } + + // + // Free this command block + // + CommandBlock->Hardware.NextPending = NE3200_NULL; + CommandBlock->Hardware.State = NE3200_STATE_FREE; + + // + // Update the correct queue. + // + (*CommandBlock->AvailableCommandBlockCounter)++; + +#if DBG + if (CommandBlock->AvailableCommandBlockCounter == &Adapter->NumberOfAvailableCommandBlocks) { + // + // This is a "private" Command Block. + // + IF_LOG('A'); + } else { + // + // This is a "public" Command Block. + // + IF_LOG('Q'); + } +#endif + +} + -- cgit v1.2.3