summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/netflex/support.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ndis/netflex/support.c')
-rw-r--r--private/ntos/ndis/netflex/support.c1986
1 files changed, 1986 insertions, 0 deletions
diff --git a/private/ntos/ndis/netflex/support.c b/private/ntos/ndis/netflex/support.c
new file mode 100644
index 000000000..73a0dc74b
--- /dev/null
+++ b/private/ntos/ndis/netflex/support.c
@@ -0,0 +1,1986 @@
+//**********************************************************************
+//**********************************************************************
+//
+// File Name: SUPPORT.C
+//
+// Program Name: NetFlex NDIS 3.0 Miniport Driver
+//
+// Companion Files: None
+//
+// Function: This module contains the NetFlex Miniport Driver
+// interface routines called by the Wrapper and the
+// configuration manager.
+//
+// (c) Compaq Computer Corporation, 1992,1993,1994
+//
+// This file is licensed by Compaq Computer Corporation to Microsoft
+// Corporation pursuant to the letter of August 20, 1992 from
+// Gary Stimac to Mark Baber.
+//
+// History:
+//
+// 04/15/94 Robert Van Cleve - Converted from NDIS Mac Driver
+//
+//**********************************************************************
+//**********************************************************************
+
+
+//-------------------------------------
+// Include all general companion files
+//-------------------------------------
+
+#if (DBG || DBGPRINT)
+#include <stdarg.h>
+#include <stdio.h>
+
+#endif
+
+#include <ndis.h>
+#include "tmsstrct.h"
+#include "macstrct.h"
+#include "adapter.h"
+#include "protos.h"
+
+
+#if (DBG || DBGPRINT)
+ULONG DebugLevel=1;
+#endif
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexInitializeAcb
+//
+// Description: This routine initializes the given ACB. This
+// routine allocates memory for certain fields
+// pointed to by the ACB.
+//
+// Input: acb - Pointer to acb to fill in.
+// parms - Settable mac driver parms.
+//
+// Output: Returns NDIS_STATUS_SUCCESS for a successful
+// completion. Otherwise, an error code is
+// returned.
+//
+// Calls: NdisAllocateMemory,NdisZeroMemory,NdisMoveMemory
+// NdisMAllocateSharedMemory,SWAPL,CTRL_ADDR
+//
+// Called By: NetFlexInitialize
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexInitializeAcb(PACB acb)
+{
+ USHORT i;
+
+ PRCV CurrentReceiveEntry;
+ PXMIT CurrentXmitEntry;
+ PVOID start, next, current;
+ ULONG next_phys, current_phys, temp;
+ PETH_OBJS ethobjs;
+ NDIS_STATUS Status;
+ PBUFFER_DESCRIPTOR OurBuf;
+ ULONG LowPart;
+ PUCHAR CurrentReceiveBuffer;
+ PUCHAR CurrentMergeBuffer;
+ PNETFLEX_PARMS parms = acb->acb_parms;
+ ULONG Alignment, FrameSizeCacheAligned;
+
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb entered.\n",acb->anum));
+
+ //
+ // Initialize pointers and counters
+ //
+ acb->InterruptsDisabled = FALSE; // interrupts are enabled after a reset.
+ acb->ResetState = 0;
+
+ //
+ // Set up rest of general oid variables.
+ //
+ acb->acb_smallbufsz = parms->utd_smallbufsz;
+ acb->acb_maxmaps = parms->utd_maxtrans * MAX_BUFS_PER_XMIT;
+ acb->acb_gen_objs.max_frame_size = parms->utd_maxframesz;
+ acb->acb_lastringstate = NdisRingStateClosed;
+ acb->acb_curmap = 0;
+
+ //
+ // Get the max frame size, cache align it and a save it for later.
+ //
+
+ Alignment = NdisGetCacheFillSize();
+
+ if ( Alignment < sizeof(ULONG) ) {
+
+ Alignment = sizeof(ULONG);
+ }
+
+ FrameSizeCacheAligned = (parms->utd_maxframesz + Alignment - 1) & ~(Alignment - 1);
+
+ //
+ // Allocate the map registers
+ //
+
+ if (NdisMAllocateMapRegisters(
+ acb->acb_handle,
+ 0,
+ TRUE,
+ acb->acb_maxmaps,
+ acb->acb_gen_objs.max_frame_size
+ ) != NDIS_STATUS_SUCCESS)
+ {
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Get the OID structures set up. The list of oids is determined
+ // by the network type of the adapter. Also set up any network type
+ // specific information.
+ //
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_3)
+ {
+ // ETHERNET
+
+ //
+ // Load up the oid pointers and lengths
+ //
+ acb->acb_gbl_oid_list = (PNDIS_OID)NetFlexGlobalOIDs_Eth;
+ acb->acb_gbl_oid_list_size = NetFlexGlobalOIDs_Eth_size;
+ acb->acb_spec_oid_list = (PNDIS_OID)NetFlexNetworkOIDs_Eth;
+ acb->acb_spec_oid_list_size = NetFlexNetworkOIDs_Eth_size;
+
+ //
+ // Allocate and Zero out the Memory for Ethernet specific objects
+ //
+ NdisAllocateMemory( (PVOID *)&(acb->acb_spec_objs),
+ (UINT) (sizeof (ETH_OBJS)),
+ (UINT) 0,
+ NetFlexHighestAddress);
+
+ if (acb->acb_spec_objs == NULL)
+ {
+ return(NDIS_STATUS_RESOURCES);
+ }
+ NdisZeroMemory( acb->acb_spec_objs, sizeof (ETH_OBJS) );
+
+ //
+ // Allocate and Zero out Memory for the Multicast table.
+ //
+ ethobjs = (PETH_OBJS)(acb->acb_spec_objs);
+ ethobjs->MaxMulticast = parms->utd_maxmulticast;
+
+ NdisAllocateMemory( (PVOID *)&ethobjs->MulticastEntries,
+ (UINT) (ethobjs->MaxMulticast * NET_ADDR_SIZE),
+ (UINT) 0,
+ NetFlexHighestAddress);
+ if (ethobjs->MulticastEntries == NULL)
+ {
+ return(NDIS_STATUS_RESOURCES);
+ }
+ NdisZeroMemory(ethobjs->MulticastEntries, ethobjs->MaxMulticast * NET_ADDR_SIZE);
+ ethobjs->NumberOfEntries = 0;
+
+ //
+ // Allocate Memory for sending multicast requests to the adapter.
+ //
+ NdisMAllocateSharedMemory( acb->acb_handle,
+ (ULONG)(sizeof(MULTI_BLOCK) * 2),
+ FALSE,
+ (PVOID *)(&(acb->acb_multiblk_virtptr)),
+ &acb->acb_multiblk_physptr);
+
+ if (acb->acb_multiblk_virtptr == NULL)
+ {
+ return(NDIS_STATUS_RESOURCES);
+ }
+ }
+ else
+ {
+ // TOKEN RING
+
+ //
+ // Load up the oid pointers and lengths
+ //
+ acb->acb_gbl_oid_list = (PNDIS_OID)NetFlexGlobalOIDs_Tr;
+ acb->acb_gbl_oid_list_size = NetFlexGlobalOIDs_Tr_size;
+ acb->acb_spec_oid_list = (PNDIS_OID)NetFlexNetworkOIDs_Tr;
+ acb->acb_spec_oid_list_size = NetFlexNetworkOIDs_Tr_size;
+
+ //
+ // Allocate and Zero out Memory for Token Ring specific objects
+ //
+ NdisAllocateMemory( (PVOID *)&(acb->acb_spec_objs),
+ (UINT) (sizeof (TR_OBJS)),
+ (UINT) 0,
+ NetFlexHighestAddress);
+
+ if (acb->acb_spec_objs == NULL)
+ {
+ return(NDIS_STATUS_RESOURCES);
+ }
+ NdisZeroMemory( acb->acb_spec_objs, sizeof (TR_OBJS) );
+ }
+
+ //
+ // Allocate the SCB for this adapter.
+ //
+ NdisMAllocateSharedMemory( acb->acb_handle,
+ (ULONG)SIZE_SCB,
+ FALSE,
+ (PVOID *)(&(acb->acb_scb_virtptr)),
+ &acb->acb_scb_physptr);
+
+ if (acb->acb_scb_virtptr == NULL)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating SCB failed.\n",acb->anum));
+
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Allocate the SSB for this adapter.
+ //
+ NdisMAllocateSharedMemory( acb->acb_handle,
+ (ULONG)SIZE_SSB,
+ FALSE,
+ (PVOID *)(&(acb->acb_ssb_virtptr)),
+ &acb->acb_ssb_physptr);
+
+ if (acb->acb_ssb_virtptr == NULL)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating SSB failed.\n",acb->anum));
+
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ acb->acb_maxinternalbufs = parms->utd_maxinternalbufs;
+ acb->acb_numsmallbufs = parms->utd_numsmallbufs;
+
+ //
+ // Allocate Flush Buffer Pool for our InteralBuffers and the ReceiveBuffers
+ //
+ NdisAllocateBufferPool(
+ &Status,
+ (PVOID*)&acb->FlushBufferPoolHandle,
+ acb->acb_gen_objs.max_frame_size * ( parms->utd_maxinternalbufs + acb->acb_maxrcvs + acb->acb_maxinternalbufs));
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating flush buffer pool failed.\n",acb->anum));
+
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Now allocate our internal buffers, and their flush buffers...
+ //
+ NdisAllocateMemory(
+ (PVOID *) &acb->OurBuffersVirtPtr,
+ sizeof(BUFFER_DESCRIPTOR) * acb->acb_maxinternalbufs,
+ (UINT) 0,
+ NetFlexHighestAddress);
+
+ //
+ // 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(
+ acb->OurBuffersVirtPtr,
+ sizeof(BUFFER_DESCRIPTOR) * acb->acb_maxinternalbufs );
+
+
+ //
+ // Allocate each of the buffers and fill in the
+ // buffer descriptor.
+ //
+ OurBuf = acb->OurBuffersVirtPtr;
+
+ NdisMAllocateSharedMemory(
+ acb->acb_handle,
+ FrameSizeCacheAligned * acb->acb_maxinternalbufs,
+ TRUE,
+ &acb->MergeBufferPoolVirt,
+ &acb->MergeBufferPoolPhys);
+
+ if ( acb->MergeBufferPoolVirt != NULL )
+ {
+ acb->MergeBuffersAreContiguous = TRUE;
+
+ CurrentMergeBuffer = acb->MergeBufferPoolVirt;
+
+ LowPart = NdisGetPhysicalAddressLow(acb->MergeBufferPoolPhys);
+
+ //
+ // If the high part is non-zero then this adapter is hosed anyway since
+ // its a 32-bit busmaster device.
+ //
+ ASSERT( NdisGetPhysicalAddressHigh(acb->MergeBufferPoolPhys) == 0 );
+ }
+ else
+ {
+ acb->MergeBuffersAreContiguous = FALSE;
+
+ acb->MergeBufferPoolVirt = NULL;
+
+ CurrentMergeBuffer = NULL;
+ }
+
+ for (i = 0; i < acb->acb_maxinternalbufs; i++ )
+ {
+ //
+ // Allocate a buffer
+ //
+ if ( acb->MergeBuffersAreContiguous )
+ {
+ OurBuf->VirtualBuffer = CurrentMergeBuffer;
+
+ NdisSetPhysicalAddressLow(OurBuf->PhysicalBuffer, LowPart);
+ NdisSetPhysicalAddressHigh(OurBuf->PhysicalBuffer, 0);
+
+ CurrentMergeBuffer += FrameSizeCacheAligned;
+
+ LowPart += FrameSizeCacheAligned;
+ }
+ else
+ {
+ NdisMAllocateSharedMemory(
+ acb->acb_handle,
+ parms->utd_maxframesz,
+ TRUE,
+ &OurBuf->VirtualBuffer,
+ &OurBuf->PhysicalBuffer);
+
+ if ( OurBuf->VirtualBuffer == NULL )
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating individual merge buffer failed.\n",acb->anum));
+
+ return NDIS_STATUS_RESOURCES;
+ }
+ }
+
+ //
+ // Build flush buffers
+ //
+ NdisAllocateBuffer(
+ &Status,
+ &OurBuf->FlushBuffer,
+ acb->FlushBufferPoolHandle,
+ OurBuf->VirtualBuffer,
+ acb->acb_gen_objs.max_frame_size );
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating FLUSH buffer failed.\n",acb->anum));
+
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ //
+ // Insert this buffer into the queue
+ //
+ OurBuf->Next = (OurBuf + 1);
+ OurBuf->BufferSize = acb->acb_gen_objs.max_frame_size;
+ OurBuf = OurBuf->Next;
+ }
+
+ //
+ // Make sure that the last buffer correctly terminates the free list.
+ //
+ (OurBuf - 1)->Next = NULL;
+ acb->OurBuffersListHead = acb->OurBuffersVirtPtr;
+
+ //
+ // Now allocate our internal buffers, and their flush buffers...
+ //
+ NdisAllocateMemory(
+ (PVOID *) &acb->SmallBuffersVirtPtr,
+ sizeof(BUFFER_DESCRIPTOR) * parms->utd_numsmallbufs,
+ (UINT) 0,
+ NetFlexHighestAddress);
+
+ //
+ // 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(
+ acb->SmallBuffersVirtPtr,
+ sizeof(BUFFER_DESCRIPTOR) * parms->utd_numsmallbufs);
+
+ //
+ // Allocate each of the buffers and fill in the
+ // buffer descriptor.
+ //
+ OurBuf = acb->SmallBuffersVirtPtr;
+
+ NdisMAllocateSharedMemory(
+ acb->acb_handle,
+ acb->acb_smallbufsz * parms->utd_numsmallbufs,
+ TRUE,
+ &acb->SmallBufferPoolVirt,
+ &acb->SmallBufferPoolPhys);
+
+ if ( acb->SmallBufferPoolVirt != NULL )
+ {
+ acb->SmallBuffersAreContiguous = TRUE;
+
+ CurrentMergeBuffer = acb->SmallBufferPoolVirt;
+
+ LowPart = NdisGetPhysicalAddressLow(acb->SmallBufferPoolPhys);
+
+ //
+ // If the high part is non-zero then this adapter is hosed anyway since
+ // its a 32-bit busmaster device.
+ //
+
+ ASSERT( NdisGetPhysicalAddressHigh(acb->SmallBufferPoolPhys) == 0 );
+
+ }
+ else
+ {
+ acb->SmallBuffersAreContiguous = FALSE;
+
+ acb->SmallBufferPoolVirt = NULL;
+
+ CurrentMergeBuffer = NULL;
+ }
+
+ for (i = 0; i < parms->utd_numsmallbufs; i++ )
+ {
+ //
+ // Allocate a small buffer
+ //
+
+ if ( acb->SmallBuffersAreContiguous ) {
+
+ OurBuf->VirtualBuffer = CurrentMergeBuffer;
+
+ NdisSetPhysicalAddressLow(OurBuf->PhysicalBuffer, LowPart);
+ NdisSetPhysicalAddressHigh(OurBuf->PhysicalBuffer, 0);
+
+ CurrentMergeBuffer += acb->acb_smallbufsz;
+
+ LowPart += acb->acb_smallbufsz;
+
+ } else {
+
+ NdisMAllocateSharedMemory(
+ acb->acb_handle,
+ acb->acb_smallbufsz,
+ TRUE,
+ &OurBuf->VirtualBuffer,
+ &OurBuf->PhysicalBuffer
+ );
+
+ if ( OurBuf->VirtualBuffer == NULL ) {
+
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating individual merge buffer failed.\n",acb->anum));
+
+ return NDIS_STATUS_RESOURCES;
+ }
+ }
+
+ //
+ // Build flush buffers
+ //
+
+ NdisAllocateBuffer( &Status,
+ &OurBuf->FlushBuffer,
+ acb->FlushBufferPoolHandle,
+ OurBuf->VirtualBuffer,
+ acb->acb_smallbufsz );
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating FLUSH buffer failed.\n",acb->anum));
+
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ //
+ // Insert this buffer into the queue
+ //
+ OurBuf->Next = (OurBuf + 1);
+ OurBuf->BufferSize = acb->acb_smallbufsz;
+ OurBuf = OurBuf->Next;
+ }
+
+ //
+ // Make sure that the last buffer correctly terminates the free list.
+ //
+ (OurBuf - 1)->Next = NULL;
+ acb->SmallBuffersListHead = acb->SmallBuffersVirtPtr;
+
+ //
+ // Now, Allocate the transmit lists
+ //
+ acb->acb_maxtrans = parms->utd_maxtrans * (USHORT)MAX_LISTS_PER_XMIT;
+ NdisMAllocateSharedMemory( acb->acb_handle,
+ (ULONG)(SIZE_XMIT * acb->acb_maxtrans),
+ FALSE,
+ (PVOID *)&acb->acb_xmit_virtptr,
+ &acb->acb_xmit_physptr);
+
+ if (acb->acb_xmit_virtptr == NULL)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating transmit list failed.\n",acb->anum));
+
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Initialize the transmit lists and link them together.
+ //
+
+ acb->acb_xmit_head = acb->acb_xmit_virtptr;
+
+ current_phys = NdisGetPhysicalAddressLow(acb->acb_xmit_physptr);
+
+ for (i = 0, CurrentXmitEntry = acb->acb_xmit_virtptr;
+ i < acb->acb_maxtrans;
+ i++, CurrentXmitEntry++ )
+ {
+ NdisSetPhysicalAddressHigh(CurrentXmitEntry->XMIT_Phys, 0);
+ NdisSetPhysicalAddressLow( CurrentXmitEntry->XMIT_Phys,
+ current_phys);
+
+ CurrentXmitEntry->XMIT_MyMoto = SWAPL(CTRL_ADDR((LONG)current_phys));
+
+ CurrentXmitEntry->XMIT_CSTAT = 0;
+
+#ifdef XMIT_INTS
+ CurrentXmitEntry->XMIT_Number = i;
+#endif
+ next_phys = current_phys + SIZE_XMIT;
+
+ //
+ // Make the forward pointer odd.
+ //
+ CurrentXmitEntry->XMIT_FwdPtr = SWAPL(CTRL_ADDR((LONG)next_phys));
+
+ CurrentXmitEntry->XMIT_Next = (CurrentXmitEntry + 1);
+ CurrentXmitEntry->XMIT_OurBufferPtr = NULL;
+ current_phys = next_phys;
+ }
+
+ //
+ // Make sure the last entry is properly set to the begining...
+ //
+ (CurrentXmitEntry - 1)->XMIT_Next = acb->acb_xmit_virtptr;
+ (CurrentXmitEntry - 1)->XMIT_FwdPtr =
+ SWAPL(CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_xmit_physptr)));
+
+ acb->acb_avail_xmit = parms->utd_maxtrans;
+
+ //
+ // Now, Allocate the Receive lists.
+ //
+ NdisMAllocateSharedMemory( acb->acb_handle,
+ (ULONG)(sizeof(RCV) * parms->utd_maxrcvs),
+ FALSE,
+ (PVOID *) &acb->acb_rcv_virtptr,
+ &acb->acb_rcv_physptr);
+
+ if (acb->acb_rcv_virtptr == NULL)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating receive list failed.\n",acb->anum));
+
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ //
+ // Point the head to the first one...
+ //
+ acb->acb_rcv_head = acb->acb_rcv_virtptr;
+ //
+ // Clear the receive lists
+ //
+ NdisZeroMemory( acb->acb_rcv_virtptr,
+ sizeof(RCV) * parms->utd_maxrcvs );
+
+ //
+ // Initialize the receive lists and link them together.
+ //
+
+ acb->acb_maxrcvs = parms->utd_maxrcvs;
+ current_phys = NdisGetPhysicalAddressLow(acb->acb_rcv_physptr);
+
+ CurrentReceiveEntry = acb->acb_rcv_virtptr;
+
+ //
+ // Create the receive buffer pool.
+ //
+
+ NdisMAllocateSharedMemory(
+ acb->acb_handle,
+ FrameSizeCacheAligned * parms->utd_maxrcvs,
+ TRUE,
+ &acb->ReceiveBufferPoolVirt,
+ &acb->ReceiveBufferPoolPhys
+ );
+
+ if ( acb->ReceiveBufferPoolVirt != NULL ) {
+
+ acb->RecvBuffersAreContiguous = TRUE;
+
+ CurrentReceiveBuffer = acb->ReceiveBufferPoolVirt;
+
+ LowPart = NdisGetPhysicalAddressLow(acb->ReceiveBufferPoolPhys);
+
+ //
+ // If the high part is non-zero then this adapter is hosed anyway since
+ // its a 32-bit busmaster device.
+ //
+
+ ASSERT( NdisGetPhysicalAddressHigh(acb->ReceiveBufferPoolPhys) == 0 );
+
+ } else {
+
+ acb->RecvBuffersAreContiguous = FALSE;
+
+ acb->ReceiveBufferPoolVirt = NULL;
+
+ CurrentReceiveBuffer = NULL;
+ }
+
+ for ( i = 0; i < parms->utd_maxrcvs; ++i, ++CurrentReceiveEntry )
+ {
+ //
+ // Allocate the actual receive frame buffers.
+ //
+
+ if ( acb->RecvBuffersAreContiguous ) {
+
+ CurrentReceiveEntry->RCV_Buf = CurrentReceiveBuffer;
+
+ NdisSetPhysicalAddressLow(CurrentReceiveEntry->RCV_BufPhys, LowPart);
+ NdisSetPhysicalAddressHigh(CurrentReceiveEntry->RCV_BufPhys, 0);
+
+ CurrentReceiveBuffer += FrameSizeCacheAligned;
+
+ LowPart += FrameSizeCacheAligned;
+
+ } else {
+
+ NdisMAllocateSharedMemory(
+ acb->acb_handle,
+ parms->utd_maxframesz,
+ TRUE,
+ &CurrentReceiveEntry->RCV_Buf,
+ &CurrentReceiveEntry->RCV_BufPhys
+ );
+
+ if ( CurrentReceiveEntry->RCV_Buf == NULL ) {
+
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating individual receive buffer failed.\n",acb->anum));
+
+ return NDIS_STATUS_RESOURCES;
+ }
+ }
+
+ //
+ // Build flush buffers
+ //
+
+ NdisAllocateBuffer(
+ &Status,
+ &CurrentReceiveEntry->RCV_FlushBuffer,
+ acb->FlushBufferPoolHandle,
+ CurrentReceiveEntry->RCV_Buf,
+ acb->acb_gen_objs.max_frame_size);
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating FLUSH receive buffer failed.\n",acb->anum));
+
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ //
+ // Initialize receive buffers
+ //
+ NdisFlushBuffer(CurrentReceiveEntry->RCV_FlushBuffer, FALSE);
+
+ CurrentReceiveEntry->RCV_Number = i;
+ CurrentReceiveEntry->RCV_CSTAT = ((i % acb->RcvIntRatio) == 0) ? RCSTAT_GO_INT : RCSTAT_GO;
+
+ CurrentReceiveEntry->RCV_Dsize = (SHORT) SWAPS((USHORT)(acb->acb_gen_objs.max_frame_size));
+ CurrentReceiveEntry->RCV_Dsize &= DATA_LAST;
+
+ temp = NdisGetPhysicalAddressLow(CurrentReceiveEntry->RCV_BufPhys);
+ temp = SWAPL(temp);
+
+ CurrentReceiveEntry->RCV_DptrHi = (USHORT)temp;
+ CurrentReceiveEntry->RCV_DptrLo = (USHORT)(temp >> 16);
+
+ NdisSetPhysicalAddressHigh(CurrentReceiveEntry->RCV_Phys, 0);
+ NdisSetPhysicalAddressLow( CurrentReceiveEntry->RCV_Phys,
+ current_phys);
+
+ next_phys = current_phys + SIZE_RCV;
+
+ CurrentReceiveEntry->RCV_FwdPtr = SWAPL(CTRL_ADDR(next_phys));
+ CurrentReceiveEntry->RCV_MyMoto = SWAPL(CTRL_ADDR(current_phys));
+
+ CurrentReceiveEntry->RCV_Next = (CurrentReceiveEntry + 1);
+ current_phys = next_phys;
+ }
+
+ //
+ // Make sure the last entry is properly set to the begining...
+ //
+ (CurrentReceiveEntry - 1)->RCV_Next = acb->acb_rcv_virtptr;
+ (CurrentReceiveEntry - 1)->RCV_FwdPtr =
+ SWAPL(CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_rcv_physptr)));
+
+ //
+ // Allocate and initialize the OPEN parameter block.
+ //
+ NdisMAllocateSharedMemory( acb->acb_handle,
+ (ULONG)SIZE_OPEN,
+ FALSE,
+ (PVOID *)(&(acb->acb_opnblk_virtptr)),
+ &acb->acb_opnblk_physptr );
+
+ if (acb->acb_opnblk_virtptr == NULL)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating OPEN block failed.\n",acb->anum));
+
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ NdisMoveMemory(acb->acb_opnblk_virtptr, &(parms->utd_open), SIZE_OPEN);
+
+ //
+ // Convert the product ID pointer in the Open parameter block
+ // into a big endian type address.
+ //
+ acb->acb_opnblk_virtptr->OPEN_ProdIdPtr =
+ (CHAR *) (SWAPL((LONG) acb->acb_opnblk_virtptr->OPEN_ProdIdPtr));
+
+ acb->acb_openoptions = parms->utd_open.OPEN_Options;
+
+ //
+ // Initialize the intialization block.
+ //
+ NdisMoveMemory(&acb->acb_initblk, &init_mask, SIZE_INIT);
+
+ //
+ // Allocate Memory to hold the Read Statistics Log information.
+ //
+ NdisMAllocateSharedMemory( acb->acb_handle,
+ (ULONG)(sizeof(RSL)),
+ FALSE,
+ (PVOID *)(&(acb->acb_logbuf_virtptr)),
+ &acb->acb_logbuf_physptr );
+
+ if (acb->acb_logbuf_virtptr == NULL)
+ {
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Allocate Memory for internal SCB requests.
+ //
+ NdisAllocateMemory( (PVOID *)&(start),
+ (UINT) (SCBREQSIZE * parms->utd_maxinternalreqs),
+ (UINT) NDIS_MEMORY_CONTIGUOUS,
+ NetFlexHighestAddress);
+ if (start == NULL)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating internal SCB request failed.\n",acb->anum));
+
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Initialize the SCB requests and place them on the free queue.
+ //
+ acb->acb_maxreqs = parms->utd_maxinternalreqs;
+ current = start;
+ for (i = 0; i < parms->utd_maxinternalreqs; i++)
+ {
+ next = (PVOID)( ((PUCHAR)(current)) + SCBREQSIZE);
+ ((PSCBREQ) current)->req_next = next;
+ if (i < (USHORT)(parms->utd_maxinternalreqs-1))
+ {
+ current = next;
+ }
+ }
+ ((PSCBREQ)current)->req_next = (PSCBREQ) NULL;
+ acb->acb_scbreq_ptr = (PSCBREQ)start;
+ acb->acb_scbreq_free = (PSCBREQ)start;
+
+ //
+ // Allocate Memory for the internal MAC requests.
+ //
+ NdisAllocateMemory( (PVOID *)&(start),
+ (UINT) (MACREQSIZE * parms->utd_maxinternalreqs),
+ (UINT) NDIS_MEMORY_CONTIGUOUS,
+ NetFlexHighestAddress);
+ if (start == NULL)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating internal MAC request failed.\n",acb->anum));
+
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Initialize the internal MAC requests and place them
+ // on the free queue.
+ //
+ current = start;
+ for (i = 0; i < parms->utd_maxinternalreqs; i++)
+ {
+ next = (PVOID)( ((PUCHAR)(current)) + MACREQSIZE);
+ ((PMACREQ) current)->req_next = next;
+ if (i < (USHORT)(parms->utd_maxinternalreqs-1))
+ {
+ current = next;
+ }
+ }
+ ((PMACREQ)current)->req_next = (PMACREQ) NULL;
+ acb->acb_macreq_ptr = (PMACREQ)start;
+ acb->acb_macreq_free = (PMACREQ)start;
+
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb completed successfully!\n",acb->anum));
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDeallocateAcb
+//
+// Description: This routine deallocates the acb resources.
+//
+// Input: acb - Our Driver Context for this adapter or head.
+//
+// Output: None.
+//
+// Called By: NetFlexInitialize,
+// NetFlexDeregisterAdapter
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexDeallocateAcb(
+ PACB acb
+ )
+{
+ PETH_OBJS ethobjs;
+ PRCV CurrentReceiveEntry;
+ PNETFLEX_PARMS parms = acb->acb_parms;
+ USHORT i;
+ PBUFFER_DESCRIPTOR OurBuf;
+ ULONG Alignment, FrameSizeCacheAligned;
+
+ //
+ // Get the max frame size, cache align it and a save it for later.
+ //
+
+ Alignment = NdisGetCacheFillSize();
+
+ if ( Alignment < sizeof(ULONG) ) {
+
+ Alignment = sizeof(ULONG);
+ }
+
+ FrameSizeCacheAligned = (parms->utd_maxframesz + Alignment - 1) & ~(Alignment - 1);
+
+ //
+ // If we have allocated memory for the network specific information,
+ // release this memory now.
+ //
+
+ if (acb->acb_spec_objs)
+ {
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_3)
+ {
+ // ETHERNET
+
+ ethobjs = (PETH_OBJS)(acb->acb_spec_objs);
+ //
+ // If we have allocated the multicast table entries, free
+ // the memory.
+ //
+ if (ethobjs->MulticastEntries)
+ {
+ NdisFreeMemory( (PVOID)(ethobjs->MulticastEntries),
+ (UINT) (ethobjs->MaxMulticast * NET_ADDR_SIZE),
+ (UINT) 0);
+ }
+ //
+ // Deallocate Memory for Ethernet specific objects
+ //
+ NdisFreeMemory((PVOID)(acb->acb_spec_objs),
+ (UINT) (sizeof (ETH_OBJS)),
+ (UINT) 0);
+ }
+ else
+ {
+ // Token Ring
+ //
+ // Deallocate Memory for Token Ring specific objects
+ //
+ NdisFreeMemory( (PVOID)(acb->acb_spec_objs),
+ (UINT) (sizeof (TR_OBJS)),
+ (UINT) 0);
+
+ }
+ }
+
+ //
+ // If we have allocated memory for the multicast request to the
+ // adapter, free the memory.
+ //
+ if (acb->acb_multiblk_virtptr)
+ {
+ NdisMFreeSharedMemory( acb->acb_handle,
+ (ULONG)(sizeof(MULTI_BLOCK) * 2),
+ FALSE,
+ (PVOID)(acb->acb_multiblk_virtptr),
+ acb->acb_multiblk_physptr);
+ }
+
+ //
+ // If we have allocated memory for the scb, free the memory.
+ //
+ if (acb->acb_scb_virtptr)
+ {
+ NdisMFreeSharedMemory( acb->acb_handle,
+ (ULONG)SIZE_SCB,
+ FALSE,
+ (PVOID)(acb->acb_scb_virtptr),
+ acb->acb_scb_physptr);
+ }
+
+ //
+ // If we have allocated memory for the ssb, free the memory.
+ //
+ if (acb->acb_ssb_virtptr)
+ {
+ NdisMFreeSharedMemory( acb->acb_handle,
+ (ULONG)SIZE_SSB,
+ FALSE,
+ (PVOID)(acb->acb_ssb_virtptr),
+ acb->acb_ssb_physptr);
+ }
+
+ //
+ // Free merge buffer pool.
+ //
+
+ if (acb->MergeBufferPoolVirt) {
+
+ OurBuf = acb->OurBuffersVirtPtr;
+
+ //
+ // Free flush buffers
+ //
+
+ for (i = 0; i < acb->acb_maxinternalbufs; ++i, ++OurBuf) {
+
+ if (OurBuf->FlushBuffer)
+ {
+ NdisFreeBuffer(OurBuf->FlushBuffer);
+
+ if ( !acb->MergeBuffersAreContiguous ) {
+
+ NdisMFreeSharedMemory(
+ acb->acb_handle,
+ parms->utd_maxframesz,
+ TRUE,
+ OurBuf->VirtualBuffer,
+ OurBuf->PhysicalBuffer
+ );
+ }
+ }
+ }
+
+ //
+ // Free the pool itself.
+ //
+
+ if ( acb->MergeBuffersAreContiguous ) {
+
+ NdisMFreeSharedMemory(
+ acb->acb_handle,
+ FrameSizeCacheAligned * acb->acb_maxinternalbufs,
+ TRUE,
+ acb->MergeBufferPoolVirt,
+ acb->MergeBufferPoolPhys
+ );
+ }
+ }
+ //
+ // Free our own transmit buffers.
+ //
+
+ if (acb->OurBuffersVirtPtr)
+ {
+ //
+ // Free OurBuffers
+ //
+
+ NdisFreeMemory(
+ acb->OurBuffersVirtPtr,
+ sizeof(BUFFER_DESCRIPTOR) * acb->acb_maxinternalbufs,
+ 0
+ );
+ }
+
+ //
+ // Free Small Merge buffer pool.
+ //
+ if (acb->SmallBufferPoolVirt)
+ {
+ OurBuf = acb->SmallBuffersVirtPtr;
+
+ //
+ // Free flush buffers
+ //
+ for (i = 0; i < acb->acb_numsmallbufs; ++i, ++OurBuf)
+ {
+ if (OurBuf->FlushBuffer)
+ {
+ NdisFreeBuffer(OurBuf->FlushBuffer);
+
+ if ( !acb->SmallBuffersAreContiguous ) {
+
+ NdisMFreeSharedMemory(
+ acb->acb_handle,
+ acb->acb_smallbufsz,
+ TRUE,
+ OurBuf->VirtualBuffer,
+ OurBuf->PhysicalBuffer);
+ }
+ }
+ }
+
+ //
+ // Free the pool itself.
+ //
+ if ( acb->SmallBuffersAreContiguous )
+ {
+ NdisMFreeSharedMemory(
+ acb->acb_handle,
+ acb->acb_smallbufsz * acb->acb_numsmallbufs,
+ TRUE,
+ acb->SmallBufferPoolVirt,
+ acb->SmallBufferPoolPhys);
+ }
+ }
+
+ //
+ // Free our Small transmit buffers.
+ //
+ if (acb->SmallBuffersVirtPtr)
+ {
+ //
+ // Free Small Buffers
+ //
+
+ NdisFreeMemory(
+ acb->SmallBuffersVirtPtr,
+ sizeof(BUFFER_DESCRIPTOR) * acb->acb_numsmallbufs,
+ 0
+ );
+ }
+ //
+ // If we have allocated memory for the transmit lists, free it.
+ //
+ if (acb->acb_xmit_virtptr)
+ {
+ NdisMFreeSharedMemory( acb->acb_handle,
+ (ULONG)(SIZE_XMIT * acb->acb_maxtrans),
+ FALSE,
+ (PVOID)(acb->acb_xmit_virtptr),
+ acb->acb_xmit_physptr );
+ }
+
+ //
+ // If we have allocated memory for the receive lists, free it.
+ //
+
+ if ( acb->acb_rcv_virtptr ) {
+
+ //
+ // If we allocated the receive buffer pool, free it.
+ //
+ CurrentReceiveEntry = acb->acb_rcv_virtptr;
+
+ for (i = 0; i < parms->utd_maxrcvs; ++i, ++CurrentReceiveEntry) {
+ //
+ // Free flush buffers
+ //
+
+ if ( CurrentReceiveEntry->RCV_FlushBuffer )
+ {
+ NdisFreeBuffer(CurrentReceiveEntry->RCV_FlushBuffer);
+
+ }
+
+ //
+ // Free individual buffer, if allocated.
+ //
+ if ((!acb->RecvBuffersAreContiguous) &&
+ (CurrentReceiveEntry->RCV_Buf))
+ {
+ NdisMFreeSharedMemory(
+ acb->acb_handle,
+ parms->utd_maxframesz,
+ TRUE,
+ CurrentReceiveEntry->RCV_Buf,
+ CurrentReceiveEntry->RCV_BufPhys
+ );
+ }
+ }
+
+ //
+ // Free the pool itself, if it was allocated contiguously.
+ //
+ if ( acb->RecvBuffersAreContiguous && acb->ReceiveBufferPoolVirt)
+ {
+ NdisMFreeSharedMemory(
+ acb->acb_handle,
+ FrameSizeCacheAligned * parms->utd_maxrcvs,
+ TRUE,
+ acb->ReceiveBufferPoolVirt,
+ acb->ReceiveBufferPoolPhys
+ );
+ }
+
+ //
+ // Now Free the RCV Lists
+ //
+
+ NdisMFreeSharedMemory( acb->acb_handle,
+ (ULONG)(SIZE_RCV * parms->utd_maxrcvs),
+ FALSE,
+ (PVOID)acb->acb_rcv_virtptr,
+ acb->acb_rcv_physptr);
+ }
+
+ //
+ // Free the Flush Pool
+ //
+ if (acb->FlushBufferPoolHandle)
+ {
+ // Free the buffer pool
+ //
+ NdisFreeBufferPool(acb->FlushBufferPoolHandle);
+ }
+
+
+ //
+ // If we have allocated memory for the open block, free it.
+ //
+ if (acb->acb_opnblk_virtptr)
+ {
+ NdisMFreeSharedMemory( acb->acb_handle,
+ (ULONG)SIZE_OPEN,
+ FALSE,
+ (PVOID)(acb->acb_opnblk_virtptr),
+ acb->acb_opnblk_physptr);
+ }
+
+ //
+ // If we have allocated memory for the Read Statistics Log, free it.
+ //
+ if (acb->acb_logbuf_virtptr)
+ {
+ NdisMFreeSharedMemory( acb->acb_handle,
+ (ULONG)(sizeof(RSL)),
+ FALSE,
+ (PVOID)(acb->acb_logbuf_virtptr),
+ acb->acb_logbuf_physptr);
+ }
+
+ //
+ // If we have allocated memory for the internal SCB requests,
+ // free it.
+ //
+ if (acb->acb_scbreq_ptr)
+ {
+ NdisFreeMemory( (PVOID)acb->acb_scbreq_ptr,
+ (UINT) (SCBREQSIZE * acb->acb_maxreqs),
+ (UINT) NDIS_MEMORY_CONTIGUOUS);
+ }
+ //
+ // If we have allocated memory for the internal MAC requests,
+ // free it.
+ //
+ if (acb->acb_macreq_ptr)
+ {
+ NdisFreeMemory( (PVOID)acb->acb_macreq_ptr,
+ (UINT) (MACREQSIZE * acb->acb_maxreqs),
+ (UINT) NDIS_MEMORY_CONTIGUOUS);
+ }
+
+ //
+ // Free map registers
+ //
+ NdisMFreeMapRegisters(acb->acb_handle);
+
+ //
+ // Deregister IO mappings
+ //
+
+ if (acb->acb_dualport)
+ {
+ BOOLEAN OtherHeadStillActive = FALSE;
+ PACB tmp_acb = macgbls.mac_adapters;
+ while (tmp_acb)
+ {
+ if ((tmp_acb->acb_baseaddr == acb->acb_baseaddr) &&
+ (tmp_acb->acb_portnumber != acb->acb_portnumber))
+ {
+ OtherHeadStillActive = TRUE;
+ break;
+ }
+ else
+ {
+ tmp_acb = tmp_acb->acb_next;
+ }
+ }
+
+ if (!OtherHeadStillActive)
+ {
+ // Remove ports for both heads
+ //
+
+ // free ports z000 - -z02f
+ //
+ NdisMDeregisterIoPortRange( acb->acb_handle,
+ acb->acb_baseaddr,
+ NUM_DUALHEAD_CFG_PORTS,
+ (PVOID) acb->MasterBasePorts );
+
+ // free ports zc80 - zc87
+ //
+ NdisMDeregisterIoPortRange( acb->acb_handle,
+ acb->acb_baseaddr + CFG_PORT_OFFSET,
+ NUM_CFG_PORTS,
+ (PVOID)acb->ConfigPorts );
+
+ // free ports zc63 - zc67
+ //
+ NdisMDeregisterIoPortRange( acb->acb_handle,
+ acb->acb_baseaddr + EXTCFG_PORT_OFFSET,
+ NUM_EXTCFG_PORTS,
+ (PVOID)acb->ExtConfigPorts );
+ }
+ }
+ else
+ {
+ // free ports z000 - z01f
+ //
+ NdisMDeregisterIoPortRange( acb->acb_handle,
+ acb->acb_baseaddr,
+ NUM_BASE_PORTS,
+ (PVOID) acb->BasePorts );
+
+ // free ports zc80 - zc87
+ //
+ NdisMDeregisterIoPortRange( acb->acb_handle,
+ acb->acb_baseaddr + CFG_PORT_OFFSET,
+ NUM_CFG_PORTS,
+ (PVOID)acb->ConfigPorts );
+
+ // free ports zc63 - zc67
+ //
+ NdisMDeregisterIoPortRange( acb->acb_handle,
+ acb->acb_baseaddr + EXTCFG_PORT_OFFSET,
+ NUM_EXTCFG_PORTS,
+ (PVOID)acb->ExtConfigPorts );
+ }
+
+ //
+ // Free the Memory for the adapter's acb.
+ //
+ if (acb->acb_parms != NULL)
+ {
+ NdisFreeMemory( (PVOID) acb->acb_parms, (UINT) sizeof(PNETFLEX_PARMS), (UINT) 0);
+ }
+ if (acb != NULL)
+ {
+ NdisFreeMemory( (PVOID)acb, (UINT) (sizeof (ACB)),(UINT) 0);
+ }
+ //
+ // Indicate New Number of Adapters
+ //
+ macgbls.mac_numadpts--;
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexSendNextSCB
+//
+// Description:
+// This routine either sends a TMS_TRANSMIT SCB
+// command to the adapter or sends a command on
+// the SCBReq active queue.
+//
+// Input:
+// acb - Our Driver Context for this adapter or head.
+//
+// Output:
+// None
+//
+// Called By:
+// NetFlexSCBClear,
+// NetFlexQueueSCB,
+// NetFlexTransmitStatus
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexSendNextSCB(
+ PACB acb
+ )
+{
+ USHORT sifint_reg;
+ PSCBREQ req;
+ PMACREQ macreq;
+ PMULTI_BLOCK tempmulti;
+
+ //
+ // If there is a Transmit command waiting, issue it. Otherwise,
+ // issue the first SCBReq on the SCBReq active queue.
+ //
+ if (acb->acb_xmit_whead)
+ {
+ // Load up the real SCB with a Transmit command
+ //
+ DebugPrint(2,("!S!"));
+ acb->acb_scb_virtptr->SCB_Cmd = TMS_TRANSMIT;
+ acb->acb_scb_virtptr->SCB_Ptr = acb->acb_xmit_whead->XMIT_MyMoto;
+
+ //
+ // If the transmit lists on the waiting queue are ready to
+ // transmit, put them on the active queue.
+ //
+ if ((acb->acb_xmit_whead->XMIT_CSTAT & XCSTAT_GO) != 0)
+ {
+ acb->acb_xmit_ahead = acb->acb_xmit_whead;
+ acb->acb_xmit_atail = acb->acb_xmit_wtail;
+ }
+
+ acb->acb_xmit_whead = 0;
+ acb->acb_xmit_wtail = 0;
+ }
+ //
+ // If there is a Receive command waiting, issue it.
+ //
+ else if (acb->acb_rcv_whead)
+ {
+
+ // Load up the real SCB with a receive command
+ //
+ acb->acb_scb_virtptr->SCB_Cmd = TMS_RECEIVE;
+ acb->acb_scb_virtptr->SCB_Ptr = acb->acb_rcv_whead->RCV_MyMoto;
+
+ acb->acb_rcv_head = acb->acb_rcv_whead;
+ acb->acb_rcv_whead = 0;
+ }
+ //
+ // Otherwise, if there is a SCB request waiting, issue it.
+ //
+ else if (acb->acb_scbreq_next)
+ {
+ // First, let's skip over any dummy SCB commands
+ //
+ req = acb->acb_scbreq_next;
+
+ //
+ // Fill in the real SCB with the first SCBReq on the SCBReq active
+ // queue.
+ //
+ acb->acb_scbreq_next = acb->acb_scbreq_next->req_next;
+ acb->acb_scb_virtptr->SCB_Cmd = req->req_scb.SCB_Cmd;
+
+ //
+ // If this is a Multicast request, we have to fill in a Multicast
+ // buffer.
+ //
+ if (req->req_scb.SCB_Cmd == TMS_MULTICAST)
+ {
+ acb->acb_scb_virtptr->SCB_Ptr = SWAPL(CTRL_ADDR((ULONG)(NdisGetPhysicalAddressLow(acb->acb_multiblk_physptr) +
+ (acb->acb_multi_index * sizeof(MULTI_BLOCK)))) );
+
+ tempmulti = (PMULTI_BLOCK)((ULONG)(acb->acb_multiblk_virtptr) +
+ (acb->acb_multi_index * sizeof(MULTI_BLOCK)));
+
+ acb->acb_multi_index = acb->acb_multi_index ^ (SHORT)1;
+
+ tempmulti->MB_Option = req->req_multi.MB_Option;
+ tempmulti->MB_Addr_Hi = req->req_multi.MB_Addr_Hi;
+ tempmulti->MB_Addr_Med = req->req_multi.MB_Addr_Med;
+ tempmulti->MB_Addr_Lo = req->req_multi.MB_Addr_Lo;
+ }
+ else
+ {
+ acb->acb_scb_virtptr->SCB_Ptr = req->req_scb.SCB_Ptr;
+ }
+ }
+ else
+ {
+ // Nothing to do
+ //
+ return;
+ }
+
+ sifint_reg = SIFINT_CMD;
+
+ //
+ // If there are other requests to send and we are not waiting for
+ // an SCB clear interrupt, tell the adapter we want an SCB clear int.
+ //
+ if ((!acb->acb_scbclearout) &&
+ ((acb->acb_scbreq_next) || (acb->acb_rcv_whead))
+ )
+ {
+ sifint_reg |= SIFINT_SCBREQST;
+ acb->acb_scbclearout = TRUE;
+ }
+
+ //
+ // Send the SCB to the adapter.
+ //
+ NdisRawWritePortUshort(acb->SifIntPort, (USHORT) sifint_reg);
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexQueueSCB
+//
+// Description:
+// This routine places the given SCBReq onto the
+// active SCBreq queue.
+//
+// Input:
+// acb - Our Driver Context for this adapter or head.
+// scbreq - Ptr to the SCBReq to execute
+//
+// Output:
+// None
+//
+// Called By:
+// NetFlexQueryInformation
+// NetFlexSetInformation,
+// NetFlexDeleteMulticast,
+// NetFlexAddMulticast
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID NetFlexQueueSCB(
+ PACB acb,
+ PSCBREQ scbreq
+)
+{
+ //
+ // Place the scbreq on the SCBReq active queue.
+ //
+ NetFlexEnqueue_TwoPtrQ_Tail(
+ (PVOID *)&(acb->acb_scbreq_head),
+ (PVOID *)&(acb->acb_scbreq_tail),
+ (PVOID)scbreq
+ );
+
+ //
+ // If there are no requests waiting for the SCB to clear,
+ // point the request waiting queue to this SCBReq.
+ //
+ if (!acb->acb_scbreq_next)
+ acb->acb_scbreq_next = scbreq;
+
+ //
+ // If the SCB is clear, send a SCB command off now.
+ // Otherwise, if we are not currently waiting for an SCB clear
+ // interrupt, signal the adapter to send us a SCB clear interrupt
+ // when it is done with the SCB.
+ //
+ if (acb->acb_scb_virtptr->SCB_Cmd == 0)
+ {
+ NetFlexSendNextSCB(acb);
+ }
+ else if (!acb->acb_scbclearout)
+ {
+ acb->acb_scbclearout = TRUE;
+ NdisRawWritePortUshort(acb->SifIntPort, (USHORT)SIFINT_SCBREQST);
+ }
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexGetBIA
+//
+// Description:
+// This routine gets the Burned In Address of the adapter.
+//
+// Input:
+// acb - Acb pointer
+//
+// Output:
+// NDIS_STATUS_SUCCESS if successful
+//
+// Called By:
+// NetFlexBoardInitandReg
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexGetBIA(
+ PACB acb
+ )
+{
+ USHORT value;
+ SHORT i;
+
+ NdisRawWritePortUshort( acb->SifAddrPort, (USHORT) 0x0a00);
+ NdisRawReadPortUshort( acb->SifDataPort, (PUSHORT) &value);
+ NdisRawWritePortUshort( acb->SifAddrPort, (USHORT) value);
+
+ for (i = 0; i < 3; i++)
+ {
+ NdisRawReadPortUshort( acb->SifDIncPort, (PUSHORT) &value);
+ //
+ // Copy the value into the permanent and current station addresses
+ //
+ acb->acb_gen_objs.perm_staddr[i*2] = (UCHAR)(SWAPS(value));
+ acb->acb_gen_objs.perm_staddr[(i*2)+1] = (UCHAR)(value);
+ }
+
+ //
+ // Figure out whether the current station address will be the bia or
+ // an address set up in the configuration file.
+ //
+ if ( (acb->acb_opnblk_virtptr->OPEN_NodeAddr[0] == 0) &&
+ (acb->acb_opnblk_virtptr->OPEN_NodeAddr[1] == 0) &&
+ (acb->acb_opnblk_virtptr->OPEN_NodeAddr[2] == 0) &&
+ (acb->acb_opnblk_virtptr->OPEN_NodeAddr[3] == 0) &&
+ (acb->acb_opnblk_virtptr->OPEN_NodeAddr[4] == 0) &&
+ (acb->acb_opnblk_virtptr->OPEN_NodeAddr[5] == 0) )
+ {
+ NdisMoveMemory(acb->acb_gen_objs.current_staddr,
+ acb->acb_gen_objs.perm_staddr,
+ NET_ADDR_SIZE);
+ }
+ else
+ {
+ NdisMoveMemory(acb->acb_gen_objs.current_staddr,
+ acb->acb_opnblk_virtptr->OPEN_NodeAddr,
+ NET_ADDR_SIZE);
+ }
+}
+
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexGetUpstreamAddrPtr
+//
+// Description: This routine saves the address of where to
+// get the upstream address after opening.
+//
+// Input:
+// acb - Our Driver Context for this adapter or head.
+//
+// Output:
+// NDIS_STATUS_SUCCESS if successful
+//
+// Called By:
+// NetFlexAdapterReset
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexGetUpstreamAddrPtr(
+ PACB acb
+ )
+{
+ USHORT value;
+
+ NdisRawWritePortUshort( acb->SifAddrPort, (USHORT) 0x0a06); // RVC: what is this value for?
+
+ NdisRawReadPortUshort( acb->SifDataPort, (PUSHORT) &value);
+
+ //
+ // Save the address of where to get the UNA for later requests
+ //
+ acb->acb_upstreamaddrptr = value;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexAsciiToHex
+//
+// Description:
+// This routine takes an ascii string an converts
+// it into hex digits storing them in an array provided.
+//
+// Input:
+// src - source string.
+// dst - destiniation string
+// dst_length - length of dst
+//
+// Output:
+// NDIS_STATUS_SUCCESS if the string was converted successfully.
+//
+// Called By:
+// NetFlexReadConfigurationParameters
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS NetFlexAsciiToHex(
+ PNDIS_STRING src,
+ PUCHAR dst,
+ USHORT dst_length
+ )
+{
+ ULONG i;
+ UCHAR num;
+
+ //
+ // If the string is too short, return an error.
+ //
+ if (src->Length < (USHORT)(dst_length*2))
+ return(NDIS_STATUS_FAILURE);
+
+ //
+ // Begin to convert.
+ //
+ for (i = 0; i < dst_length; i++)
+ {
+ //
+ // Get first digit of the byte
+ //
+ num = (UCHAR)(src->Buffer[i*2]);
+ if ( (num >= '0') && (num <= '9') )
+ *dst = (UCHAR)(num - '0') * 0x10;
+ else if ( (num >= 'a') && (num <= 'f') )
+ *dst = (UCHAR)(num - 'a' + 10) * 0x10;
+ else if ( (num >= 'A') && (num <= 'F') )
+ *dst = (UCHAR)(num - 'A' + 10) * 0x10;
+ else
+ return(NDIS_STATUS_FAILURE);
+
+ //
+ // Get second digit of the byte
+ //
+ num = (UCHAR)(src->Buffer[(i*2)+1]);
+ if ( (num >= '0') && (num <= '9') )
+ *dst += (UCHAR)(num - '0');
+ else if ( (num >= 'a') && (num <= 'f') )
+ *dst += (UCHAR)(num - 'a' + 10);
+ else if ( (num >= 'A') && (num <= 'F') )
+ *dst += (UCHAR)(num - 'A' + 10);
+ else
+ return(NDIS_STATUS_FAILURE);
+
+ dst++;
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexFindEntry
+//
+// Description:
+// This routine finds the given entry in a queue given to it.
+//
+// Input:
+// head - Ptr to the head of the queue.
+// entry - Ptr to the entry to find.
+//
+// Output:
+// back - Ptr to the address of the entry in front of the
+// entry given.
+// Returns TRUE if found and FALSE if not.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+BOOLEAN
+NetFlexFindEntry(
+ PVOID head,
+ PVOID *back,
+ PVOID entry
+ )
+{
+ PVOID current;
+
+ current = *back = head;
+ while (current)
+ {
+ if (current == entry)
+ return(TRUE);
+ *back = current;
+ current = (PVOID)( ( (PNETFLEX_ENTRY)(current) )->next );
+ }
+
+ return FALSE;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDequeue_OnePtrQ
+//
+// Description: This routine finds the given entry and removes
+// it from the queueu given.
+//
+// Input: head - Ptr to the head of the queue.
+// entry - Ptr to the entry to remove.
+//
+// Output: None.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexDequeue_OnePtrQ(
+ PVOID *head,
+ PVOID entry
+ )
+{
+ PNETFLEX_ENTRY back;
+
+ if (NetFlexFindEntry(*head, (PVOID *) &back, entry))
+ {
+ if (entry == *head)
+ *head = (PVOID)( ( (PNETFLEX_ENTRY)(entry) )->next );
+ else
+ back->next = ( (PNETFLEX_ENTRY)(entry) )->next;
+ }
+}
+
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexEnqueue_OnePtrQ_Head
+//
+// Description:
+// This routine places the entry given on the front of the
+// queue given.
+//
+// Input:
+// head - Ptr to the ptr of the head of the queue.
+// entry - Pointer to the entry to add
+//
+// Output: None
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexEnqueue_OnePtrQ_Head(
+ PVOID *head,
+ PVOID entry
+ )
+{
+ ((PNETFLEX_ENTRY)(entry))->next = *head;
+ *head = entry;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDequeue_OnePtrQ_Head
+//
+// Description:
+// This routine dequeues a the first entry of the given queue
+//
+// Input:
+// head - Ptr to the ptr of the head of the queue.
+//
+// Output:
+// entry - Ptr to the ptr of the dequeued entry.
+//
+// Returns NDIS_STATUS_SUCCESS if an entry is freed.
+// Otherwise, NDIS_STATUS_RESOURCES.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexDequeue_OnePtrQ_Head(
+ PVOID *head,
+ PVOID *entry
+ )
+{
+ //
+ // Is there a free entry? If not, return an error.
+ //
+ if (!(*head))
+ {
+ *entry = NULL;
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ //
+ // Dequeue the free entry from the queue.
+ //
+ *entry = *head;
+ *head = ( (PNETFLEX_ENTRY)(*head))->next;
+ ((PNETFLEX_ENTRY)(*entry))->next = NULL;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexEnqueue_TwoPtrQ_Tail
+//
+// Description:
+// This routine places an entry on the tail of
+// a queue with a head and tail pointer.
+//
+// Input:
+// head - Ptr to address of the head of the queue.
+// tail - Ptr to the address of the tail of the queue.
+// entry - Ptr to the entry to enqueue
+//
+// Output:
+// Status.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexEnqueue_TwoPtrQ_Tail(
+ PVOID *head,
+ PVOID *tail,
+ PVOID entry)
+{
+ //
+ // Place the entry on tail of the queue.
+ //
+ ((PNETFLEX_ENTRY)(entry))->next = NULL;
+ if (*tail)
+ ((PNETFLEX_ENTRY)(*tail))->next = entry;
+ else
+ *head = entry;
+ *tail = entry;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDequeue_TwoPtrQ
+//
+// Description:
+// This routine finds the given entry and removes it from
+// the queue. Queue has a head and tail pointer.
+//
+// Input:
+// head - Ptr to address of the head of the queue.
+// tail - Ptr to the address of the tail of the queue.
+// entry - Ptr to the entry to enqueue
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexDequeue_TwoPtrQ(
+ PVOID *head,
+ PVOID *tail,
+ PVOID entry
+ )
+{
+ PVOID back;
+
+ if (NetFlexFindEntry(*head, &back, entry))
+ {
+ if (entry == *head)
+ {
+ if ( (*head = ((PNETFLEX_ENTRY)entry)->next) == NULL)
+ *tail = NULL;
+ }
+ else
+ {
+ ((PNETFLEX_ENTRY)back)->next = ((PNETFLEX_ENTRY)entry)->next;
+ if (*tail == entry)
+ *tail = back;
+ }
+ }
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDequeue_TwoPtrQ_Head
+//
+// Description:
+// This routine dequeues a the first entry of the given queue
+//
+// Input:
+// head - Ptr to the ptr of the head of the queue.
+// tail - Ptr to the address of the tail of the queue.
+//
+// Output:
+// entry - Ptr to the ptr of the dequeued entry.
+//
+// Status - NDIS_STATUS_SUCCESS if an entry is freed.
+// Otherwise, NDIS_STATUS_RESOURCES.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexDequeue_TwoPtrQ_Head(
+ PVOID *head,
+ PVOID *tail,
+ PVOID *entry
+ )
+{
+ //
+ // Is there a free entry? If not, return an error.
+ //
+ if (!(*head))
+ {
+ *entry = NULL;
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Dequeue the free entry from the queue.
+ //
+ *entry = *head;
+ *head = ((PNETFLEX_ENTRY)(*head))->next;
+ if (*head == NULL)
+ *tail = NULL;
+ ((PNETFLEX_ENTRY)(*entry))->next = NULL;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+#if (DBG || DBGPRINT)
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: _DebugPrint
+//
+// Description:
+// Level sensitive debug print. It is called through
+// a the DebugPrint macro which compares the current
+// DebugLevel to that specified. If the level indicated
+// is less than or equal, the message is displayed.
+//
+// Input:
+// Variable PrintF style Message to display
+//
+// Output:
+// Displays Message on Debug Screen
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+VOID
+_DebugPrint(PCHAR DebugMessage,
+ ...
+ )
+{
+ char buffer[256];
+ va_list ap;
+
+ va_start(ap, DebugMessage);
+ vsprintf(buffer, DebugMessage, ap);
+ DbgPrint(buffer);
+ va_end(ap);
+
+} // end _DebugPrint()
+
+#endif /* DBG */