summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/ne3200
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ndis/ne3200
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/ndis/ne3200')
-rw-r--r--private/ntos/ndis/ne3200/command.c272
-rw-r--r--private/ntos/ndis/ne3200/interrup.c835
-rw-r--r--private/ntos/ndis/ne3200/keywords.h43
-rw-r--r--private/ntos/ndis/ne3200/mac2hex/mac.binbin0 -> 4096 bytes
-rw-r--r--private/ntos/ndis/ne3200/mac2hex/mac2hex.c309
-rw-r--r--private/ntos/ndis/ne3200/mac2hex/mac2hex.def5
-rw-r--r--private/ntos/ndis/ne3200/mac2hex/makefile6
-rw-r--r--private/ntos/ndis/ne3200/mac2hex/sources19
-rw-r--r--private/ntos/ndis/ne3200/makefile6
-rw-r--r--private/ntos/ndis/ne3200/makefile.inc5
-rw-r--r--private/ntos/ndis/ne3200/ne3200.binbin0 -> 4096 bytes
-rw-r--r--private/ntos/ndis/ne3200/ne3200.c2497
-rw-r--r--private/ntos/ndis/ne3200/ne3200.ini18
-rw-r--r--private/ntos/ndis/ne3200/ne3200.prf40
-rw-r--r--private/ntos/ndis/ne3200/ne3200.rc39
-rw-r--r--private/ntos/ndis/ne3200/ne3200hw.h964
-rw-r--r--private/ntos/ndis/ne3200/ne3200pr.h273
-rw-r--r--private/ntos/ndis/ne3200/ne3200sw.h805
-rw-r--r--private/ntos/ndis/ne3200/request.c954
-rw-r--r--private/ntos/ndis/ne3200/reset.c1805
-rw-r--r--private/ntos/ndis/ne3200/send.c816
-rw-r--r--private/ntos/ndis/ne3200/sources51
22 files changed, 9762 insertions, 0 deletions
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 <ne3200sw.h>
+
+
+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
+
+}
+
diff --git a/private/ntos/ndis/ne3200/interrup.c b/private/ntos/ndis/ne3200/interrup.c
new file mode 100644
index 000000000..d1fef19b0
--- /dev/null
+++ b/private/ntos/ndis/ne3200/interrup.c
@@ -0,0 +1,835 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ interrup.c
+
+Abstract:
+
+ This module contains the interrupt-processing code for the Novell
+ NE3200 NDIS 3.0 miniport driver.
+
+Author:
+
+ Keith Moore (KeithMo) 04-Feb-1991
+
+Environment:
+
+Revision History:
+
+--*/
+
+#include <ne3200sw.h>
+
+//
+// Forward declarations of functions in this file
+//
+STATIC
+BOOLEAN
+FASTCALL
+NE3200ProcessReceiveInterrupts(
+ IN PNE3200_ADAPTER Adapter
+ );
+
+STATIC
+BOOLEAN
+FASTCALL
+NE3200ProcessCommandInterrupts(
+ IN PNE3200_ADAPTER Adapter
+ );
+
+VOID
+NE3200Isr(
+ OUT PBOOLEAN InterruptRecognized,
+ OUT PBOOLEAN QueueDpc,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ Interrupt service routine for the NE3200. It's main job is
+ to get the value of the System Doorbell Register and record the
+ changes in the adapters own list of interrupt reasons.
+
+Arguments:
+
+ Interrupt - Interrupt object for the NE3200.
+
+ Context - Really a pointer to the adapter.
+
+Return Value:
+
+ Returns true if the interrupt really was from our NE3200.
+
+--*/
+
+{
+
+ //
+ // Will hold the value from the System Doorbell Register.
+ //
+ UCHAR SystemDoorbell;
+
+ //
+ // Holds the pointer to the adapter.
+ //
+ PNE3200_ADAPTER Adapter = Context;
+
+ IF_LOG('i');
+
+ //
+ // Get the interrupt status
+ //
+ NE3200_READ_SYSTEM_DOORBELL_INTERRUPT(Adapter, &SystemDoorbell);
+
+ //
+ // Are any of the bits expected?
+ //
+ if (SystemDoorbell & NE3200_SYSTEM_DOORBELL_MASK) {
+
+ IF_LOG(SystemDoorbell);
+
+ //
+ // It's our interrupt. Disable further interrupts.
+ //
+ NE3200_WRITE_SYSTEM_DOORBELL_MASK(
+ Adapter,
+ 0
+ );
+
+ IF_LOG('I');
+
+ //
+ // Return that we recognize it
+ //
+ *InterruptRecognized = TRUE;
+
+ } else {
+
+ IF_LOG('I');
+
+ //
+ // Return that we don't recognize it
+ //
+ *InterruptRecognized = FALSE;
+
+ }
+
+ //
+ // No Dpc call is needed for initialization
+ //
+ *QueueDpc = FALSE;
+
+}
+
+
+STATIC
+VOID
+NE3200HandleInterrupt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+
+/*++
+
+Routine Description:
+
+ Main routine for processing interrupts.
+
+Arguments:
+
+ Adapter - The Adapter to process interrupts for.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // The adapter for which to handle interrupts.
+ //
+ PNE3200_ADAPTER Adapter = ((PNE3200_ADAPTER)MiniportAdapterContext);
+
+ //
+ // Holds a value of SystemDoorbellInterrupt.
+ //
+ USHORT SystemDoorbell = 0;
+
+ //
+ // Should NdisMEthIndicateReceiveComplete() be called?
+ //
+ BOOLEAN IndicateReceiveComplete = FALSE;
+
+ IF_LOG('p');
+
+ //
+ // Get the current reason for interrupts
+ //
+ NE3200_READ_SYSTEM_DOORBELL_INTERRUPT(Adapter, &SystemDoorbell);
+
+ //
+ // Acknowledge those interrupts.
+ //
+ NE3200_WRITE_SYSTEM_DOORBELL_INTERRUPT(
+ Adapter,
+ SystemDoorbell
+ );
+
+ //
+ // Get just the important ones.
+ //
+ SystemDoorbell &= NE3200_SYSTEM_DOORBELL_MASK;
+
+ while (TRUE) {
+
+ //
+ // If we have a reset in progress then start the reset.
+ //
+
+ if (Adapter->ResetInProgress) goto check_reset;
+
+not_reset:
+
+ //
+ // Check the interrupt source and other reasons
+ // for processing. If there are no reasons to
+ // process then exit this loop.
+ //
+
+ //
+ // Check the interrupt vector and see if there are any
+ // more receives to process. After we process any
+ // other interrupt source we always come back to the top
+ // of the loop to check if any more receive packets have
+ // come in. This is to lessen the probability that we
+ // drop a receive.
+ //
+ if (SystemDoorbell & NE3200_SYSTEM_DOORBELL_PACKET_RECEIVED) {
+
+ IF_LOG('r');
+
+ //
+ // Process receive interrupts.
+ //
+ if (NE3200ProcessReceiveInterrupts(Adapter)) {
+
+ //
+ // If done with all receives, then clear the interrupt
+ // from our status.
+ //
+ SystemDoorbell &= ~NE3200_SYSTEM_DOORBELL_PACKET_RECEIVED;
+
+ }
+
+ //
+ // Note that we got a receive.
+ //
+ Adapter->ReceiveInterrupt = TRUE;
+ IndicateReceiveComplete = TRUE;
+
+ IF_LOG('R');
+
+ } else if ((SystemDoorbell &
+ NE3200_SYSTEM_DOORBELL_COMMAND_COMPLETE) == 0 ) {
+
+ //
+ // If the command is not completed, and no receives, then
+ // exit the loop.
+ //
+ break;
+ }
+
+ //
+ // First we check that this is a packet that was transmitted
+ // but not already processed. Recall that this routine
+ // will be called repeatedly until this tests false, Or we
+ // hit a packet that we don't completely own.
+ //
+ if ((Adapter->FirstCommandOnCard == NULL) ||
+ (Adapter->FirstCommandOnCard->Hardware.State != NE3200_STATE_EXECUTION_COMPLETE)) {
+
+ //
+ // No more work to do, clear the interrupt status bit.
+ //
+ IF_LOG('V');
+ SystemDoorbell &= ~NE3200_SYSTEM_DOORBELL_COMMAND_COMPLETE;
+
+ } else {
+
+ IF_LOG('c');
+
+ //
+ // Complete this transmit.
+ //
+ if ( NE3200ProcessCommandInterrupts(Adapter) ) {
+ SystemDoorbell &= ~NE3200_SYSTEM_DOORBELL_COMMAND_COMPLETE;
+ }
+
+ IF_LOG('C');
+
+ }
+
+ //
+ // Get more interrupt bits for processing
+ //
+ if (SystemDoorbell == 0) {
+
+ //
+ // Get the current reason for interrupts
+ //
+ NE3200_READ_SYSTEM_DOORBELL_INTERRUPT(Adapter, &SystemDoorbell);
+
+ //
+ // Acknowledge those interrupts.
+ //
+ NE3200_WRITE_SYSTEM_DOORBELL_INTERRUPT(
+ Adapter,
+ SystemDoorbell
+ );
+
+ //
+ // Get just the important ones.
+ //
+ SystemDoorbell &= NE3200_SYSTEM_DOORBELL_MASK;
+
+ }
+
+ }
+
+done:
+
+ IF_LOG('P');
+
+ if (IndicateReceiveComplete) {
+
+ NdisMEthIndicateReceiveComplete(Adapter->MiniportAdapterHandle);
+
+ }
+
+ return;
+
+check_reset:
+
+ if (Adapter->ResetState != NE3200ResetStateComplete) {
+
+ //
+ // The adapter is not in a state where it can process a reset.
+ //
+ goto not_reset;
+
+ }
+
+ //
+ // Start the reset
+ //
+ NE3200DoAdapterReset(Adapter);
+
+ goto done;
+
+}
+
+STATIC
+BOOLEAN
+FASTCALL
+NE3200ProcessReceiveInterrupts(
+ IN PNE3200_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ Process the packets that have the adapter has finished receiving.
+
+Arguments:
+
+ Adapter - The adapter to indicate to.
+
+Return Value:
+
+ Whether to clear interrupt bit 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.
+ //
+ // Examine each receive block for errors.
+ //
+ // We keep an array whose elements are indexed by the block
+ // index of the receive blocks. The arrays elements are the
+ // virtual addresses of the buffers pointed to by each block.
+ //
+ // 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.
+ //
+ PNE3200_SUPER_RECEIVE_ENTRY CurrentEntry = Adapter->ReceiveQueueHead;
+
+ //
+ // Pointer to last receive block in the queue.
+ //
+ PNE3200_SUPER_RECEIVE_ENTRY LastEntry;
+
+ //
+ // Limit the number of consecutive receives we will do. This way
+ // we do not starve transmit interrupts when processing many, many
+ // receives
+ //
+#define MAX_RECEIVES_PROCESSED 10
+ ULONG ReceivePacketCount = 0;
+
+
+ //
+ // Loop forever
+ //
+ while (TRUE) {
+
+ //
+ // Ensure that our Receive Entry is on an even boundary.
+ //
+ ASSERT(!(NdisGetPhysicalAddressLow(CurrentEntry->Self) & 1));
+
+ //
+ // Check to see whether we own the packet. If
+ // we don't then simply return to the caller.
+ //
+ if (CurrentEntry->Hardware.State != NE3200_STATE_FREE) {
+
+ //
+ // We've found a packet. Prepare the parameters
+ // for indication, then indicate.
+ //
+ if (ReceivePacketCount < MAX_RECEIVES_PROCESSED) {
+
+ //
+ // Increment the limit.
+ //
+ ReceivePacketCount++;
+
+ //
+ // Flush the receive buffer
+ //
+ NdisFlushBuffer(CurrentEntry->FlushBuffer, FALSE);
+
+ //
+ // Check the packet for a runt
+ //
+ if ((UINT)(CurrentEntry->Hardware.FrameSize) <
+ NE3200_HEADER_SIZE) {
+
+ if ((UINT)(CurrentEntry->Hardware.FrameSize) >=
+ NE3200_LENGTH_OF_ADDRESS) {
+
+ //
+ // Runt Packet, indicate it.
+ //
+ NdisMEthIndicateReceive(
+ Adapter->MiniportAdapterHandle,
+ (NDIS_HANDLE)(CurrentEntry->ReceiveBuffer),
+ CurrentEntry->ReceiveBuffer,
+ (UINT)CurrentEntry->Hardware.FrameSize,
+ NULL,
+ 0,
+ 0
+ );
+
+ }
+
+ } else {
+
+ //
+ // Good frame, indicate it
+ //
+ NdisMEthIndicateReceive(
+ Adapter->MiniportAdapterHandle,
+ (NDIS_HANDLE)(CurrentEntry->ReceiveBuffer),
+ CurrentEntry->ReceiveBuffer,
+ NE3200_HEADER_SIZE,
+ ((PUCHAR)CurrentEntry->ReceiveBuffer) + NE3200_HEADER_SIZE,
+ (UINT)CurrentEntry->Hardware.FrameSize - NE3200_HEADER_SIZE,
+ (UINT)CurrentEntry->Hardware.FrameSize - NE3200_HEADER_SIZE
+ );
+
+ }
+
+ //
+ // Give the packet back to the hardware.
+ //
+ // Chain the current block onto the tail of the Receive Queue.
+ //
+ CurrentEntry->Hardware.NextPending = NE3200_NULL;
+ CurrentEntry->Hardware.State = NE3200_STATE_FREE;
+
+ //
+ // Update receive ring
+ //
+ LastEntry = Adapter->ReceiveQueueTail;
+ LastEntry->Hardware.NextPending =
+ NdisGetPhysicalAddressLow(CurrentEntry->Self);
+
+ //
+ // Update the queue tail.
+ //
+ Adapter->ReceiveQueueTail = LastEntry->NextEntry;
+
+ //
+ // Advance to the next block.
+ //
+ CurrentEntry = CurrentEntry->NextEntry;
+
+ //
+ // See if the adapter needs to be restarted. The NE3200
+ // stops if it runs out receive buffers. Since we just
+ // released one, we restart the adapter.
+ //
+ if (LastEntry->Hardware.State != NE3200_STATE_FREE) {
+
+ //
+ // We've exhausted all Receive Blocks. Now we
+ // must restart the adapter.
+ //
+ IF_LOG('O');
+ NE3200StartChipAndDisableInterrupts(Adapter, Adapter->ReceiveQueueTail);
+
+ }
+
+ } else {
+
+ //
+ // Update statistics, we are exiting to check for
+ // transmit interrupts.
+ //
+ Adapter->ReceiveQueueHead = CurrentEntry;
+ Adapter->GoodReceives += MAX_RECEIVES_PROCESSED+1;
+
+ IF_LOG('o');
+
+ return FALSE;
+
+ }
+
+ } else {
+
+ //
+ // All done, update statistics and exit.
+ //
+ Adapter->ReceiveQueueHead = CurrentEntry;
+ Adapter->GoodReceives += ReceivePacketCount;
+ return TRUE;
+
+ }
+
+ }
+
+}
+
+
+STATIC
+BOOLEAN
+FASTCALL
+NE3200ProcessCommandInterrupts(
+ IN PNE3200_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ Process the Command Complete interrupts.
+
+Arguments:
+
+ Adapter - The adapter that was sent from.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Pointer to command block being processed.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK CurrentCommandBlock = Adapter->FirstCommandOnCard;
+
+ //
+ // Holds whether the packet successfully transmitted or not.
+ //
+ NDIS_STATUS StatusToReturn;
+
+ //
+ // Pointer to the packet that started this transmission.
+ //
+ PNDIS_PACKET OwningPacket;
+
+ //
+ // Points to the reserved part of the OwningPacket.
+ //
+ PNE3200_RESERVED Reserved;
+
+ //
+ // Ensure that the Command Block is on an even boundary.
+ //
+ ASSERT(!(NdisGetPhysicalAddressLow(CurrentCommandBlock->Self) & 1));
+
+ IF_LOG('t');
+
+ if (CurrentCommandBlock->Hardware.CommandCode == NE3200_COMMAND_TRANSMIT) {
+
+ //
+ // The current command block is from a transmit.
+ //
+ Adapter->SendInterrupt = TRUE;
+
+ //
+ // Get a pointer to the owning packet and the reserved part of
+ // the packet.
+ //
+ OwningPacket = CurrentCommandBlock->OwningPacket;
+ Reserved = PNE3200_RESERVED_FROM_PACKET(OwningPacket);
+
+ if (CurrentCommandBlock->UsedNE3200Buffer) {
+
+ //
+ // This packet used adapter buffers. We can
+ // now return these buffers to the adapter.
+ //
+
+ //
+ // The adapter buffer descriptor that was allocated to this packet.
+ //
+ PNE3200_BUFFER_DESCRIPTOR BufferDescriptor = Adapter->NE3200Buffers +
+ CurrentCommandBlock->NE3200BuffersIndex;
+
+ //
+ // Put the adapter buffer back on the free list.
+ //
+ BufferDescriptor->Next = Adapter->NE3200BufferListHead;
+ Adapter->NE3200BufferListHead = CurrentCommandBlock->NE3200BuffersIndex;
+
+ } else {
+
+ //
+ // Ndis buffer mapped
+ //
+ PNDIS_BUFFER CurrentBuffer;
+
+ //
+ // Map register that was used
+ //
+ UINT CurMapRegister;
+
+ //
+ // The transmit is finished, so we can release
+ // the physical mapping used for it.
+ //
+ NdisQueryPacket(
+ OwningPacket,
+ NULL,
+ NULL,
+ &CurrentBuffer,
+ NULL
+ );
+
+ //
+ // Get starting map register
+ //
+ CurMapRegister = CurrentCommandBlock->CommandBlockIndex *
+ NE3200_MAXIMUM_BLOCKS_PER_PACKET;
+
+ //
+ // For each buffer
+ //
+ while (CurrentBuffer) {
+
+ //
+ // Finish the mapping
+ //
+ NdisMCompleteBufferPhysicalMapping(
+ Adapter->MiniportAdapterHandle,
+ CurrentBuffer,
+ CurMapRegister
+ );
+
+ ++CurMapRegister;
+
+ NdisGetNextBuffer(
+ CurrentBuffer,
+ &CurrentBuffer
+ );
+
+ }
+
+ }
+
+ //
+ // If there was an error transmitting this
+ // packet, update our error counters.
+ //
+ if (CurrentCommandBlock->Hardware.Status & NE3200_STATUS_FATALERROR_MASK) {
+
+ if (CurrentCommandBlock->Hardware.Status &
+ NE3200_STATUS_MAXIMUM_COLLISIONS) {
+
+ Adapter->RetryFailure++;
+
+ } else if (CurrentCommandBlock->Hardware.Status &
+ NE3200_STATUS_NO_CARRIER) {
+
+ Adapter->LostCarrier++;
+
+ } else if (CurrentCommandBlock->Hardware.Status &
+ NE3200_STATUS_HEART_BEAT) {
+
+ Adapter->NoClearToSend++;
+
+ } else if (CurrentCommandBlock->Hardware.Status &
+ NE3200_STATUS_DMA_UNDERRUN) {
+
+ Adapter->UnderFlow++;
+
+ }
+
+ StatusToReturn = NDIS_STATUS_FAILURE;
+
+ } else {
+
+ //
+ // Update good transmit counter
+ //
+ StatusToReturn = NDIS_STATUS_SUCCESS;
+ Adapter->GoodTransmits++;
+ }
+
+ ASSERT(sizeof(UINT) == sizeof(PNDIS_PACKET));
+
+ //
+ // Release the command block.
+ //
+ NE3200RelinquishCommandBlock(Adapter, CurrentCommandBlock);
+
+ //
+ // The transmit is now complete
+ //
+ NdisMSendComplete(
+ Adapter->MiniportAdapterHandle,
+ OwningPacket,
+ StatusToReturn
+ );
+
+ } else if (CurrentCommandBlock->Hardware.CommandCode ==
+ NE3200_COMMAND_READ_ADAPTER_STATISTICS) {
+
+ //
+ // Release the command block.
+ //
+ Adapter->OutOfResources =
+ CurrentCommandBlock->Hardware.PARAMETERS.STATISTICS.ResourceErrors;
+
+ Adapter->CrcErrors =
+ CurrentCommandBlock->Hardware.PARAMETERS.STATISTICS.CrcErrors;
+
+ Adapter->AlignmentErrors =
+ CurrentCommandBlock->Hardware.PARAMETERS.STATISTICS.AlignmentErrors;
+
+ Adapter->DmaOverruns =
+ CurrentCommandBlock->Hardware.PARAMETERS.STATISTICS.OverrunErrors;
+
+
+ //
+ // If this was from a request, complete it
+ //
+ if (Adapter->RequestInProgress) {
+
+ NE3200FinishQueryInformation(Adapter);
+
+ }
+
+ //
+ // Release the command block
+ //
+ NE3200RelinquishCommandBlock(Adapter, CurrentCommandBlock);
+
+ } else if (CurrentCommandBlock->Hardware.CommandCode ==
+ NE3200_COMMAND_CLEAR_ADAPTER_STATISTICS) {
+
+ //
+ // Release the command block.
+ //
+ NE3200RelinquishCommandBlock(Adapter, CurrentCommandBlock);
+
+ } else if (CurrentCommandBlock->Hardware.CommandCode ==
+ NE3200_COMMAND_SET_STATION_ADDRESS) {
+
+ //
+ // Ignore
+ //
+
+ } else {
+
+ //
+ // The current command block is not from a transmit.
+ //
+ // Complete the request.
+ //
+ // if the CurrentCommandBlock->Set is FALSE,
+ // it means this multicast operation was not caused by
+ // a SetInformation request.
+ //
+
+ if (CurrentCommandBlock->Set) {
+
+ //
+ // Release the command block.
+ //
+ NE3200RelinquishCommandBlock(Adapter, CurrentCommandBlock);
+
+ if (!Adapter->RequestInProgress) {
+
+ //
+ // Bogus interrupt. Ignore it
+ //
+
+ } else {
+
+ IF_LOG(']');
+
+ Adapter->RequestInProgress = FALSE;
+
+ //
+ // Complete the request
+ //
+ NdisMSetInformationComplete(
+ Adapter->MiniportAdapterHandle,
+ NDIS_STATUS_SUCCESS);
+
+ }
+
+ } else {
+ IF_LOG('T');
+ return TRUE;
+ }
+
+ }
+
+ return FALSE;
+
+}
+
diff --git a/private/ntos/ndis/ne3200/keywords.h b/private/ntos/ndis/ne3200/keywords.h
new file mode 100644
index 000000000..30b52656f
--- /dev/null
+++ b/private/ntos/ndis/ne3200/keywords.h
@@ -0,0 +1,43 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ keywords.h
+
+Abstract:
+
+ Contains all Ndis2 and Ndis3 mac-specific keywords.
+
+Author:
+
+ Bob Noradki
+
+Environment:
+
+ Architecturally, there is an assumption in this driver that we are
+ on a little endian machine.
+
+Notes:
+
+ optional-notes
+
+Revision History:
+
+
+
+--*/
+#ifndef NDIS2
+#define NDIS2 0
+#endif
+
+#if NDIS2
+
+#define NETWORK_ADDRESS NDIS_STRING_CONST("NETADDRESS")
+
+#else // NDIS3
+
+#define NETWORK_ADDRESS NDIS_STRING_CONST("NetworkAddress")
+
+#endif
diff --git a/private/ntos/ndis/ne3200/mac2hex/mac.bin b/private/ntos/ndis/ne3200/mac2hex/mac.bin
new file mode 100644
index 000000000..259f85a8e
--- /dev/null
+++ b/private/ntos/ndis/ne3200/mac2hex/mac.bin
Binary files differ
diff --git a/private/ntos/ndis/ne3200/mac2hex/mac2hex.c b/private/ntos/ndis/ne3200/mac2hex/mac2hex.c
new file mode 100644
index 000000000..661e768c1
--- /dev/null
+++ b/private/ntos/ndis/ne3200/mac2hex/mac2hex.c
@@ -0,0 +1,309 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ mac2hex.c
+
+Abstract:
+
+ This program will read in MAC.BIN and produce MACBIN.H. MACBIN.H
+ will consist of a character array representation (MacBinImage[])
+ of MAC.BIN.
+
+Author:
+
+ Keith Moore (KeithMo) 23-Jan-1991
+
+Environment:
+
+ OS/2 1.x/2.x Protected Mode
+
+Revision History:
+
+
+--*/
+
+#define INCL_BASE
+#include <os2.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+//
+// Macros
+//
+#define CHECK_RETURN(code) \
+{ \
+ if ((code) != NO_ERROR) { \
+ printf( \
+ "Error %d, File %s, Line %ld\n", \
+ (code), \
+ __FILE__, \
+ (long)__LINE__ \
+ ); \
+ exit(1); \
+ } \
+}
+
+
+//
+// Prototypes
+//
+int
+main(
+ int nArgc,
+ char *pArgv[]
+ );
+
+VOID
+CreateHeaderFile(
+ PUCHAR pBuffer,
+ USHORT usLength
+ );
+
+
+//
+// main
+//
+int
+main(
+ int nArgc,
+ char *pArgv[]
+ )
+
+/*++
+
+Routine Description:
+
+ Usual C entry point.
+
+Arguments:
+
+ nArgc - Count of command line arguments.
+ pArgv - Array of pointers to the command line arguments.
+
+Return Value:
+
+ 0 if everything went OK.
+ 1 if something horrible happened.
+
+--*/
+
+{
+
+ FILESTATUS FileStatus;
+ HFILE hFile;
+ PCHAR pFileName;
+ PVOID pBuffer;
+ SEL Selector;
+ USHORT usAction;
+ USHORT usFileSize;
+ USHORT usNumRead;
+ USHORT usResult;
+
+ //
+ // If no command line arguments are given, then
+ // use "MAC.BIN" for the input file. Otherwise,
+ // assume that the first (only?) argument is the
+ // name of the download file.
+ //
+
+ pFileName = (nArgc > 1) ? (PCHAR)pArgv[1] : (PCHAR)"MAC.BIN";
+
+ //
+ // Open MAC.BIN.
+ //
+
+ usResult = DosOpen(
+ pFileName,
+ &hFile,
+ &usAction,
+ 0L,
+ FILE_NORMAL,
+ FILE_OPEN,
+ OPEN_ACCESS_READONLY
+ | OPEN_SHARE_DENYNONE,
+ 0L
+ );
+ CHECK_RETURN(usResult);
+
+ //
+ // Query the file so we can retrive its length.
+ //
+
+ usResult = DosQFileInfo(
+ hFile,
+ FIL_STANDARD,
+ (PBYTE)&FileStatus,
+ sizeof(FILESTATUS)
+ );
+ CHECK_RETURN(usResult);
+
+ usFileSize = (USHORT)FileStatus.cbFile;
+
+ //
+ // Allocate a chunk of memory to use.
+ //
+
+ usResult = DosAllocSeg(
+ usFileSize,
+ &Selector,
+ SEG_NONSHARED
+ );
+ CHECK_RETURN(usResult);
+
+ //
+ // Build our pointer from the selector we just allocated.
+ //
+
+ pBuffer = MAKEP(Selector, 0);
+
+ //
+ // Read MAC.BIN into our buffer.
+ //
+
+ usResult = DosRead(
+ hFile,
+ pBuffer,
+ usFileSize,
+ &usNumRead
+ );
+ CHECK_RETURN(usResult);
+
+ //
+ // Close MAC.BIN.
+ //
+
+ usResult = DosClose(
+ hFile
+ );
+ CHECK_RETURN(usResult);
+
+ //
+ // Write the new file.
+ //
+ CreateHeaderFile(pBuffer, usFileSize);
+
+ //
+ // Free the allocated memory.
+ //
+ usResult = DosFreeSeg(
+ Selector
+ );
+ CHECK_RETURN(usResult);
+
+ return 0;
+
+}
+
+
+//
+// CreateHeaderFile
+//
+VOID
+CreateHeaderFile(
+ PUCHAR pBuffer,
+ USHORT usLength
+ )
+
+/*++
+
+Routine Description:
+
+ Create a C header file containing a character
+ array representation of the specified buffer.
+
+Arguments:
+
+ pBuffer - Pointer to the buffer to convert.
+
+ usLength - The length (in bytes) of the buffer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // TRUE if we're starting a new line.
+ //
+ BOOL fNewLine;
+
+ //
+ // Number of bytes on current line.
+ //
+ USHORT usNumBytes;
+
+ //
+ // Create the prologue
+ //
+
+ printf("/*++\n");
+ printf("\n");
+ printf("Copyright (c) 1990 Microsoft Corporation\n");
+ printf("\n");
+ printf("Module Name:\n");
+ printf("\n");
+ printf(" macbin.h\n");
+ printf("\n");
+ printf("Abstract:\n");
+ printf("\n");
+ printf(" This module is generated by MAC2HEX.EXE. MAC2HEX reads in the\n");
+ printf(" NE3200's MAC.BIN module and produces this C character array\n");
+ printf(" representation. This is an unfortunate artifact of having\n");
+ printf(" all device drivers linked into the kernel. Once we have real\n");
+ printf(" installable device drivers, this will be unnecessary (the\n");
+ printf(" NE3200 driver will just open MAC.BIN and read it). But for now,\n");
+ printf(" all device drivers get initialized *before* the filesystem.\n");
+ printf(" Ergo, device drivers cannot open files at initialization time.\n");
+ printf("\n");
+ printf("Author:\n");
+ printf("\n");
+ printf(" Keith Moore (KeithMo) 24-Jan-1991\n");
+ printf("\n");
+ printf("Environment:\n");
+ printf("\n");
+ printf(" Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.\n");
+ printf("\n");
+ printf("Revision History:\n");
+ printf("\n");
+ printf("\n");
+ printf("--*/\n");
+ printf("\n");
+ printf("#define NE3200_MACBIN_LENGTH %u\n", usLength);
+ printf("\n");
+ printf("UCHAR NE3200MacBinImage[] = {");
+
+ fNewLine = TRUE;
+
+ while(usLength--) {
+
+ if (fNewLine) {
+
+ printf("\n");
+ printf(" ");
+ fNewLine = FALSE;
+ usNumBytes = 0;
+
+ }
+
+ printf("0x%02X", (UINT)(*pBuffer++));
+
+ if (usLength > 0)
+ printf(",");
+
+ if (++usNumBytes >= 13)
+ fNewLine = TRUE;
+
+ }
+
+ printf("\n");
+ printf(" };\n");
+
+}
diff --git a/private/ntos/ndis/ne3200/mac2hex/mac2hex.def b/private/ntos/ndis/ne3200/mac2hex/mac2hex.def
new file mode 100644
index 000000000..d879f7eb3
--- /dev/null
+++ b/private/ntos/ndis/ne3200/mac2hex/mac2hex.def
@@ -0,0 +1,5 @@
+NAME MAC2HEX WINDOWCOMPAT
+
+DESCRIPTION 'Convert MAC.BIN to C Header File'
+
+STACKSIZE 8192
diff --git a/private/ntos/ndis/ne3200/mac2hex/makefile b/private/ntos/ndis/ne3200/mac2hex/makefile
new file mode 100644
index 000000000..ac264b66c
--- /dev/null
+++ b/private/ntos/ndis/ne3200/mac2hex/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)\maketool.def
diff --git a/private/ntos/ndis/ne3200/mac2hex/sources b/private/ntos/ndis/ne3200/mac2hex/sources
new file mode 100644
index 000000000..055ce7ff7
--- /dev/null
+++ b/private/ntos/ndis/ne3200/mac2hex/sources
@@ -0,0 +1,19 @@
+MAJORCOMP=ne3200
+MINORCOMP=mac2hex
+
+TARGETNAME=mac2hex
+TARGETPATH=obj
+TARGETTYPE=PROGRAM
+
+INCLUDES=\nt\private\tools\inc
+
+SOURCES=mac2hex.c
+
+BUILDTOOL=1
+TOOL_MODEL=/AS /G2s
+TOOL_LIBS=\nt\private\tools\lib\slibcep /NOD/NOE
+TOOL_TYPE=WINDOWCOMPAT
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+
diff --git a/private/ntos/ndis/ne3200/makefile b/private/ntos/ndis/ne3200/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/ndis/ne3200/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/ne3200/makefile.inc b/private/ntos/ndis/ne3200/makefile.inc
new file mode 100644
index 000000000..439bc1088
--- /dev/null
+++ b/private/ntos/ndis/ne3200/makefile.inc
@@ -0,0 +1,5 @@
+ne3200.bin: $(TARGETEXEFILES)
+ chmode -r ne3200.bin
+ binplace ne3200.bin
+ touch ne3200.bin
+ chmode +r ne3200.bin
diff --git a/private/ntos/ndis/ne3200/ne3200.bin b/private/ntos/ndis/ne3200/ne3200.bin
new file mode 100644
index 000000000..91b9b0dec
--- /dev/null
+++ b/private/ntos/ndis/ne3200/ne3200.bin
Binary files differ
diff --git a/private/ntos/ndis/ne3200/ne3200.c b/private/ntos/ndis/ne3200/ne3200.c
new file mode 100644
index 000000000..f4bd1dbab
--- /dev/null
+++ b/private/ntos/ndis/ne3200/ne3200.c
@@ -0,0 +1,2497 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ne3200.c
+
+Abstract:
+
+ This is the main file for the Novell NE3200 EISA Ethernet adapter.
+ This driver conforms to the NDIS 3.0 miniport interface.
+
+Author:
+
+ Keith Moore (KeithMo) 08-Jan-1991
+
+Environment:
+
+Revision History:
+
+--*/
+
+#include <ne3200sw.h>
+#include "keywords.h"
+
+//
+// Global data block for holding MAC.BIN infomormation.
+//
+NE3200_GLOBAL_DATA NE3200Globals = {0};
+BOOLEAN FirstAdd = TRUE;
+
+//
+// Global for the largest acceptable piece of memory
+//
+NDIS_PHYSICAL_ADDRESS MinusOne = NDIS_PHYSICAL_ADDRESS_CONST (-1, -1);
+
+#if DBG
+
+//
+// Debugging flags for various debugging modes.
+//
+ULONG NE3200Debug = 0 ; // NE3200_DEBUG_LOUD |
+ // NE3200_DEBUG_ACQUIRE |
+ // NE3200_DEBUG_SUBMIT |
+ // NE3200_DEBUG_DUMP_COMMAND
+ // ;
+#endif
+
+
+//
+// Forward declarations for functions in this file
+//
+STATIC
+BOOLEAN
+NE3200AllocateAdapterMemory(
+ IN PNE3200_ADAPTER Adapter
+ );
+
+STATIC
+VOID
+NE3200DeleteAdapterMemory(
+ IN PNE3200_ADAPTER Adapter
+ );
+
+STATIC
+BOOLEAN
+NE3200InitialInit(
+ IN PNE3200_ADAPTER Adapter,
+ IN UINT NE3200InterruptVector,
+ IN NDIS_INTERRUPT_MODE NE3200InterruptMode
+ );
+
+STATIC
+BOOLEAN
+NE3200InitializeGlobals(
+ OUT PNE3200_GLOBAL_DATA Globals,
+ IN NDIS_HANDLE MiniportAdapterHandle
+ );
+
+STATIC
+VOID
+NE3200DestroyGlobals(
+ IN PNE3200_GLOBAL_DATA Globals
+ );
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+
+VOID
+NE3200Shutdown(
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+#pragma NDIS_INIT_FUNCTION(DriverEntry)
+
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+/*++
+
+Routine Description:
+
+ This is the primary initialization routine for the NE3200 driver.
+ It is simply responsible for the intializing the wrapper and registering
+ the Miniport driver. 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 NdisRegisterMiniport operation.
+ //
+ NDIS_STATUS Status;
+
+ //
+ // The characteristics table
+ //
+ NDIS_MINIPORT_CHARACTERISTICS NE3200Char;
+
+ //
+ // The handle returned by NdisMInitializeWrapper
+ //
+ NDIS_HANDLE NdisWrapperHandle;
+
+#if NDIS_WIN
+ UCHAR pIds[sizeof (EISA_MCA_ADAPTER_IDS) + sizeof (ULONG)];
+#endif
+
+#if NDIS_WIN
+ ((PEISA_MCA_ADAPTER_IDS)pIds)->nEisaAdapters=1;
+ ((PEISA_MCA_ADAPTER_IDS)pIds)->nMcaAdapters=0;
+ *(PULONG)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray)=EISA_NE3200_IDENTIFICATION;
+ (PVOID)DriverObject=(PVOID)pIds;
+#endif
+
+ //
+ // Initialize the wrapper.
+ //
+ NdisMInitializeWrapper(
+ &NdisWrapperHandle,
+ DriverObject,
+ RegistryPath,
+ NULL
+ );
+
+ //
+ // Initialize the Miniport characteristics for the call to
+ // NdisMRegisterMiniport.
+ //
+ NE3200Globals.NE3200NdisWrapperHandle = NdisWrapperHandle;
+
+ NE3200Char.MajorNdisVersion = NE3200_NDIS_MAJOR_VERSION;
+ NE3200Char.MinorNdisVersion = NE3200_NDIS_MINOR_VERSION;
+ NE3200Char.CheckForHangHandler = NE3200CheckForHang;
+ NE3200Char.DisableInterruptHandler = NE3200DisableInterrupt;
+ NE3200Char.EnableInterruptHandler = NE3200EnableInterrupt;
+ NE3200Char.HaltHandler = NE3200Halt;
+ NE3200Char.HandleInterruptHandler = NE3200HandleInterrupt;
+ NE3200Char.InitializeHandler = NE3200Initialize;
+ NE3200Char.ISRHandler = NE3200Isr;
+ NE3200Char.QueryInformationHandler = NE3200QueryInformation;
+ NE3200Char.ReconfigureHandler = NULL;
+ NE3200Char.ResetHandler = NE3200Reset;
+ NE3200Char.SendHandler = NE3200Send;
+ NE3200Char.SetInformationHandler = NE3200SetInformation;
+ NE3200Char.TransferDataHandler = NE3200TransferData;
+
+ //
+ // Register this driver with NDIS
+ //
+ Status = NdisMRegisterMiniport(
+ NdisWrapperHandle,
+ &NE3200Char,
+ sizeof(NE3200Char)
+ );
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+
+ return STATUS_SUCCESS;
+
+ }
+
+ //
+ // We can only get here if something went wrong with registering
+ // the driver or *all* of the adapters.
+ //
+ NE3200DestroyGlobals(&NE3200Globals);
+ NdisTerminateWrapper(NdisWrapperHandle, NULL);
+
+ return STATUS_UNSUCCESSFUL;
+
+}
+
+
+#pragma NDIS_INIT_FUNCTION(NE3200RegisterAdapter)
+
+BOOLEAN
+NE3200RegisterAdapter(
+ IN NDIS_HANDLE MiniportAdapterHandle,
+ IN UINT EisaSlot,
+ IN UINT InterruptVector,
+ IN NDIS_INTERRUPT_MODE InterruptMode,
+ IN PUCHAR CurrentAddress
+ )
+
+/*++
+
+Routine Description:
+
+ 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:
+
+ MiniportAdapterHandle - The handle given by ndis identifying this mini-port.
+
+ EisaSlot - The EISA Slot Number for this NE3200 adapter.
+
+ InterruptVector - The interrupt vector to used for the adapter.
+
+ InterruptMode - The interrupt mode (Latched or LevelSensitive)
+ used for this adapter.
+
+ CurrentAddress - The address the card will assume. If this is NULL,
+ then the card will use the BIA.
+
+Return Value:
+
+ Returns false if anything occurred that prevents the initialization
+ of the adapter.
+
+--*/
+
+{
+ //
+ // Status of nt calls
+ //
+ NDIS_STATUS Status;
+
+ //
+ // Pointer for the adapter root.
+ //
+ PNE3200_ADAPTER Adapter;
+
+ //
+ // All of the code that manipulates physical addresses depends
+ // on the fact that physical addresses are 4 byte quantities.
+ //
+ ASSERT(sizeof(NE3200_PHYSICAL_ADDRESS) == 4);
+
+ //
+ // Allocate the Adapter block.
+ //
+ NE3200_ALLOC_PHYS(&Status, &Adapter, sizeof(NE3200_ADAPTER));
+
+ if ( Status == NDIS_STATUS_SUCCESS ) {
+
+ //
+ // The IoBase Address for this adapter
+ //
+ ULONG AdapterIoBase;
+
+ //
+ // The resulting mapped base address
+ //
+ PUCHAR MappedIoBase;
+
+ //
+ // Initialize the adapter structure to all zeros
+ //
+ NdisZeroMemory(
+ Adapter,
+ sizeof(NE3200_ADAPTER)
+ );
+
+#if DBG
+ Adapter->LogAddress = Adapter->Log;
+#endif
+
+ //
+ // Save the adapter handle
+ //
+ Adapter->MiniportAdapterHandle = MiniportAdapterHandle;
+
+ //
+ // Compute the base address
+ //
+ AdapterIoBase = (ULONG)(EisaSlot << 12);
+
+ //
+ // Save the base address
+ //
+ Adapter->AdapterIoBase = AdapterIoBase;
+
+ //
+ // Set the attributes for this adapter
+ //
+ NdisMSetAttributes(
+ MiniportAdapterHandle,
+ (NDIS_HANDLE)Adapter,
+ TRUE,
+ NdisInterfaceEisa
+ );
+
+ //
+ // Register the reset port addresses.
+ //
+ Status = NdisMRegisterIoPortRange(
+ (PVOID *)(&(Adapter->ResetPort)),
+ MiniportAdapterHandle,
+ AdapterIoBase,
+ 0x4
+ );
+
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NE3200_FREE_PHYS(Adapter);
+ return FALSE;
+ }
+
+ //
+ // Register the command ports
+ //
+ Status = NdisMRegisterIoPortRange(
+ (PVOID *)(&(MappedIoBase)),
+ MiniportAdapterHandle,
+ AdapterIoBase + NE3200_ID_PORT,
+ 0x20
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NE3200_FREE_PHYS(Adapter);
+ NdisMDeregisterIoPortRange(MiniportAdapterHandle,
+ AdapterIoBase,
+ 4,
+ (PVOID)Adapter->ResetPort
+ );
+ return FALSE;
+ }
+
+ //
+ // Allocate the map registers
+ //
+ Status = NdisMAllocateMapRegisters(
+ MiniportAdapterHandle,
+ 0,
+ FALSE,
+ NE3200_NUMBER_OF_COMMAND_BLOCKS * NE3200_MAXIMUM_BLOCKS_PER_PACKET,
+ MAXIMUM_ETHERNET_PACKET_SIZE
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NE3200_FREE_PHYS(Adapter);
+ NdisMDeregisterIoPortRange(MiniportAdapterHandle,
+ AdapterIoBase,
+ 4,
+ (PVOID)Adapter->ResetPort
+ );
+ NdisMDeregisterIoPortRange(MiniportAdapterHandle,
+ AdapterIoBase + NE3200_ID_PORT,
+ 0x20,
+ (PVOID)MappedIoBase
+ );
+ return FALSE;
+ }
+
+ //
+ // Should an alternative ethernet address be used?
+ //
+ if (CurrentAddress != NULL) {
+
+ Adapter->AddressChanged = TRUE;
+
+ NdisMoveMemory(
+ Adapter->CurrentAddress,
+ CurrentAddress,
+ NE3200_LENGTH_OF_ADDRESS
+ );
+ } else {
+
+ Adapter->AddressChanged = FALSE;
+ }
+
+ //
+ // Save the eisa slot number
+ //
+ Adapter->EisaSlot = EisaSlot;
+ //DbgPrint( "NE3200: Adapter %x is slot %d\n", Adapter, EisaSlot );
+
+ //
+ // ResetPort is set by NdisRegisterAdapter.
+ // MappedIoBase is set in NdisRegisterAdapter to be the mapped
+ // of NE3200_ID_PORT. Now we set the other ports based on
+ // this offset.
+ //
+ Adapter->SystemInterruptPort = MappedIoBase + NE3200_SYSTEM_INTERRUPT_PORT - NE3200_ID_PORT;
+ Adapter->LocalDoorbellInterruptPort = MappedIoBase + NE3200_LOCAL_DOORBELL_INTERRUPT_PORT - NE3200_ID_PORT;
+ Adapter->SystemDoorbellMaskPort = MappedIoBase + NE3200_SYSTEM_DOORBELL_MASK_PORT - NE3200_ID_PORT;
+ Adapter->SystemDoorbellInterruptPort = MappedIoBase + NE3200_SYSTEM_DOORBELL_INTERRUPT_PORT - NE3200_ID_PORT;
+ Adapter->BaseMailboxPort = MappedIoBase + NE3200_BASE_MAILBOX_PORT - NE3200_ID_PORT;
+
+ //
+ // Allocate the global resources if needed.
+ //
+ if (FirstAdd) {
+
+ if (!NE3200InitializeGlobals(&NE3200Globals, Adapter->MiniportAdapterHandle)) {
+
+ NdisMFreeMapRegisters(MiniportAdapterHandle);
+ NdisMDeregisterIoPortRange(MiniportAdapterHandle,
+ AdapterIoBase,
+ 4,
+ (PVOID)Adapter->ResetPort
+ );
+ NdisMDeregisterIoPortRange(MiniportAdapterHandle,
+ AdapterIoBase + NE3200_ID_PORT,
+ 0x20,
+ (PVOID)MappedIoBase
+ );
+ NE3200_FREE_PHYS(Adapter);
+ return FALSE;
+
+ }
+
+ FirstAdd = FALSE;
+ }
+
+ //
+ // Setup default numbers for resources
+ //
+ Adapter->NumberOfTransmitBuffers = NE3200_NUMBER_OF_TRANSMIT_BUFFERS;
+ Adapter->NumberOfReceiveBuffers = NE3200_NUMBER_OF_RECEIVE_BUFFERS;
+ Adapter->NumberOfCommandBlocks = NE3200_NUMBER_OF_COMMAND_BLOCKS;
+ Adapter->NumberOfPublicCommandBlocks = NE3200_NUMBER_OF_PUBLIC_CMD_BLOCKS;
+
+ //
+ // Allocate memory for all of the adapter structures.
+ //
+ if (NE3200AllocateAdapterMemory(Adapter)) {
+
+ //
+ // Set the initial internal state
+ //
+ NE3200ResetVariables(Adapter);
+
+ //
+ // Initialize the timer for doing asynchronous resets
+ //
+ NdisMInitializeTimer(
+ &Adapter->ResetTimer,
+ MiniportAdapterHandle,
+ (PVOID) NE3200ResetHandler,
+ (PVOID) Adapter
+ );
+
+ //
+ // Now start the adapter
+ //
+ if (!NE3200InitialInit(
+ Adapter,
+ InterruptVector,
+ InterruptMode
+ )) {
+
+ NdisWriteErrorLogEntry(
+ MiniportAdapterHandle,
+ NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
+ 0
+ );
+
+ NE3200DeleteAdapterMemory(Adapter);
+ NdisMFreeMapRegisters(MiniportAdapterHandle);
+ NdisMDeregisterIoPortRange(MiniportAdapterHandle,
+ AdapterIoBase,
+ 4,
+ (PVOID)Adapter->ResetPort
+ );
+ NdisMDeregisterIoPortRange(MiniportAdapterHandle,
+ AdapterIoBase + NE3200_ID_PORT,
+ 0x20,
+ (PVOID)MappedIoBase
+ );
+ NE3200_FREE_PHYS(Adapter);
+ return FALSE;
+ }
+
+ //
+ // Enable further interrupts.
+ //
+ NE3200_WRITE_SYSTEM_DOORBELL_MASK(
+ Adapter,
+ NE3200_SYSTEM_DOORBELL_MASK
+ );
+
+ //
+ // Record it in the global adapter list.
+ //
+
+ InsertTailList(&NE3200Globals.AdapterList,
+ &Adapter->AdapterList,
+ );
+
+ //
+ // Register our shutdown handler.
+ //
+
+ NdisMRegisterAdapterShutdownHandler(
+ Adapter->MiniportAdapterHandle, // miniport handle.
+ Adapter, // shutdown context.
+ NE3200Shutdown // shutdown handler.
+ );
+
+ return(TRUE);
+
+ } else {
+
+ NdisWriteErrorLogEntry(
+ MiniportAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 3,
+ registerAdapter,
+ NE3200_ERRMSG_ALLOC_MEM,
+ 0
+ );
+
+ NdisMFreeMapRegisters(MiniportAdapterHandle);
+ NdisMDeregisterIoPortRange(MiniportAdapterHandle,
+ AdapterIoBase,
+ 4,
+ (PVOID)Adapter->ResetPort
+ );
+ NdisMDeregisterIoPortRange(MiniportAdapterHandle,
+ AdapterIoBase + NE3200_ID_PORT,
+ 0x20,
+ (PVOID)MappedIoBase
+ );
+ return(FALSE);
+
+ }
+
+ } else {
+
+ NdisWriteErrorLogEntry(
+ MiniportAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 3,
+ registerAdapter,
+ NE3200_ERRMSG_ALLOC_MEM,
+ 1
+ );
+
+ return FALSE;
+ }
+}
+
+
+#pragma NDIS_INIT_FUNCTION(NE3200AllocateAdapterMemory)
+
+STATIC
+BOOLEAN
+NE3200AllocateAdapterMemory(
+ IN PNE3200_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates memory for:
+
+ - Configuration Block
+
+ - Command Queue
+
+ - Receive Queue
+
+ - Receive Buffers
+
+ - Transmit Buffers for use if user transmit buffers don't meet hardware
+ contraints
+
+ - Structures to map Command Queue entries back to the packets.
+
+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 Receive Entry. Used while initializing
+ // the Receive Queue.
+ //
+ PNE3200_SUPER_RECEIVE_ENTRY CurrentReceiveEntry;
+
+ //
+ // Pointer to a Command Block. Used while initializing
+ // the Command Queue.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK CurrentCommandBlock;
+
+ //
+ // Simple iteration variable.
+ //
+ UINT i;
+
+ //
+ // Status of allocation
+ //
+ NDIS_STATUS Status;
+
+ //
+ // Allocate the public command block
+ //
+ NdisMAllocateSharedMemory(
+ Adapter->MiniportAdapterHandle,
+ sizeof(NE3200_SUPER_COMMAND_BLOCK) * NE3200_NUMBER_OF_PUBLIC_CMD_BLOCKS,
+ FALSE,
+ (PVOID *) &Adapter->PublicCommandQueue,
+ &Adapter->PublicCommandQueuePhysical
+ );
+
+ if (Adapter->PublicCommandQueue == NULL) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 3,
+ allocateAdapterMemory,
+ NE3200_ERRMSG_ALLOC_MEM,
+ 1
+ );
+
+ NE3200DeleteAdapterMemory(Adapter);
+ return FALSE;
+
+ }
+
+ //
+ // Allocate the card multicast table
+ //
+ NdisMAllocateSharedMemory(
+ Adapter->MiniportAdapterHandle,
+ NE3200_SIZE_OF_MULTICAST_TABLE_ENTRY *
+ NE3200_MAXIMUM_MULTICAST,
+ FALSE, // noncached
+ (PVOID*)&Adapter->CardMulticastTable,
+ &Adapter->CardMulticastTablePhysical
+ );
+
+ if (Adapter->CardMulticastTable == NULL) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 3,
+ allocateAdapterMemory,
+ NE3200_ERRMSG_ALLOC_MEM,
+ 2
+ );
+
+ NE3200DeleteAdapterMemory(Adapter);
+ return FALSE;
+
+ }
+
+ //
+ // Allocate the Configuration Block.
+ //
+ NdisMAllocateSharedMemory(
+ Adapter->MiniportAdapterHandle,
+ sizeof(NE3200_CONFIGURATION_BLOCK),
+ FALSE, // noncached
+ (PVOID*)&Adapter->ConfigurationBlock,
+ &Adapter->ConfigurationBlockPhysical
+ );
+
+ if (Adapter->ConfigurationBlock == NULL) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 3,
+ allocateAdapterMemory,
+ NE3200_ERRMSG_ALLOC_MEM,
+ 3
+ );
+
+ NE3200DeleteAdapterMemory(Adapter);
+ return FALSE;
+ }
+
+ //
+ // Allocate the Padding Buffer used to pad very short
+ // packets to the minimum Ethernet packet size (60 bytes).
+ //
+ NdisMAllocateSharedMemory(
+ Adapter->MiniportAdapterHandle,
+ MINIMUM_ETHERNET_PACKET_SIZE,
+ FALSE,
+ (PVOID*)&Adapter->PaddingVirtualAddress,
+ &Adapter->PaddingPhysicalAddress
+ );
+
+ if (Adapter->PaddingVirtualAddress == NULL) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 3,
+ allocateAdapterMemory,
+ NE3200_ERRMSG_ALLOC_MEM,
+ 4
+ );
+
+ NE3200DeleteAdapterMemory(Adapter);
+ return FALSE;
+
+ }
+
+ //
+ // Zero the Padding Buffer so we don't pad with garbage.
+ //
+ NdisZeroMemory(
+ Adapter->PaddingVirtualAddress,
+ MINIMUM_ETHERNET_PACKET_SIZE
+ );
+
+
+ //
+ // Allocate the Command Queue.
+ //
+ NdisMAllocateSharedMemory(
+ Adapter->MiniportAdapterHandle,
+ sizeof(NE3200_SUPER_COMMAND_BLOCK) *
+ Adapter->NumberOfCommandBlocks,
+ FALSE,
+ (PVOID*)&Adapter->CommandQueue,
+ &Adapter->CommandQueuePhysical
+ );
+
+
+ if (!Adapter->CommandQueue) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 3,
+ allocateAdapterMemory,
+ NE3200_ERRMSG_ALLOC_MEM,
+ 5
+ );
+
+ NE3200DeleteAdapterMemory(Adapter);
+ return FALSE;
+ }
+
+ //
+ // Set the tail pointer
+ //
+ Adapter->LastCommandBlockAllocated =
+ Adapter->CommandQueue + Adapter->NumberOfCommandBlocks;
+
+ //
+ // Clear the command list
+ //
+ NdisZeroMemory(
+ Adapter->CommandQueue,
+ sizeof(NE3200_SUPER_COMMAND_BLOCK) * Adapter->NumberOfCommandBlocks
+ );
+
+ //
+ // Put the Command Blocks into a known state.
+ //
+ for(
+ i = 0, CurrentCommandBlock = Adapter->CommandQueue;
+ i < Adapter->NumberOfCommandBlocks;
+ i++, CurrentCommandBlock++
+ ) {
+
+ CurrentCommandBlock->Hardware.State = NE3200_STATE_FREE;
+ CurrentCommandBlock->Hardware.NextPending = NE3200_NULL;
+
+ CurrentCommandBlock->NextCommand = NULL;
+
+ NdisSetPhysicalAddressHigh (CurrentCommandBlock->Self, 0);
+ NdisSetPhysicalAddressLow(
+ CurrentCommandBlock->Self,
+ NdisGetPhysicalAddressLow(Adapter->CommandQueuePhysical) +
+ i * sizeof(NE3200_SUPER_COMMAND_BLOCK));
+
+ CurrentCommandBlock->AvailableCommandBlockCounter =
+ &Adapter->NumberOfAvailableCommandBlocks;
+ CurrentCommandBlock->CommandBlockIndex = (USHORT)i;
+ CurrentCommandBlock->Timeout = FALSE;
+ }
+
+ //
+ // Now do the same for the public command queue.
+ //
+ for(
+ i = 0, CurrentCommandBlock = Adapter->PublicCommandQueue;
+ i < NE3200_NUMBER_OF_PUBLIC_CMD_BLOCKS;
+ i++, CurrentCommandBlock++
+ ) {
+
+ CurrentCommandBlock->Hardware.State = NE3200_STATE_FREE;
+ CurrentCommandBlock->Hardware.NextPending = NE3200_NULL;
+
+ CurrentCommandBlock->NextCommand = NULL;
+
+ NdisSetPhysicalAddressHigh (CurrentCommandBlock->Self, 0);
+ NdisSetPhysicalAddressLow(
+ CurrentCommandBlock->Self,
+ NdisGetPhysicalAddressLow(Adapter->PublicCommandQueuePhysical) +
+ i * sizeof(NE3200_SUPER_COMMAND_BLOCK));
+
+ CurrentCommandBlock->AvailableCommandBlockCounter =
+ &Adapter->NumberOfPublicCommandBlocks;
+ CurrentCommandBlock->CommandBlockIndex = (USHORT)i;
+ CurrentCommandBlock->Timeout = FALSE;
+ }
+
+
+ //
+ // Allocate Flush Buffer Pool
+ //
+ NdisAllocateBufferPool(
+ &Status,
+ (PVOID*)&Adapter->FlushBufferPoolHandle,
+ NE3200_NUMBER_OF_TRANSMIT_BUFFERS +
+ Adapter->NumberOfReceiveBuffers
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 3,
+ allocateAdapterMemory,
+ NE3200_ERRMSG_ALLOC_MEM,
+ 6
+ );
+
+ NE3200DeleteAdapterMemory(Adapter);
+ return FALSE;
+ }
+
+ //
+ // Allocate the Receive Queue.
+ //
+ NdisMAllocateSharedMemory(
+ Adapter->MiniportAdapterHandle,
+ sizeof(NE3200_SUPER_RECEIVE_ENTRY) *
+ Adapter->NumberOfReceiveBuffers,
+ FALSE,
+ (PVOID*)&Adapter->ReceiveQueue,
+ &Adapter->ReceiveQueuePhysical
+ );
+
+ if (!Adapter->ReceiveQueue) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 3,
+ allocateAdapterMemory,
+ NE3200_ERRMSG_ALLOC_MEM,
+ 7
+ );
+
+ NE3200DeleteAdapterMemory(Adapter);
+ return FALSE;
+
+ }
+
+ //
+ // Clear the receive ring
+ //
+ NdisZeroMemory(
+ Adapter->ReceiveQueue,
+ sizeof(NE3200_SUPER_RECEIVE_ENTRY) * Adapter->NumberOfReceiveBuffers
+ );
+
+
+ //
+ // Allocate the receive buffers and attach them to the Receive
+ // Queue entries.
+ //
+ for(
+ i = 0, CurrentReceiveEntry = Adapter->ReceiveQueue;
+ i < Adapter->NumberOfReceiveBuffers;
+ i++, CurrentReceiveEntry++
+ ) {
+
+ //
+ // Allocate the actual receive buffers
+ //
+ NdisMAllocateSharedMemory(
+ Adapter->MiniportAdapterHandle,
+ NE3200_SIZE_OF_RECEIVE_BUFFERS,
+ TRUE,
+ &CurrentReceiveEntry->ReceiveBuffer,
+ &CurrentReceiveEntry->ReceiveBufferPhysical
+ );
+
+ if (!CurrentReceiveEntry->ReceiveBuffer) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 3,
+ allocateAdapterMemory,
+ NE3200_ERRMSG_ALLOC_MEM,
+ 8
+ );
+
+ NE3200DeleteAdapterMemory(Adapter);
+ return FALSE;
+
+ }
+
+ //
+ // Build flush buffers
+ //
+ NdisAllocateBuffer(
+ &Status,
+ &CurrentReceiveEntry->FlushBuffer,
+ Adapter->FlushBufferPoolHandle,
+ CurrentReceiveEntry->ReceiveBuffer,
+ NE3200_SIZE_OF_RECEIVE_BUFFERS
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 3,
+ allocateAdapterMemory,
+ NE3200_ERRMSG_ALLOC_MEM,
+ 9
+ );
+
+ NE3200DeleteAdapterMemory(Adapter);
+ return FALSE;
+ }
+
+ //
+ // Initialize receive buffers
+ //
+ NdisFlushBuffer(CurrentReceiveEntry->FlushBuffer, FALSE);
+
+ CurrentReceiveEntry->Hardware.State = NE3200_STATE_FREE;
+ CurrentReceiveEntry->Hardware.FrameSize = NE3200_SIZE_OF_RECEIVE_BUFFERS;
+ CurrentReceiveEntry->Hardware.NextPending =
+ NdisGetPhysicalAddressLow(Adapter->ReceiveQueuePhysical) +
+ (i + 1) * sizeof(NE3200_SUPER_RECEIVE_ENTRY);
+
+ CurrentReceiveEntry->Hardware.BufferDescriptor.BlockLength =
+ NE3200_SIZE_OF_RECEIVE_BUFFERS;
+ CurrentReceiveEntry->Hardware.BufferDescriptor.PhysicalAddress =
+ NdisGetPhysicalAddressLow(CurrentReceiveEntry->ReceiveBufferPhysical);
+
+ NdisSetPhysicalAddressHigh (CurrentReceiveEntry->Self, 0);
+ NdisSetPhysicalAddressLow(
+ CurrentReceiveEntry->Self,
+ NdisGetPhysicalAddressLow(Adapter->ReceiveQueuePhysical) +
+ i * sizeof(NE3200_SUPER_RECEIVE_ENTRY));
+
+ CurrentReceiveEntry->NextEntry = CurrentReceiveEntry + 1;
+
+ }
+
+ //
+ // Make sure the last entry is properly terminated.
+ //
+ (CurrentReceiveEntry - 1)->Hardware.NextPending = NE3200_NULL;
+ (CurrentReceiveEntry - 1)->NextEntry = Adapter->ReceiveQueue;
+
+ //
+ // Allocate the array of buffer descriptors.
+ //
+ NE3200_ALLOC_PHYS(
+ &Status,
+ &Adapter->NE3200Buffers,
+ sizeof(NE3200_BUFFER_DESCRIPTOR)*
+ (NE3200_NUMBER_OF_TRANSMIT_BUFFERS)
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 3,
+ allocateAdapterMemory,
+ NE3200_ERRMSG_ALLOC_MEM,
+ 0xA
+ );
+
+ NE3200DeleteAdapterMemory(Adapter);
+ return FALSE;
+ }
+
+ //
+ // Zero the memory of all the descriptors so that we can
+ // know which buffers weren't allocated incase we can't allocate
+ // them all.
+ //
+ NdisZeroMemory(
+ Adapter->NE3200Buffers,
+ sizeof(NE3200_BUFFER_DESCRIPTOR)*
+ (NE3200_NUMBER_OF_TRANSMIT_BUFFERS)
+ );
+
+
+ //
+ // Allocate each of the buffers and fill in the
+ // buffer descriptor.
+ //
+ Adapter->NE3200BufferListHead = 0;
+
+ for (
+ i = 0;
+ i < NE3200_NUMBER_OF_TRANSMIT_BUFFERS;
+ i++
+ ) {
+
+ //
+ // Allocate a buffer
+ //
+ NdisMAllocateSharedMemory(
+ Adapter->MiniportAdapterHandle,
+ NE3200_SIZE_OF_TRANSMIT_BUFFERS,
+ TRUE,
+ &Adapter->NE3200Buffers[i].VirtualNE3200Buffer,
+ &Adapter->NE3200Buffers[i].PhysicalNE3200Buffer
+ );
+
+ if (!Adapter->NE3200Buffers[i].VirtualNE3200Buffer) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 3,
+ allocateAdapterMemory,
+ NE3200_ERRMSG_ALLOC_MEM,
+ 0xB
+ );
+
+ NE3200DeleteAdapterMemory(Adapter);
+ return FALSE;
+
+ }
+
+ //
+ // Build flush buffers
+ //
+ NdisAllocateBuffer(
+ &Status,
+ &Adapter->NE3200Buffers[i].FlushBuffer,
+ Adapter->FlushBufferPoolHandle,
+ Adapter->NE3200Buffers[i].VirtualNE3200Buffer,
+ NE3200_SIZE_OF_TRANSMIT_BUFFERS
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 3,
+ allocateAdapterMemory,
+ NE3200_ERRMSG_ALLOC_MEM,
+ 0xC
+ );
+
+ NE3200DeleteAdapterMemory(Adapter);
+ return FALSE;
+ }
+
+ //
+ // Insert this buffer into the queue
+ //
+ Adapter->NE3200Buffers[i].Next = i+1;
+ Adapter->NE3200Buffers[i].BufferSize = NE3200_SIZE_OF_TRANSMIT_BUFFERS;
+
+ }
+
+ //
+ // Make sure that the last buffer correctly terminates the free list.
+ //
+ Adapter->NE3200Buffers[i-1].Next = -1;
+
+ return TRUE;
+
+}
+
+
+STATIC
+VOID
+NE3200DeleteAdapterMemory(
+ IN PNE3200_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine deallocates memory for:
+
+ - Command Queue.
+
+ - Receive Queue.
+
+ - Receive buffers
+
+ - Transmit Buffers for use if user transmit buffers don't meet hardware
+ contraints
+
+ - Structures to map transmit ring entries back to the packets.
+
+Arguments:
+
+ Adapter - The adapter to deallocate memory for.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Do the public command queue
+ //
+ if (Adapter->PublicCommandQueue) {
+ NdisMFreeSharedMemory(
+ Adapter->MiniportAdapterHandle,
+ sizeof(NE3200_SUPER_COMMAND_BLOCK) * NE3200_NUMBER_OF_PUBLIC_CMD_BLOCKS,
+ FALSE,
+ Adapter->PublicCommandQueue,
+ Adapter->PublicCommandQueuePhysical
+ );
+ }
+
+ //
+ // The table for downloading multicast addresses
+ //
+ if (Adapter->CardMulticastTable) {
+ NdisMFreeSharedMemory(
+ Adapter->MiniportAdapterHandle,
+ NE3200_SIZE_OF_MULTICAST_TABLE_ENTRY *
+ NE3200_MAXIMUM_MULTICAST,
+ FALSE,
+ Adapter->CardMulticastTable,
+ Adapter->CardMulticastTablePhysical
+ );
+
+ }
+
+ //
+ // The configuration block
+ //
+ if (Adapter->ConfigurationBlock) {
+
+ NdisMFreeSharedMemory(
+ Adapter->MiniportAdapterHandle,
+ sizeof(NE3200_CONFIGURATION_BLOCK),
+ FALSE,
+ Adapter->ConfigurationBlock,
+ Adapter->ConfigurationBlockPhysical
+ );
+
+ }
+
+ //
+ // The pad buffer for short packets
+ //
+ if (Adapter->PaddingVirtualAddress) {
+
+ NdisMFreeSharedMemory(
+ Adapter->MiniportAdapterHandle,
+ MINIMUM_ETHERNET_PACKET_SIZE,
+ FALSE,
+ Adapter->PaddingVirtualAddress,
+ Adapter->PaddingPhysicalAddress
+ );
+
+ }
+
+ //
+ // The private command blocks
+ //
+ if (Adapter->CommandQueue) {
+
+ NdisMFreeSharedMemory(
+ Adapter->MiniportAdapterHandle,
+ sizeof(NE3200_SUPER_COMMAND_BLOCK) *
+ Adapter->NumberOfCommandBlocks,
+ FALSE,
+ Adapter->CommandQueue,
+ Adapter->CommandQueuePhysical
+ );
+
+ }
+
+
+ //
+ // The receive buffers
+ //
+ if (Adapter->ReceiveQueue) {
+
+ //
+ // Pointer to current Receive Entry being deallocated.
+ //
+ PNE3200_SUPER_RECEIVE_ENTRY CurrentReceiveEntry;
+
+ //
+ // Simple iteration counter.
+ //
+ UINT i;
+
+
+ for(
+ i = 0, CurrentReceiveEntry = Adapter->ReceiveQueue;
+ i < Adapter->NumberOfReceiveBuffers;
+ i++, CurrentReceiveEntry++
+ ) {
+
+
+ if (CurrentReceiveEntry->ReceiveBuffer) {
+
+ //
+ // Free the memory
+ //
+ NdisMFreeSharedMemory(
+ Adapter->MiniportAdapterHandle,
+ NE3200_SIZE_OF_RECEIVE_BUFFERS,
+ TRUE,
+ CurrentReceiveEntry->ReceiveBuffer,
+ CurrentReceiveEntry->ReceiveBufferPhysical
+ );
+
+
+ if (CurrentReceiveEntry->FlushBuffer) {
+
+ //
+ // Free the flush buffer
+ //
+ NdisFreeBuffer(
+ CurrentReceiveEntry->FlushBuffer
+ );
+ }
+
+ }
+
+ }
+
+ //
+ // Free the receive ring
+ //
+ NdisMFreeSharedMemory(
+ Adapter->MiniportAdapterHandle,
+ sizeof(NE3200_SUPER_RECEIVE_ENTRY) *
+ Adapter->NumberOfReceiveBuffers,
+ FALSE,
+ Adapter->ReceiveQueue,
+ Adapter->ReceiveQueuePhysical
+ );
+
+ }
+
+ //
+ // Free the merge buffers
+ //
+ if (Adapter->NE3200Buffers) {
+
+ //
+ // Loop counter
+ //
+ UINT i;
+
+ for (
+ i = 0;
+ i < NE3200_NUMBER_OF_TRANSMIT_BUFFERS;
+ i++
+ ) {
+
+
+ if (Adapter->NE3200Buffers[i].VirtualNE3200Buffer) {
+
+ //
+ // Free the memory
+ //
+ NdisMFreeSharedMemory(
+ Adapter->MiniportAdapterHandle,
+ NE3200_SIZE_OF_TRANSMIT_BUFFERS,
+ TRUE,
+ Adapter->NE3200Buffers[i].VirtualNE3200Buffer,
+ Adapter->NE3200Buffers[i].PhysicalNE3200Buffer
+ );
+
+ if (Adapter->NE3200Buffers[i].FlushBuffer) {
+
+ //
+ // Free the flush buffer
+ //
+ NdisFreeBuffer(
+ Adapter->NE3200Buffers[i].FlushBuffer
+ );
+
+ }
+
+ }
+
+ }
+
+ //
+ // Free the buffer ring
+ //
+ NE3200_FREE_PHYS(Adapter->NE3200Buffers);
+
+ }
+
+ if (Adapter->FlushBufferPoolHandle) {
+
+ //
+ // Free the buffer pool
+ //
+ NdisFreeBufferPool(
+ Adapter->FlushBufferPoolHandle
+ );
+
+ }
+
+}
+
+#pragma NDIS_INIT_FUNCTION(NE3200InitializeGlobals)
+
+STATIC
+BOOLEAN
+NE3200InitializeGlobals(
+ OUT PNE3200_GLOBAL_DATA Globals,
+ IN NDIS_HANDLE MiniportAdapterHandle
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will initialize the global data structure used
+ by all adapters managed by this driver. This routine is only
+ called once, when the driver is initializing the first
+ adapter.
+
+Arguments:
+
+ Globals - Pointer to the global data structure to initialize.
+
+ AdapterHandle - The handle to be used to allocate shared memory.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // File with the download code.
+ //
+ NDIS_STRING FileName=NDIS_STRING_CONST("ne3200.bin");
+
+ //
+ // Handle for the file.
+ //
+ NDIS_HANDLE FileHandle;
+
+ //
+ // Length of the file.
+ //
+ UINT FileLength;
+
+ //
+ // Status of NDIS calls
+ //
+ NDIS_STATUS Status;
+
+ //
+ // Virtual address of the download software in the file.
+ //
+ PVOID ImageBuffer;
+
+ //
+ // The value to return
+ //
+ BOOLEAN ReturnValue = TRUE;
+
+ //
+ // Save the adpater handle that did the allocations
+ //
+ Globals->MacBinAdapterHandle = MiniportAdapterHandle;
+
+ //
+ // Allocate the buffer.
+ //
+ NdisMAllocateSharedMemory(
+ MiniportAdapterHandle,
+ NE3200_MACBIN_LENGTH,
+ FALSE,
+ &Globals->MacBinVirtualAddress,
+ &Globals->MacBinPhysicalAddress
+ );
+
+ if (Globals->MacBinVirtualAddress == NULL) {
+ NE3200DestroyGlobals(Globals);
+ return FALSE;
+ }
+
+ //
+ // Store the length
+ //
+ Globals->MacBinLength = NE3200_MACBIN_LENGTH;
+
+
+ //
+ // Open the file with the download code
+ //
+ NdisOpenFile(
+ &Status,
+ &FileHandle,
+ &FileLength,
+ &FileName,
+ MinusOne
+ );
+
+ if (Status==NDIS_STATUS_SUCCESS) {
+
+ //
+ // Map the file into virtual memory
+ //
+ NdisMapFile(
+ &Status,
+ &ImageBuffer,
+ FileHandle
+ );
+
+ if (Status==NDIS_STATUS_SUCCESS) {
+
+ //
+ // Copy the download code into the shared memory space
+ //
+ NdisMoveMemory(Globals->MacBinVirtualAddress,ImageBuffer,FileLength);
+
+ //
+ // Done with the file
+ //
+ NdisUnmapFile(FileHandle);
+
+ } else {
+
+ ReturnValue = FALSE;
+
+ }
+
+ //
+ // Close the file
+ //
+ NdisCloseFile(FileHandle);
+
+ } else {
+
+ ReturnValue = FALSE;
+
+ }
+
+ //
+ // AdapterListHead is initially empty
+ //
+ InitializeListHead(&Globals->AdapterList);
+
+ //
+ // All done.
+ //
+ return ReturnValue;
+
+}
+
+
+STATIC
+VOID
+NE3200DestroyGlobals(
+ IN PNE3200_GLOBAL_DATA Globals
+ )
+
+/*++
+
+Routine Description:
+
+ This routine frees all global data allocated with
+ NE3200InitializeGlobals. This routine is called just before
+ the driver is unloaded.
+
+Arguments:
+
+ Globals - Pointer to the global data structure to destroy.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Free the memory with the download software in it.
+ //
+ if (Globals->MacBinVirtualAddress != NULL) {
+
+ NdisMFreeSharedMemory(
+ Globals->MacBinAdapterHandle,
+ NE3200_MACBIN_LENGTH,
+ FALSE,
+ Globals->MacBinVirtualAddress,
+ Globals->MacBinPhysicalAddress
+ );
+
+ }
+
+}
+
+#pragma NDIS_INIT_FUNCTION(NE3200Initialize)
+
+NDIS_STATUS
+NE3200Initialize(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ OUT PUINT SelectedMediumIndex,
+ IN PNDIS_MEDIUM MediumArray,
+ IN UINT MediumArraySize,
+ IN NDIS_HANDLE MiniportAdapterHandle,
+ IN NDIS_HANDLE ConfigurationHandle
+ )
+
+/*++
+
+Routine Description:
+
+ NE3200Initialize starts an adapter.
+
+Arguments:
+
+ See NDIS 3.0 Miniport spec.
+
+Return Value:
+
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_PENDING
+
+--*/
+
+{
+ //
+ // Handle returned by NdisOpenConfiguration
+ //
+ NDIS_HANDLE ConfigHandle;
+
+ //
+ // For changing the network address of this adapter.
+ //
+ NDIS_STRING NetAddrStr = NETWORK_ADDRESS;
+ UCHAR NetworkAddress[NE3200_LENGTH_OF_ADDRESS];
+ PUCHAR CurrentAddress;
+ PVOID NetAddress;
+ ULONG Length;
+
+ //
+ // The type of interrupt the adapter is set to use, level
+ // sensitive, or edged.
+ //
+ NDIS_INTERRUPT_MODE InterruptType;
+
+ //
+ // The interrupt number to use.
+ //
+ UINT InterruptVector;
+
+ //
+ // The slot number the adapter is located in
+ //
+ UINT EisaSlot;
+
+ //
+ // The port to look for in the EISA slot information
+ //
+ USHORT Portz800;
+
+ //
+ // The default value to use.
+ //
+ UCHAR z800Value;
+
+ //
+ // The mast to apply to the default values
+ //
+ UCHAR Mask;
+
+ //
+ // The type of initialization described in the EISA slot information.
+ //
+ UCHAR InitType;
+
+ //
+ // The port value for this iteration
+ //
+ UCHAR PortValue;
+
+ //
+ // The current port address to initialize
+ //
+ USHORT PortAddress;
+
+ //
+ // The location in the EISA slot information buffer
+ //
+ PUCHAR CurrentChar;
+
+ //
+ // Set to TRUE when done processing EISA slot information
+ //
+ BOOLEAN LastEntry;
+
+ //
+ // The EISA data
+ //
+ NDIS_EISA_FUNCTION_INFORMATION EisaData;
+
+ //
+ // Temporary looping variable
+ //
+ ULONG i;
+
+ //
+ // For signalling a configuration error
+ //
+ BOOLEAN ConfigError = FALSE;
+ NDIS_STATUS ConfigErrorCode;
+
+ //
+ // Status of NDIS calls
+ //
+ NDIS_STATUS Status;
+
+ //
+ // Search for the medium type (802.3)
+ //
+ for (i = 0; i < MediumArraySize; i++){
+
+ if (MediumArray[i] == NdisMedium802_3){
+
+ break;
+
+ }
+
+ }
+
+ //
+ // Ethernet was not found. Return an error.
+ //
+ if (i == MediumArraySize){
+
+ return NDIS_STATUS_UNSUPPORTED_MEDIA;
+
+ }
+
+ //
+ // Select ethernet
+ //
+ *SelectedMediumIndex = i;
+
+ //
+ // Open the configuration handle
+ //
+ NdisOpenConfiguration(
+ &Status,
+ &ConfigHandle,
+ ConfigurationHandle
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ return Status;
+ }
+
+ //
+ // Set address to default, using the burned in adapter address
+ //
+ CurrentAddress = NULL;
+
+ //
+ // Read an overriding net address
+ //
+ NdisReadNetworkAddress(
+ &Status,
+ &NetAddress,
+ &Length,
+ ConfigHandle
+ );
+
+ if ((Length == NE3200_LENGTH_OF_ADDRESS) && (Status == NDIS_STATUS_SUCCESS)) {
+
+ //
+ // Save overriding net address
+ //
+ NdisMoveMemory(
+ NetworkAddress,
+ NetAddress,
+ NE3200_LENGTH_OF_ADDRESS
+ );
+
+ CurrentAddress = NetworkAddress;
+
+ }
+
+ //
+ // Read the EISA configuration information
+ //
+ NdisReadEisaSlotInformation(
+ &Status,
+ ConfigurationHandle,
+ &EisaSlot,
+ &EisaData
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ ConfigError = TRUE;
+ ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
+
+ goto RegisterAdapter;
+
+ }
+
+ //
+ // Start at the beginning of the buffer
+ //
+ CurrentChar = EisaData.InitializationData;
+
+ //
+ // This is the port to look for
+ //
+ Portz800 = (EisaSlot << 12) + 0x800;
+
+ LastEntry = FALSE;
+
+ while (!LastEntry) {
+
+
+ InitType = *(CurrentChar++);
+ PortAddress = *((USHORT UNALIGNED *) CurrentChar++);
+ CurrentChar++;
+
+ //
+ // Check for last entry in EISA information
+ //
+ if ((InitType & 0x80) == 0) {
+ LastEntry = TRUE;
+ }
+
+ //
+ // Is this the port we are interested in?
+ //
+ if (PortAddress != Portz800) {
+ continue;
+ }
+
+ //
+ // Yes, get the port value to use
+ //
+ PortValue = *(CurrentChar++);
+
+ //
+ // Get the mask to use.
+ //
+ if (InitType & 0x40) {
+ Mask = *(CurrentChar++);
+ } else {
+ Mask = 0;
+ }
+
+ //
+ // Mask old value and or on new value.
+ //
+ z800Value &= Mask;
+ z800Value |= PortValue;
+ }
+
+ //
+ // Now, interpret the port data
+ //
+ // Get interrupt
+ //
+
+ switch (z800Value & 0x07) {
+ case 0x00:
+
+ ConfigError = TRUE;
+ ConfigErrorCode = NDIS_ERROR_CODE_HARDWARE_FAILURE;
+
+ goto RegisterAdapter;
+
+ case 0x01:
+ InterruptVector = 5;
+ break;
+ case 0x02:
+ InterruptVector = 9;
+ break;
+ case 0x03:
+ InterruptVector = 10;
+ break;
+ case 0x04:
+ InterruptVector = 11;
+ break;
+ case 0x05:
+ InterruptVector = 15;
+ break;
+ default:
+
+ ConfigError = TRUE;
+ ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
+
+ goto RegisterAdapter;
+
+ }
+
+ //
+ // Get interrupt mode
+ //
+
+ if (z800Value & 0x20) {
+ InterruptType = NdisInterruptLatched;
+ } else {
+ InterruptType = NdisInterruptLevelSensitive;
+ }
+
+RegisterAdapter:
+
+ //
+ // Were there any errors?
+ //
+ if (ConfigError) {
+
+ NdisWriteErrorLogEntry(
+ MiniportAdapterHandle,
+ ConfigErrorCode,
+ 0
+ );
+
+ Status = NDIS_STATUS_FAILURE;
+
+ } else if (NE3200RegisterAdapter(
+ MiniportAdapterHandle,
+ EisaSlot,
+ InterruptVector,
+ InterruptType,
+ CurrentAddress
+ )) {
+
+ Status = NDIS_STATUS_SUCCESS;
+
+ } else {
+
+ Status = NDIS_STATUS_FAILURE;
+
+ }
+
+ //
+ // All done
+ //
+ NdisCloseConfiguration(ConfigHandle);
+
+ return Status;
+}
+
+
+VOID
+NE3200Halt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+
+/*++
+
+Routine Description:
+
+ NE3200Halts removes an adapter previously initialized.
+
+Arguments:
+
+ MacAdapterContext - The context value that the Miniport returned
+ from Ne3200Initialize; actually as pointer to an NE3200_ADAPTER.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // The adapter to halt
+ //
+ PNE3200_ADAPTER Adapter;
+
+ Adapter = PNE3200_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
+
+ //
+ // Shut down the h/w
+ //
+ NE3200Shutdown(Adapter);
+
+ //
+ // Disconnect the interrupt
+ //
+ NdisMDeregisterInterrupt(&Adapter->Interrupt);
+
+ //
+ // Delete all resources
+ //
+ NE3200DeleteAdapterMemory(Adapter);
+
+ //
+ // Free map registers
+ //
+ NdisMFreeMapRegisters(Adapter->MiniportAdapterHandle);
+
+ //
+ // Remove ports
+ //
+ NdisMDeregisterIoPortRange(Adapter->MiniportAdapterHandle,
+ Adapter->AdapterIoBase,
+ 4,
+ (PVOID)Adapter->ResetPort
+ );
+
+ //
+ // Remove ports
+ //
+ NdisMDeregisterIoPortRange(Adapter->MiniportAdapterHandle,
+ Adapter->AdapterIoBase + NE3200_ID_PORT,
+ 0x20,
+ (PVOID)(Adapter->SystemInterruptPort -
+ NE3200_SYSTEM_INTERRUPT_PORT + NE3200_ID_PORT)
+ );
+
+ //
+ // Remove from global adapter list
+ //
+ RemoveEntryList(&Adapter->AdapterList);
+
+ //
+ // Free the adapter structure
+ //
+ NE3200_FREE_PHYS(Adapter);
+
+ return;
+}
+
+
+VOID
+NE3200Shutdown(
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+
+/*++
+
+Routine Description:
+
+ NE3200Shutdown shuts down the h/w.
+
+Arguments:
+
+ MacAdapterContext - The context value that the Miniport returned
+ from Ne3200Initialize; actually as pointer to an NE3200_ADAPTER.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // The adapter to halt
+ //
+ PNE3200_ADAPTER Adapter;
+
+ //
+ // Temporary looping variable
+ //
+ ULONG i;
+
+ Adapter = PNE3200_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
+
+ //
+ // Shut down the chip.
+ //
+ NE3200StopChip(Adapter);
+
+ //
+ // Pause, waiting for the chip to stop.
+ //
+ NdisStallExecution(500000);
+
+ //
+ // Unfortunately, a hardware reset to the NE3200 does *not*
+ // reset the BMIC chip. To ensure that we read a proper status,
+ // we'll clear all of the BMIC's registers.
+ //
+ NE3200_WRITE_SYSTEM_INTERRUPT(
+ Adapter,
+ 0
+ );
+
+ //
+ // I changed this to ff since the original 0 didn't work for
+ // some cases. since we don't have the specs....
+ //
+ NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT(
+ Adapter,
+ 0xff
+ );
+
+ NE3200_WRITE_SYSTEM_DOORBELL_MASK(
+ Adapter,
+ 0
+ );
+
+ SyncNE3200ClearDoorbellInterrupt(Adapter);
+
+ for (i = 0 ; i < 16 ; i += 4 ) {
+
+ NE3200_WRITE_MAILBOX_ULONG(
+ Adapter,
+ i,
+ 0L
+ );
+ }
+
+ //
+ // Toggle the NE3200's reset line.
+ //
+ NE3200_WRITE_RESET(
+ Adapter,
+ NE3200_RESET_BIT_ON
+ );
+}
+
+
+NDIS_STATUS
+NE3200TransferData(
+ 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 NE3200TransferData request (indirectly via
+ NdisTransferData) from within its Receive event handler
+ to instruct the Miniport to copy the contents of the received packet
+ a specified paqcket buffer.
+
+Arguments:
+
+ MiniportAdapterContext - The context value returned by the driver when the
+ adapter was initialized. In reality this is a pointer to NE3200_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 MAC 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.
+
+
+--*/
+
+{
+ //
+ // The adapter to transfer from
+ //
+ PNE3200_ADAPTER Adapter;
+
+ //
+ // 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 track of the bytes transferred so far.
+ //
+ UINT LocalBytesCopied = 0;
+
+ //
+ // Get the adapter structure
+ //
+ Adapter = PNE3200_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
+
+ *BytesTransferred = 0;
+
+ //
+ // Take care of boundary condition of zero length copy.
+ //
+ if (!BytesToTransfer) {
+ return NDIS_STATUS_SUCCESS;
+ }
+
+ //
+ // Get the first buffer of the destination.
+ //
+ NdisQueryPacket(
+ Packet,
+ NULL,
+ &DestinationBufferCount,
+ &DestinationCurrentBuffer,
+ NULL
+ );
+
+ //
+ // Could have a null packet.
+ //
+ if (!DestinationBufferCount) {
+ return NDIS_STATUS_SUCCESS;
+ }
+
+ //
+ // Get first buffer information
+ //
+ NdisQueryBuffer(
+ DestinationCurrentBuffer,
+ &DestinationVirtualAddress,
+ &DestinationCurrentLength
+ );
+
+ //
+ // Set up the source address.
+ //
+ SourceCurrentAddress = (PUCHAR)(MiniportReceiveContext) + ByteOffset + NE3200_HEADER_SIZE;
+
+ //
+ // While there is still data to copy
+ //
+ while (LocalBytesCopied < BytesToTransfer) {
+
+ //
+ // Check to see whether we've exhausted the current destination
+ // buffer. If so, move onto the next one.
+ //
+ if (!DestinationCurrentLength) {
+
+ //
+ // Get the next buffer
+ //
+ 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;
+
+ }
+
+ //
+ // Get this buffers information
+ //
+ 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 - LocalBytesCopied;
+
+
+ AmountToMove = DestinationCurrentLength;
+
+ AmountToMove = ((Remaining < AmountToMove)?
+ (Remaining):(AmountToMove));
+
+ NE3200_MOVE_MEMORY(
+ DestinationVirtualAddress,
+ SourceCurrentAddress,
+ AmountToMove
+ );
+
+ SourceCurrentAddress += AmountToMove;
+ LocalBytesCopied += AmountToMove;
+ DestinationCurrentLength -= AmountToMove;
+
+ }
+
+ }
+
+ *BytesTransferred = LocalBytesCopied;
+
+ return NDIS_STATUS_SUCCESS;
+
+}
+
+STATIC
+NDIS_STATUS
+NE3200Reset(
+ OUT PBOOLEAN AddressingReset,
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+/*++
+
+Routine Description:
+
+ The NE3200Reset 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.
+
+
+--*/
+
+{
+ //
+ // The adapter to reset
+ //
+ PNE3200_ADAPTER Adapter = PNE3200_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
+
+ IF_LOG('w');
+
+ //
+ // Start the reset process
+ //
+ NE3200SetupForReset(
+ Adapter
+ );
+
+ //
+ // Call Handle interrupt to continue the reset process
+ //
+ NE3200HandleInterrupt(
+ (NDIS_HANDLE)Adapter
+ );
+
+ IF_LOG('W');
+
+ return NDIS_STATUS_PENDING;
+}
+
+BOOLEAN
+NE3200CheckForHang(
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to check on the head of the command
+ block queue. It will fire off the queue if the head has
+ been sleeping on the job.
+
+ It also detects when the ne3200 adapter has failed, where the
+ symptoms are that the adapter will transmit packets, but will
+ not receive them.
+
+Arguments:
+
+ Context - Really a pointer to the adapter.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // The adapter to check over
+ //
+ PNE3200_ADAPTER Adapter = PNE3200_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
+
+ //
+ // The first command that is outstanding
+ //
+ PNE3200_SUPER_COMMAND_BLOCK FirstPending = Adapter->FirstCommandOnCard;
+
+ //
+ // Check if the command is stalled
+ //
+ if( (FirstPending != NULL) &&
+ (FirstPending->Hardware.State == NE3200_STATE_WAIT_FOR_ADAPTER) ) {
+
+ //
+ // See if the command block has timed-out.
+ //
+
+ if ( FirstPending->Timeout ) {
+
+ if ( FirstPending->TimeoutCount >= 2) {
+
+ //
+ // Give up, the card appears dead.
+ //
+ Adapter->ResetAsynchronous = TRUE;
+ Adapter->SendInterrupt = FALSE;
+ Adapter->NoReceiveInterruptCount = 0;
+
+ return TRUE;
+
+ } else {
+
+ //
+ // Re-sumbit the block.
+ //
+ NE3200_WRITE_COMMAND_POINTER(
+ Adapter,
+ NdisGetPhysicalAddressLow(FirstPending->Self)
+ );
+
+ NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT(
+ Adapter,
+ NE3200_LOCAL_DOORBELL_NEW_COMMAND
+ );
+
+ IF_LOG('+');
+
+ FirstPending->TimeoutCount++;
+
+ }
+
+ } else {
+
+ IF_LOG('0');
+
+ //
+ // Let the next call find the stall
+ //
+ FirstPending->Timeout = TRUE;
+ FirstPending->TimeoutCount = 0;
+
+ }
+
+ }
+
+ //
+ // Check if the receive side has died.
+ //
+ if ((!Adapter->ReceiveInterrupt) && (Adapter->SendInterrupt)) {
+
+ //
+ // If we go five times with no receives, but we are sending then
+ // we will reset the adapter.
+ //
+ if ((Adapter->NoReceiveInterruptCount == 5) && !Adapter->ResetInProgress) {
+
+ //
+ // We've waited long enough
+ //
+ Adapter->ResetAsynchronous = TRUE;
+ Adapter->SendInterrupt = FALSE;
+ Adapter->NoReceiveInterruptCount = 0;
+
+ return(TRUE);
+
+ } else {
+
+ Adapter->NoReceiveInterruptCount++;
+
+ }
+
+ } else {
+
+ //
+ // If we got a receive or there are no sends, doesn't matter. Reset
+ // the state.
+ //
+ Adapter->SendInterrupt = FALSE;
+ Adapter->ReceiveInterrupt = FALSE;
+ Adapter->NoReceiveInterruptCount = 0;
+
+ }
+
+ return(FALSE);
+
+}
diff --git a/private/ntos/ndis/ne3200/ne3200.ini b/private/ntos/ndis/ne3200/ne3200.ini
new file mode 100644
index 000000000..356d754e9
--- /dev/null
+++ b/private/ntos/ndis/ne3200/ne3200.ini
@@ -0,0 +1,18 @@
+//
+// This section is used to configure the Novell NE3200 Ethernet adapter for
+// non-Compaq machines. This section will be removed when the registry
+// becomes available. These values must matched the ones configured using
+// the EISA configuration utility.
+//
+// Defaults are shown below.
+//
+
+
+[NE3200Sys]
+ Bind1=\Device\NE32001
+
+[NE32001]
+ InterruptNumber = 9
+ InterruptType = EdgeTriggered
+ SlotNumber = 3
+
diff --git a/private/ntos/ndis/ne3200/ne3200.prf b/private/ntos/ndis/ne3200/ne3200.prf
new file mode 100644
index 000000000..814c0d1ff
--- /dev/null
+++ b/private/ntos/ndis/ne3200/ne3200.prf
@@ -0,0 +1,40 @@
+NE3200ChangeClass@8
+@NE3200RelinquishCommandBlock@8
+NE3200CheckForHang@4
+NE3200DisableInterrupt@4
+NE3200HandleInterrupt@4
+NE3200TransmitPacket@20
+@NE3200ProcessCommandInterrupts@4
+@Ne3200Stall@4
+NE3200EnableInterrupt@4
+NE3200Send@12
+@NE3200ProcessReceiveInterrupts@4
+NE3200UpdateMulticastTable@12
+NE3200EnableAdapter@4
+NE3200ChangeCurrentAddress@4
+NE3200FinishQueryInformation@4
+NE3200QueryInformation@24
+NE3200SetConfigurationBlock@4
+NE3200DoAdapterReset@4
+NE3200ConstrainPacket@8
+NE3200SetupForReset@4
+NE3200ResetHandler@16
+NE3200Reset@8
+NE3200TransmitMergedPacket@8
+NE3200GetStationAddress@4
+NE3200SetInformation@24
+NE3200ResetCommandBlocks@4
+SyncNE3200ClearDoorbellInterrupt@4
+NE3200StartChipAndDisableInterrupts@8
+NE3200DoResetIndications@8
+NE3200AcquirePublicCommandBlock@8
+NE3200Isr@12
+NE3200SetConfigurationBlockAndInit@4
+NE3200ResetVariables@4
+NE3200Initialize@24
+NE3200StopChip@4
+NE3200AllocateAdapterMemory@4
+NE3200InitialInit@12
+NE3200RegisterAdapter@20
+NE3200InitializeGlobals@8
+DriverEntry@8
diff --git a/private/ntos/ndis/ne3200/ne3200.rc b/private/ntos/ndis/ne3200/ne3200.rc
new file mode 100644
index 000000000..14c68c9ad
--- /dev/null
+++ b/private/ntos/ndis/ne3200/ne3200.rc
@@ -0,0 +1,39 @@
+#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 "Novell NE3200 network driver"
+#define VER_INTERNALNAME_STR "NE3200.SYS"
+#define VER_ORIGINALFILENAME_STR "NE3200.SYS"
+
+#include "common.ver"
+
diff --git a/private/ntos/ndis/ne3200/ne3200hw.h b/private/ntos/ndis/ne3200/ne3200hw.h
new file mode 100644
index 000000000..ab640b819
--- /dev/null
+++ b/private/ntos/ndis/ne3200/ne3200hw.h
@@ -0,0 +1,964 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ne3200hw.h
+
+Abstract:
+
+ Hardware specific values for the Novell NE3200 NDIS 3.0 driver.
+
+Author:
+
+ Keith Moore (KeithMo) 08-Jan-1991
+
+Environment:
+
+ Architecturally, there is an assumption in this driver that we are
+ on a little endian machine.
+
+Notes:
+
+ optional-notes
+
+Revision History:
+
+
+--*/
+
+#ifndef _NE3200HARDWARE_
+#define _NE3200HARDWARE_
+
+//
+// Defines for the packet and media specific information
+//
+#define MINIMUM_ETHERNET_PACKET_SIZE ((UINT)60)
+#define MAXIMUM_ETHERNET_PACKET_SIZE ((UINT)1514)
+#define NE3200_LENGTH_OF_ADDRESS 6
+
+//
+// The default interrupt number.
+//
+#define NE3200_DEFAULT_INTERRUPT_VECTOR ((CCHAR)11)
+
+//
+// The following parameters *MUST* each be a greater than one!
+//
+// The number of receive buffers to allocate.
+// The number of transmit buffers to allocate.
+// The number of command blocks for transmits that the driver has available.
+// The number of command blocks for requests the driver has availabale.
+//
+#define NE3200_NUMBER_OF_RECEIVE_BUFFERS ((UINT)16)
+#define NE3200_NUMBER_OF_TRANSMIT_BUFFERS ((UINT)4)
+#define NE3200_NUMBER_OF_COMMAND_BLOCKS ((UINT)8)
+#define NE3200_NUMBER_OF_PUBLIC_CMD_BLOCKS ((UINT)3)
+
+
+//
+// MAC.BIN info.
+//
+#define NE3200_MAXIMUM_MACBIN_SIZE ((ULONG)16384)
+#define NE3200_MACBIN_LENGTH 4096
+
+
+//
+// This is the number of bytes per entry in the multicast table
+// as presented to the NE3200. Note that this is *not* the number
+// of bytes in a multicast address, just the number of bytes per
+// table entry. For some goofy reason, MAC.BIN requires the table
+// used in the NE3200_COMMAND_SET_MULTICAST_ADDRESS command to have
+// 16 bytes per entry.
+//
+#define NE3200_SIZE_OF_MULTICAST_TABLE_ENTRY ((UINT)16)
+#define NE3200_MAXIMUM_MULTICAST ((UINT)50)
+
+
+//
+// Our buffer sizes.
+//
+// These are *not* configurable. Portions of the code assumes
+// that these buffers can contain *any* legal Ethernet packet.
+//
+#define NE3200_SIZE_OF_TRANSMIT_BUFFERS (MAXIMUM_ETHERNET_PACKET_SIZE)
+#define NE3200_SIZE_OF_RECEIVE_BUFFERS (MAXIMUM_ETHERNET_PACKET_SIZE)
+
+
+//
+// I/O Port Address.
+//
+// Note that the NE3200 uses EISA Slot-Specific Addressing. In
+// this method, each slot has its own I/O address space. This space
+// begins at the slot number shifted left 12 bits. For example,
+// the I/O space for slot number 6 begins at I/O address 6000h.
+//
+// Each of the following addresses are offset from the start of
+// slot-specific I/O space.
+//
+#define NE3200_RESET_PORT ((USHORT)0x0000)
+#define NE3200_ID_PORT ((USHORT)0x0C80)
+#define NE3200_GLOBAL_CONFIGURATION_PORT ((USHORT)0x0C88)
+#define NE3200_SYSTEM_INTERRUPT_PORT ((USHORT)0x0C89)
+#define NE3200_LOCAL_DOORBELL_MASK_PORT ((USHORT)0x0C8C)
+#define NE3200_LOCAL_DOORBELL_INTERRUPT_PORT ((USHORT)0x0C8D)
+#define NE3200_SYSTEM_DOORBELL_MASK_PORT ((USHORT)0x0C8E)
+#define NE3200_SYSTEM_DOORBELL_INTERRUPT_PORT ((USHORT)0x0C8F)
+#define NE3200_BASE_MAILBOX_PORT ((USHORT)0x0C90)
+
+
+//
+// Definitions for NE3200_RESET_PORT.
+//
+#define NE3200_RESET_BIT_ON ((UCHAR)1)
+#define NE3200_RESET_BIT_OFF ((UCHAR)0)
+
+
+//
+// Mailbox Registers
+//
+#define NE3200_MAILBOX_RESET_STATUS ((USHORT)0x0000)
+#define NE3200_MAILBOX_COMMAND_POINTER ((USHORT)0x0000)
+#define NE3200_MAILBOX_MACBIN_LENGTH ((USHORT)0x0001)
+#define NE3200_MAILBOX_MACBIN_DOWNLOAD_MODE ((USHORT)0x0003)
+#define NE3200_MAILBOX_RECEIVE_POINTER ((USHORT)0x0004)
+#define NE3200_MAILBOX_MACBIN_POINTER ((USHORT)0x0004)
+#define NE3200_MAILBOX_STATUS ((USHORT)0x0008)
+#define NE3200_MAILBOX_MACBIN_TARGET ((USHORT)0x0008)
+#define NE3200_MAILBOX_STATION_ID ((USHORT)0x000A)
+
+
+//
+// Values for MAC.BIN download
+//
+#define NE3200_MACBIN_DIRECT ((UCHAR)0x80)
+#define NE3200_MACBIN_TARGET_ADDRESS ((USHORT)0x0400)
+
+
+//
+// Status read from NE3200_MAILBOX_RESET_STATUS after hardware reset
+//
+#define NE3200_RESET_FAILED ((UCHAR)0x40)
+#define NE3200_RESET_PASSED ((UCHAR)0x80)
+
+
+//
+// Status read from NE3200_MAILBOX_STATUS after initialization
+//
+#define NE3200_INITIALIZATION_FAILED ((UCHAR)0x20)
+#define NE3200_INITIALIZATION_PASSED ((UCHAR)0x60)
+
+
+//
+// Local DoorBell bits
+//
+#define NE3200_LOCAL_DOORBELL_NEW_COMMAND ((UCHAR)0x01)
+#define NE3200_LOCAL_DOORBELL_RESET ((UCHAR)0x04)
+#define NE3200_LOCAL_DOORBELL_INITIALIZE ((UCHAR)0x10)
+#define NE3200_LOCAL_DOORBELL_NEW_RECEIVE ((UCHAR)0x20)
+
+#define NE3200_LOCAL_DOORBELL_MASK \
+ ( NE3200_LOCAL_DOORBELL_NEW_COMMAND \
+ | NE3200_LOCAL_DOORBELL_RESET \
+ | NE3200_LOCAL_DOORBELL_INITIALIZE \
+ | NE3200_LOCAL_DOORBELL_NEW_RECEIVE )
+
+
+//
+// System DoorBell bits
+//
+#define NE3200_SYSTEM_DOORBELL_PACKET_RECEIVED ((UCHAR)0x01)
+#define NE3200_SYSTEM_DOORBELL_COMMAND_COMPLETE ((UCHAR)0x02)
+#define NE3200_SYSTEM_DOORBELL_RESET_COMPLETE ((UCHAR)0x04)
+#define NE3200_SYSTEM_DOORBELL_INIT_COMPLETE ((UCHAR)0x08)
+#define NE3200_SYSTEM_DOORBELL_SELF_RESET ((UCHAR)0x10)
+
+#define NE3200_SYSTEM_DOORBELL_MASK \
+ ( NE3200_SYSTEM_DOORBELL_PACKET_RECEIVED \
+ | NE3200_SYSTEM_DOORBELL_COMMAND_COMPLETE)
+
+
+//
+// System Interrupt Mask/Control bits
+//
+#define NE3200_SYSTEM_INTERRUPT_ENABLE ((UCHAR)0x01)
+#define NE3200_SYSTEM_INTERRUPT_PENDING ((UCHAR)0x02)
+
+
+//
+// NE3200 Command Codes
+//
+#define NE3200_COMMAND_NOP ((UCHAR)0x00)
+#define NE3200_COMMAND_SET_STATION_ADDRESS ((UCHAR)0x01)
+#define NE3200_COMMAND_CONFIGURE_82586 ((UCHAR)0x02)
+#define NE3200_COMMAND_SET_MULTICAST_ADDRESS ((UCHAR)0x03)
+#define NE3200_COMMAND_TRANSMIT ((UCHAR)0x04)
+#define NE3200_COMMAND_READ_ADAPTER_STATISTICS ((UCHAR)0x08)
+#define NE3200_COMMAND_INITIALIZE_ADAPTER ((UCHAR)0x09)
+#define NE3200_COMMAND_CLEAR_ADAPTER_STATISTICS ((UCHAR)0x0A)
+
+
+//
+// NE3200 Receive/Command Block States
+//
+#define NE3200_STATE_FREE ((USHORT)0x0000)
+#define NE3200_STATE_EXECUTION_COMPLETE ((USHORT)0x0001)
+#define NE3200_STATE_WAIT_FOR_ADAPTER ((USHORT)0x0002)
+
+
+//
+// NE3200 Command Block Status
+//
+
+//
+// These apply to all commands.
+//
+#define NE3200_STATUS_COMPLETE ((USHORT)0x8000)
+#define NE3200_STATUS_BUSY ((USHORT)0x4000)
+#define NE3200_STATUS_SUCCESS ((USHORT)0x2000)
+#define NE3200_STATUS_ABORTED ((USHORT)0x1000)
+#define NE3200_STATUS_GENERIC_MASK ((USHORT)0xF000)
+
+//
+// These apply to transmit only.
+//
+#define NE3200_STATUS_NO_CARRIER ((USHORT)0x0400)
+#define NE3200_STATUS_NO_CLEAR_TO_SEND ((USHORT)0x0200)
+#define NE3200_STATUS_DMA_UNDERRUN ((USHORT)0x0100)
+#define NE3200_STATUS_TRANSMIT_DEFERRED ((USHORT)0x0080)
+#define NE3200_STATUS_HEART_BEAT ((USHORT)0x0040)
+#define NE3200_STATUS_MAXIMUM_COLLISIONS ((USHORT)0x0020)
+#define NE3200_STATUS_COLLISION_MASK ((USHORT)0x000F)
+#define NE3200_STATUS_FATALERROR_MASK (NE3200_STATUS_NO_CARRIER | \
+ NE3200_STATUS_NO_CLEAR_TO_SEND | \
+ NE3200_STATUS_DMA_UNDERRUN | \
+ NE3200_STATUS_HEART_BEAT | \
+ NE3200_STATUS_MAXIMUM_COLLISIONS)
+
+//
+// This defines a "proper" command complete status.
+//
+#define NE3200_STATUS_COMMAND_COMPLETE (NE3200_STATUS_COMPLETE | \
+ NE3200_STATUS_SUCCESS)
+
+
+//
+// Timeout constants
+//
+// Each of these timeout constants represents the time to wait
+// for a particular event to occur. For example, NE3200_TIMEOUT_RESET
+// represents the amount of time to wait for an adapter reset to
+// complete. Each of these values is in units of 1/100 of a second.
+// Therefore, a value of 200 would be approximately 2 seconds.
+//
+#define NE3200_TIMEOUT_RESET 200
+#define NE3200_TIMEOUT_DOWNLOAD 100
+
+//
+// This timeout represents the maximum amount of time we'll wait
+// for an NE3200 command to complete. This value is in units of
+// 1/1000 of a second. Therefore, a value of 2000 would be approximately
+// 2 seconds.
+//
+#define NE3200_TIMEOUT_COMMAND 2000
+
+
+//
+// This type defines the physical addresses used by the NE3200
+// card itself. This should always be four bytes.
+//
+typedef ULONG NE3200_PHYSICAL_ADDRESS, *PNE3200_PHYSICAL_ADDRESS;
+
+
+//
+// Miscellaneous Constants
+//
+#define NE3200_NULL ((NE3200_PHYSICAL_ADDRESS)(-1L))
+#define NE3200_MAXIMUM_BLOCKS_PER_PACKET ((UINT)4)
+#define NE3200_IMMEDIATE_DATA_LENGTH ((UINT)64)
+
+
+
+//
+// Force misalignment of the following structures
+//
+#include <pshpack1.h>
+
+
+//
+// NE3200 Data Block Descriptor
+//
+typedef struct _NE3200_DATA_BLOCK {
+
+ //
+ // This is the length (in bytes) of this block.
+ //
+ USHORT BlockLength;
+
+ //
+ // This is the physical address of this block.
+ //
+ NE3200_PHYSICAL_ADDRESS PhysicalAddress;
+
+} NE3200_DATA_BLOCK, *PNE3200_DATA_BLOCK;
+
+
+//
+// NE3200 Receive Ring Entry
+//
+typedef struct _NE3200_RECEIVE_ENTRY {
+
+ //
+ // This 4-byte field is unused by MAC.BIN and is
+ // available for use by the driver. We'll use
+ // this field as . . .
+ //
+ UCHAR Available1[4];
+
+ //
+ // This is the state of this Receive Ring entry.
+ //
+ USHORT State;
+
+ //
+ // This is the total size of the received frame.
+ //
+ USHORT FrameSize;
+
+ //
+ // This is the physical address of the next entry
+ // in the Receive Ring.
+ //
+ NE3200_PHYSICAL_ADDRESS NextPending;
+
+ //
+ // This 6-byte field is unused by MAC.BIN and is
+ // available for use by the driver. We'll use
+ // this field as . . .
+ //
+ UCHAR Available2[6];
+
+ //
+ // This is the descriptor which specifies the
+ // receive buffer used by this entry.
+ //
+ NE3200_DATA_BLOCK BufferDescriptor;
+
+} NE3200_RECEIVE_ENTRY, *PNE3200_RECEIVE_ENTRY;
+
+
+//
+// NE3200 Command Block
+//
+typedef struct _NE3200_COMMAND_BLOCK {
+
+ //
+ // This 4-byte field is unused by MAC.BIN and is
+ // available for use by the driver. We'll use
+ // this field as . . .
+ //
+ UCHAR Available1[4];
+
+ //
+ // 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.
+ //
+ NE3200_PHYSICAL_ADDRESS NextPending;
+
+ //
+ // This 1-byte field is unused by MAC.BIN and is
+ // available for use by the driver. We'll use
+ // this field as . . .
+ //
+ UCHAR Available2[1];
+
+ //
+ // This is the NE3200 Command Code.
+ //
+ UCHAR CommandCode;
+
+ //
+ // This 1-byte field is unused by MAC.BIN and is
+ // available for use by the driver. We'll use
+ // this field as . . .
+ //
+ UCHAR Available3[1];
+
+ //
+ // The following eight bytes are used as parameters
+ // by various NE3200 commands.
+ //
+ union _PARAMETERS {
+
+ //
+ // Parameters for NE3200_COMMAND_SET_STATION_ADDRESS.
+ //
+ struct _SET_ADDRESS {
+
+ //
+ // This field contains the new station address.
+ //
+ IN UCHAR NewStationAddress[NE3200_LENGTH_OF_ADDRESS];
+
+ } SET_ADDRESS;
+
+ //
+ // Parameters for NE3200_COMMAND_CONFIGURE_82586.
+ //
+ struct _CONFIGURE {
+
+ //
+ // This field holds the physical address of
+ // the configuration block.
+ //
+ IN NE3200_PHYSICAL_ADDRESS ConfigurationBlock;
+
+ } CONFIGURE;
+
+ //
+ // Parameters for NE3200_COMMAND_SET_MULTICAST_ADDRESS.
+ //
+ struct _MULTICAST {
+
+ //
+ // This field holds the physical address of
+ // the multicast address table.
+ //
+ IN NE3200_PHYSICAL_ADDRESS MulticastAddressTable;
+
+ //
+ // This field holds the number of multicast
+ // address in the multicast address table.
+ //
+ IN USHORT NumberOfMulticastAddresses;
+
+ } MULTICAST;
+
+ //
+ // Parameters for NE3200_COMMAND_TRANSMIT.
+ //
+ struct _TRANSMIT {
+
+ //
+ // This field holds the length of "immediate data"
+ // to be transmitted.
+ //
+ IN USHORT ImmediateDataLength;
+
+ } TRANSMIT;
+
+ //
+ // Parameters for NE3200_READ_ADAPTER_STATISTICS.
+ //
+ struct _STATISTICS {
+
+ //
+ // The following fields are filled in by the adapter
+ // when it executes the NE3200_READ_ADAPTER_STATISTICS
+ // command.
+ //
+
+ //
+ // This field holds the number of properly aligned
+ // frames received with a CRC error.
+ //
+ OUT USHORT CrcErrors;
+
+ //
+ // This field holds the number of misaligned frames
+ // received.
+ //
+ OUT USHORT AlignmentErrors;
+
+ //
+ // This field holds the number of resource errors
+ // (the number of frames which were discarded due
+ // to lack of memory resources such as buffer space
+ // or receive frame descriptors).
+ //
+ OUT USHORT ResourceErrors;
+
+ //
+ // This field holds the number of received frame
+ // sequeneces lost because the memory bus was
+ // not available in time for the transfer.
+ //
+ OUT USHORT OverrunErrors;
+
+ } STATISTICS;
+
+ //
+ // This field holds the raw data.
+ //
+ IN OUT USHORT RawParameters[4];
+
+ } PARAMETERS;
+
+ //
+ // This is the total size of the frame to be transmitted.
+ //
+ USHORT TransmitFrameSize;
+
+ //
+ // This is the number of data blocks in the frame to be
+ // transmitted.
+ //
+ UCHAR NumberOfDataBlocks;
+
+ //
+ // These are the descriptors describing the transmit packet.
+ //
+ NE3200_DATA_BLOCK TransmitDataBlocks[NE3200_MAXIMUM_BLOCKS_PER_PACKET];
+
+ //
+ // This is the immediate data to be used by all commands
+ // other than transmit.
+ //
+ UCHAR ImmediateData[NE3200_IMMEDIATE_DATA_LENGTH];
+
+} NE3200_COMMAND_BLOCK, *PNE3200_COMMAND_BLOCK;
+
+
+//
+// NE3200 Configuration Block
+//
+// This structure contains configuration data for the NE3200's
+// on-board 82586 Lan Coprocessor. The majority of this data
+// will not change during operation of the driver.
+//
+typedef struct _NE3200_CONFIGURATION_BLOCK {
+
+ //
+ // This field contains the number of bytes in the
+ // Configuration Block.
+ //
+ // In this implementation, this will always be 12.
+ //
+ USHORT ByteCount:4;
+
+ //
+ // This field is undefined by the 82586.
+ //
+ USHORT Undefined1:4;
+
+ //
+ // This field contains the FIFO threshold.
+ //
+ // In this implementation, this will always be 8.
+ //
+ USHORT FifoThreshold:4;
+
+ //
+ // This field is undefined by the 82586.
+ //
+ USHORT Undefined2:4;
+
+ //
+ // This field is undefined by the 82586.
+ //
+ USHORT Undefined3:6;
+
+ //
+ // If this field is set to 0, the 82586 operates with
+ // internal synchronization. If set to 1, the 82586
+ // uses external synchronization.
+ //
+ // This will always be set to 0 in this implementation
+ // (internal synchronization).
+ //
+ USHORT Synchronization:1;
+
+ //
+ // If this field is set to 0, the 82586 will not save
+ // bad frames in memory. If set to 1, the 82856 will
+ // save bad frames.
+ //
+ // In this implementation, this will always be 0
+ // (don't save bad frames).
+ //
+ USHORT SaveBadFrames:1;
+
+ //
+ // This field contains the number of bytes in a
+ // network address.
+ //
+ // In this implementation, this will always be 6.
+ //
+ USHORT AddressLength:3;
+
+ //
+ // If this field is set to 0, then the Destination
+ // Network Address is part of the Transmit Command Block
+ // and the Source Address is inserted by the 82586. If
+ // set to 1, then the Destination and Source Addresses
+ // are part of the Transmit/Receive data buffers.
+ //
+ // In this implementation, this is always set to 1
+ // (Addresses are part of the data buffers).
+ //
+ USHORT SeparateAddressAndLength:1;
+
+ //
+ // These two bits determine the length of the packet
+ // preamble according to the following table:
+ //
+ // Bits Preamble Length
+ // ---- ---------------
+ // 00 2 bytes
+ // 01 4 bytes
+ // 10 8 bytes
+ // 11 16 bytes
+ //
+ // In this implementation, these bits will always be
+ // set to 10 (8 byte preamble).
+ //
+ USHORT PreambleLength:2;
+
+ //
+ // These two field control internal/external loopback on
+ // the 82586.
+ //
+ // In this implementation, these two fields should be set to 0.
+ //
+ USHORT InternalLoopback:1;
+ USHORT ExternalLoopback:1;
+
+ //
+ // This field contains the linear backoff priority.
+ //
+ // In this implementation, this field will always be 0.
+ //
+ USHORT LinearPriority:3;
+
+ //
+ // This field is undefined by the 82586.
+ //
+ USHORT Undefined4:1;
+
+ //
+ // This field contains the exponential backoff priority.
+ //
+ // In this implementation, this field will always be 0.
+ //
+ USHORT ExponentialPriority:3;
+
+ //
+ // If this field is set to 0, the 82586 will use the
+ // IEEE 802.3/Ethernet exponential backoff method. If
+ // set to 1, the 82586 will use an alternate backoff
+ // method.
+ //
+ // In this implementation, this field will always be 0
+ // (use the IEEE 802.3/Ethernet backoff method).
+ //
+ USHORT ExponentialBackoffMethod:1;
+
+ //
+ // This field contains the Interframe Spacing in TxC units.
+ //
+ // In this implementation, this field will always be 96.
+ //
+ USHORT InterframeSpacing:8;
+
+ //
+ // This field contains the Slot Time Number.
+ //
+ // In this implementation, this field will always be 512.
+ //
+ USHORT SlotTime:11;
+
+ //
+ // This field is undefined by the 82586.
+ //
+ USHORT Undefined5:1;
+
+ //
+ // This field contains the maximum number of transmission
+ // retries on collisions.
+ //
+ // In this implementation, this field will always be 15.
+ //
+ USHORT MaximumRetries:4;
+
+ //
+ // If this field is set to 0, Promiscuous Mode will be disabled.
+ // If set to 1, then Promiscuous Mode will be enabled and the
+ // 82586 will receive *all* packets.
+ //
+ // This field will initially be set to 0 (disable Promiscuous
+ // Mode) but may be changed when a protocol requests a change
+ // to the packet filter.
+ //
+ USHORT PromiscuousMode:1;
+
+ //
+ // If this field is set to 0, then all Broadcast Packets will be
+ // received. If set to 1, then Broadcast reception is disabled.
+ //
+ // This field will initially be set to 1 (disable Broadcast
+ // reception) but may be changed when a protocol requests a change
+ // to the packet filter.
+ //
+ USHORT DisableBroadcast:1;
+
+ //
+ // If this field is set to 0, then the 82586 will use NRZ encoding
+ // and decoding. If set to 1, the 82586 will use Manchester
+ // encoding and decoding.
+ //
+ // In this implementation, this field will always be set to 0
+ // (use NRZ encoding).
+ //
+ USHORT EncodingMethod:1;
+
+ //
+ // If this field is set to 0, then the 82586 will cease transmission
+ // if CRS goes inactive during frame transmission. If set to 1,
+ // the 82586 will continue transmission even if there is no carrier
+ // sense.
+ //
+ // In this implementation, this field will always be set to 0
+ // (cease transmission if carrier lost).
+ //
+ USHORT TransmitOnNoCarrier:1;
+
+ //
+ // If this field is set to 0, then the 82586 will insert a CRC
+ // field into the packet. If set to 1, then no CRC will be
+ // inserted
+ //
+ // In this implementation, this field will always be set to 0
+ // (insert CRC field).
+ //
+ USHORT DisableCrcInsertion:1;
+
+ //
+ // If this field is set to 0, then the 82856 will use the
+ // 32-bit Autodin II CRC polynomial. If set to 1 then the
+ // 16-bit CCITT CRC polynomial will be used.
+ //
+ // In this implementation, this field will always be set to 0
+ // (use the 32-bit Autodin II CRC polynomial).
+ //
+ USHORT CrcType:1;
+
+ //
+ // If this field is set to 0, then the 82586 will use the
+ // Ethernet bitstuffing method. If set to 1 then the 82586 will
+ // use an HDLC-like bitstuffing method.
+ //
+ // In this implementation, this field will always be set to 0
+ // (use the Ethernet bitstuffing method).
+ //
+ USHORT BitStuffingMethod:1;
+
+ //
+ // If this field is set to 0, then the 82586 will perform no
+ // padding. If set to 1 then the 82586 will pad transmits
+ // out to the full slot time.
+ //
+ // In this implementation, this field will always be set to 0
+ // (no padding).
+ //
+ USHORT EnablePadding:1;
+
+ //
+ // This field contains the Carrier Sense Filter (in bit times).
+ //
+ // In this implementation, this field will always be set to 0.
+ //
+ USHORT CarrierSenseFilter:2;
+
+ //
+ // If this field is set to 0, then the 82586 will use an external
+ // carrier sense source. If set to 1 than an internal carrier
+ // sense source is used.
+ //
+ // In this implementation, this field will always be set to 0
+ // (external carrier sense source).
+ //
+ USHORT CarrierSenseSource:1;
+
+ //
+ // This field contains the Collision Detect Filter (in bit times).
+ //
+ // In this implementation, this field will always be set to 0.
+ //
+ USHORT CollisionDetectFilter:2;
+
+ //
+ // If this field is set to 0, then the 82586 will use an external
+ // collision detect source. If set to 1 then an internal
+ // collision detect source is used.
+ //
+ // In this implementation, this field will always be set to 0
+ // (external collision detect source).
+ //
+ USHORT CollisionDetectSource:1;
+
+ //
+ // Padding bits to align MinimumFrameLength
+ //
+ USHORT TempPadding:2;
+
+ //
+ // This field contains the minimum number of bytes in a frame.
+ //
+ // In this implementation, this field will always be 64.
+ //
+ USHORT MinimumFrameLength:8;
+
+ //
+ // The following three bits are technically undefined by the
+ // 82586, but are used by MAC.BIN.
+ //
+
+ //
+ // This bit must be set to 1 to enable packet reception. If
+ // this bit is not set, then no packets will be received.
+ //
+ USHORT MacBinEnablePacketReception:1;
+
+ //
+ // This bit is unused.
+ //
+ USHORT MacBinUnused:1;
+
+ //
+ // If promiscuous mode is enabled, then this but must also
+ // be set. This short-circuits MAC.BIN's multicast filtering.
+ //
+ USHORT MacBinPromiscuous:1;
+
+ //
+ // This field is (honest!) unused.
+ //
+ USHORT Undefined6:5;
+
+} NE3200_CONFIGURATION_BLOCK, *PNE3200_CONFIGURATION_BLOCK;
+
+#include <poppack.h>
+
+
+
+//
+// Macros to read/write BMIC registers
+//
+#define NE3200_READ_MAILBOX_UCHAR(_Adapter, _MailboxIndex, _pValue) \
+ NdisRawReadPortUchar( \
+ (ULONG)(_Adapter)->BaseMailboxPort+(_MailboxIndex), \
+ (PUCHAR)(_pValue) \
+ )
+
+#define NE3200_READ_MAILBOX_USHORT(_Adapter, _MailboxIndex, _pValue) \
+ NdisRawReadPortUshort( \
+ (ULONG)(_Adapter)->BaseMailboxPort+(_MailboxIndex), \
+ (PUSHORT)(_pValue) \
+ )
+
+#define NE3200_READ_MAILBOX_ULONG(_Adapter, _MailboxIndex, _pValue) \
+ NdisRawReadPortUlong( \
+ (ULONG)(_Adapter)->BaseMailboxPort+(_MailboxIndex), \
+ (PULONG)(_pValue) \
+ )
+
+#define NE3200_WRITE_MAILBOX_UCHAR(_Adapter, _MailboxIndex, _Value) \
+ NdisRawWritePortUchar( \
+ (ULONG)(_Adapter)->BaseMailboxPort+(_MailboxIndex), \
+ (UCHAR)(_Value) \
+ )
+
+#define NE3200_WRITE_MAILBOX_USHORT(_Adapter, _MailboxIndex, _Value) \
+ NdisRawWritePortUshort( \
+ (ULONG)(_Adapter)->BaseMailboxPort+(_MailboxIndex), \
+ (USHORT)(_Value) \
+ )
+
+#define NE3200_WRITE_MAILBOX_ULONG(_Adapter, _MailboxIndex, _Value) \
+ NdisRawWritePortUlong( \
+ (ULONG)(_Adapter)->BaseMailboxPort+(_MailboxIndex), \
+ (ULONG)(_Value) \
+ )
+
+#define NE3200_WRITE_COMMAND_POINTER(_Adapter, _Address) \
+ NE3200_WRITE_MAILBOX_ULONG( \
+ _Adapter, \
+ NE3200_MAILBOX_COMMAND_POINTER, \
+ (_Address) \
+ )
+
+#define NE3200_WRITE_RECEIVE_POINTER(_Adapter, _Address) \
+ NE3200_WRITE_MAILBOX_ULONG( \
+ _Adapter, \
+ NE3200_MAILBOX_RECEIVE_POINTER, \
+ (_Address) \
+ )
+
+#define NE3200_READ_LOCAL_DOORBELL_INTERRUPT(_Adapter, _pValue) \
+ NdisRawReadPortUchar( \
+ (ULONG)(_Adapter)->LocalDoorbellInterruptPort, \
+ (PUCHAR)(_pValue) \
+ )
+
+#define NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT(_Adapter, _Value) \
+ NdisRawWritePortUchar( \
+ (ULONG)(_Adapter)->LocalDoorbellInterruptPort, \
+ (UCHAR)(_Value) \
+ )
+
+#define NE3200_READ_SYSTEM_DOORBELL_INTERRUPT(_Adapter, _pValue) \
+ NdisRawReadPortUchar( \
+ (ULONG)(_Adapter)->SystemDoorbellInterruptPort, \
+ (PUCHAR)(_pValue) \
+ )
+
+#define NE3200_SYNC_CLEAR_SYSTEM_DOORBELL_INTERRUPT(_Adapter) \
+ NdisMSynchronizeWithInterrupt(\
+ &(_Adapter)->Interrupt,\
+ SyncNE3200ClearDoorbellInterrupt,\
+ (PVOID)(_Adapter)\
+ )
+
+#define NE3200_WRITE_SYSTEM_DOORBELL_INTERRUPT(_Adapter, _Value) \
+ NdisRawWritePortUchar( \
+ (ULONG)(_Adapter)->SystemDoorbellInterruptPort, \
+ (UCHAR)(_Value) \
+ )
+
+#define NE3200_READ_SYSTEM_DOORBELL_MASK(_Adapter, _pValue) \
+ NdisRawReadPortUchar( \
+ (ULONG)(_Adapter)->SystemDoorbellMaskPort, \
+ (PUCHAR)(_pValue) \
+ )
+
+#define NE3200_WRITE_SYSTEM_DOORBELL_MASK(_Adapter, _Value) \
+ NdisRawWritePortUchar( \
+ (ULONG)(_Adapter)->SystemDoorbellMaskPort, \
+ (UCHAR)(_Value) \
+ )
+
+#define NE3200_WRITE_SYSTEM_INTERRUPT(_Adapter, _Value) \
+ NdisRawWritePortUchar( \
+ (ULONG)(_Adapter)->SystemInterruptPort, \
+ (UCHAR)(_Value) \
+ )
+
+#define NE3200_WRITE_RESET(_Adapter, _Value) \
+ NdisRawWritePortUchar( \
+ (ULONG)(_Adapter)->ResetPort, \
+ (UCHAR)(_Value) \
+ )
+
+#endif // _NE3200HARDWARE_
diff --git a/private/ntos/ndis/ne3200/ne3200pr.h b/private/ntos/ndis/ne3200/ne3200pr.h
new file mode 100644
index 000000000..68485cf0e
--- /dev/null
+++ b/private/ntos/ndis/ne3200/ne3200pr.h
@@ -0,0 +1,273 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ne3200proc.h
+
+Abstract:
+
+ Procedure declarations for the Novell NE3200 NDIS 3.0 driver.
+ Moved most of these from ne3200sw.h
+
+Author:
+
+ Johnson R. Apacible (johnsona) 21-Aug-1991
+
+Environment:
+
+ Architecturally, there is an assumption in this driver that we are
+ on a little endian machine.
+
+Notes:
+
+ optional-notes
+
+Revision History:
+
+
+--*/
+
+#ifndef _NE3200PROC_
+#define _NE3200PROC_
+
+//
+// We define the external interfaces to the NE3200 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
+BOOLEAN
+NE3200CheckForHang(
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+extern
+VOID
+NE3200DisableInterrupt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+extern
+VOID
+NE3200EnableInterrupt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+extern
+VOID
+NE3200Halt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+extern
+VOID
+NE3200HandleInterrupt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+extern
+NDIS_STATUS
+NE3200Initialize(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ OUT PUINT SelectedMediumIndex,
+ IN PNDIS_MEDIUM MediumArray,
+ IN UINT MediumArraySize,
+ IN NDIS_HANDLE MiniportAdapterHandle,
+ IN NDIS_HANDLE WrapperConfigurationContext
+ );
+
+extern
+VOID
+NE3200Isr(
+ OUT PBOOLEAN InterruptRecognized,
+ OUT PBOOLEAN QueueDpc,
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+extern
+NDIS_STATUS
+NE3200QueryInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesWritten,
+ OUT PULONG BytesNeeded
+ );
+
+extern
+NDIS_STATUS
+NE3200Reset(
+ OUT PBOOLEAN AddressingReset,
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+extern
+NDIS_STATUS
+NE3200Send(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN PNDIS_PACKET Packet,
+ IN UINT Flags
+ );
+
+extern
+NDIS_STATUS
+NE3200SetInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesRead,
+ OUT PULONG BytesNeeded
+ );
+
+extern
+NDIS_STATUS
+NE3200TransferData(
+ OUT PNDIS_PACKET Packet,
+ OUT PUINT BytesTransferred,
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_HANDLE MiniportReceiveContext,
+ IN UINT ByteOffset,
+ IN UINT BytesToTransfer
+ );
+
+VOID
+NE3200StartChipAndDisableInterrupts(
+ IN PNE3200_ADAPTER Adapter,
+ IN PNE3200_SUPER_RECEIVE_ENTRY FirstReceiveEntry
+ );
+
+VOID
+NE3200FinishQueryInformation(
+ IN PNE3200_ADAPTER Adapter
+ );
+
+
+VOID
+NE3200GetStationAddress(
+ IN PNE3200_ADAPTER Adapter
+ );
+
+VOID
+NE3200StopChip(
+ IN PNE3200_ADAPTER Adapter
+ );
+
+BOOLEAN
+NE3200RegisterAdapter(
+ IN NDIS_HANDLE MiniportAdapterHandle,
+ IN UINT EisaSlot,
+ IN UINT InterruptVector,
+ IN NDIS_INTERRUPT_MODE InterruptMode,
+ IN PUCHAR CurrentAddress
+ );
+
+VOID
+NE3200AcquirePublicCommandBlock(
+ IN PNE3200_ADAPTER Adapter,
+ OUT PNE3200_SUPER_COMMAND_BLOCK * CommandBlock
+ );
+
+VOID
+FASTCALL
+NE3200RelinquishCommandBlock(
+ IN PNE3200_ADAPTER Adapter,
+ IN PNE3200_SUPER_COMMAND_BLOCK CommandBlock
+ );
+
+VOID
+NE3200DoAdapterReset(
+ IN PNE3200_ADAPTER Adapter
+ );
+
+VOID
+NE3200SetupForReset(
+ IN PNE3200_ADAPTER Adapter
+ );
+
+NDIS_STATUS
+NE3200UpdateMulticastTable(
+ IN PNE3200_ADAPTER Adapter,
+ IN UINT CurrentAddressCount,
+ IN CHAR CurrentAddresses[][NE3200_LENGTH_OF_ADDRESS]
+ );
+
+VOID
+NE3200ResetVariables(
+ IN PNE3200_ADAPTER Adapter
+ );
+
+BOOLEAN
+SyncNE3200ClearDoorbellInterrupt(
+ IN PVOID SyncContext
+ );
+
+VOID
+NE3200ResetHandler(
+ IN PVOID SystemSpecific1,
+ IN PNE3200_ADAPTER Adapter,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ );
+
+VOID
+NE3200DeferredTimer(
+ IN PVOID SystemSpecific1,
+ IN PNE3200_ADAPTER Adapter,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ );
+
+VOID
+FASTCALL
+Ne3200Stall(
+ PULONG Dummy
+ );
+
+#define NE3200SubmitCommandBlock( _Adapter, _CommandBlock ) \
+{ \
+ ASSERT(!(NdisGetPhysicalAddressLow(_CommandBlock->Self) & 1)); \
+ _CommandBlock->Timeout = FALSE; \
+ if (_Adapter->FirstCommandOnCard != NULL) { \
+ if (_Adapter->FirstWaitingCommand == NULL) { \
+ _Adapter->FirstWaitingCommand = _CommandBlock; \
+ } else { \
+ PNE3200_SUPER_COMMAND_BLOCK PreviousCommandBlock; \
+ PreviousCommandBlock = _Adapter->LastWaitingCommand; \
+ PreviousCommandBlock->Hardware.NextPending = \
+ NdisGetPhysicalAddressLow(_CommandBlock->Self); \
+ PreviousCommandBlock->NextCommand = _CommandBlock; \
+ } \
+ _Adapter->LastWaitingCommand = _CommandBlock; \
+ IF_LOG('2'); \
+ } else { \
+ ASSERT(_Adapter->FirstWaitingCommand == NULL); \
+ IF_LOG('1'); \
+ _Adapter->FirstCommandOnCard = _CommandBlock; \
+ _Adapter->LastCommandOnCard = _CommandBlock; \
+ NE3200_WRITE_COMMAND_POINTER(_Adapter,NdisGetPhysicalAddressLow(_CommandBlock->Self)); \
+ { ULONG i; Ne3200Stall(&i); } \
+ NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT(_Adapter,NE3200_LOCAL_DOORBELL_NEW_COMMAND); \
+ } \
+}
+
+#define NE3200AcquireCommandBlock( _Adapter, _CommandBlock ) \
+{ \
+ if (_Adapter->NumberOfAvailableCommandBlocks) { \
+ IF_LOG('a'); \
+ _Adapter->NumberOfAvailableCommandBlocks--; \
+ *(_CommandBlock) = _Adapter->NextCommandBlock; \
+ _Adapter->NextCommandBlock++; \
+ if (_Adapter->NextCommandBlock >= _Adapter->LastCommandBlockAllocated ) {\
+ Adapter->NextCommandBlock = Adapter->CommandQueue; \
+ } \
+ } else { \
+ *(_CommandBlock) = NULL; \
+ } \
+}
+
+#endif //_NE3200PROC_
diff --git a/private/ntos/ndis/ne3200/ne3200sw.h b/private/ntos/ndis/ne3200/ne3200sw.h
new file mode 100644
index 000000000..28300334f
--- /dev/null
+++ b/private/ntos/ndis/ne3200/ne3200sw.h
@@ -0,0 +1,805 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ne3200sw.h
+
+Abstract:
+
+ Software specific values for the Novell NE3200 NDIS 3.0 driver.
+
+Author:
+
+ Keith Moore (KeithMo) 08-Jan-1991
+
+Environment:
+
+ Architecturally, there is an assumption in this driver that we are
+ on a little endian machine.
+
+Notes:
+
+ optional-notes
+
+Revision History:
+
+
+--*/
+
+#ifndef _NE3200SOFTWARE_
+#define _NE3200SOFTWARE_
+
+#include <ndis.h>
+#include <ne3200hw.h>
+
+//
+// Debugging flags. This buffer is used to record whenever the driver
+// does something important. If there is a bug, then this buffer
+// can be viewed from the debugger and an effective trace of events
+// can be found.
+//
+
+#if DBG
+
+#define IF_NE3200DBG(flag) if (NE3200Debug & (NE3200_DEBUG_ ## flag))
+
+//
+// Macro for putting a character in the buffer.
+//
+#define IF_LOG(ch) { \
+ UCHAR lp = Adapter->LogPlace; \
+ Adapter->LogPlace++; \
+ Adapter->Log[(UCHAR)(lp+3)] = (UCHAR)'\0'; \
+ Adapter->Log[lp] = (ch); \
+ }
+
+//
+// Debug flag, determines what debug information is kept around
+//
+extern ULONG NE3200Debug;
+
+//
+// Possible values for the above flag
+//
+#define NE3200_DEBUG_DUMP_LOOKAHEAD 0x00000001 // dump lookahead buffer
+#define NE3200_DEBUG_DUMP_TRANSFER 0x00000002 // dump transfer buffer
+#define NE3200_DEBUG_DUMP_SEND 0x00000004 // dump send packet
+#define NE3200_DEBUG_DUMP_COMMAND 0x00000008 // dump command block & buffer
+
+#define NE3200_DEBUG_ACQUIRE 0x00000010 // NE3200AcquireCommandBlock activity
+#define NE3200_DEBUG_SUBMIT 0x00000020 // NE3200SubmitCommandBlock activity
+#define NE3200_DEBUG_ASSIGN 0x00000040 // NE3200AssignPacketToCommandBlock activity
+#define NE3200_DEBUG_RECEIVE 0x00000080 // ProcessReceiveInterrupts activity
+
+#define NE3200_DEBUG_LOUD 0x00000100 // print things
+#define NE3200_DEBUG_VERY_LOUD 0x00000200 // print lots of things
+
+#define DPrint1(fmt) DbgPrint(fmt)
+#define DPrint2(fmt,v1) DbgPrint(fmt,v1)
+#define DPrint3(fmt,v1,v2) DbgPrint(fmt,v1,v2)
+#define DPrint4(fmt,v1,v2,v3) DbgPrint(fmt,v1,v2,v3)
+
+#else // DBG
+
+#define IF_LOG(ch)
+
+#define IF_NE3200DBG(flag) if (0)
+#define DPrint1(fmt)
+#define DPrint2(fmt,v1)
+#define DPrint3(fmt,v1,v2)
+#define DPrint4(fmt,v1,v2,v3)
+
+#endif // DBG
+
+//
+// Keep symbols for internal functions
+//
+#define STATIC
+
+//
+// NDIS version of this driver
+//
+#define NE3200_NDIS_MAJOR_VERSION 3
+#define NE3200_NDIS_MINOR_VERSION 0
+
+
+extern NDIS_PHYSICAL_ADDRESS MinusOne;
+
+//
+// Macro for allocating memory
+//
+#define NE3200_ALLOC_PHYS(_Status, _pBuffer, _Length) \
+{ \
+ *(_Status) = NdisAllocateMemory( \
+ (PVOID*)(_pBuffer), \
+ (_Length), \
+ 0, \
+ MinusOne); \
+}
+
+//
+// Macro for freeing memory
+//
+#define NE3200_FREE_PHYS(_Buffer) NdisFreeMemory((_Buffer), 0, 0)
+
+
+//
+// Macro for moving memory around
+//
+#define NE3200_MOVE_MEMORY(Destination,Source,Length) NdisMoveMemory(Destination,Source,Length)
+
+//
+// Size of ethernet header
+//
+#define NE3200_HEADER_SIZE 14
+
+//
+// Size of lookahead buffer for loopback packets
+//
+#define NE3200_SIZE_OF_LOOPBACK 256
+
+
+//
+// The implementation of RESET.
+//
+// The NE3200 must be "held by the hand" during the reset & download
+// operations. Typically, the reset (or download) is initiated and
+// the status ports are POLLED, waiting for pass/fail status. This
+// is unacceptable in NT.
+//
+// To handle this cleanly in NT, the reset & download operations will
+// be controlled by a state machine. This state machine will be
+// contained by a flag and driven by a Timer Object.
+//
+// This ENUM represents the current state of the reset operation.
+//
+typedef enum _NE3200_RESET_STATE {
+
+ NE3200ResetStateStarting,
+ NE3200ResetStateResetting,
+ NE3200ResetStateDownloading,
+ NE3200ResetStateReloadAddress,
+ NE3200ResetStateComplete
+
+} NE3200_RESET_STATE, *PNE3200_RESET_STATE;
+
+//
+// This ENUM represents the result of the reset operation.
+//
+typedef enum _NE3200_RESET_RESULT {
+
+ NE3200ResetResultSuccessful,
+ NE3200ResetResultResetFailure,
+ NE3200ResetResultResetTimeout,
+ NE3200ResetResultInitializationFailure,
+ NE3200ResetResultInitializationTimeout,
+ NE3200ResetResultInvalidState,
+ NE3200ResetResultResources
+
+} NE3200_RESET_RESULT, *PNE3200_RESET_RESULT;
+
+
+struct _NE3200_ADAPTER;
+
+//
+// This structure defines the global data needed by the driver.
+//
+typedef struct _NE3200_GLOBAL_DATA {
+
+ //
+ // We need to allocate a buffer to contain the MAC.BIN code to be
+ // downloaded to the NE3200 adapter(s). This field will contain
+ // the virtual address of this buffer.
+ //
+ PVOID MacBinVirtualAddress;
+ NDIS_PHYSICAL_ADDRESS MacBinPhysicalAddress;
+
+ //
+ // Chain of Adapters
+ //
+ LIST_ENTRY AdapterList;
+
+ //
+ // The handle of the adapter used for the allocaton of
+ // the MAC.BIN buffer (the first one added for this MAC).
+ //
+ NDIS_HANDLE MacBinAdapterHandle;
+
+ //
+ // Handle to our driver
+ //
+ NDIS_HANDLE NE3200DriverHandle;
+
+ //
+ // Handle for NdisTerminateWrapper
+ //
+ NDIS_HANDLE NE3200NdisWrapperHandle;
+
+ //
+ // This field contains the actual length (in bytes) of MAC.BIN.
+ //
+ USHORT MacBinLength;
+
+} NE3200_GLOBAL_DATA, *PNE3200_GLOBAL_DATA;
+
+//
+// In addition to the Command Block fields which the NE3200
+// 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" NE3200 Command Block plus some additional
+// fields.
+//
+typedef struct _NE3200_SUPER_COMMAND_BLOCK {
+
+ //
+ // The actual NE3200 Command Block.
+ //
+ NE3200_COMMAND_BLOCK Hardware;
+
+ //
+ // This contains the physical address of the above Command Block.
+ //
+ NDIS_PHYSICAL_ADDRESS Self;
+
+ //
+ // Points to the packet from which data is being transmitted
+ // through this Command Block.
+ //
+ PNDIS_PACKET OwningPacket;
+
+ //
+ // This tells if the command block is a public or private command block.
+ //
+ PUINT AvailableCommandBlockCounter;
+
+ //
+ // This contains the virtual address of the next pending command.
+ //
+ struct _NE3200_SUPER_COMMAND_BLOCK *NextCommand;
+
+ //
+ // Is this from a set
+ //
+ BOOLEAN Set;
+
+ //
+ // 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;
+
+ //
+ // 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;
+
+ //
+ // Count of the number of times we have retried a command.
+ //
+ UCHAR TimeoutCount;
+
+ //
+ // When a packet is submitted to the hardware we record
+ // here whether it used adapter buffers and if so, the buffer
+ // index.
+ //
+ BOOLEAN UsedNE3200Buffer;
+ UINT NE3200BuffersIndex;
+
+} NE3200_SUPER_COMMAND_BLOCK, *PNE3200_SUPER_COMMAND_BLOCK;
+
+//
+// In addition to the Receive Entry fields which the NE3200
+// 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" NE3200 Receive Entry plus some additional
+// fields.
+//
+typedef struct _NE3200_SUPER_RECEIVE_ENTRY {
+
+ //
+ // The actual NE3200 Receive Entry.
+ //
+ NE3200_RECEIVE_ENTRY Hardware;
+
+ //
+ // This contains the physical address of the above Receive Entry.
+ //
+ NDIS_PHYSICAL_ADDRESS Self;
+
+ //
+ // This contains the virtual address of the next
+ // Receive Entry in the Receive Queue.
+ //
+ struct _NE3200_SUPER_RECEIVE_ENTRY *NextEntry;
+
+ //
+ // This contains the virtual address of this Receive Entry's
+ // frame buffer.
+ //
+ PVOID ReceiveBuffer;
+ NDIS_PHYSICAL_ADDRESS ReceiveBufferPhysical;
+
+ //
+ // Points to an NDIS buffer which describes this buffer
+ //
+ PNDIS_BUFFER FlushBuffer;
+
+} NE3200_SUPER_RECEIVE_ENTRY, *PNE3200_SUPER_RECEIVE_ENTRY;
+
+
+
+//
+// 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 _NE3200_RESERVED {
+
+ //
+ // Points to the next packet in the chain of queued packets
+ // being allocated or waiting for the finish of transmission.
+ //
+ PNDIS_PACKET Next;
+
+ //
+ // If TRUE then the packet caused an adapter buffer to
+ // be allocated.
+ //
+ BOOLEAN UsedNE3200Buffer;
+
+ //
+ // If the previous field was TRUE then this gives the
+ // index into the array of adapter buffer descriptors that
+ // contains the old packet information.
+ //
+ UCHAR NE3200BuffersIndex;
+
+ //
+ // Gives the index of the Command Block as well as the
+ // command block to packet structure.
+ //
+ USHORT CommandBlockIndex;
+
+} NE3200_RESERVED,*PNE3200_RESERVED;
+
+//
+// This macro will return a pointer to the NE3200 reserved portion
+// of a packet given a pointer to a packet.
+//
+#define PNE3200_RESERVED_FROM_PACKET(Packet) \
+ ((PNE3200_RESERVED)((Packet)->MiniportReserved))
+
+//
+// If an ndis packet does not meet the hardware contraints then
+// an adapter buffer will be allocated. Enough data will be copied
+// out of the ndis packet so that by using a combination of the
+// adapter buffer and remaining ndis buffers the hardware
+// constraints are satisfied.
+//
+// In the NE3200_ADAPTER structure three threaded lists are kept in
+// one array. One points to a list of NE3200_BUFFER_DESCRIPTORS
+// that point to small adapter buffers. Another is for medium sized
+// buffers and the last for full sized (large) buffers.
+//
+// The allocation is controlled via a free list head and
+// the free lists are "threaded" by a field in the adapter buffer
+// descriptor.
+//
+typedef struct _NE3200_BUFFER_DESCRIPTOR {
+
+ //
+ // A physical pointer to a small, medium, or large buffer.
+ //
+ NDIS_PHYSICAL_ADDRESS PhysicalNE3200Buffer;
+
+ //
+ // A virtual pointer to a small, medium, or large buffer.
+ //
+ PVOID VirtualNE3200Buffer;
+
+ //
+ // Flush buffer
+ //
+ PNDIS_BUFFER FlushBuffer;
+
+ //
+ // Threads the elements of an array of these descriptors into
+ // a free list. -1 implies no more entries in the list.
+ //
+ INT Next;
+
+ //
+ // Holds the amount of space (in bytes) available in the buffer
+ //
+ UINT BufferSize;
+
+ //
+ // Holds the length of data placed into the buffer. This
+ // can (and likely will) be less that the actual buffers
+ // length.
+ //
+ UINT DataLength;
+
+} NE3200_BUFFER_DESCRIPTOR,*PNE3200_BUFFER_DESCRIPTOR;
+
+//
+// This is the main structure for each adapter.
+//
+typedef struct _NE3200_ADAPTER {
+
+#if DBG
+ PUCHAR LogAddress;
+#endif
+
+ PUCHAR SystemDoorbellInterruptPort;
+ PUCHAR SystemDoorbellMaskPort;
+
+ //
+ // Flag that when enabled lets routines know that a reset
+ // is in progress.
+ //
+ BOOLEAN ResetInProgress;
+
+ //
+ // TRUE when a receive interrupt is received
+ //
+ BOOLEAN ReceiveInterrupt;
+
+ BOOLEAN InterruptsDisabled;
+
+ //
+ // Handle given by NDIS when the widget was initialized.
+ //
+ NDIS_HANDLE MiniportAdapterHandle;
+
+ //
+ // Pointer to the head of the Receive Queue.
+ //
+ PNE3200_SUPER_RECEIVE_ENTRY ReceiveQueueHead;
+
+ //
+ // Pointer to the tail of the Receive Queue.
+ //
+ PNE3200_SUPER_RECEIVE_ENTRY ReceiveQueueTail;
+
+ //
+ // Packet counts
+ //
+ UINT GoodReceives;
+
+ //
+ // Pointer to the next command to complete execution.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK FirstCommandOnCard;
+
+ //
+ // Pointers to an array of adapter buffer descriptors.
+ // The array will actually be threaded together by
+ // three free lists. The lists will be for small,
+ // medium and full sized packets.
+ //
+ PNE3200_BUFFER_DESCRIPTOR NE3200Buffers;
+
+ //
+ // List head for the adapters buffers. If the list
+ // head is equal to -1 then there are no free elements
+ // on the list.
+ //
+ INT NE3200BufferListHead;
+
+ UINT GoodTransmits;
+
+ //
+ // Is there an outstanding request
+ //
+ BOOLEAN RequestInProgress;
+
+ //
+ // Is this a packet resubmission?
+ //
+ BOOLEAN PacketResubmission;
+
+ //
+ // Pointer to the most recently submitted command.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK LastCommandOnCard;
+
+ //
+ // Pointer to the first command waiting to be put on the list to the card.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK FirstWaitingCommand;
+
+ //
+ // Pointer to the last command waiting to be put on the list to the card.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK LastWaitingCommand;
+
+ PUCHAR BaseMailboxPort;
+
+ //
+ // Total number of Command Blocks in the PublicCommandQueue.
+ //
+ UINT NumberOfPublicCommandBlocks;
+
+ //
+ // Number of available Command Blocks in the Command Queue.
+ //
+ UINT NumberOfAvailableCommandBlocks;
+
+ //
+ // Pointer to the next available Command Block.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK NextCommandBlock;
+
+ PNE3200_SUPER_COMMAND_BLOCK LastCommandBlockAllocated;
+//----
+ //
+ // Used for filter and statistics operations
+ //
+ PNE3200_SUPER_COMMAND_BLOCK PublicCommandQueue;
+ NDIS_PHYSICAL_ADDRESS PublicCommandQueuePhysical;
+
+ //
+ // Used for padding short packets
+ //
+ PUCHAR PaddingVirtualAddress;
+ NDIS_PHYSICAL_ADDRESS PaddingPhysicalAddress;
+
+ //
+ // Points to the card multicast entry table
+ //
+ PUCHAR CardMulticastTable;
+ NDIS_PHYSICAL_ADDRESS CardMulticastTablePhysical;
+
+ //
+ // Holds the interrupt object for this adapter.
+ //
+ NDIS_MINIPORT_INTERRUPT Interrupt;
+
+ //
+ // Current packet filter on adapter
+ //
+ UINT CurrentPacketFilter;
+
+ //
+ // Is this the initial initialization reset?
+ //
+ BOOLEAN InitialInit;
+
+ //
+ // These variables hold information about a pending request.
+ //
+ PUINT BytesWritten;
+ PUINT BytesNeeded;
+ NDIS_OID Oid;
+ PVOID InformationBuffer;
+ UINT InformationBufferLength;
+
+ //
+ // The EISA Slot Number for this adapter.
+ //
+ USHORT EisaSlot;
+
+ //
+ // The I/O Base address of the adapter.
+ //
+ ULONG AdapterIoBase;
+
+ //
+ // Various mapped I/O Port Addresses for this adapter.
+ //
+ PUCHAR ResetPort;
+ PUCHAR SystemInterruptPort;
+ PUCHAR LocalDoorbellInterruptPort;
+
+ //
+ // Count of CheckForHang calls that have occurred without
+ // a receive interrupt.
+ //
+ UCHAR NoReceiveInterruptCount;
+
+ //
+ // TRUE when a send interrupt is received
+ //
+ BOOLEAN SendInterrupt;
+
+ //
+ // Should we use an alternative address
+ //
+ BOOLEAN AddressChanged;
+
+ //
+ // The network address from the hardware.
+ //
+ CHAR NetworkAddress[NE3200_LENGTH_OF_ADDRESS];
+ CHAR CurrentAddress[NE3200_LENGTH_OF_ADDRESS];
+
+ //
+ // Pointer to the Receive Queue.
+ //
+ PNE3200_SUPER_RECEIVE_ENTRY ReceiveQueue;
+ NDIS_PHYSICAL_ADDRESS ReceiveQueuePhysical;
+
+ //
+ // Pointer to the Command Queue.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK CommandQueue;
+ NDIS_PHYSICAL_ADDRESS CommandQueuePhysical;
+
+ //
+ // Next free public command block
+ //
+ UINT NextPublicCommandBlock;
+
+ //
+ // Total number of Command Blocks in the Command Queue.
+ //
+ UINT NumberOfCommandBlocks;
+
+ //
+ // Total number of Receive Buffers.
+ //
+ UINT NumberOfReceiveBuffers;
+
+ //
+ // Total number of Transmit Buffers.
+ //
+ UINT NumberOfTransmitBuffers;
+
+ //
+ // The Flush buffer pool
+ //
+ PNDIS_HANDLE FlushBufferPoolHandle;
+
+ //
+ // Is the reset to be done asynchronously?
+ //
+ BOOLEAN ResetAsynchronous;
+
+ //
+ // Used to store the command block for asynchronous resetting.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK ResetHandlerCommandBlock;
+
+ //
+ // Index of the receive ring descriptor that started the
+ // last packet not completely received by the hardware.
+ //
+ UINT CurrentReceiveIndex;
+
+ //
+ // Counters to hold the various number of errors/statistics for both
+ // reception and transmission.
+ //
+
+ //
+ // Packet counts
+ //
+ UINT TransmitsQueued;
+
+ //
+ // Count of transmit errors
+ //
+ UINT RetryFailure;
+ UINT LostCarrier;
+ UINT UnderFlow;
+ UINT NoClearToSend;
+ UINT Deferred;
+ UINT OneRetry;
+ UINT MoreThanOneRetry;
+
+ //
+ // Count of receive errors
+ //
+ UINT CrcErrors;
+ UINT AlignmentErrors;
+ UINT OutOfResources;
+ UINT DmaOverruns;
+
+ //
+ // This holds the current state of the reset operation.
+ //
+ NE3200_RESET_STATE ResetState;
+
+ //
+ // This hold the result of the reset operation.
+ //
+ NE3200_RESET_RESULT ResetResult;
+
+ //
+ // This is a timeout counter. Before a timed operation is
+ // started, a positive value is placed in this field. Every
+ // time the particular state is entered in the ResetDpc, this
+ // value is decremented. If this value becomes zero, then
+ // the operation has timed-out and the adapter is toast.
+ //
+ UINT ResetTimeoutCounter;
+
+ //
+ // This timer object will be used to queue the deferred processing routine
+ //
+ NDIS_MINIPORT_TIMER DeferredTimer;
+
+ //
+ // This timer is for handling resets from when the card is dead.
+ //
+ NDIS_MINIPORT_TIMER ResetTimer;
+
+ //
+ // Place for holding command block for pending commands during
+ // reset processing.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK ResetCommandBlock;
+
+ //
+ // This is a pointer to the Configuration Block for this
+ // adapter. The Configuration Block will be modified during
+ // changes to the packet filter.
+ //
+ PNE3200_CONFIGURATION_BLOCK ConfigurationBlock;
+ NDIS_PHYSICAL_ADDRESS ConfigurationBlockPhysical;
+
+ //
+ // This points to the next adapter registered for the same Mac
+ //
+ LIST_ENTRY AdapterList;
+
+#if DBG
+ UCHAR Log[256];
+ UCHAR LogPlace;
+#endif
+
+} NE3200_ADAPTER,*PNE3200_ADAPTER;
+
+//
+// Given a MiniportContextHandle return the PNE3200_ADAPTER
+// it represents.
+//
+#define PNE3200_ADAPTER_FROM_CONTEXT_HANDLE(Handle) \
+ ((PNE3200_ADAPTER)(Handle))
+
+//
+// Procedures which do error logging
+//
+
+typedef enum _NE3200_PROC_ID{
+ allocateAdapterMemory,
+ initialInit,
+ setConfigurationBlockAndInit,
+ registerAdapter,
+ openAdapter,
+ wakeUpDpc,
+ resetDpc
+}NE3200_PROC_ID;
+
+//
+// Error log codes.
+//
+#define NE3200_ERRMSG_ALLOC_MEM (ULONG)0x01
+#define NE3200_ERRMSG_INIT_INTERRUPT (ULONG)0x02
+#define NE3200_ERRMSG_NO_DELAY (ULONG)0x03
+#define NE3200_ERRMSG_INIT_DB (ULONG)0x04
+#define NE3200_ERRMSG_OPEN_DB (ULONG)0x05
+#define NE3200_ERRMSG_BAD_STATE (ULONG)0x06
+#define NE3200_ERRMSG_ (ULONG)0x06
+
+
+//
+// Define our block of global data. The actual data resides in NE3200.C.
+//
+extern NE3200_GLOBAL_DATA NE3200Globals;
+
+#include <ne3200pr.h>
+
+#endif // _NE3200SOFTWARE_
diff --git a/private/ntos/ndis/ne3200/request.c b/private/ntos/ndis/ne3200/request.c
new file mode 100644
index 000000000..5c294ce9d
--- /dev/null
+++ b/private/ntos/ndis/ne3200/request.c
@@ -0,0 +1,954 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ request.c
+
+Abstract:
+
+ This file contains code to implement request processing.
+ This driver conforms to the NDIS 3.0 miniport interface.
+
+Author:
+
+ Johnson R. Apacible (JohnsonA) 10-June-1991
+
+Environment:
+
+Revision History:
+
+--*/
+
+#include <ne3200sw.h>
+
+extern
+NDIS_STATUS
+NE3200ChangeClass(
+ PNE3200_ADAPTER Adapter,
+ IN UINT NewFilterClasses
+ )
+
+/*++
+
+Routine Description:
+
+ Action routine that will get called when a particular filter
+ class is first used or last cleared.
+
+Arguments:
+
+ NewFilterClasses - The current value of the class filter
+
+Return Value:
+
+ None.
+
+
+--*/
+
+{
+ //
+ // Holds the change that should be returned to the filtering package.
+ //
+ NDIS_STATUS StatusOfChange;
+
+ //
+ // Holds the list of changes;
+ //
+ UINT PacketChanges;
+
+ //
+ // This points to the public Command Block.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK CommandBlock;
+
+ //
+ // This points to the adapter's configuration block.
+ //
+ PNE3200_CONFIGURATION_BLOCK ConfigurationBlock =
+ Adapter->ConfigurationBlock;
+
+ //
+ // The NE3200 has no method for easily disabling multicast
+ // packets. Therefore, we'll only reconfigure the 82586
+ // when there is a change in either directed, broadcast, or
+ // promiscuous filtering.
+ //
+ PacketChanges = (Adapter->CurrentPacketFilter ^ NewFilterClasses) &
+ (NDIS_PACKET_TYPE_PROMISCUOUS |
+ NDIS_PACKET_TYPE_BROADCAST |
+ NDIS_PACKET_TYPE_DIRECTED);
+
+ if (!PacketChanges) {
+
+ return(NDIS_STATUS_SUCCESS);
+
+ }
+
+ //
+ // Use the generic command block
+ //
+ IF_LOG('F');
+
+ NE3200AcquirePublicCommandBlock(
+ Adapter,
+ &CommandBlock
+ );
+
+ //
+ // This from a set.
+ //
+ CommandBlock->Set = TRUE;
+
+ //
+ // Setup the command block.
+ //
+ CommandBlock->NextCommand = NULL;
+
+ CommandBlock->Hardware.State = NE3200_STATE_WAIT_FOR_ADAPTER;
+ CommandBlock->Hardware.Status = 0;
+ CommandBlock->Hardware.NextPending = NE3200_NULL;
+ CommandBlock->Hardware.CommandCode =
+ NE3200_COMMAND_CONFIGURE_82586;
+ CommandBlock->Hardware.PARAMETERS.CONFIGURE.ConfigurationBlock =
+ NdisGetPhysicalAddressLow(Adapter->ConfigurationBlockPhysical);
+
+ //
+ // Update the configuration block to reflect the new
+ // packet filtering.
+ //
+ if (NewFilterClasses == 0) {
+
+ ConfigurationBlock->PromiscuousMode = 0;
+ ConfigurationBlock->MacBinPromiscuous = 0;
+ ConfigurationBlock->DisableBroadcast = 1;
+
+ } else {
+
+ ConfigurationBlock->MacBinEnablePacketReception = 1;
+
+ if (PacketChanges & NDIS_PACKET_TYPE_PROMISCUOUS) {
+
+ ConfigurationBlock->PromiscuousMode = 1;
+ ConfigurationBlock->MacBinPromiscuous = 1;
+
+ } else {
+
+ ConfigurationBlock->PromiscuousMode = 0;
+ ConfigurationBlock->MacBinPromiscuous = 0;
+
+ }
+
+ if (PacketChanges & NDIS_PACKET_TYPE_BROADCAST) {
+
+ ConfigurationBlock->DisableBroadcast = 0;
+
+ } else {
+
+ ConfigurationBlock->DisableBroadcast = 1;
+
+ }
+
+ }
+
+ //
+ // Now that we've got the command block built,
+ // let's do it!
+ //
+ NE3200SubmitCommandBlock(Adapter, CommandBlock);
+
+ StatusOfChange = NDIS_STATUS_PENDING;
+
+ return StatusOfChange;
+}
+
+
+STATIC
+NDIS_STATUS
+NE3200UpdateMulticastTable(
+ IN PNE3200_ADAPTER Adapter,
+ IN UINT CurrentAddressCount,
+ IN CHAR CurrentAddresses[][NE3200_LENGTH_OF_ADDRESS]
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to update the list of multicast addreses
+ on the adapter.
+
+Arguments:
+
+ Adapter - The adapter where the multicast is to be changed.
+
+ CurrentAddressCount - The number of addresses in the address array.
+
+ CurrentAddresses - An array of multicast addresses. Note that this
+ array already contains the new address.
+
+Return Value:
+
+ None.
+
+
+--*/
+
+{
+
+ //
+ // This points to the public Command Block.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK CommandBlock;
+
+ //
+ // Holds the status that should be returned to the filtering package.
+ //
+ NDIS_STATUS StatusOfUpdate;
+
+ //
+ // Multicast address table
+ //
+ PUCHAR MulticastAddressTable;
+
+ IF_LOG('f');
+
+ //
+ // See if we can acquire a private command block.
+ //
+ NE3200AcquirePublicCommandBlock(Adapter, &CommandBlock);
+
+ //
+ // Store the request that uses this command block.
+ //
+ CommandBlock->Set = TRUE;
+
+ //
+ // Get the multicast address table.
+ //
+ MulticastAddressTable = Adapter->CardMulticastTable;
+
+ //
+ // Clear out the old address
+ //
+ NdisZeroMemory(
+ MulticastAddressTable,
+ CurrentAddressCount * NE3200_SIZE_OF_MULTICAST_TABLE_ENTRY
+ );
+
+ {
+
+ //
+ // Simple iteration counter.
+ //
+ UINT i;
+
+ //
+ // Pointer into the multicast address table.
+ //
+ PCHAR OriginalAddress;
+
+ //
+ // Pointer into our temporary buffer.
+ //
+ PCHAR MungedAddress;
+
+ //
+ // Munge the address to 16 bytes per entry.
+ //
+ OriginalAddress = &CurrentAddresses[0][0];
+ MungedAddress = MulticastAddressTable;
+
+ for ( i = CurrentAddressCount ; i > 0 ; i-- ) {
+
+ NdisMoveMemory(
+ MungedAddress,
+ OriginalAddress,
+ NE3200_LENGTH_OF_ADDRESS
+ );
+
+ OriginalAddress += NE3200_LENGTH_OF_ADDRESS;
+ MungedAddress += NE3200_SIZE_OF_MULTICAST_TABLE_ENTRY;
+
+ }
+
+
+ //
+ // Setup the command block.
+ //
+ CommandBlock->NextCommand = NULL;
+
+ CommandBlock->Hardware.State = NE3200_STATE_WAIT_FOR_ADAPTER;
+ CommandBlock->Hardware.Status = 0;
+ CommandBlock->Hardware.NextPending = NE3200_NULL;
+ CommandBlock->Hardware.CommandCode = NE3200_COMMAND_SET_MULTICAST_ADDRESS;
+ CommandBlock->Hardware.PARAMETERS.MULTICAST.NumberOfMulticastAddresses =
+ (USHORT)CurrentAddressCount;
+
+ if (CurrentAddressCount == 0) {
+
+ CommandBlock->Hardware.PARAMETERS.MULTICAST.MulticastAddressTable =
+ (NE3200_PHYSICAL_ADDRESS)NULL;
+
+ } else {
+
+ CommandBlock->Hardware.PARAMETERS.MULTICAST.MulticastAddressTable =
+ NdisGetPhysicalAddressLow(Adapter->CardMulticastTablePhysical);
+
+ }
+
+ //
+ // Now that we've got the command block built,
+ // let's do it!
+ //
+ NE3200SubmitCommandBlock(Adapter, CommandBlock);
+
+ StatusOfUpdate = NDIS_STATUS_PENDING;
+
+ }
+
+ return StatusOfUpdate;
+
+}
+
+extern
+NDIS_STATUS
+NE3200SetInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesRead,
+ OUT PULONG BytesNeeded
+ )
+
+/*++
+
+Routine Description:
+
+ NE3200SetInformation handles a set operation for a
+ single OID.
+
+Arguments:
+
+ MiniportAdapterContext - The adapter that the set is for.
+
+ Oid - The OID of the set.
+
+ InformationBuffer - Holds the data to be set.
+
+ InformationBufferLength - The length of InformationBuffer.
+
+ BytesRead - If the call is successful, returns the number
+ of bytes read from InformationBuffer.
+
+ 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
+
+--*/
+
+{
+ //
+ // Variable to hold the new packet filter
+ //
+ ULONG PacketFilter;
+
+ //
+ // The adapter to process the request for.
+ //
+ PNE3200_ADAPTER Adapter = PNE3200_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
+
+ //
+ // Status of NDIS operation
+ //
+ NDIS_STATUS Status;
+
+ IF_LOG('w');
+
+ //
+ // Now check for the most common OIDs
+ //
+ switch (Oid) {
+
+ case OID_802_3_MULTICAST_LIST:
+
+ if (InformationBufferLength % NE3200_LENGTH_OF_ADDRESS != 0) {
+
+ //
+ // The data must be a multiple of the Ethernet
+ // address size.
+ //
+ return(NDIS_STATUS_INVALID_DATA);
+
+ }
+
+ //
+ // Now call the routine that does this.
+ //
+ Status = NE3200UpdateMulticastTable(
+ Adapter,
+ InformationBufferLength /
+ NE3200_LENGTH_OF_ADDRESS,
+ InformationBuffer
+ );
+
+ *BytesRead = InformationBufferLength;
+ break;
+
+ case OID_GEN_CURRENT_PACKET_FILTER:
+
+ if (InformationBufferLength != 4) {
+
+ return NDIS_STATUS_INVALID_DATA;
+
+ }
+
+ //
+ // Now call the filter package to set the packet filter.
+ //
+ NdisMoveMemory ((PVOID)&PacketFilter, InformationBuffer, sizeof(ULONG));
+
+ //
+ // Verify bits
+ //
+ if (PacketFilter & (NDIS_PACKET_TYPE_SOURCE_ROUTING |
+ NDIS_PACKET_TYPE_SMT |
+ NDIS_PACKET_TYPE_MAC_FRAME |
+ NDIS_PACKET_TYPE_FUNCTIONAL |
+ NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
+ NDIS_PACKET_TYPE_ALL_MULTICAST |
+ NDIS_PACKET_TYPE_GROUP
+ )) {
+
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+
+ *BytesRead = 4;
+ *BytesNeeded = 0;
+
+ break;
+
+ }
+
+ //
+ // Submit the change
+ //
+ Status = NE3200ChangeClass(
+ Adapter,
+ PacketFilter
+ );
+
+ *BytesRead = InformationBufferLength;
+
+ break;
+
+ case OID_GEN_CURRENT_LOOKAHEAD:
+
+ *BytesRead = 4;
+ Status = NDIS_STATUS_SUCCESS;
+ break;
+
+ default:
+
+ Status = NDIS_STATUS_INVALID_OID;
+ break;
+
+ }
+
+ if (Status == NDIS_STATUS_PENDING) {
+
+ Adapter->RequestInProgress = TRUE;
+
+ }
+
+ IF_LOG('W');
+ return Status;
+}
+
+STATIC
+NDIS_STATUS
+NE3200QueryInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesWritten,
+ OUT PULONG BytesNeeded
+)
+
+/*++
+
+Routine Description:
+
+ The NE3200QueryInformation process a Query request for
+ NDIS_OIDs that are specific about the Driver.
+
+Arguments:
+
+ MiniportAdapterContext - a pointer to the adapter.
+
+ Oid - the NDIS_OID to process.
+
+ InformationBuffer - a pointer into the
+ NdisRequest->InformationBuffer into which 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
+ then this will contain the number of bytes needed to complete the
+ request.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+ //
+ // The command block for getting the statistics from the adapter.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK CommandBlock;
+
+ //
+ // The adapter to process the request for.
+ //
+ PNE3200_ADAPTER Adapter = PNE3200_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
+
+ //
+ // Save the information about the request
+ //
+ Adapter->BytesWritten = BytesWritten;
+ Adapter->BytesNeeded = BytesNeeded;
+ Adapter->Oid = Oid;
+ Adapter->InformationBuffer = InformationBuffer;
+ Adapter->InformationBufferLength = InformationBufferLength;
+
+ IF_LOG('?');
+
+ //
+ // Get a public command block. This will succeed since
+ // the wrapper will only give one request at a time, and
+ // there are more than 1 public command block.
+ //
+ NE3200AcquirePublicCommandBlock(Adapter,
+ &CommandBlock
+ );
+
+ //
+ // Store the request that uses this CB
+ //
+ CommandBlock->Set = TRUE;
+
+ //
+ // Setup the command block.
+ //
+ CommandBlock->NextCommand = NULL;
+
+ CommandBlock->Hardware.State = NE3200_STATE_WAIT_FOR_ADAPTER;
+ CommandBlock->Hardware.Status = 0;
+ CommandBlock->Hardware.NextPending = NE3200_NULL;
+ CommandBlock->Hardware.CommandCode = NE3200_COMMAND_READ_ADAPTER_STATISTICS;
+
+ //
+ // Now that we're set up, let's do it!
+ //
+ Adapter->RequestInProgress = TRUE;
+ NE3200SubmitCommandBlock(Adapter, CommandBlock);
+
+ //
+ // Catch the ball at the interrupt handler
+ //
+
+ IF_LOG('/');
+ return NDIS_STATUS_PENDING;
+}
+
+STATIC
+VOID
+NE3200FinishQueryInformation(
+ IN PNE3200_ADAPTER Adapter
+)
+
+/*++
+
+Routine Description:
+
+ The NE3200FinishQueryInformation 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.
+
+--*/
+
+{
+
+static
+NDIS_OID NE3200GlobalSupportedOids[] = {
+ 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_3_PERMANENT_ADDRESS,
+ OID_802_3_CURRENT_ADDRESS,
+ OID_802_3_MULTICAST_LIST,
+ OID_802_3_MAXIMUM_LIST_SIZE,
+ OID_802_3_RCV_ERROR_ALIGNMENT,
+ OID_802_3_XMIT_ONE_COLLISION,
+ OID_802_3_XMIT_MORE_COLLISIONS,
+ OID_802_3_XMIT_DEFERRED,
+ OID_802_3_XMIT_MAX_COLLISIONS,
+ OID_802_3_RCV_OVERRUN,
+ OID_802_3_XMIT_UNDERRUN,
+ OID_802_3_XMIT_HEARTBEAT_FAILURE,
+ OID_802_3_XMIT_TIMES_CRS_LOST,
+ OID_802_3_XMIT_LATE_COLLISIONS
+ };
+
+ //
+ // Get the saved information about the request.
+ //
+ PUINT BytesWritten = Adapter->BytesWritten;
+ PUINT BytesNeeded = Adapter->BytesNeeded;
+ NDIS_OID Oid = Adapter->Oid;
+ PVOID InformationBuffer = Adapter->InformationBuffer;
+ UINT InformationBufferLength = Adapter->InformationBufferLength;
+
+
+ //
+ // Variables for holding the data that satisfies the request.
+ //
+ NDIS_MEDIUM Medium = NdisMedium802_3;
+ UINT GenericUlong;
+ USHORT GenericUShort;
+ UCHAR GenericArray[6];
+ NDIS_HARDWARE_STATUS HardwareStatus;
+
+ //
+ // Common variables for pointing to result of query
+ //
+ PVOID MoveSource = (PVOID)(&GenericUlong);
+ ULONG MoveBytes = sizeof(ULONG);
+
+ //
+ // The status of the request.
+ //
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+
+ //
+ // Initialize the result
+ //
+ *BytesWritten = 0;
+ *BytesNeeded = 0;
+
+ IF_LOG('!');
+
+ //
+ // Switch on request type
+ //
+ switch(Oid){
+
+ case OID_GEN_MAC_OPTIONS:
+
+ GenericUlong = (ULONG)(NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
+ NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
+ NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
+ NDIS_MAC_OPTION_NO_LOOPBACK
+ );
+
+ break;
+
+ case OID_GEN_SUPPORTED_LIST:
+
+ MoveSource = (PVOID)(NE3200GlobalSupportedOids);
+ MoveBytes = sizeof(NE3200GlobalSupportedOids);
+ break;
+
+ case OID_GEN_HARDWARE_STATUS:
+
+ if (Adapter->ResetInProgress){
+
+ HardwareStatus = NdisHardwareStatusReset;
+
+ } else {
+
+ HardwareStatus = NdisHardwareStatusReady;
+
+ }
+
+
+ MoveSource = (PVOID)(&HardwareStatus);
+ MoveBytes = sizeof(NDIS_HARDWARE_STATUS);
+
+ break;
+
+ case OID_GEN_MEDIA_SUPPORTED:
+ case OID_GEN_MEDIA_IN_USE:
+
+ MoveSource = (PVOID) (&Medium);
+ MoveBytes = sizeof(NDIS_MEDIUM);
+ break;
+
+ case OID_GEN_MAXIMUM_LOOKAHEAD:
+ case OID_GEN_CURRENT_LOOKAHEAD:
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+
+ GenericUlong = (ULONG) (MAXIMUM_ETHERNET_PACKET_SIZE - NE3200_HEADER_SIZE);
+
+ break;
+
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+
+ GenericUlong = (ULONG) (MAXIMUM_ETHERNET_PACKET_SIZE);
+
+ break;
+
+
+ case OID_GEN_LINK_SPEED:
+
+ //
+ // 10 Mbps
+ //
+ GenericUlong = (ULONG)100000;
+
+ break;
+
+
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:
+
+ GenericUlong = (ULONG) MAXIMUM_ETHERNET_PACKET_SIZE *
+ NE3200_NUMBER_OF_TRANSMIT_BUFFERS;
+
+ break;
+
+ case OID_GEN_RECEIVE_BUFFER_SPACE:
+
+ GenericUlong = (ULONG) MAXIMUM_ETHERNET_PACKET_SIZE *
+ NE3200_NUMBER_OF_RECEIVE_BUFFERS;
+
+ break;
+
+
+ case OID_GEN_VENDOR_ID:
+
+ NdisMoveMemory(
+ (PVOID)&GenericUlong,
+ Adapter->NetworkAddress,
+ 3
+ );
+ GenericUlong &= 0xFFFFFF00;
+ MoveSource = (PVOID)(&GenericUlong);
+ MoveBytes = sizeof(GenericUlong);
+ break;
+
+ case OID_GEN_VENDOR_DESCRIPTION:
+
+ MoveSource = (PVOID)"NE3200 Adapter";
+ MoveBytes = 15;
+ break;
+
+ case OID_GEN_DRIVER_VERSION:
+
+ GenericUShort = (USHORT)0x0300;
+
+ MoveSource = (PVOID)(&GenericUShort);
+ MoveBytes = sizeof(GenericUShort);
+ break;
+
+ case OID_802_3_PERMANENT_ADDRESS:
+
+ NdisMoveMemory(
+ (PCHAR)GenericArray,
+ Adapter->NetworkAddress,
+ NE3200_LENGTH_OF_ADDRESS
+ );
+
+ MoveSource = (PVOID)(GenericArray);
+ MoveBytes = NE3200_LENGTH_OF_ADDRESS;
+ break;
+
+ case OID_802_3_CURRENT_ADDRESS:
+ NdisMoveMemory(
+ (PCHAR)GenericArray,
+ Adapter->CurrentAddress,
+ NE3200_LENGTH_OF_ADDRESS
+ );
+
+ MoveSource = (PVOID)(GenericArray);
+ MoveBytes = NE3200_LENGTH_OF_ADDRESS;
+ break;
+
+ case OID_802_3_MAXIMUM_LIST_SIZE:
+
+ GenericUlong = (ULONG) NE3200_MAXIMUM_MULTICAST;
+
+ break;
+
+ default:
+
+ switch(Oid){
+
+ case OID_GEN_XMIT_OK:
+ GenericUlong = (ULONG) Adapter->GoodTransmits;
+ break;
+
+ case OID_GEN_RCV_OK:
+ GenericUlong = (ULONG) Adapter->GoodReceives;
+ break;
+
+ case OID_GEN_XMIT_ERROR:
+ GenericUlong = (ULONG) (Adapter->RetryFailure +
+ Adapter->LostCarrier +
+ Adapter->UnderFlow +
+ Adapter->NoClearToSend);
+ break;
+
+ case OID_GEN_RCV_ERROR:
+ GenericUlong = (ULONG) (Adapter->CrcErrors +
+ Adapter->AlignmentErrors +
+ Adapter->OutOfResources +
+ Adapter->DmaOverruns);
+ break;
+
+ case OID_GEN_RCV_NO_BUFFER:
+ GenericUlong = (ULONG) Adapter->OutOfResources;
+ break;
+
+ case OID_GEN_RCV_CRC_ERROR:
+ GenericUlong = (ULONG) Adapter->CrcErrors;
+ break;
+
+ case OID_GEN_TRANSMIT_QUEUE_LENGTH:
+ GenericUlong = (ULONG) Adapter->TransmitsQueued;
+ break;
+
+ case OID_802_3_RCV_ERROR_ALIGNMENT:
+ GenericUlong = (ULONG) Adapter->AlignmentErrors;
+ break;
+
+ case OID_802_3_XMIT_ONE_COLLISION:
+ GenericUlong = (ULONG) Adapter->OneRetry;
+ break;
+
+ case OID_802_3_XMIT_MORE_COLLISIONS:
+ GenericUlong = (ULONG) Adapter->MoreThanOneRetry;
+ break;
+
+ case OID_802_3_XMIT_DEFERRED:
+ GenericUlong = (ULONG) Adapter->Deferred;
+ break;
+
+ case OID_802_3_XMIT_MAX_COLLISIONS:
+ GenericUlong = (ULONG) Adapter->RetryFailure;
+ break;
+
+ case OID_802_3_RCV_OVERRUN:
+ GenericUlong = (ULONG) Adapter->DmaOverruns;
+ break;
+
+ case OID_802_3_XMIT_UNDERRUN:
+ GenericUlong = (ULONG) Adapter->UnderFlow;
+ break;
+
+ case OID_802_3_XMIT_HEARTBEAT_FAILURE:
+ GenericUlong = (ULONG) Adapter->NoClearToSend;
+ break;
+
+ case OID_802_3_XMIT_TIMES_CRS_LOST:
+ GenericUlong = (ULONG) Adapter->LostCarrier;
+ break;
+
+ default:
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+ break;
+
+ }
+
+ }
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+
+ if (MoveBytes > InformationBufferLength) {
+
+ //
+ // Not enough room in InformationBuffer. Punt
+ //
+ *BytesNeeded = MoveBytes;
+
+ Status = NDIS_STATUS_INVALID_LENGTH;
+
+ } else {
+
+ //
+ // Copy result into InformationBuffer
+ //
+ *BytesWritten = MoveBytes;
+
+ if (MoveBytes > 0) {
+
+ NE3200_MOVE_MEMORY(
+ InformationBuffer,
+ MoveSource,
+ MoveBytes
+ );
+ }
+ }
+ }
+
+ Adapter->RequestInProgress = FALSE;
+
+ //
+ // Complete the request
+ //
+ NdisMQueryInformationComplete(
+ Adapter->MiniportAdapterHandle,
+ Status
+ );
+
+ IF_LOG('@');
+
+ return;
+}
+
diff --git a/private/ntos/ndis/ne3200/reset.c b/private/ntos/ndis/ne3200/reset.c
new file mode 100644
index 000000000..1da22a03e
--- /dev/null
+++ b/private/ntos/ndis/ne3200/reset.c
@@ -0,0 +1,1805 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ reset.c
+
+Abstract:
+
+ This is the file containing the reset code for the Novell NE3200 EISA
+ Ethernet adapter. This driver conforms to the NDIS 3.0 miniport
+ interface.
+
+Author:
+
+ Keith Moore (KeithMo) 08-Jan-1991
+
+Environment:
+
+Revision History:
+
+--*/
+
+#include <ne3200sw.h>
+
+//
+// Global information stored in ne3200.c. This is used for
+// getting at the download software
+//
+extern NE3200_GLOBAL_DATA NE3200Globals;
+
+//
+// Forward declarations of functions in this file
+//
+extern
+VOID
+NE3200ProcessRequestQueue(
+ IN PNE3200_ADAPTER Adapter,
+ IN BOOLEAN StatisticsUpdated
+ );
+
+STATIC
+VOID
+NE3200SetConfigurationBlock(
+ IN PNE3200_ADAPTER Adapter
+ );
+
+STATIC
+BOOLEAN
+NE3200SetConfigurationBlockAndInit(
+ IN PNE3200_ADAPTER Adapter
+ );
+
+NDIS_STATUS
+NE3200ChangeCurrentAddress(
+ IN PNE3200_ADAPTER Adapter
+ );
+
+VOID
+NE3200ResetCommandBlocks(
+ IN PNE3200_ADAPTER Adapter
+ );
+
+extern
+VOID
+NE3200GetStationAddress(
+ IN PNE3200_ADAPTER Adapter
+ );
+
+extern
+VOID
+NE3200SetupForReset(
+ IN PNE3200_ADAPTER Adapter
+ );
+
+STATIC
+VOID
+NE3200DoResetIndications(
+ IN PNE3200_ADAPTER Adapter,
+ IN NDIS_STATUS Status
+ );
+
+VOID
+NE3200ResetHandler(
+ IN PVOID SystemSpecific1,
+ IN PNE3200_ADAPTER Adapter,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ );
+
+BOOLEAN
+NE3200InitialInit(
+ IN PNE3200_ADAPTER Adapter,
+ IN UINT NE3200InterruptVector,
+ IN NDIS_INTERRUPT_MODE NE3200InterruptMode
+ );
+
+
+#pragma NDIS_INIT_FUNCTION(NE3200InitialInit)
+
+BOOLEAN
+NE3200InitialInit(
+ IN PNE3200_ADAPTER Adapter,
+ IN UINT NE3200InterruptVector,
+ IN NDIS_INTERRUPT_MODE NE3200InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets up the initial init of the driver, by
+ stopping the adapter, connecting the interrupt and initializing
+ the adapter.
+
+Arguments:
+
+ Adapter - The adapter for the hardware.
+
+Return Value:
+
+ TRUE if the initialization succeeds, else FALSE.
+
+--*/
+
+{
+ //
+ // Status of NDIS calls
+ //
+ NDIS_STATUS Status;
+
+ //
+ // First we make sure that the device is stopped.
+ //
+ NE3200StopChip(Adapter);
+
+ //
+ // The ISR will set this to FALSE if we get an interrupt
+ //
+ Adapter->InitialInit = TRUE;
+
+ //
+ // Initialize the interrupt.
+ //
+ Status = NdisMRegisterInterrupt(
+ &Adapter->Interrupt,
+ Adapter->MiniportAdapterHandle,
+ NE3200InterruptVector,
+ NE3200InterruptVector,
+ FALSE,
+ FALSE,
+ NE3200InterruptMode
+ );
+
+ //
+ // So far so good
+ //
+ if (Status == NDIS_STATUS_SUCCESS) {
+
+ //
+ // Now try to initialize the adapter
+ //
+ if (!NE3200SetConfigurationBlockAndInit(Adapter)) {
+
+ //
+ // Failed. Write out an error log entry.
+ //
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_TIMEOUT,
+ 2,
+ initialInit,
+ NE3200_ERRMSG_NO_DELAY
+ );
+
+ //
+ // Unhook the interrupt
+ //
+ NdisMDeregisterInterrupt(&Adapter->Interrupt);
+
+ Adapter->InitialInit = FALSE;
+
+ return FALSE;
+
+ }
+
+ //
+ // Get hardware assigned network address.
+ //
+ NE3200GetStationAddress(
+ Adapter
+ );
+
+ //
+ // We can start the chip. We may not
+ // have any bindings to indicate to but this
+ // is unimportant.
+ //
+ Status = NE3200ChangeCurrentAddress(Adapter);
+
+ Adapter->InitialInit = FALSE;
+
+ return(Status == NDIS_STATUS_SUCCESS);
+
+ } else {
+
+ //
+ // Interrupt line appears to be taken. Notify user.
+ //
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_INTERRUPT_CONNECT,
+ 2,
+ initialInit,
+ NE3200_ERRMSG_INIT_INTERRUPT
+ );
+
+ Adapter->InitialInit = FALSE;
+
+ return(FALSE);
+ }
+
+}
+
+VOID
+NE3200StartChipAndDisableInterrupts(
+ IN PNE3200_ADAPTER Adapter,
+ IN PNE3200_SUPER_RECEIVE_ENTRY FirstReceiveEntry
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to start an already initialized NE3200,
+ but to keep the interrupt line masked.
+
+Arguments:
+
+ Adapter - The adapter for the NE3200 to start.
+
+ FirstReceiveEntry - Pointer to the first receive entry to be
+ used by the adapter.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ IF_LOG('%');
+
+ //
+ // Write the new receive pointer.
+ //
+ NE3200_WRITE_RECEIVE_POINTER(
+ Adapter,
+ NdisGetPhysicalAddressLow(FirstReceiveEntry->Self)
+ );
+
+ NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT(
+ Adapter,
+ NE3200_LOCAL_DOORBELL_NEW_RECEIVE
+ );
+
+ //
+ // Initialize the doorbell & system interrupt masks
+ //
+ NE3200_WRITE_SYSTEM_DOORBELL_MASK(
+ Adapter,
+ 0
+ );
+
+ NE3200_WRITE_SYSTEM_INTERRUPT(
+ Adapter,
+ NE3200_SYSTEM_INTERRUPT_ENABLE
+ );
+
+ NE3200_WRITE_MAILBOX_UCHAR(
+ Adapter,
+ NE3200_MAILBOX_STATUS,
+ 0
+ );
+
+}
+
+VOID
+NE3200EnableAdapter(
+ IN NDIS_HANDLE Context
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to start an already initialized NE3200.
+
+Arguments:
+
+ Context - The adapter for the NE3200 to start.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PNE3200_ADAPTER Adapter = (PNE3200_ADAPTER)Context;
+
+ IF_LOG('#');
+
+ //
+ // Initialize the doorbell & system interrupt masks
+ //
+ NE3200_WRITE_SYSTEM_INTERRUPT(
+ Adapter,
+ NE3200_SYSTEM_INTERRUPT_ENABLE
+ );
+
+ if (!Adapter->InterruptsDisabled) {
+ NE3200_WRITE_SYSTEM_DOORBELL_MASK(
+ Adapter,
+ NE3200_SYSTEM_DOORBELL_MASK
+ );
+ }
+
+ NE3200_WRITE_SYSTEM_DOORBELL_INTERRUPT(
+ Adapter,
+ NE3200_SYSTEM_DOORBELL_MASK
+ );
+
+ NE3200_WRITE_MAILBOX_UCHAR(
+ Adapter,
+ NE3200_MAILBOX_STATUS,
+ 0
+ );
+
+}
+
+VOID
+NE3200EnableInterrupt(
+ IN NDIS_HANDLE Context
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to turn on the interrupt mask.
+
+Arguments:
+
+ Context - The adapter for the NE3200 to start.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PNE3200_ADAPTER Adapter = (PNE3200_ADAPTER)Context;
+
+ IF_LOG('E');
+
+ //
+ // Enable further interrupts.
+ //
+ Adapter->InterruptsDisabled = FALSE;
+ NE3200_WRITE_SYSTEM_DOORBELL_MASK(
+ Adapter,
+ NE3200_SYSTEM_DOORBELL_MASK
+ );
+
+}
+
+VOID
+NE3200DisableInterrupt(
+ IN NDIS_HANDLE Context
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to turn off the interrupt mask.
+
+Arguments:
+
+ Context - The adapter for the NE3200 to start.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PNE3200_ADAPTER Adapter = (PNE3200_ADAPTER)Context;
+
+ //
+ // Initialize the doorbell mask
+ //
+ Adapter->InterruptsDisabled = TRUE;
+ NE3200_WRITE_SYSTEM_DOORBELL_MASK(
+ Adapter,
+ 0
+ );
+
+ IF_LOG('D');
+}
+
+VOID
+NE3200StopChip(
+ IN PNE3200_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to stop the NE3200.
+
+Arguments:
+
+ Adapter - The NE3200 adapter to stop.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ IF_LOG('h');
+
+ //
+ // Packet reception can be stopped by writing a
+ // (ULONG)-1 to the Receive Packet Mailbox port.
+ // Also, commands can be stopped by writing a -1
+ // to the Command Pointer Mailbox port.
+ //
+ NE3200_WRITE_RECEIVE_POINTER(
+ Adapter,
+ NE3200_NULL
+ );
+
+ NE3200_WRITE_COMMAND_POINTER(
+ Adapter,
+ NE3200_NULL
+ );
+
+ //
+ // Ack any outstanding interrupts
+ //
+ NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT(
+ Adapter,
+ NE3200_LOCAL_DOORBELL_NEW_RECEIVE | NE3200_LOCAL_DOORBELL_NEW_COMMAND
+ );
+
+ //
+ // Disable the doorbell & system interrupt masks.
+ //
+ NE3200_WRITE_SYSTEM_INTERRUPT(
+ Adapter,
+ 0
+ );
+
+ NE3200_WRITE_SYSTEM_DOORBELL_MASK(
+ Adapter,
+ 0
+ );
+
+ NE3200_WRITE_SYSTEM_DOORBELL_INTERRUPT(
+ Adapter,
+ 0
+ );
+
+}
+
+STATIC
+VOID
+NE3200SetConfigurationBlock(
+ IN PNE3200_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine simply fills the configuration block
+ with the information necessary for initialization.
+
+Arguments:
+
+ Adapter - The adapter which holds the initialization block
+ to initialize.
+
+Return Value:
+
+ None.
+
+
+--*/
+
+{
+
+ PNE3200_CONFIGURATION_BLOCK Configuration;
+
+ //
+ // Get the configuration block
+ //
+ Configuration = Adapter->ConfigurationBlock;
+
+ //
+ // Initialize it to zero
+ //
+ NdisZeroMemory(
+ Configuration,
+ sizeof(NE3200_CONFIGURATION_BLOCK)
+ );
+
+ //
+ // Set up default values
+ //
+ Configuration->ByteCount = 12;
+ Configuration->FifoThreshold = 8;
+ Configuration->AddressLength = 6;
+ Configuration->SeparateAddressAndLength = 1;
+ Configuration->PreambleLength = 2;
+ Configuration->InterframeSpacing = 96;
+ Configuration->SlotTime = 512;
+ Configuration->MaximumRetries = 15;
+ Configuration->DisableBroadcast = 1;
+ Configuration->MinimumFrameLength = 64;
+
+}
+
+VOID
+NE3200DoAdapterReset(
+ IN PNE3200_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This is the resetting the adapter hardware.
+
+ It makes the following assumptions:
+
+ 1) That the hardware has been stopped.
+
+ 2) That no other adapter activity can occur.
+
+ When this routine is finished all of the adapter information
+ will be as if the driver was just initialized.
+
+Arguments:
+
+ Adapter - The adapter whose hardware is to be reset.
+
+Return Value:
+
+ not.
+
+--*/
+{
+
+ //
+ // Recover all of the adapter transmit merge buffers.
+ //
+ {
+
+ UINT i;
+
+ for (
+ i = 0;
+ i < NE3200_NUMBER_OF_TRANSMIT_BUFFERS;
+ i++
+ ) {
+
+ Adapter->NE3200Buffers[i].Next = i+1;
+
+ }
+
+ Adapter->NE3200BufferListHead = 0;
+ Adapter->NE3200Buffers[NE3200_NUMBER_OF_TRANSMIT_BUFFERS-1].Next = -1;
+
+ }
+
+ //
+ // Reset all state variables
+ //
+ NE3200ResetVariables(Adapter);
+
+ //
+ // Recover all command blocks
+ //
+ NE3200ResetCommandBlocks(Adapter);
+
+ //
+ // Initialize the adapter
+ //
+ NE3200SetConfigurationBlockAndInit(Adapter);
+
+
+}
+
+STATIC
+BOOLEAN
+NE3200SetConfigurationBlockAndInit(
+ IN PNE3200_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ It is this routine's responsibility to make sure that the
+ Configuration block is filled and the adapter is initialized
+ *but not* started.
+
+Arguments:
+
+ Adapter - The adapter whose hardware is to be initialized.
+
+Return Value:
+
+ If ResetAsynchoronous is FALSE, then returns TRUE if reset successful,
+ FALSE if reset unsuccessful.
+
+ If ResetAsynchoronous is TRUE, then always returns TRUE.
+
+--*/
+{
+
+ //
+ // Fill in the adapter's initialization block.
+ //
+ NE3200SetConfigurationBlock(Adapter);
+
+ //
+ // Set the initial state for the ResetDpc state machine.
+ //
+ Adapter->ResetState = NE3200ResetStateStarting;
+
+ //
+ // Go through the reset
+ //
+ NE3200ResetHandler(NULL, Adapter, NULL, NULL);
+
+ //
+ // Is Synchronous resets, then check the final result
+ //
+ if (!Adapter->ResetAsynchronous) {
+
+ return((Adapter->ResetResult == NE3200ResetResultSuccessful));
+
+ } else {
+
+ return(TRUE);
+
+ }
+
+}
+
+VOID
+NE3200ResetHandler(
+ IN PVOID SystemSpecific1,
+ IN PNE3200_ADAPTER Adapter,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ )
+
+/*++
+
+Routine Description:
+
+ This manages the reset/download process. It is
+ responsible for resetting the adapter, waiting for proper
+ status, downloading MAC.BIN, waiting for MAC.BIN initialization,
+ and optionally sending indications to the appropriate protocol.
+
+ Since the NE3200's status registers must be polled during the
+ reset/download process, this is implemented as a state machine.
+
+Arguments:
+
+ Adapter - The adapter whose hardware is to be initialized.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Physical address of the MAC.BIN buffer.
+ //
+ NDIS_PHYSICAL_ADDRESS MacBinPhysicalAddress;
+
+ //
+ // Status from the adapter.
+ //
+ UCHAR Status;
+
+ //
+ // Simple iteration counter.
+ //
+ UINT i;
+
+ //
+ // Loop until the reset has completed.
+ //
+ while (Adapter->ResetState != NE3200ResetStateComplete) {
+
+ switch (Adapter->ResetState) {
+
+ //
+ // The first stage of resetting an NE3200
+ //
+ case NE3200ResetStateStarting :
+
+ //
+ // Unfortunately, a hardware reset to the NE3200 does *not*
+ // reset the BMIC chip. To ensure that we read a proper status,
+ // we'll clear all of the BMIC's registers.
+ //
+ NE3200_WRITE_SYSTEM_INTERRUPT(
+ Adapter,
+ 0
+ );
+
+ //
+ // I changed this to ff since the original 0 didn't work for
+ // some cases. since we don't have the specs....
+ //
+ NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT(
+ Adapter,
+ 0xff
+ );
+
+ NE3200_WRITE_SYSTEM_DOORBELL_MASK(
+ Adapter,
+ 0
+ );
+
+ NE3200_SYNC_CLEAR_SYSTEM_DOORBELL_INTERRUPT(
+ Adapter
+ );
+
+ for (i = 0 ; i < 16 ; i += 4 ) {
+
+ NE3200_WRITE_MAILBOX_ULONG(
+ Adapter,
+ i,
+ 0L
+ );
+
+ }
+
+ //
+ // Toggle the NE3200's reset line.
+ //
+ NE3200_WRITE_RESET(
+ Adapter,
+ NE3200_RESET_BIT_ON
+ );
+
+ NE3200_WRITE_RESET(
+ Adapter,
+ NE3200_RESET_BIT_OFF
+ );
+
+ //
+ // Switch to the next state.
+ //
+ Adapter->ResetState = NE3200ResetStateResetting;
+ Adapter->ResetTimeoutCounter = NE3200_TIMEOUT_RESET;
+
+ //
+ // Loop to the next processing
+ //
+ break;
+
+ //
+ // Part Deux. The actual downloading of the software.
+ //
+ case NE3200ResetStateResetting :
+
+ //
+ // Read the status mailbox.
+ //
+ NE3200_READ_MAILBOX_UCHAR(Adapter, NE3200_MAILBOX_RESET_STATUS, &Status);
+
+ if (Status == NE3200_RESET_PASSED) {
+
+ //
+ // We have good reset. Initiate the MAC.BIN download.
+ //
+
+ //
+ // The station address for this adapter can be forced to
+ // a specific value at initialization time. When MAC.BIN
+ // first gets control, it reads mailbox 10. If this mailbox
+ // contains a 0xFF, then the burned-in PROM station address
+ // is used. If this mailbox contains any value other than
+ // 0xFF, then mailboxes 10-15 are read. The six bytes
+ // stored in these mailboxes then become the station address.
+ //
+ // Since we have no need for this feature, we will always
+ // initialize mailbox 10 with a 0xFF.
+ //
+ NE3200_WRITE_MAILBOX_UCHAR(
+ Adapter,
+ NE3200_MAILBOX_STATION_ID,
+ 0xFF
+ );
+
+
+ //
+ // Get the MAC.BIN buffer.
+ //
+ MacBinPhysicalAddress = NE3200Globals.MacBinPhysicalAddress;
+
+ //
+ // Download MAC.BIN to the card.
+ //
+ NE3200_WRITE_MAILBOX_USHORT(
+ Adapter,
+ NE3200_MAILBOX_MACBIN_LENGTH,
+ NE3200Globals.MacBinLength
+ );
+
+ NE3200_WRITE_MAILBOX_UCHAR(
+ Adapter,
+ NE3200_MAILBOX_MACBIN_DOWNLOAD_MODE,
+ NE3200_MACBIN_DIRECT
+ );
+
+ NE3200_WRITE_MAILBOX_ULONG(
+ Adapter,
+ NE3200_MAILBOX_MACBIN_POINTER,
+ NdisGetPhysicalAddressLow(MacBinPhysicalAddress)
+ );
+
+ NE3200_WRITE_MAILBOX_USHORT(
+ Adapter,
+ NE3200_MAILBOX_MACBIN_TARGET,
+ NE3200_MACBIN_TARGET_ADDRESS >> 1
+ );
+
+ //
+ // This next OUT "kicks" the loader into action.
+ //
+ NE3200_WRITE_MAILBOX_UCHAR(
+ Adapter,
+ NE3200_MAILBOX_RESET_STATUS,
+ 0
+ );
+
+ //
+ // Switch to the next state.
+ //
+ Adapter->ResetState = NE3200ResetStateDownloading;
+ Adapter->ResetTimeoutCounter = NE3200_TIMEOUT_DOWNLOAD;
+
+ //
+ // Loop to the next state.
+ //
+
+ } else if (Status == NE3200_RESET_FAILED) {
+
+ //
+ // Reset failure. Notify the authorities and
+ // next of kin.
+ //
+ Adapter->ResetResult = NE3200ResetResultResetFailure;
+ Adapter->ResetState = NE3200ResetStateComplete;
+
+ NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);
+
+ } else {
+
+ //
+ // Still waiting for results, check if we have
+ // timed out waiting.
+ //
+ Adapter->ResetTimeoutCounter--;
+
+ if (Adapter->ResetTimeoutCounter == 0) {
+
+ //
+ // We've timed-out. Bad news. Notify the death.
+ //
+ Adapter->ResetResult = NE3200ResetResultResetTimeout;
+ Adapter->ResetState = NE3200ResetStateComplete;
+
+ NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);
+
+ } else {
+
+ //
+ // For Synchronous resets, we stall. For async,
+ // we set a timer to check later.
+ //
+ if (!Adapter->ResetAsynchronous) {
+
+ //
+ // Otherwise, wait and try again.
+ //
+ NdisStallExecution(10000);
+
+ } else{
+
+ //
+ // Try again later.
+ //
+ NdisMSetTimer(&Adapter->ResetTimer, 100);
+
+ return;
+
+ }
+
+ }
+
+ }
+
+ break;
+
+ //
+ // Part Three: The download was started. Check for completion,
+ // and reload the current station address.
+ //
+ case NE3200ResetStateDownloading :
+
+ //
+ // Read the download status.
+ //
+ NE3200_READ_MAILBOX_UCHAR(Adapter, NE3200_MAILBOX_STATUS, &Status);
+
+ if (Status == NE3200_INITIALIZATION_PASSED) {
+
+ //
+ // According to documentation from Compaq, this next port
+ // write will (in a future MAC.BIN) tell MAC.BIN whether or
+ // not to handle loopback internally. This value is currently
+ // not used, but must still be written to the port.
+ //
+ NE3200_WRITE_MAILBOX_UCHAR(
+ Adapter,
+ NE3200_MAILBOX_STATUS,
+ 1
+ );
+
+ //
+ // Initialization is good, the card is ready.
+ //
+ NE3200StartChipAndDisableInterrupts(Adapter,
+ Adapter->ReceiveQueueHead
+ );
+
+ {
+
+ //
+ // Do the work for updating the current address
+ //
+
+ //
+ // This points to the public Command Block.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK CommandBlock;
+
+ //
+ // This points to the adapter's configuration block.
+ //
+ PNE3200_CONFIGURATION_BLOCK ConfigurationBlock =
+ Adapter->ConfigurationBlock;
+
+ //
+ // Get a public command block.
+ //
+ NE3200AcquirePublicCommandBlock(Adapter,
+ &CommandBlock
+ );
+
+ Adapter->ResetHandlerCommandBlock = CommandBlock;
+
+ //
+ // Setup the command block.
+ //
+
+ CommandBlock->NextCommand = NULL;
+
+ CommandBlock->Hardware.State = NE3200_STATE_WAIT_FOR_ADAPTER;
+ CommandBlock->Hardware.Status = 0;
+ CommandBlock->Hardware.NextPending = NE3200_NULL;
+ CommandBlock->Hardware.CommandCode =
+ NE3200_COMMAND_CONFIGURE_82586;
+ CommandBlock->Hardware.PARAMETERS.CONFIGURE.ConfigurationBlock =
+ NdisGetPhysicalAddressLow(Adapter->ConfigurationBlockPhysical);
+
+ //
+ // Now that we've got the command block built,
+ // let's do it!
+ //
+ NE3200SubmitCommandBlock(Adapter, CommandBlock);
+
+ Adapter->ResetState = NE3200ResetStateReloadAddress;
+ Adapter->ResetTimeoutCounter = NE3200_TIMEOUT_DOWNLOAD;
+
+ }
+
+ } else if (Status == NE3200_INITIALIZATION_FAILED) {
+
+ //
+ // Initialization failed. Notify the wrapper.
+ //
+ Adapter->ResetResult = NE3200ResetResultInitializationFailure;
+ Adapter->ResetState = NE3200ResetStateComplete;
+
+ NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);
+
+ } else {
+
+ //
+ // See if we've timed-out waiting for the download to
+ // complete.
+ //
+ Adapter->ResetTimeoutCounter--;
+
+ if (Adapter->ResetTimeoutCounter == 0) {
+
+ //
+ // We've timed-out. Bad news.
+ //
+ Adapter->ResetResult = NE3200ResetResultInitializationTimeout;
+ Adapter->ResetState = NE3200ResetStateComplete;
+
+ NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);
+
+ } else {
+
+ //
+ // For Synchronous resets, we stall. For async,
+ // we set a timer to check later.
+ //
+ if (!Adapter->ResetAsynchronous) {
+
+ //
+ // Otherwise, wait and try again.
+ //
+ NdisStallExecution(10000);
+
+ } else{
+
+ //
+ // Try again later.
+ //
+ NdisMSetTimer(&Adapter->ResetTimer, 100);
+ return;
+
+ }
+
+ }
+
+ }
+
+ break;
+
+ //
+ // Part Last: Waiting for the configuring of the adapter
+ // to complete
+ //
+ case NE3200ResetStateReloadAddress :
+
+ //
+ // Read the command block status.
+ //
+ if (Adapter->ResetHandlerCommandBlock->Hardware.State ==
+ NE3200_STATE_EXECUTION_COMPLETE) {
+
+ //
+ // return this command block
+ //
+ NE3200RelinquishCommandBlock(Adapter,
+ Adapter->ResetHandlerCommandBlock
+ );
+
+ //
+ // Reset is complete. Do those indications.
+ //
+ Adapter->ResetResult = NE3200ResetResultSuccessful;
+ Adapter->ResetState = NE3200ResetStateComplete;
+
+ NE3200DoResetIndications(Adapter, NDIS_STATUS_SUCCESS);
+
+ } else {
+
+ //
+ // See if we've timed-out.
+ //
+ Adapter->ResetTimeoutCounter--;
+
+ if (Adapter->ResetTimeoutCounter == 0) {
+
+ //
+ // We've timed-out. Bad news.
+ //
+
+ //
+ // return this command block
+ //
+ NE3200RelinquishCommandBlock(Adapter,
+ Adapter->ResetHandlerCommandBlock
+ );
+
+ Adapter->ResetResult = NE3200ResetResultInitializationTimeout;
+ Adapter->ResetState = NE3200ResetStateComplete;
+
+ NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);
+
+ } else {
+
+ if ( Adapter->ResetTimeoutCounter ==
+ (NE3200_TIMEOUT_DOWNLOAD/2) ) {
+
+ //
+ // The command may have stalled, try again.
+ //
+ NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT(
+ Adapter,
+ NE3200_LOCAL_DOORBELL_NEW_COMMAND
+ );
+
+ }
+
+ //
+ // For Synchronous resets, we stall. For async,
+ // we set a timer to check later.
+ //
+ if (!Adapter->ResetAsynchronous) {
+
+ //
+ // Otherwise, wait and try again.
+ //
+ NdisStallExecution(10000);
+
+ } else{
+
+ //
+ // Check again later
+ //
+ NdisMSetTimer(&Adapter->ResetTimer, 100);
+ return;
+
+ }
+
+ }
+
+ }
+
+ break;
+
+ default :
+
+ //
+ // Somehow, we reached an invalid state.
+ //
+
+ //
+ // We'll try to salvage our way out of this.
+ //
+ Adapter->ResetResult = NE3200ResetResultInvalidState;
+ Adapter->ResetState = NE3200ResetStateComplete;
+
+ NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);
+
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_HARDWARE_FAILURE,
+ 3,
+ resetDpc,
+ NE3200_ERRMSG_BAD_STATE,
+ (ULONG)(Adapter->ResetState)
+ );
+
+ break;
+ }
+
+ }
+
+}
+
+STATIC
+VOID
+NE3200DoResetIndications(
+ IN PNE3200_ADAPTER Adapter,
+ IN NDIS_STATUS Status
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called by NE3200ResetHandler 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.
+
+--*/
+{
+ //
+ // Re-start the card if the reset was successful, else stop it.
+ //
+ if (Status == NDIS_STATUS_SUCCESS) {
+
+ NdisMSynchronizeWithInterrupt(
+ &(Adapter->Interrupt),
+ NE3200EnableAdapter,
+ (PVOID)(Adapter)
+ );
+
+ } else {
+
+ //
+ // Reset has failed.
+ //
+
+ NE3200StopChip(Adapter);
+
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_HARDWARE_FAILURE,
+ 0
+ );
+ }
+
+ //
+ // Setup the network address.
+ //
+ NE3200ChangeCurrentAddress(Adapter);
+
+ Adapter->ResetInProgress = FALSE;
+
+ //
+ // Reset default reset method
+ //
+ Adapter->ResetAsynchronous = FALSE;
+
+ if (!Adapter->InitialInit) {
+
+ //
+ // Signal the end of the reset
+ //
+ NdisMResetComplete(
+ Adapter->MiniportAdapterHandle,
+ Status,
+ TRUE
+ );
+
+ }
+
+}
+
+extern
+VOID
+NE3200SetupForReset(
+ IN PNE3200_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to fill in the who and why a reset is
+ being set up as well as setting the appropriate fields in the
+ adapter.
+
+ NOTE: This routine must be called with the lock acquired.
+
+Arguments:
+
+ Adapter - The adapter whose hardware is to be initialized.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Ndis buffer mapped
+ //
+ PNDIS_BUFFER CurrentBuffer;
+
+ //
+ // Map register that was used
+ //
+ UINT CurMapRegister;
+
+ //
+ // Packet to abort
+ //
+ PNDIS_PACKET Packet;
+
+ //
+ // Reserved portion of the packet.
+ //
+ PNE3200_RESERVED Reserved;
+
+ //
+ // Pointer to command block being processed.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK CurrentCommandBlock = Adapter->FirstCommandOnCard;
+
+
+
+ Adapter->ResetInProgress = TRUE;
+
+ //
+ // Shut down the chip. We won't be doing any more work until
+ // the reset is complete.
+ //
+ NE3200StopChip(Adapter);
+
+ //
+ // Un-map all outstanding transmits
+ //
+ while (CurrentCommandBlock != NULL) {
+
+ if (CurrentCommandBlock->Hardware.CommandCode == NE3200_COMMAND_TRANSMIT) {
+
+ //
+ // Remove first packet from the queue
+ //
+ Packet = CurrentCommandBlock->OwningPacket;
+ Reserved = PNE3200_RESERVED_FROM_PACKET(Packet);
+
+ if (Reserved->UsedNE3200Buffer) {
+ goto GetNextCommandBlock;
+ }
+
+ //
+ // The transmit is finished, so we can release
+ // the physical mapping used for it.
+ //
+ NdisQueryPacket(
+ Packet,
+ NULL,
+ NULL,
+ &CurrentBuffer,
+ NULL
+ );
+
+ //
+ // Get starting map register
+ //
+ CurMapRegister = Reserved->CommandBlockIndex *
+ NE3200_MAXIMUM_BLOCKS_PER_PACKET;
+
+ //
+ // For each buffer
+ //
+ while (CurrentBuffer) {
+
+ //
+ // Finish the mapping
+ //
+ NdisMCompleteBufferPhysicalMapping(
+ Adapter->MiniportAdapterHandle,
+ CurrentBuffer,
+ CurMapRegister
+ );
+
+ ++CurMapRegister;
+
+ NdisGetNextBuffer(
+ CurrentBuffer,
+ &CurrentBuffer
+ );
+
+ }
+
+ }
+
+GetNextCommandBlock:
+
+ CurrentCommandBlock = CurrentCommandBlock->NextCommand;
+
+ //
+ // Now do the pending queue
+ //
+ if (CurrentCommandBlock == NULL) {
+
+ if (Adapter->FirstWaitingCommand != NULL) {
+
+ CurrentCommandBlock = Adapter->FirstWaitingCommand;
+ Adapter->FirstWaitingCommand = NULL;
+
+ }
+
+ }
+
+ }
+
+}
+
+
+#pragma NDIS_INIT_FUNCTION(NE3200GetStationAddress)
+
+VOID
+NE3200GetStationAddress(
+ IN PNE3200_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets the network address from the hardware.
+
+ NOTE: This routine assumes that it is called *immediately*
+ after MAC.BIN has been downloaded. It should only be called
+ immediately after SetConfigurationBlockAndInit() has completed.
+
+Arguments:
+
+ Adapter - Where to store the network address.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Read the station address from the ports
+ //
+ NE3200_READ_MAILBOX_UCHAR(
+ Adapter,
+ NE3200_MAILBOX_STATION_ID,
+ &Adapter->NetworkAddress[0]
+ );
+
+ NE3200_READ_MAILBOX_UCHAR(
+ Adapter,
+ NE3200_MAILBOX_STATION_ID + 1,
+ &Adapter->NetworkAddress[1]
+ );
+ NE3200_READ_MAILBOX_UCHAR(
+ Adapter,
+ NE3200_MAILBOX_STATION_ID + 2,
+ &Adapter->NetworkAddress[2]
+ );
+ NE3200_READ_MAILBOX_UCHAR(
+ Adapter,
+ NE3200_MAILBOX_STATION_ID + 3,
+ &Adapter->NetworkAddress[3]
+ );
+ NE3200_READ_MAILBOX_UCHAR(
+ Adapter,
+ NE3200_MAILBOX_STATION_ID + 4,
+ &Adapter->NetworkAddress[4]
+ );
+ NE3200_READ_MAILBOX_UCHAR(
+ Adapter,
+ NE3200_MAILBOX_STATION_ID +5,
+ &Adapter->NetworkAddress[5]
+ );
+
+ if (!Adapter->AddressChanged) {
+
+ //
+ // Copy the real address to be used as the current address.
+ //
+ NdisMoveMemory(
+ Adapter->CurrentAddress,
+ Adapter->NetworkAddress,
+ NE3200_LENGTH_OF_ADDRESS
+ );
+
+ }
+
+}
+
+
+VOID
+NE3200ResetVariables(
+ IN PNE3200_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets variables to their proper value after a reset.
+
+Arguments:
+
+ Adapter - Adapter we are resetting.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Clear the command queues
+ //
+ Adapter->FirstCommandOnCard = NULL;
+ Adapter->FirstWaitingCommand = NULL;
+
+ //
+ // Reset the receive buffer ring
+ //
+ Adapter->ReceiveQueueHead = Adapter->ReceiveQueue;
+ Adapter->ReceiveQueueTail =
+ Adapter->ReceiveQueue + Adapter->NumberOfReceiveBuffers - 1;
+
+ //
+ // Reset count of available command blocks
+ //
+ Adapter->NumberOfAvailableCommandBlocks = Adapter->NumberOfCommandBlocks;
+ Adapter->NumberOfPublicCommandBlocks = NE3200_NUMBER_OF_PUBLIC_CMD_BLOCKS;
+ Adapter->NextPublicCommandBlock = 0;
+ Adapter->NextCommandBlock = Adapter->CommandQueue;
+
+ //
+ // Reset transmitting and receiving states
+ //
+ Adapter->PacketResubmission = FALSE;
+ Adapter->TransmitsQueued = 0;
+ Adapter->CurrentReceiveIndex = 0;
+
+}
+
+VOID
+NE3200ResetCommandBlocks(
+ IN PNE3200_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets command block elementsto their proper value after a reset.
+
+Arguments:
+
+ Adapter - Adapter we are resetting.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Pointer to a Receive Entry. Used while initializing
+ // the Receive Queue.
+ //
+ PNE3200_SUPER_RECEIVE_ENTRY CurrentReceiveEntry;
+
+ //
+ // Pointer to a Command Block. Used while initializing
+ // the Command Queue.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK CurrentCommandBlock;
+
+ //
+ // Simple iteration variable.
+ //
+ UINT i;
+
+ //
+ // Put the Command Blocks into a known state.
+ //
+ for(
+ i = 0, CurrentCommandBlock = Adapter->CommandQueue;
+ i < Adapter->NumberOfCommandBlocks;
+ i++, CurrentCommandBlock++
+ ) {
+
+ CurrentCommandBlock->Hardware.State = NE3200_STATE_FREE;
+ CurrentCommandBlock->Hardware.NextPending = NE3200_NULL;
+
+ CurrentCommandBlock->NextCommand = NULL;
+ CurrentCommandBlock->AvailableCommandBlockCounter =
+ &Adapter->NumberOfAvailableCommandBlocks;
+ CurrentCommandBlock->Timeout = FALSE;
+ }
+
+ //
+ // Now do the same for the public command queue.
+ //
+ for(
+ i = 0, CurrentCommandBlock = Adapter->PublicCommandQueue;
+ i < NE3200_NUMBER_OF_PUBLIC_CMD_BLOCKS;
+ i++, CurrentCommandBlock++
+ ) {
+
+ CurrentCommandBlock->Hardware.State = NE3200_STATE_FREE;
+ CurrentCommandBlock->Hardware.NextPending = NE3200_NULL;
+ CurrentCommandBlock->NextCommand = NULL;
+ CurrentCommandBlock->AvailableCommandBlockCounter =
+ &Adapter->NumberOfPublicCommandBlocks;
+ CurrentCommandBlock->CommandBlockIndex = (USHORT)i;
+ CurrentCommandBlock->Timeout = FALSE;
+ }
+
+ //
+ // Reset the receive buffers.
+ //
+ for(
+ i = 0, CurrentReceiveEntry = Adapter->ReceiveQueue;
+ i < Adapter->NumberOfReceiveBuffers;
+ i++, CurrentReceiveEntry++
+ ) {
+
+
+ //
+ // Initialize receive buffers
+ //
+ CurrentReceiveEntry->Hardware.State = NE3200_STATE_FREE;
+ CurrentReceiveEntry->Hardware.NextPending =
+ NdisGetPhysicalAddressLow(Adapter->ReceiveQueuePhysical) +
+ (i + 1) * sizeof(NE3200_SUPER_RECEIVE_ENTRY);
+ CurrentReceiveEntry->NextEntry = CurrentReceiveEntry + 1;
+
+ }
+
+ //
+ // Make sure the last entry is properly terminated.
+ //
+ (CurrentReceiveEntry - 1)->Hardware.NextPending = NE3200_NULL;
+ (CurrentReceiveEntry - 1)->NextEntry = Adapter->ReceiveQueue;
+
+}
+
+
+NDIS_STATUS
+NE3200ChangeCurrentAddress(
+ IN PNE3200_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to modify the card address.
+
+Arguments:
+
+ Adapter - The adapter for the NE3200 to change address.
+
+Return Value:
+
+ NDIS_STATUS_SUCCESS, if everything went ok
+ NDIS_STATUS_FAILURE, otherwise
+
+--*/
+{
+
+ //
+ // Modify the card address if needed
+ //
+
+ if (Adapter->AddressChanged) {
+
+ //
+ // The command block for submitting the change
+ //
+ PNE3200_SUPER_COMMAND_BLOCK CommandBlock;
+
+ //
+ // Temporary looping variable
+ //
+ UINT i;
+
+ //
+ // Get a public command block for the request
+ //
+ NE3200AcquirePublicCommandBlock(Adapter,
+ &CommandBlock
+ );
+
+ //
+ // Setup the command block.
+ //
+ CommandBlock->NextCommand = NULL;
+
+ CommandBlock->Hardware.State = NE3200_STATE_WAIT_FOR_ADAPTER;
+ CommandBlock->Hardware.Status = 0;
+ CommandBlock->Hardware.NextPending = NE3200_NULL;
+ CommandBlock->Hardware.CommandCode = NE3200_COMMAND_SET_STATION_ADDRESS;
+
+ //
+ // Copy in the address
+ //
+ NdisMoveMemory(
+ CommandBlock->Hardware.PARAMETERS.SET_ADDRESS.NewStationAddress,
+ Adapter->CurrentAddress,
+ NE3200_LENGTH_OF_ADDRESS
+ );
+
+ //
+ // Now that we've got the command block built,
+ // let's do it!
+ //
+ NE3200SubmitCommandBlock(Adapter, CommandBlock);
+
+ //
+ // Wait for the command block to finish
+ //
+ for (i = 0; i < 100000; i++) {
+ NdisStallExecution(100);
+ if (CommandBlock->Hardware.State == NE3200_STATE_EXECUTION_COMPLETE) {
+ break;
+ }
+ }
+
+ //
+ // Check the status of the command.
+ //
+ if (CommandBlock->Hardware.State != NE3200_STATE_EXECUTION_COMPLETE) {
+
+ //
+ // Failed
+ //
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_HARDWARE_FAILURE,
+ 0
+ );
+
+ return NDIS_STATUS_FAILURE;
+
+ }
+
+ //
+ // return this command block
+ //
+ NE3200RelinquishCommandBlock(Adapter, CommandBlock);
+
+ }
+ return NDIS_STATUS_SUCCESS;
+}
+
+BOOLEAN
+SyncNE3200ClearDoorbellInterrupt(
+ IN PVOID SyncContext
+ )
+/*++
+
+Routine Description:
+
+ Clears the Doorbell Interrupt Port.
+
+Arguments:
+
+ SyncContext - pointer to the adapter block
+
+Return Value:
+
+ Always TRUE
+
+--*/
+
+{
+
+ PNE3200_ADAPTER Adapter = (PNE3200_ADAPTER)SyncContext;
+
+ //
+ // Clear the value
+ //
+ NdisRawWritePortUchar(
+ (ULONG)(Adapter->SystemDoorbellInterruptPort),
+ (UCHAR)0
+ );
+
+ return(FALSE);
+}
+
diff --git a/private/ntos/ndis/ne3200/send.c b/private/ntos/ndis/ne3200/send.c
new file mode 100644
index 000000000..e2eee44bb
--- /dev/null
+++ b/private/ntos/ndis/ne3200/send.c
@@ -0,0 +1,816 @@
+/*++
+
+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.
+
+ This is a process of
+
+ 1) Calculating the what would need to be done to the
+ packet so that the packet can be transmitted on the hardware.
+
+ 2) Potentially allocating adapter buffers and copying user data
+ to those buffers so that the packet data is transmitted under
+ the hardware constraints.
+
+ 3) Allocating enough hardware ring entries so that the packet
+ can be transmitted.
+
+ 4) Relinquish those ring entries to the hardware.
+
+Author:
+
+ Anthony V. Ercolano (Tonye) 12-Sept-1990
+ Keith Moore (KeithMo) 08-Jan-1991
+
+Environment:
+
+ Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
+
+Revision History:
+
+
+--*/
+
+#include <ne3200sw.h>
+
+//
+// Forward declarations of functions in this file.
+//
+VOID
+NE3200ConstrainPacket(
+ IN PNE3200_ADAPTER Adapter,
+ IN PNDIS_PACKET Packet
+ );
+
+NDIS_STATUS
+NE3200TransmitPacket(
+ IN PNE3200_ADAPTER Adapter,
+ PNDIS_PACKET FirstPacket,
+ UINT TotalDataLength,
+ UINT NdisBufferCount,
+ PNDIS_BUFFER CurrentBuffer
+ );
+
+NDIS_STATUS
+NE3200TransmitMergedPacket(
+ IN PNE3200_ADAPTER Adapter,
+ PNDIS_PACKET FirstPacket
+ );
+
+
+NDIS_STATUS
+NE3200Send(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN PNDIS_PACKET Packet,
+ IN UINT Flags
+ )
+
+/*++
+
+Routine Description:
+
+ The NE3200Send 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 NE3200_ADAPTER.
+
+ Packet - A pointer to a descriptor for the packet that is to be
+ transmitted.
+
+ Flags - The send options to use.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+ //
+ // Pointer to the adapter.
+ //
+ PNE3200_ADAPTER Adapter;
+
+ //
+ // The number of physical buffers in the entire packet.
+ //
+ UINT PhysicalBufferCount;
+
+ //
+ // 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;
+
+ //
+ // Points to the miniport reserved portion of this packet. This
+ // interpretation of the reserved section is only valid during
+ // the allocation phase of the packet.
+ //
+ PNE3200_RESERVED Reserved = PNE3200_RESERVED_FROM_PACKET(Packet);
+
+ //
+ // Status of the transmit.
+ //
+ NDIS_STATUS Status;
+
+ //
+ // The adapter upon which to transmit the packet.
+ //
+ Adapter = PNE3200_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
+
+ IF_LOG('s');
+
+ //
+ // Check if this is a packet we rejected earlier due to a lack
+ // of resources. If so, we don't have to recalculate all the
+ // constraints.
+ //
+ if (!Adapter->PacketResubmission) {
+
+ ASSERT(sizeof(NE3200_RESERVED) <= sizeof(Packet->MiniportReserved));
+
+ //
+ // Determine if and how much adapter space would need to be allocated
+ // to meet hardware constraints.
+ //
+ NdisQueryPacket(
+ Packet,
+ &PhysicalBufferCount,
+ &NdisBufferCount,
+ &CurrentBuffer,
+ &TotalDataLength
+ );
+
+
+ //
+ // See if the packet exceeds NE3200_MAXIMUM_BLOCKS_PER_PACKET.
+ // Keep in mind that if the total virtual packet length is less than
+ // MINIMUM_ETHERNET_PACKET_SIZE then we'll have to chain on an
+ // additional buffer to pad the packet out to the minimum size.
+ //
+ if ( PhysicalBufferCount < NE3200_MAXIMUM_BLOCKS_PER_PACKET ) {
+
+ //
+ // This packet will not need a merge buffer
+ //
+ Reserved->UsedNE3200Buffer = FALSE;
+
+ //
+ // See if we can send it now.
+ //
+ Status = NE3200TransmitPacket(
+ Adapter,
+ Packet,
+ TotalDataLength,
+ NdisBufferCount,
+ CurrentBuffer
+ );
+
+ Adapter->PacketResubmission =
+ (BOOLEAN)(Status == NDIS_STATUS_RESOURCES);
+
+ IF_LOG('S');
+
+ return(Status);
+
+ } else {
+
+ //
+ // We will have to use a merge buffer. Let the processing
+ // below handle this.
+ //
+ if ( (PhysicalBufferCount > NE3200_MAXIMUM_BLOCKS_PER_PACKET) ||
+ (TotalDataLength < MINIMUM_ETHERNET_PACKET_SIZE) ) {
+
+ Reserved->UsedNE3200Buffer = TRUE;
+
+ } else {
+
+ Reserved->UsedNE3200Buffer = FALSE;
+
+ }
+
+ }
+
+ }
+
+ //
+ // Check if we have to merge this packet.
+ //
+ if ( Reserved->UsedNE3200Buffer ) {
+
+ //
+ // Try and send it now.
+ //
+ Status = NE3200TransmitMergedPacket(Adapter, Packet);
+
+ } else {
+
+ //
+ // Determine if and how much adapter space would need to be allocated
+ // to meet hardware constraints.
+ //
+
+ NdisQueryPacket(
+ Packet,
+ NULL,
+ &NdisBufferCount,
+ &CurrentBuffer,
+ &TotalDataLength
+ );
+
+
+ Status = NE3200TransmitPacket(
+ Adapter,
+ Packet,
+ TotalDataLength,
+ NdisBufferCount,
+ CurrentBuffer);
+
+ }
+
+ //
+ // Save if this packet was rejected due to lack of resources.
+ //
+ Adapter->PacketResubmission = (BOOLEAN)(Status == NDIS_STATUS_RESOURCES);
+
+ IF_LOG('S');
+
+ return(Status);
+}
+
+
+//
+// Put this code inline to save the overhead of the function call.
+//
+#ifdef _X86_
+__inline
+#endif
+
+NDIS_STATUS
+NE3200TransmitPacket(
+ IN PNE3200_ADAPTER Adapter,
+ PNDIS_PACKET FirstPacket,
+ UINT TotalDataLength,
+ UINT NdisBufferCount,
+ PNDIS_BUFFER CurrentBuffer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine attempts to take a packet through a stage of allocation
+ and transmit it.
+
+Arguments:
+
+ Adapter - The adapter that the packets are coming through.
+
+Return Value:
+
+ NDIS_STATUS_RESOURCES - if there are not enough resources
+ NDIS_STATUS_PENDING - if sending.
+
+--*/
+
+{
+ //
+ // If we successfully acquire a command block, this
+ // is a pointer to it.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK CommandBlock;
+
+ //
+ // Pointer to the NE3200 data block descriptor being filled.
+ //
+ PNE3200_DATA_BLOCK DataBlock;
+
+ //
+ // Array to hold the physical segments
+ //
+ NDIS_PHYSICAL_ADDRESS_UNIT PhysicalSegmentArray[NE3200_MAXIMUM_BLOCKS_PER_PACKET];
+
+ //
+ // Number of physical segments in the buffer
+ //
+ UINT BufferPhysicalSegments;
+
+ //
+ // map register to use for this buffer
+ //
+ UINT CurMapRegister;
+
+ //
+ // Iteration variable
+ //
+ UINT i;
+
+ //
+ // We look to see if there is an available Command Block.
+ // If there isn't then stage 3 will close.
+ //
+
+ NE3200AcquireCommandBlock(
+ Adapter,
+ &CommandBlock
+ );
+
+ if (CommandBlock != NULL) {
+
+ //
+ // We have a command block. Assign all packet
+ // buffers to the command block.
+ //
+
+ //
+ // Get a pointer to the the first data block descriptor
+ // in the Command Block.
+ //
+ DataBlock = &CommandBlock->Hardware.TransmitDataBlocks[0];
+
+ //
+ // We record the owning packet information in the ring packet packet
+ // structure.
+ //
+ CommandBlock->OwningPacket = FirstPacket;
+ CommandBlock->UsedNE3200Buffer = FALSE;
+ CommandBlock->NextCommand = NULL;
+
+ //
+ // Initialize the various fields of the Command Block.
+ //
+ CommandBlock->Hardware.State = NE3200_STATE_WAIT_FOR_ADAPTER;
+ CommandBlock->Hardware.Status = 0;
+ CommandBlock->Hardware.NextPending = NE3200_NULL;
+ CommandBlock->Hardware.CommandCode = NE3200_COMMAND_TRANSMIT;
+ CommandBlock->Hardware.PARAMETERS.TRANSMIT.ImmediateDataLength = 0;
+
+ CommandBlock->Hardware.NumberOfDataBlocks = 0;
+ CommandBlock->Hardware.TransmitFrameSize = (USHORT)TotalDataLength;
+
+ //
+ // Set the map registers to use
+ //
+ CurMapRegister = CommandBlock->CommandBlockIndex *
+ NE3200_MAXIMUM_BLOCKS_PER_PACKET;
+
+ //
+ // Go through all of the buffers in the packet getting
+ // the actual physical buffers from each NDIS_BUFFER.
+ //
+ do {
+
+ NdisMStartBufferPhysicalMapping(
+ Adapter->MiniportAdapterHandle,
+ CurrentBuffer,
+ CurMapRegister,
+ TRUE,
+ PhysicalSegmentArray,
+ &BufferPhysicalSegments
+ );
+
+ //
+ // Go to the next map register
+ //
+ CurMapRegister++;
+
+ //
+ // Store segments into command block
+ //
+ for (i = 0; i < BufferPhysicalSegments ; i++, DataBlock++ ) {
+
+ DataBlock->BlockLength = (USHORT)PhysicalSegmentArray[i].Length;
+ DataBlock->PhysicalAddress = NdisGetPhysicalAddressLow(PhysicalSegmentArray[i].PhysicalAddress);
+
+ }
+
+ //
+ // Update the number of fragments.
+ //
+ CommandBlock->Hardware.NumberOfDataBlocks += BufferPhysicalSegments;
+
+ NdisFlushBuffer(CurrentBuffer, TRUE);
+
+ //
+ // Go to the next buffer.
+ //
+ NdisGetNextBuffer(
+ CurrentBuffer,
+ &CurrentBuffer
+ );
+
+ } while (CurrentBuffer != NULL);
+
+ //
+ // If the total packet length is less than MINIMUM_ETHERNET_PACKET_SIZE
+ // then we must chain the Padding buffer onto the end and update
+ // the transfer size.
+ //
+ if (TotalDataLength >= MINIMUM_ETHERNET_PACKET_SIZE) {
+
+ PNE3200_RESERVED_FROM_PACKET(FirstPacket)->CommandBlockIndex =
+ CommandBlock->CommandBlockIndex;
+
+ IF_LOG('x');
+
+ NE3200SubmitCommandBlock(
+ Adapter,
+ CommandBlock
+ );
+
+ return(NDIS_STATUS_PENDING);
+ }
+
+ //
+ // Must do padding
+ //
+ DataBlock->BlockLength =
+ (USHORT)(MINIMUM_ETHERNET_PACKET_SIZE - TotalDataLength);
+
+ DataBlock->PhysicalAddress = NdisGetPhysicalAddressLow(Adapter->PaddingPhysicalAddress);
+
+ DataBlock++;
+ CommandBlock->Hardware.NumberOfDataBlocks++;
+
+ CommandBlock->Hardware.TransmitFrameSize = MINIMUM_ETHERNET_PACKET_SIZE;
+
+ PNE3200_RESERVED_FROM_PACKET(FirstPacket)->CommandBlockIndex =
+ CommandBlock->CommandBlockIndex;
+
+ IF_LOG('x');
+
+ NE3200SubmitCommandBlock(
+ Adapter,
+ CommandBlock
+ );
+
+ return(NDIS_STATUS_PENDING);
+
+ } else {
+
+ //
+ // Not enough resources
+ //
+ return(NDIS_STATUS_RESOURCES);
+
+ }
+
+}
+
+
+NDIS_STATUS
+NE3200TransmitMergedPacket(
+ IN PNE3200_ADAPTER Adapter,
+ PNDIS_PACKET FirstPacket
+ )
+
+/*++
+
+Routine Description:
+
+ This routine attempts to take a packet through a stage of allocation
+ and tranmit it. The packet needs to be merged into a single
+ before transmitting because it contains more fragments than the
+ adapter can handle.
+
+Arguments:
+
+ Adapter - The adapter that the packets are coming through.
+
+Return Value:
+
+ NDIS_STATUS_RESOURCES - if there are not enough resources
+ NDIS_STATUS_PENDING - if sending.
+
+--*/
+
+{
+ //
+ // If we successfully acquire a command block, this
+ // is a pointer to it.
+ //
+ PNE3200_SUPER_COMMAND_BLOCK CommandBlock;
+
+ //
+ // Points to the reserved portion of the packet.
+ //
+ PNE3200_RESERVED Reserved;
+
+ //
+ // Pointer to the NE3200 data block descriptor being filled.
+ //
+ PNE3200_DATA_BLOCK DataBlock;
+
+ //
+ // Points to the adapter buffer descriptor allocated
+ // for this packet.
+ //
+ PNE3200_BUFFER_DESCRIPTOR BufferDescriptor;
+
+ //
+ // Check that we have a merge buffer if one will be necessary.
+ //
+ if ( Adapter->NE3200BufferListHead == -1 ) {
+
+ //
+ // Not enough space for the packet -- save state
+ //
+ return NDIS_STATUS_RESOURCES;
+
+ }
+
+ //
+ // We look to see if there is an available Command Block.
+ // If there isn't then stage 3 will close.
+ //
+ NE3200AcquireCommandBlock(
+ Adapter,
+ &CommandBlock
+ );
+
+ if (CommandBlock != NULL) {
+
+ //
+ // We have a command block. Assign all packet
+ // buffers to the command block.
+ //
+ Reserved = PNE3200_RESERVED_FROM_PACKET(FirstPacket);
+
+ //
+ // Get a pointer to the the first data block descriptor
+ // in the Command Block.
+ //
+ DataBlock = &CommandBlock->Hardware.TransmitDataBlocks[0];
+
+ //
+ // Now we merge the packet into a buffer
+ //
+ NE3200ConstrainPacket(Adapter, FirstPacket);
+
+ //
+ // We record the owning packet information in the ring packet packet
+ // structure.
+ //
+ CommandBlock->OwningPacket = FirstPacket;
+ CommandBlock->UsedNE3200Buffer = TRUE;
+ CommandBlock->NE3200BuffersIndex = Reserved->NE3200BuffersIndex;
+ CommandBlock->NextCommand = NULL;
+
+ //
+ // Initialize the various fields of the Command Block.
+ //
+ CommandBlock->Hardware.State = NE3200_STATE_WAIT_FOR_ADAPTER;
+ CommandBlock->Hardware.Status = 0;
+ CommandBlock->Hardware.NextPending = NE3200_NULL;
+ CommandBlock->Hardware.CommandCode = NE3200_COMMAND_TRANSMIT;
+ CommandBlock->Hardware.PARAMETERS.TRANSMIT.ImmediateDataLength = 0;
+
+ //
+ // Get the buffer descriptor
+ //
+ BufferDescriptor = Adapter->NE3200Buffers + Reserved->NE3200BuffersIndex;
+
+ //
+ // Since this packet used one of the adapter buffers, the
+ // following is known:
+ //
+ // o There is exactly one physical buffer for this packet.
+ // o The buffer's length is the transmit frame size.
+ //
+
+ //
+ // Set the number of data blocks and the transmit frame size.
+ //
+ NdisFlushBuffer(BufferDescriptor->FlushBuffer, TRUE);
+ CommandBlock->Hardware.NumberOfDataBlocks = 1;
+ CommandBlock->Hardware.TransmitFrameSize =
+ (USHORT)BufferDescriptor->DataLength;
+
+ //
+ // Initialize the (one) data block for this transmit.
+ //
+ DataBlock->BlockLength = (USHORT)BufferDescriptor->DataLength;
+ DataBlock->PhysicalAddress = NdisGetPhysicalAddressLow(BufferDescriptor->PhysicalNE3200Buffer);
+
+ Adapter->TransmitsQueued++;
+
+ Reserved->CommandBlockIndex = CommandBlock->CommandBlockIndex;
+
+ IF_LOG('x');
+
+ //
+ // Start the transmit.
+ //
+ NE3200SubmitCommandBlock(
+ Adapter,
+ CommandBlock
+ );
+
+ return(NDIS_STATUS_PENDING);
+ }
+
+ return(NDIS_STATUS_RESOURCES);
+
+}
+
+STATIC
+VOID
+NE3200ConstrainPacket(
+ IN PNE3200_ADAPTER Adapter,
+ IN PNDIS_PACKET Packet
+ )
+
+/*++
+
+Routine Description:
+
+ Given a packet and if necessary attempt to acquire adapter
+ buffer resources so that the packet meets NE3200 hardware/MAC.BIN
+ contraints.
+
+ NOTE : MUST BE CALLED WITH NE3200BufferListHead != -1!!
+
+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.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Holds the adapter buffer index available for allocation.
+ //
+ INT NE3200BuffersIndex;
+
+ //
+ // Points to a successfully allocated adapter buffer descriptor.
+ //
+ PNE3200_BUFFER_DESCRIPTOR BufferDescriptor;
+
+ //
+ // 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;
+
+ //
+ // The number of ndis buffers in the packet.
+ //
+ UINT NdisBufferCount;
+
+ //
+ // 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;
+
+ NE3200BuffersIndex = Adapter->NE3200BufferListHead;
+
+ BufferDescriptor = Adapter->NE3200Buffers + NE3200BuffersIndex;
+ Adapter->NE3200BufferListHead = BufferDescriptor->Next;
+
+ //
+ // Fill in the adapter buffer with the data from the users
+ // buffers.
+ //
+ CurrentDestination = BufferDescriptor->VirtualNE3200Buffer;
+
+ NdisQueryPacket(
+ Packet,
+ NULL,
+ &NdisBufferCount,
+ &SourceBuffer,
+ &TotalVirtualLength
+ );
+
+ NdisQueryBuffer(
+ SourceBuffer,
+ &SourceData,
+ &SourceLength
+ );
+
+ BufferDescriptor->DataLength = TotalVirtualLength;
+
+ for (
+ i = NdisBufferCount;
+ i;
+ i--
+ ) {
+
+ //
+ // Copy this buffer
+ //
+ NE3200_MOVE_MEMORY(
+ CurrentDestination,
+ SourceData,
+ SourceLength
+ );
+
+ //
+ // Update destination address
+ //
+ CurrentDestination = (PCHAR)CurrentDestination + SourceLength;
+
+ //
+ // Update count of packet length.
+ //
+ TotalDataMoved += SourceLength;
+
+ if (i > 1) {
+
+ //
+ // Get the next buffers information
+ //
+ NdisGetNextBuffer(
+ SourceBuffer,
+ &SourceBuffer
+ );
+
+ NdisQueryBuffer(
+ SourceBuffer,
+ &SourceData,
+ &SourceLength
+ );
+
+ }
+
+ }
+
+ //
+ // If the packet is less than the minimum Ethernet
+ // packet size, then clear the remaining part of
+ // the buffer up to the minimum packet size.
+ //
+ if (TotalVirtualLength < MINIMUM_ETHERNET_PACKET_SIZE) {
+
+ NdisZeroMemory(
+ CurrentDestination,
+ MINIMUM_ETHERNET_PACKET_SIZE - TotalVirtualLength
+ );
+
+ }
+
+ //
+ // We need to save in the packet which adapter buffer descriptor
+ // it is using so that we can deallocate it later.
+ //
+ PNE3200_RESERVED_FROM_PACKET(Packet)->NE3200BuffersIndex = NE3200BuffersIndex;
+}
+
diff --git a/private/ntos/ndis/ne3200/sources b/private/ntos/ndis/ne3200/sources
new file mode 100644
index 000000000..a10b25497
--- /dev/null
+++ b/private/ntos/ndis/ne3200/sources
@@ -0,0 +1,51 @@
+!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=ne3200
+TARGETPATH=\nt\public\sdk\lib
+TARGETTYPE=DRIVER
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\ndis.lib
+C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER
+
+NTPROFILEINPUT=yes
+
+INCLUDES=..\..\inc;..\..\..\inc
+
+SOURCES=command.c \
+ interrup.c \
+ ne3200.c \
+ request.c \
+ reset.c \
+ send.c \
+ ne3200.rc
+
+RELATIVE_DEPTH=..\..
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+NTTARGETFILES=ne3200.bin