summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/madge/driver/ftk_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ndis/madge/driver/ftk_user.c')
-rw-r--r--private/ntos/ndis/madge/driver/ftk_user.c2187
1 files changed, 2187 insertions, 0 deletions
diff --git a/private/ntos/ndis/madge/driver/ftk_user.c b/private/ntos/ndis/madge/driver/ftk_user.c
new file mode 100644
index 000000000..5a58b90d4
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/ftk_user.c
@@ -0,0 +1,2187 @@
+/****************************************************************************
+*
+* FTK_USER.C
+*
+* FastMAC Plus based NDIS3 miniport driver FTK interface. This module
+* contains all of the routines required to interface with the FastMAC
+* Plus FTK. This is includes the routines traditionally found in transmit.c
+* and receive.c.
+*
+* Copyright (c) Madge Networks Ltd 1994
+*
+* COMPANY CONFIDENTIAL
+*
+* Created: PBA 21/06/1994
+*
+****************************************************************************/
+
+#include <ndis.h>
+
+#include "ftk_defs.h"
+#include "ftk_extr.h"
+#include "ftk_intr.h"
+
+#include "mdgmport.upd"
+#include "ndismod.h"
+
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL VARIABLES
+|
+---------------------------------------------------------------------------*/
+
+//
+// To cut down on accesses to the slot structures on the card we keep
+// a host cache of various detaisl we need.
+//
+
+typedef struct
+{
+ DWORD PhysicalAddress;
+ PVOID VirtualAddress;
+}
+RX_SLOT_CACHE, *PRX_SLOT_CACHE;
+
+
+typedef struct
+{
+ ULONG BufferSize;
+ ULONG SharedMemoryAllocation;
+ PVOID SharedMemoryVirtAddr;
+ DWORD SharedMemoryPhysAddr;
+
+ RX_SLOT_CACHE rx_slot_cache[FMPLUS_MAX_RX_SLOTS];
+
+ UINT active_rx_slot; /* Used to count through the slot array */
+}
+RX_SLOT_MGMNT, *PRX_SLOT_MGMNT;
+
+
+typedef struct
+{
+ DWORD PhysicalAddress;
+ PVOID VirtualAddress;
+}
+TX_SLOT_CACHE, *PTX_SLOT_CACHE;
+
+
+typedef struct
+{
+ ULONG BufferSize;
+ ULONG SharedMemoryAllocation;
+ PVOID SharedMemoryVirtAddr;
+ DWORD SharedMemoryPhysAddr;
+
+ TX_SLOT_CACHE tx_slot_cache[FMPLUS_MAX_TX_SLOTS];
+
+ UINT active_tx_slot;
+ UINT first_tx_in_use;
+ UINT number_tx_in_use;
+}
+TX_SLOT_MGMNT, *PTX_SLOT_MGMNT;
+
+
+#define FRAME_TYPE_MASK ((BYTE) 0xC0) // What is ANDed with FC byte.
+#define FRAME_TYPE_MAC ((BYTE) 0x00) // What's left for a MAC frame.
+
+
+typedef struct
+{
+ ADAPTER_HANDLE adapter_handle;
+ ADAPTER * adapter;
+ TX_SLOT * tx_slot_ptr;
+ RX_SLOT * rx_slot_ptr;
+ UINT frame_length;
+ UINT result1;
+ UINT result2;
+}
+MPSAFE_INFO;
+
+
+#if 0
+
+typedef struct
+{
+ ADAPTER_HANDLE handle;
+ WORD location;
+ WORD result;
+}
+RDIO;
+
+WORD
+_madge_rdio(
+ void * ptr
+ )
+{
+ RDIO * rdio;
+
+ rdio = (RDIO *) ptr;
+
+ sys_outsw(
+ rdio->handle,
+ adapter_record[rdio->handle]->sif_adr,
+ rdio->location
+ );
+
+ rdio->result = sys_insw(
+ rdio->handle,
+ adapter_record[rdio->handle]->sif_dat
+ );
+
+ return 0;
+}
+
+
+WORD
+madge_rdio(
+ ADAPTER_HANDLE adapter_handle,
+ WORD dio_location
+ )
+{
+ RDIO rdio;
+
+ rdio.handle = adapter_handle;
+ rdio.location = dio_location;
+
+ sys_sync_with_interrupt(
+ adapter_handle,
+ _madge_rdio,
+ (void *) &rdio
+ );
+
+ return rdio.result;
+}
+
+
+void
+madge_dump_fmplus_info(
+ ADAPTER_HANDLE adapter_handle
+ )
+{
+ ADAPTER * adapter;
+ PRX_SLOT_MGMNT rx_slot_mgmnt;
+ PTX_SLOT_MGMNT tx_slot_mgmnt;
+ PMADGE_ADAPTER ndisAdap;
+ RX_SLOT * * rx_slot_array;
+ TX_SLOT * * tx_slot_array;
+ UINT active_rx_slot;
+ UINT active_tx_slot;
+ UINT first_tx_slot;
+ UINT rx_slots;
+ UINT tx_slots;
+ UINT i;
+
+ adapter = adapter_record[adapter_handle];
+
+ rx_slot_array = adapter->rx_slot_array;
+ rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
+ active_rx_slot = rx_slot_mgmnt->active_rx_slot;
+ rx_slots = adapter->init_block->fastmac_parms.rx_slots;
+
+ tx_slot_array = adapter->tx_slot_array;
+ tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
+ active_tx_slot = tx_slot_mgmnt->active_tx_slot;
+ first_tx_slot = tx_slot_mgmnt->first_tx_in_use;
+ tx_slots = adapter->init_block->fastmac_parms.tx_slots;
+
+ DbgPrint("----------------------------------------------------------\n");
+
+ DbgPrint(
+ "SIFADR high word = %04x\n\n",
+ sys_insw(adapter_handle, adapter->sif_adx)
+ );
+
+ DbgPrint("RX SLOTS:\n\n");
+ DbgPrint("Active slot = %d\n", active_rx_slot);
+
+ DbgPrint(" Len Res Buffer Stat Next\n");
+ DbgPrint(" ---- ---- --------- ---- ----\n");
+
+ for (i = 0; i < rx_slots; i++)
+ {
+ DbgPrint(
+ "%04x: %04x %04x %04x %04x %04x %04x\n",
+ (WORD) (card_t) rx_slot_array[i],
+ madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->buffer_len),
+ madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->reserved),
+ madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->buffer_hiw),
+ madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->buffer_low),
+ madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->rx_status),
+ madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->next_slot)
+ );
+ }
+
+ DbgPrint("\n");
+
+ DbgPrint("TX SLOTS:\n\n");
+ DbgPrint("Active slot = %d\n", active_tx_slot);
+ DbgPrint("First used slot = %d\n", first_tx_slot);
+
+ DbgPrint(" Stat SLen LLen Res1 Res2 Sbuffer Next LBuffer\n");
+ DbgPrint(" ---- ---- ---- ---- ---- --------- ---- ---------\n");
+
+ for (i = 0; i < tx_slots; i++)
+ {
+ DbgPrint(
+ "%04x: %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n",
+ (WORD) (card_t) tx_slot_array[i],
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->tx_status),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->small_buffer_len),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->large_buffer_len),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->reserved[0]),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->reserved[1]),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->small_buffer_hiw),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->small_buffer_low),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->next_slot),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->large_buffer_hiw),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->large_buffer_low)
+ );
+ }
+
+ DbgPrint("\n");
+
+ DbgPrint("DIO LOCATION 0x0CE0\n\n");
+
+ for (i = 0; i < 32; i++)
+ {
+ DbgPrint(" %04x", madge_rdio(adapter_handle, (WORD) (0x0ce0 + i * 2)));
+ if (i == 15)
+ {
+ DbgPrint("\n");
+ }
+ }
+
+ DbgPrint("\n");
+}
+
+#endif
+
+/***************************************************************************
+*
+* Function - rxtx_allocate_rx_buffers
+*
+* Parameters - adapter -> Pointer to an FTK adapter structure.
+* max_frame_size -> Maximum frame size.
+* number_of_slots -> Number of receive slots.
+*
+* Purpose - Allocate buffer space for the receive slots.
+*
+* Returns - TRUE if it succeeds or FALSE otherwise.
+*
+****************************************************************************/
+
+WBOOLEAN
+rxtx_allocate_rx_buffers(
+ ADAPTER * adapter,
+ WORD max_frame_size,
+ WORD number_of_slots
+ );
+
+#pragma FTK_INIT_FUNCTION(rxtx_allocate_rx_buffers)
+
+WBOOLEAN
+rxtx_allocate_rx_buffers(
+ ADAPTER * adapter,
+ WORD max_frame_size,
+ WORD number_of_slots
+ )
+{
+ PRX_SLOT_MGMNT rx_slot_mgmnt;
+ NDIS_STATUS status;
+ ADAPTER_HANDLE adapter_handle;
+ PMADGE_ADAPTER ndisAdap;
+ DWORD SharedMemVirtAddr;
+ DWORD SharedMemPhysAddr;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
+
+ //
+ // Only want to allocate the receive buffers and slot management once
+ // per adapter.
+ //
+
+ if (rx_slot_mgmnt == NULL)
+ {
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter_handle = adapter->adapter_handle;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ //
+ // Allocate the slot management structure.
+ //
+
+ MADGE_ALLOC_MEMORY(
+ &status,
+ &adapter->rx_slot_mgmnt,
+ sizeof(RX_SLOT_MGMNT)
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ MADGE_ZERO_MEMORY(adapter->rx_slot_mgmnt, sizeof(RX_SLOT_MGMNT));
+
+ rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
+
+ //
+ // Work out how big the buffer should be. Remember to add
+ // four to the buffer allocation for the CRC. The addition
+ // of 32 provides a little space between receive buffers
+ // for those naughty transport protocols that read more
+ // then the indicated lookahead.
+ //
+
+ rx_slot_mgmnt->BufferSize = (max_frame_size + 4 + 32 + 3) & ~3;
+
+ rx_slot_mgmnt->SharedMemoryAllocation =
+ rx_slot_mgmnt->BufferSize * number_of_slots;
+
+ //
+ // Allocate the buffer.
+ //
+
+ if (!sys_alloc_dma_phys_buffer(
+ adapter_handle,
+ rx_slot_mgmnt->SharedMemoryAllocation,
+ &SharedMemPhysAddr,
+ &SharedMemVirtAddr
+ ))
+ {
+ return FALSE;
+ }
+
+ rx_slot_mgmnt->SharedMemoryVirtAddr = (VOID *) SharedMemVirtAddr;
+ rx_slot_mgmnt->SharedMemoryPhysAddr = SharedMemPhysAddr;
+ }
+
+ return TRUE;
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_setup_rx_buffers
+*
+* Parameters - adapter -> Pointer to an FTK adapter structure.
+* physical_addresses -> Use physical addresses?
+* number_of_slots -> Number of receive slots.
+*
+* Purpose - Set up the adapter receive slots.
+*
+* Returns - TRUE if it succeeds or FALSE otherwise.
+*
+****************************************************************************/
+
+void
+rxtx_setup_rx_buffers(
+ ADAPTER * adapter,
+ WBOOLEAN physical_addresses,
+ WORD number_of_slots
+ );
+
+#pragma FTK_INIT_FUNCTION(rxtx_setup_rx_buffers)
+
+void
+rxtx_setup_rx_buffers(
+ ADAPTER * adapter,
+ WBOOLEAN physical_addresses,
+ WORD number_of_slots
+ )
+{
+ PRX_SLOT_MGMNT rx_slot_mgmnt;
+ NDIS_STATUS status;
+ ADAPTER_HANDLE adapter_handle;
+ PMADGE_ADAPTER ndisAdap;
+ PVOID SharedMemVirtAddr;
+ DWORD SharedMemPhysAddr;
+ PRX_SLOT_CACHE rx_slot_cache;
+ RX_SLOT * * rx_slot_array;
+ DWORD phys_addr;
+ WORD slot_index;
+ WORD sifadr;
+ WORD sifdat;
+ WORD sifdatinc;
+ UINT buffer_size;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter_handle = adapter->adapter_handle;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ rx_slot_array = adapter->rx_slot_array;
+ rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
+ rx_slot_cache = rx_slot_mgmnt->rx_slot_cache;
+ SharedMemVirtAddr = rx_slot_mgmnt->SharedMemoryVirtAddr;
+ SharedMemPhysAddr = rx_slot_mgmnt->SharedMemoryPhysAddr;
+ buffer_size = rx_slot_mgmnt->BufferSize;
+
+ sifadr = adapter->sif_adr;
+ sifdat = adapter->sif_dat;
+ sifdatinc = adapter->sif_datinc;
+
+ MadgePrint2("rxtx_setup_rx_buffers number_of_slots = %d\n", number_of_slots);
+ MadgePrint2("rxtx_setup_rx_buffers buffer_size = %d\n", buffer_size);
+
+ //
+ // Work out the physical and virtual address of each buffer.
+ //
+
+ for (slot_index = 0; slot_index < number_of_slots; slot_index++)
+ {
+ rx_slot_cache[slot_index].VirtualAddress = SharedMemVirtAddr;
+ (PUCHAR) SharedMemVirtAddr += buffer_size;
+
+ rx_slot_cache[slot_index].PhysicalAddress = SharedMemPhysAddr;
+ SharedMemPhysAddr += buffer_size;
+
+ phys_addr = (physical_addresses)
+ ? (DWORD) rx_slot_cache[slot_index].PhysicalAddress
+ : (DWORD) rx_slot_cache[slot_index].VirtualAddress;
+
+ //
+ // Write the buffer locations into the slots.
+ //
+
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &rx_slot_array[slot_index]->buffer_hiw
+ );
+
+ sys_outsw(
+ adapter_handle,
+ sifdatinc,
+ (WORD) (phys_addr >> 16)
+ );
+
+ sys_outsw(
+ adapter_handle,
+ sifdat,
+ (WORD) (phys_addr & 0x0FFFF)
+ );
+ }
+
+ ndisAdap->RxTxBufferState |= MADGE_RX_INITIALIZED;
+ rx_slot_mgmnt->active_rx_slot = 0;
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_free_rx_buffers
+*
+* Parameters - adapter -> Pointer to an FTK adapter structure.
+* max_frame_size -> Maximum frame size.
+* number_of_slots -> Number of receive slots.
+*
+* Purpose - Free the previously allocated receive buffers.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+void
+rxtx_free_rx_buffers(
+ ADAPTER * adapter,
+ WORD max_frame_size,
+ WORD number_of_slots
+ )
+{
+ ADAPTER_HANDLE adapter_handle;
+ PMADGE_ADAPTER ndisAdap;
+ PRX_SLOT_MGMNT rx_slot_mgmnt;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter_handle = adapter->adapter_handle;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
+
+ //
+ // If the slot management structure exists them free it
+ // and the buffers.
+ //
+
+ if (rx_slot_mgmnt != NULL)
+ {
+ if (rx_slot_mgmnt->SharedMemoryVirtAddr != NULL)
+ {
+ sys_free_dma_phys_buffer(
+ adapter_handle,
+ rx_slot_mgmnt->SharedMemoryAllocation,
+ (DWORD) rx_slot_mgmnt->SharedMemoryPhysAddr,
+ (DWORD) rx_slot_mgmnt->SharedMemoryVirtAddr
+ );
+ }
+
+ MADGE_FREE_MEMORY(adapter->rx_slot_mgmnt, sizeof(RX_SLOT_MGMNT));
+
+ adapter->rx_slot_mgmnt = NULL;
+
+ ndisAdap->RxTxBufferState &= ~MADGE_RX_INITIALIZED;
+ }
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_allocate_tx_buffers
+*
+* Parameters - adapter -> Pointer to an FTK adapter structure.
+* max_frame_size -> Maximum frame size.
+* number_of_slots -> Number of transmit slots.
+*
+* Purpose - Allocate buffer space for the transmit slots.
+*
+* Returns - TRUE if it succeeds or FALSE otherwise.
+*
+****************************************************************************/
+
+WBOOLEAN
+rxtx_allocate_tx_buffers(
+ ADAPTER * adapter,
+ WORD max_frame_size,
+ WORD number_of_slots
+ );
+
+#pragma FTK_INIT_FUNCTION(rxtx_allocate_tx_buffers)
+
+WBOOLEAN
+rxtx_allocate_tx_buffers(
+ ADAPTER * adapter,
+ WORD max_frame_size,
+ WORD number_of_slots
+ )
+{
+ PTX_SLOT_MGMNT tx_slot_mgmnt;
+ NDIS_STATUS status;
+ ADAPTER_HANDLE adapter_handle;
+ PMADGE_ADAPTER ndisAdap;
+ DWORD SharedMemVirtAddr;
+ DWORD SharedMemPhysAddr;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
+
+ //
+ // Only want to allocate the receive buffers and slot management once
+ // per adapter.
+ //
+
+ if (tx_slot_mgmnt == NULL)
+ {
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter_handle = adapter->adapter_handle;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ //
+ // Allocate the slot management structure.
+ //
+
+ MADGE_ALLOC_MEMORY(
+ &status,
+ &adapter->tx_slot_mgmnt,
+ sizeof(TX_SLOT_MGMNT)
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ MADGE_ZERO_MEMORY(adapter->tx_slot_mgmnt, sizeof(TX_SLOT_MGMNT));
+
+ tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
+
+ //
+ // Work out how big the buffer should be.
+ //
+
+ tx_slot_mgmnt->BufferSize = (max_frame_size + 3) & ~3;
+
+ tx_slot_mgmnt->SharedMemoryAllocation =
+ tx_slot_mgmnt->BufferSize * number_of_slots;
+
+ //
+ // Allocate the buffer.
+ //
+
+ if (!sys_alloc_dma_phys_buffer(
+ adapter_handle,
+ tx_slot_mgmnt->SharedMemoryAllocation,
+ &SharedMemPhysAddr,
+ &SharedMemVirtAddr
+ ))
+ {
+ return FALSE;
+ }
+
+ tx_slot_mgmnt->SharedMemoryVirtAddr = (VOID *) SharedMemVirtAddr;
+ tx_slot_mgmnt->SharedMemoryPhysAddr = SharedMemPhysAddr;
+ }
+
+ return TRUE;
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_setup_tx_buffers
+*
+* Parameters - adapter -> Pointer to an FTK adapter structure.
+* physical_addresses -> Use physical addresses?
+* number_of_slots -> Number of transmit slots.
+*
+* Purpose - Set up the adapter transmit slots.
+*
+* Returns - TRUE if it succeeds or FALSE otherwise.
+*
+****************************************************************************/
+
+void
+rxtx_setup_tx_buffers(
+ ADAPTER * adapter,
+ WBOOLEAN physical_addresses,
+ WORD number_of_slots
+ );
+
+#pragma FTK_INIT_FUNCTION(rxtx_setup_tx_buffers)
+
+void
+rxtx_setup_tx_buffers(
+ ADAPTER * adapter,
+ WBOOLEAN physical_addresses,
+ WORD number_of_slots
+ )
+{
+ PTX_SLOT_MGMNT tx_slot_mgmnt;
+ NDIS_STATUS status;
+ ADAPTER_HANDLE adapter_handle;
+ PMADGE_ADAPTER ndisAdap;
+ PVOID SharedMemVirtAddr;
+ DWORD SharedMemPhysAddr;
+ PTX_SLOT_CACHE tx_slot_cache;
+ TX_SLOT * * tx_slot_array;
+ DWORD phys_addr;
+ WORD slot_index;
+ WORD sifadr;
+ WORD sifdat;
+ WORD sifdatinc;
+ UINT buffer_size;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter_handle = adapter->adapter_handle;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ tx_slot_array = adapter->tx_slot_array;
+ tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
+ tx_slot_cache = tx_slot_mgmnt->tx_slot_cache;
+ SharedMemVirtAddr = tx_slot_mgmnt->SharedMemoryVirtAddr;
+ SharedMemPhysAddr = tx_slot_mgmnt->SharedMemoryPhysAddr;
+ buffer_size = tx_slot_mgmnt->BufferSize;
+
+ sifadr = adapter->sif_adr;
+ sifdat = adapter->sif_dat;
+ sifdatinc = adapter->sif_datinc;
+
+ MadgePrint2("rxtx_setup_tx_buffers number_of_slots = %d\n", number_of_slots);
+ MadgePrint2("rxtx_setup_tx_buffers buffer_size = %d\n", buffer_size);
+
+ //
+ // Work out the physical and virtual address of each buffer.
+ //
+
+ for (slot_index = 0; slot_index < number_of_slots; slot_index++)
+ {
+ tx_slot_cache[slot_index].VirtualAddress = SharedMemVirtAddr;
+ (PUCHAR) SharedMemVirtAddr += buffer_size;
+
+ tx_slot_cache[slot_index].PhysicalAddress = SharedMemPhysAddr;
+ SharedMemPhysAddr += buffer_size;
+
+ phys_addr = (physical_addresses)
+ ? (DWORD) tx_slot_cache[slot_index].PhysicalAddress
+ : (DWORD) tx_slot_cache[slot_index].VirtualAddress;
+
+ //
+ // Write the buffer locations into the slots.
+ //
+
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &tx_slot_array[slot_index]->large_buffer_hiw
+ );
+
+ sys_outsw(
+ adapter_handle,
+ sifdatinc,
+ (WORD) (phys_addr >> 16)
+ );
+
+ sys_outsw(
+ adapter_handle,
+ sifdat,
+ (WORD) (phys_addr & 0x0FFFF)
+ );
+ }
+
+ ndisAdap->RxTxBufferState |= MADGE_TX_INITIALIZED;
+ tx_slot_mgmnt->active_tx_slot = 0;
+ tx_slot_mgmnt->first_tx_in_use = 0;
+ tx_slot_mgmnt->number_tx_in_use = 0;
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_free_tx_buffers
+*
+* Parameters - adapter -> Pointer to an FTK adapter structure.
+* max_frame_size -> Maximum frame size.
+* number_of_slots -> Number of transmit slots.
+*
+* Purpose - Free the previously allocated transmit buffers.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+void
+rxtx_free_tx_buffers(
+ ADAPTER * adapter,
+ WORD max_frame_size,
+ WORD number_of_slots
+ )
+{
+ ADAPTER_HANDLE adapter_handle;
+ PMADGE_ADAPTER ndisAdap;
+ PTX_SLOT_MGMNT tx_slot_mgmnt;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter_handle = adapter->adapter_handle;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
+
+ //
+ // If the slot management structure exists them free it
+ // and the buffers.
+ //
+
+ if (tx_slot_mgmnt != NULL)
+ {
+ if (tx_slot_mgmnt->SharedMemoryVirtAddr != NULL)
+ {
+ sys_free_dma_phys_buffer(
+ adapter_handle,
+ tx_slot_mgmnt->SharedMemoryAllocation,
+ (DWORD) tx_slot_mgmnt->SharedMemoryPhysAddr,
+ (DWORD) tx_slot_mgmnt->SharedMemoryVirtAddr
+ );
+ }
+
+ MADGE_FREE_MEMORY(adapter->tx_slot_mgmnt, sizeof(TX_SLOT_MGMNT));
+
+ adapter->tx_slot_mgmnt = NULL;
+
+ ndisAdap->RxTxBufferState &= ~MADGE_TX_INITIALIZED;
+ }
+}
+
+
+/*--------------------------------------------------------------------------
+|
+| Function - MPSafeReadTxStatus
+|
+| Paramters - ptr -> Pointer to an MPSAFE_INFO structure.
+|
+| Purpose - Reads the transmit status from the next slot to use. This
+| function is called via NdisSynchronizeWithInterrupt when
+| in PIO mode so that we don't get SIF register contention
+| on a multiprocessor.
+|
+| Returns - Nothing.
+|
+--------------------------------------------------------------------------*/
+
+STATIC BOOLEAN
+MPSafeReadTxStatus(PVOID ptr)
+{
+ MPSAFE_INFO * info = (MPSAFE_INFO *) ptr;
+
+ //
+ // Read the transmit status from the slot.
+ //
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_adr,
+ (WORD) (card_t) &(info->tx_slot_ptr)->tx_status
+ );
+
+ info->result1 = sys_insw(
+ info->adapter_handle,
+ info->adapter->sif_dat
+ );
+
+ return FALSE;
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_irq_tx_completion_check
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* adapter -> Pointer to FTK adapter structure.
+*
+* Purpose - Complete any outstanding transmits.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+void
+rxtx_irq_tx_completion_check(
+ ADAPTER_HANDLE adapter_handle,
+ ADAPTER * adapter
+ )
+{
+ UINT tx_slots;
+ PTX_SLOT_MGMNT tx_slot_mgmnt;
+ PTX_SLOT_CACHE tx_slot_cache;
+ TX_SLOT * * tx_slot_array;
+ PMADGE_ADAPTER ndisAdap;
+ UINT tx_status;
+ MPSAFE_INFO info;
+ WORD sifadr;
+ WORD sifdat;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
+ tx_slot_cache = tx_slot_mgmnt->tx_slot_cache;
+ tx_slot_array = adapter->tx_slot_array;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ tx_slots = adapter->init_block->fastmac_parms.tx_slots;
+ sifadr = adapter->sif_adr;
+ sifdat = adapter->sif_dat;
+
+ //
+ // If we're doing multiprocessor safe PIO then we need to set up
+ // the info structure.
+ //
+
+ if (ndisAdap->UseMPSafePIO)
+ {
+ info.adapter_handle = adapter_handle;
+ info.adapter = adapter;
+ }
+
+ //
+ // Iterate around the transmit slots that are are marked as in use
+ // checking if they are now free. Note: we must work with the
+ // global coopies of the first_tx_in_use and number_tx_in_use
+ // in case rxtx_transmit_frame is called during our up-call
+ // to the wrapper.
+ //
+
+ while (tx_slot_mgmnt->number_tx_in_use > 0)
+ {
+ //
+ // Read the transmit status from the slot. If we're doing
+ // multiprocessor safe PIO we must do the DIO via an ISR
+ // synchronized function.
+ //
+
+ if (ndisAdap->UseMPSafePIO)
+ {
+ info.tx_slot_ptr = tx_slot_array[tx_slot_mgmnt->first_tx_in_use];
+
+ NdisMSynchronizeWithInterrupt(
+ &ndisAdap->Interrupt,
+ MPSafeReadTxStatus,
+ &info
+ );
+
+ tx_status = info.result1;
+ }
+ else
+ {
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &tx_slot_array[
+ tx_slot_mgmnt->first_tx_in_use
+ ]->tx_status
+ );
+
+ tx_status = sys_insw(
+ adapter_handle,
+ sifdat
+ );
+ }
+
+ //
+ // If the slot is still in use then we must give up. This will
+ // also work if a PCMCIA adapter has been removed because
+ // tx_status will have been read as 0xffff.
+ //
+
+ if (tx_status >= 0x8000 || tx_status == 0)
+ {
+ break;
+ }
+
+ //
+ // Update the appropriate counters from the frame transmit
+ // status.
+ //
+
+ if ((tx_status & TX_RECEIVE_STATUS_MASK) == TX_RECEIVE_LOST_FRAME)
+ {
+ ndisAdap->LostFrames++;
+ }
+ else if ((tx_status & GOOD_TX_FRAME_MASK) != GOOD_TX_FRAME_VALUE)
+ {
+ ndisAdap->FrameTransmitErrors++;
+ }
+
+ //
+ // Update the slot usage.
+ //
+
+ tx_slot_mgmnt->number_tx_in_use--;
+
+ if (++tx_slot_mgmnt->first_tx_in_use == tx_slots)
+ {
+ tx_slot_mgmnt->first_tx_in_use = 0;
+ }
+
+ //
+ // Tell the wrapper that there is a free slot.
+ //
+
+ NdisMSendResourcesAvailable(ndisAdap->UsedInISR.MiniportHandle);
+ }
+
+ //
+ // If there are any frames we have queued for transmit that
+ // have not been completed then arm the timer so we are guaranteed
+ // to be called again. Under normal operation our DPR gets called
+ // often enough that this function is called frequently enough to
+ // complete all of the frames. However if we have an adapter in a
+ // fast bus (PCI/EISA) with a lot of RAM and we are not
+ // getting any recieve interrupts we can occasionally miss
+ // completing a frame. Hence the timer.
+ //
+
+ if (tx_slot_mgmnt->number_tx_in_use > 0)
+ {
+ NdisMSetTimer(&ndisAdap->CompletionTimer, 20);
+ }
+}
+
+
+/*--------------------------------------------------------------------------
+|
+| Function - MPSafeStartTx
+|
+| Paramters - ptr -> Pointer to an MPSAFE_INFO structure.
+|
+| Purpose - Set up a tx slot and start the transmit going. This
+| function is called via NdisSynchronizeWithInterrupt when
+| in PIO mode so that we don't get SIF register contention
+| on a multiprocessor.
+|
+| Returns - Nothing.
+|
+--------------------------------------------------------------------------*/
+
+STATIC BOOLEAN
+MPSafeStartTx(PVOID ptr)
+{
+ MPSAFE_INFO * info = (MPSAFE_INFO *) ptr;
+
+ //
+ // Reset the transmit status in the transmit slot.
+ //
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_adr,
+ (WORD) (card_t) &(info->tx_slot_ptr)->tx_status
+ );
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_dat,
+ 0x8000
+ );
+
+ //
+ // Write in the length of the buffer into the transmit slot
+ // (large buffer).
+ //
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_adr,
+ (WORD) (card_t) &(info->tx_slot_ptr)->large_buffer_len
+ );
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_dat,
+ (WORD) info->frame_length
+ );
+
+ //
+ // Write the length of the small buffer in the transmit slot to
+ // start the transmit going.
+ //
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_adr,
+ (WORD) (card_t) &(info->tx_slot_ptr)->small_buffer_len
+ );
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_dat,
+ FMPLUS_SBUFF_ZERO_LENGTH
+ );
+
+ return FALSE;
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_transmit_frame
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* tx_frame_identifier -> NDIS packet handle or a pointer
+* to some data to send.
+* tx_frame_length -> Length of the frame.
+* tx_is_packet -> TRUE if tx_frame_identifier is
+* an NDIS packet handle.
+*
+* Purpose - Attempts to transmit a frame by copying it into a transmit
+* buffer and activating a FastMAC Plus tx slot.
+*
+* Returns - DRIVER_TRANSMIT_SUCCESS if it succeeds or
+* DRIVER_TRANSMIT_FAILURE if it does not.
+*
+****************************************************************************/
+
+WORD
+rxtx_transmit_frame(
+ ADAPTER_HANDLE adapter_handle,
+ DWORD tx_frame_identifier,
+ WORD tx_frame_length,
+ WORD tx_is_packet
+ )
+{
+ ADAPTER * adapter;
+ PTX_SLOT_MGMNT tx_slot_mgmnt;
+ PTX_SLOT_CACHE tx_slot_cache;
+ TX_SLOT * tx_slot_ptr;
+ UINT active_tx_slot;
+ UINT tx_slots;
+ PMADGE_ADAPTER ndisAdap;
+ UINT bytes_copied;
+ UINT tx_status;
+ MPSAFE_INFO info;
+ WORD sifadr;
+ WORD sifdat;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter = adapter_record[adapter_handle];
+ tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
+ tx_slot_cache = tx_slot_mgmnt->tx_slot_cache;
+ active_tx_slot = tx_slot_mgmnt->active_tx_slot;
+ tx_slot_ptr = adapter->tx_slot_array[active_tx_slot];
+ tx_slots = adapter->init_block->fastmac_parms.tx_slots;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ sifadr = adapter->sif_adr;
+ sifdat = adapter->sif_dat;
+
+ //
+ // If we are a PCMCIA adapter it is possible that the adapter
+ // may have been removed. To detect this we check if SIFADR
+ // is 0xffff since this should not normally be true.
+ //
+
+ if (adapter->adapter_card_bus_type == ADAPTER_CARD_PCMCIA_BUS_TYPE)
+ {
+ if (sys_insw(adapter_handle, sifadr) == 0xffff)
+ {
+ rxtx_adapter_removed(adapter_handle);
+
+ return DRIVER_TRANSMIT_SUCCEED;
+ }
+ }
+
+ //
+ // If the next slot to be used is still in use then we must
+ // give up.
+ //
+
+ if (tx_slot_mgmnt->number_tx_in_use == tx_slots)
+ {
+
+#ifdef OID_MADGE_MONITOR
+ (ndisAdap->MonitorInfo).FailedToTransmit++;
+#endif
+
+ return DRIVER_TRANSMIT_FAIL;
+ }
+
+ //
+ // Copy the frame into the transmit buffer.
+ //
+
+ if (tx_is_packet)
+ {
+ MadgeCopyFromPacketToBuffer(
+ (PNDIS_PACKET) tx_frame_identifier,
+ 0,
+ tx_frame_length,
+ (PUCHAR) tx_slot_cache[active_tx_slot].VirtualAddress,
+ &bytes_copied
+ );
+ }
+ else
+ {
+ MADGE_MOVE_MEMORY(
+ tx_slot_cache[active_tx_slot].VirtualAddress,
+ (PUCHAR) tx_frame_identifier,
+ tx_frame_length
+ );
+ }
+
+ //
+ // Set up the tx slot and start the transmit. If we're using
+ // multiprocessor safe PIO then we must do the DIO via an ISR
+ // synchronised function.
+ //
+
+ if (ndisAdap->UseMPSafePIO)
+ {
+ info.adapter_handle = adapter_handle;
+ info.adapter = adapter;
+ info.tx_slot_ptr = tx_slot_ptr;
+ info.frame_length = tx_frame_length;
+
+ NdisMSynchronizeWithInterrupt(
+ &ndisAdap->Interrupt,
+ MPSafeStartTx,
+ &info
+ );
+ }
+ else
+ {
+ //
+ // Reset the transmit status in the transmit slot.
+ //
+
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &tx_slot_ptr->tx_status
+ );
+
+ sys_outsw(
+ adapter_handle,
+ sifdat,
+ (WORD) 0x8000
+ );
+
+ //
+ // Write in the length of the buffer into the transmit slot
+ // (large buffer).
+ //
+
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &tx_slot_ptr->large_buffer_len
+ );
+
+ sys_outsw(
+ adapter_handle,
+ sifdat,
+ (WORD) tx_frame_length
+ );
+
+ //
+ // Write the length of the small buffer in the transmit slot to
+ // start the transmit going.
+ //
+
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &tx_slot_ptr->small_buffer_len
+ );
+
+ sys_outsw(
+ adapter_handle,
+ sifdat,
+ FMPLUS_SBUFF_ZERO_LENGTH
+ );
+ }
+
+ //
+ // Note that the slot is in use.
+ //
+
+ tx_slot_mgmnt->number_tx_in_use++;
+
+ //
+ // Update the slot counter ready for the next transmit.
+ //
+
+ if (++tx_slot_mgmnt->active_tx_slot == tx_slots)
+ {
+ tx_slot_mgmnt->active_tx_slot = 0;
+ }
+
+ return DRIVER_TRANSMIT_SUCCEED;
+}
+
+
+/*--------------------------------------------------------------------------
+|
+| Function - ProcessTestAndXIDFrames
+|
+| Paramters - adapHnd -> An FTK adapter handle.
+| framePtr -> Pointer to the start of the frame.
+| frameLen -> The length of the frame.
+| headerLen -> The length of the frame header.
+|
+| Purpose - Process LLC Test and XID frames in the same way as IBM
+| adapter hardware.
+|
+| Returns - TRUE if the frame was processed or FALSE if not.
+|
+|-------------------------------------------------------------------------*/
+
+STATIC BOOLEAN
+ProcessTestAndXIDFrames(
+ ADAPTER_HANDLE adapHnd,
+ UCHAR *framePtr,
+ UINT frameLen,
+ UINT headerLen
+ )
+{
+ UINT llcCmd;
+ UINT sSAP;
+ NODE_ADDRESS tempNodeAddr;
+ BOOLEAN doneFrame;
+
+ doneFrame = FALSE;
+
+ //
+ // We are only interested in frames that are LLC (i.e. frame
+ // control byte is 0x40), have a null destination SAP and are
+ // commands (i.e. 0x01 bit of the source SAP is clear).
+ //
+
+ sSAP = framePtr[headerLen + 1];
+
+ if (framePtr[1] == 0x40 &&
+ framePtr[headerLen] == 0x00 &&
+ (sSAP & 0x01) == 0x00)
+ {
+ llcCmd = framePtr[headerLen + 2] & 0xef;
+
+ //
+ // Test frames have an LLC command byte of 0b111x0011.
+ //
+
+ if (llcCmd == 0xe3)
+ {
+ MadgePrint1("Got TEST frame\n");
+
+ //
+ // We don't need to do anything to a test frame
+ // other than send it back.
+ //
+
+ doneFrame = TRUE;
+ }
+
+ //
+ // XID frames have an LLC command byte of 0b101x1111 and
+ // a standard IEEE defined XID frame will have 3 data
+ // bytes and its first data byte set to 0x81.
+ //
+
+ else if (llcCmd == 0xaf &&
+ frameLen == headerLen + 6 &&
+ framePtr[headerLen + 3] == 0x81)
+ {
+ MadgePrint1("Got XID frame\n");
+
+ //
+ // Fill in the XID frame data with 0x81 0x01 0x00
+ // (Standard XID frame, type 1 only and 0 sized
+ // receive window).
+ //
+
+ framePtr[headerLen + 4] = 0x01;
+ framePtr[headerLen + 5] = 0x00;
+
+ doneFrame = TRUE;
+ }
+
+ //
+ // If we've had a TEST or a XID frame then doneFrame will
+ // be TRUE and we should send a frame back.
+ //
+
+ if (doneFrame)
+ {
+ //
+ // Flip the direction bit in the source routing
+ // control word and switch the source routing flag
+ // from the source to destination address.
+ //
+
+ if ((framePtr[8] & 0x80) != 0)
+ {
+ framePtr[14] &= 0x1f; // Clear broadcast bits.
+ framePtr[15] ^= 0x80; // Flip direction bit.
+ framePtr[8] &= 0x7f; // Clear source routing bit.
+ framePtr[2] |= 0x80; // Set source routing bit.
+ }
+
+ //
+ // Swap the node addresses around.
+ //
+
+ tempNodeAddr = *((NODE_ADDRESS *) &framePtr[2]);
+ *((NODE_ADDRESS *) &framePtr[2]) = *((NODE_ADDRESS *) &framePtr[8]);
+ *((NODE_ADDRESS *) &framePtr[8]) = tempNodeAddr;
+
+ //
+ // Swap the SAPs around and set the response bit in the
+ // new source SAP.
+ //
+
+ framePtr[headerLen + 1] = 0x01;
+ framePtr[headerLen] = sSAP;
+ framePtr[0] = 0x10;
+
+ //
+ // And now send the frame.
+ //
+
+ rxtx_transmit_frame(
+ adapHnd,
+ (DWORD) framePtr,
+ (WORD) frameLen,
+ FALSE
+ );
+ }
+ }
+
+ return doneFrame;
+}
+
+
+/*--------------------------------------------------------------------------
+|
+| Function - MPSafeReadRxStatus
+|
+| Paramters - ptr -> Pointer to an MPSAFE_INFO structure.
+|
+| Purpose - Read the status and length of the current rx slot. This
+| function is called via NdisSynchronizeWithInterrupt when
+| in PIO mode so that we don't get SIF register contention
+| on a multiprocessor.
+|
+| Returns - Nothing.
+|
+--------------------------------------------------------------------------*/
+
+STATIC BOOLEAN
+MPSafeReadRxStatus(PVOID ptr)
+{
+ MPSAFE_INFO * info = (MPSAFE_INFO *) ptr;
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_adr,
+ (WORD) (card_t) &(info->rx_slot_ptr)->buffer_len
+ );
+
+ info->result1 = sys_insw(
+ info->adapter_handle,
+ info->adapter->sif_dat
+ );
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_adr,
+ (WORD) (card_t) &(info->rx_slot_ptr)->rx_status
+ );
+
+ info->result2 = sys_insw(
+ info->adapter_handle,
+ info->adapter->sif_dat
+ );
+
+ return FALSE;
+}
+
+/*--------------------------------------------------------------------------
+|
+| Function - MPSafeFreeRxSlot
+|
+| Paramters - ptr -> Pointer to an MPSAFE_INFO structure.
+|
+| Purpose - Free an rx slot. This
+| function is called via NdisSynchronizeWithInterrupt when
+| in PIO mode so that we don't get SIF register contention
+| on a multiprocessor.
+|
+| Returns - Nothing.
+|
+--------------------------------------------------------------------------*/
+
+STATIC BOOLEAN
+MPSafeFreeRxSlot(PVOID ptr)
+{
+ MPSAFE_INFO * info = (MPSAFE_INFO *) ptr;
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_adr,
+ (WORD) (card_t) &(info->rx_slot_ptr)->buffer_len
+ );
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_dat,
+ (WORD) 0x0000
+ );
+
+ return FALSE;
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_irq_rx_frame_handler
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* adapter -> Pointer to an FTK adapter structure.
+*
+* Purpose - Called out of the back or our DPR route via
+* driver_get_outstanding_receive() to process received
+* frames.
+*
+* Note we preserve the value of SIFADR so that the transmit
+* code does not have to worry about it changing under its
+* feet. No we don't because we are called out of a DPR
+* and the wrapper will have grabbed a spin lock so
+* we can't be executing at the same time as the transmit
+* code.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+#define PROM_OR_MAC \
+ (NDIS_PACKET_TYPE_PROMISCUOUS | NDIS_PACKET_TYPE_MAC_FRAME)
+
+void
+rxtx_irq_rx_frame_handler(
+ ADAPTER_HANDLE adapter_handle,
+ ADAPTER * adapter
+ )
+{
+ BYTE * rx_frame_addr;
+ UINT rx_frame_stat;
+ UINT rx_frame_length;
+ UINT slot_count;
+ UINT active_rx_slot;
+ PRX_SLOT_MGMNT rx_slot_mgmnt;
+ PRX_SLOT_CACHE rx_slot_cache;
+ RX_SLOT * * rx_slot_array;
+ RX_SLOT * rx_slot_ptr;
+ UINT rx_slots;
+ PMADGE_ADAPTER ndisAdap;
+ UINT packet_filter;
+ UINT header_len;
+ BOOLEAN done_frame;
+ BOOLEAN ignore_frame;
+ BOOLEAN test_and_xid;
+ MPSAFE_INFO info;
+ WORD sifadr;
+ WORD sifdat;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ rx_slot_array = adapter->rx_slot_array;
+ rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
+ active_rx_slot = rx_slot_mgmnt->active_rx_slot;
+ rx_slot_cache = rx_slot_mgmnt->rx_slot_cache;
+ rx_slots = adapter->init_block->fastmac_parms.rx_slots;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ packet_filter = ndisAdap->CurrentPacketFilter;
+ test_and_xid = ndisAdap->TestAndXIDEnabled;
+ done_frame = FALSE;
+ sifadr = adapter->sif_adr;
+ sifdat = adapter->sif_dat;
+
+ //
+ // If we're doing multiprocessor safe PIO then we need to set up
+ // the info structure.
+ //
+
+ if (ndisAdap->UseMPSafePIO)
+ {
+ info.adapter_handle = adapter_handle;
+ info.adapter = adapter;
+ }
+
+ //
+ // Now read the length and status fields of the current receive slot.
+ // If we are doing multiprocessor safe PIO then we must do the DIO via
+ // an ISR synchronised function.
+ //
+
+ rx_slot_ptr = rx_slot_array[active_rx_slot];
+
+ if (ndisAdap->UseMPSafePIO)
+ {
+ info.rx_slot_ptr = rx_slot_ptr;
+
+ NdisMSynchronizeWithInterrupt(
+ &ndisAdap->Interrupt,
+ MPSafeReadRxStatus,
+ &info
+ );
+
+ rx_frame_length = info.result1;
+ rx_frame_stat = info.result2;
+ }
+ else
+ {
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &rx_slot_ptr->buffer_len
+ );
+
+ rx_frame_length = sys_insw(
+ adapter_handle,
+ sifdat
+ );
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &rx_slot_ptr->rx_status
+ );
+
+ rx_frame_stat = sys_insw(
+ adapter_handle,
+ sifdat
+ );
+
+ }
+
+ //
+ // Try to receive as many frames as possible, but only examine as many
+ // slots as we have, otherwise we might end up going round this loop
+ // forever! If we do stop and there is still a frame to be received, we
+ // will be re-interrupted anyway.
+ //
+
+ slot_count = 0;
+
+ while (rx_frame_length != 0 && slot_count++ < rx_slots)
+ {
+ //
+ // It is possible that a PCMCIA adapter may have been removed
+ // in which case we must not wait forever. If an adapter has
+ // been removed we would expect to read 0xffff from any IO
+ // location occupied by the adapter. 0xffff is not a valid
+ // value for an FMP RX status.
+ //
+
+ if (rx_frame_stat == 0xffff)
+ {
+ MadgePrint1("Rx frame: RX status == 0xffff\n");
+ ndisAdap->AdapterRemoved = TRUE;
+ return;
+ }
+
+ //
+ // FastMAC Plus includes the CRC in the frame length.
+ //
+
+ rx_frame_length -= 4;
+
+ if ((rx_frame_stat & GOOD_RX_FRAME_MASK) == 0)
+ {
+ //
+ // We have got a good frame here.
+ //
+
+ rx_frame_addr = rx_slot_cache[active_rx_slot].VirtualAddress;
+
+ header_len = (FRAME_IS_SOURCE_ROUTED(rx_frame_addr))
+ ? FRAME_HEADER_SIZE + FRAME_SOURCE_ROUTING_BYTES(rx_frame_addr)
+ : FRAME_HEADER_SIZE;
+
+ //
+ // Check for a frame copied error.
+ //
+
+ if ((rx_frame_addr[2] & 0x80) && (rx_frame_stat & 0x80))
+ {
+ ndisAdap->FrameCopiedErrors++;
+ }
+
+ //
+ // We may have to behave like the hardware of an IBM adapter
+ // and process LLC TEST and XID frames ourselves.
+ //
+
+ if (test_and_xid)
+ {
+ ignore_frame = ProcessTestAndXIDFrames(
+ adapter_handle,
+ rx_frame_addr,
+ rx_frame_length,
+ header_len
+ );
+ }
+ else
+ {
+ ignore_frame = FALSE;
+ }
+
+ //
+ // If we've got a valid frame then pass it up to the user.
+ //
+
+ if (!ignore_frame &&
+ ((rx_frame_addr[1] & FRAME_TYPE_MASK) != FRAME_TYPE_MAC ||
+ (packet_filter & PROM_OR_MAC) != 0))
+ {
+ //
+ // When indicating the frame, we can pass all of it
+ // as lookahead if we want, but we ought to take
+ // account of the current lookahead setting in case it
+ // is less than the frame size. This becomes important in
+ // WFWG, where it is unable to cope with large lookaheads. The
+ // lookahead length used to be :
+ // (UINT) rx_frame_length - header_len
+ //
+
+ NdisMTrIndicateReceive(
+ ndisAdap->UsedInISR.MiniportHandle,
+ (NDIS_HANDLE) (rx_frame_addr + header_len),
+ (PVOID) rx_frame_addr,
+ (UINT) header_len,
+ (PVOID) (rx_frame_addr + header_len),
+ (UINT) MIN(
+ ndisAdap->CurrentLookahead,
+ (rx_frame_length - header_len)
+ ),
+ (UINT) (rx_frame_length - header_len)
+ );
+
+ //
+ // Note that we've given the upper protocol at
+ // least one frame.
+ //
+
+ done_frame = TRUE;
+
+ ndisAdap->FramesReceived++;
+
+#ifdef OID_MADGE_MONITOR
+ //
+ // Update the appropriate parts of the monitor structure
+ //
+ (ndisAdap->MonitorInfo).ReceiveFrames++;
+ (ndisAdap->MonitorInfo).ReceiveFrameSize[rx_frame_length/128]++;
+ (ndisAdap->MonitorInfo).CurrentFrameSize = rx_frame_length;
+ (ndisAdap->MonitorInfo).ReceiveFlag = 1;
+#endif
+ }
+ }
+
+ //
+ // Otherwise we have some sort of receive error.
+ //
+
+ else
+ {
+ ndisAdap->FrameReceiveErrors++;
+ }
+
+ //
+ // Zero the frame length so that FastMAC Plus can reuse the buffer.
+ // If we're doing multiprocessor safe PIO then we must do the DIO
+ // via an ISR synchronised function.
+ //
+
+ if (ndisAdap->UseMPSafePIO)
+ {
+ info.rx_slot_ptr = rx_slot_ptr;
+
+ NdisMSynchronizeWithInterrupt(
+ &ndisAdap->Interrupt,
+ MPSafeFreeRxSlot,
+ &info
+ );
+ }
+ else
+ {
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &rx_slot_ptr->buffer_len
+ );
+
+ sys_outsw(
+ adapter_handle,
+ sifdat,
+ 0x0000
+ );
+ }
+
+ //
+ // Update the active receive slot pointer.
+ //
+
+ if (++active_rx_slot == rx_slots)
+ {
+ active_rx_slot = 0;
+ }
+
+ rx_slot_mgmnt->active_rx_slot = active_rx_slot;
+
+ //
+ // Now we had better look at the next slot in case another frame
+ // has been received.
+ //
+
+ rx_slot_ptr = rx_slot_array[active_rx_slot];
+
+ if (ndisAdap->UseMPSafePIO)
+ {
+ info.rx_slot_ptr = rx_slot_ptr;
+
+ NdisMSynchronizeWithInterrupt(
+ &ndisAdap->Interrupt,
+ MPSafeReadRxStatus,
+ &info
+ );
+
+ rx_frame_length = info.result1;
+ rx_frame_stat = info.result2;
+ }
+ else
+ {
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &rx_slot_ptr->buffer_len
+ );
+
+ rx_frame_length = sys_insw(
+ adapter_handle,
+ sifdat
+ );
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &rx_slot_ptr->rx_status
+ );
+
+ rx_frame_stat = sys_insw(
+ adapter_handle,
+ sifdat
+ );
+
+ }
+ }
+
+ //
+ // If we've given the upper protocol a frame then call the
+ // receive completion routine.
+ //
+
+ if (done_frame)
+ {
+ NdisMTrIndicateReceiveComplete(ndisAdap->UsedInISR.MiniportHandle);
+ }
+}
+
+
+
+/***************************************************************************
+*
+* Function - rxtx_abort_txing_frames
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+*
+* Purpose - Stop sending frames.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+void
+rxtx_abort_txing_frames(ADAPTER_HANDLE adapter_handle)
+{
+ //
+ // Nothing to do here.
+ //
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_await_empty_tx_slots
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+*
+* Purpose - Wait until all of the tx slots are empty.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+void
+rxtx_await_empty_tx_slots(ADAPTER_HANDLE adapter_handle)
+{
+ ADAPTER * adapter;
+ FASTMAC_INIT_PARMS * fastmac_parms;
+ TX_SLOT * * tx_slot_array;
+ UINT i;
+ UINT status;
+ PMADGE_ADAPTER ndisAdap;
+ MPSAFE_INFO info;
+ WORD sifadr;
+ WORD sifdat;
+
+ if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_ANY_STATE))
+ {
+ MadgePrint1("rxtx_await_empty_tx_slots: adapter not running\n");
+ return;
+ }
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter = adapter_record[adapter_handle];
+ fastmac_parms = &adapter->init_block->fastmac_parms;
+ tx_slot_array = adapter->tx_slot_array;
+ info.adapter_handle = adapter_handle;
+ info.adapter = adapter;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ sifadr = adapter->sif_adr;
+ sifdat = adapter->sif_dat;
+
+ for (i = 0; i < fastmac_parms->tx_slots; i++)
+ {
+ do
+ {
+ //
+ // Get the slot status. If we are doing multiprocessor safe
+ // PIO then we must do this with an ISR synchronised function.
+ //
+
+ if (ndisAdap->UseMPSafePIO)
+ {
+ info.tx_slot_ptr = tx_slot_array[i];
+
+ NdisMSynchronizeWithInterrupt(
+ &ndisAdap->Interrupt,
+ MPSafeReadTxStatus,
+ &info
+ );
+
+ status = info.result1;
+ }
+ else
+ {
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &tx_slot_array[i]->tx_status
+ );
+
+ status = sys_insw(adapter_handle, sifdat);
+ }
+
+ //
+ // It is possible that a PCMCIA adapter may have been removed
+ // in which case we must not wait forever. If an adapter has
+ // been removed we would expect to read 0xffff from any IO
+ // location occupied by the adapter. 0xffff is not a valid
+ // value for an FMP TX status.
+ //
+
+ if (status == 0xffff)
+ {
+ MadgePrint1("Await empty tx: TX status == 0xffff\n");
+ return;
+ }
+ }
+ while (status >= 0x8000 || status == 0);
+ }
+}
+
+
+/***************************************************************************
+*
+* Function - user_completed_srb
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* srb_completed_successfully -> SRB successful?
+*
+* Purpose - Record that an SRB has completed and arrange for our
+* DPR to be scheduled.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+void
+user_completed_srb(
+ ADAPTER_HANDLE adapter_handle,
+ WBOOLEAN srb_completed_successfully
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ //
+ // If we have issued a private SRB then we just clear the
+ // private SRB flag. Otherwise we need to arrange for our
+ // DPR to be told about the SRB.
+ //
+
+ if (ndisAdap->PrivateSrbInProgress)
+ {
+ ndisAdap->PrivateSrbInProgress = FALSE;
+ }
+ else
+ {
+ ndisAdap->UsedInISR.SrbRequestStatus = (BOOLEAN) srb_completed_successfully;
+ ndisAdap->UsedInISR.SrbRequestCompleted = TRUE;
+ ndisAdap->DprRequired = TRUE;
+ }
+}
+
+
+/***************************************************************************
+*
+* Function - user_shedule_receive_process
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+*
+* Purpose - Arrange for our DPR to be scheduled so that we can deal
+* with received frames.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+
+void
+user_schedule_receive_process(ADAPTER_HANDLE adapter_handle)
+{
+ PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle)->DprRequired = TRUE;
+}
+
+
+/***************************************************************************
+*
+* Function - user_adapter_removed
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+*
+* Purpose - Arrange for our DPR to be scheduled so that we can deal
+* with a removed adapter.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+
+void
+user_adapter_removed(ADAPTER_HANDLE adapter_handle)
+{
+ PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle)->DprRequired = TRUE;
+ PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle)->AdapterRemoved = TRUE;
+}
+
+
+/***************************************************************************
+*
+* Function - user_handle_adapter_check
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+*
+* Purpose - Called on an adapter check. Not a lot we can do really!
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+
+void
+user_handle_adapter_check(ADAPTER_HANDLE adapter_handle)
+{
+ MadgePrint1("Adapter Check!!!!\n");
+}
+
+
+//
+// Currently we are not supporting transmit modes that require
+// user completion routine.
+//
+
+#if 0
+
+/***************************************************************************
+*
+* Function - user_transmit_completion
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* identifier -> NDIS packet handle.
+*
+* Purpose - To notify an upper protocol that a transmit has completed.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+
+void
+user_transmit_completion(
+ ADAPTER_HANDLE adapter_handle,
+ DWORD identifier
+ )
+{
+}
+
+#endif
+
+
+/***************************************************************************
+*
+* Function - rxtx_adapter_removed
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+*
+* Purpose - Called to tidy up when we find out that the adapter has
+* been removed. All we do is tell the wrapper that we
+* have finished any submitted transmits.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+void
+rxtx_adapter_removed(
+ ADAPTER_HANDLE adapter_handle
+ )
+{
+ ADAPTER * adapter;
+ PTX_SLOT_MGMNT tx_slot_mgmnt;
+ UINT tx_slots;
+ PMADGE_ADAPTER ndisAdap;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter = adapter_record[adapter_handle];
+ tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
+ tx_slots = adapter->init_block->fastmac_parms.tx_slots;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ //
+ // Note that the adapter has been removed.
+ //
+
+ ndisAdap->AdapterRemoved = TRUE;
+
+ //
+ // Iterate around the transmit slots that are in use and
+ // up call to indicate that the transmits are over.
+ //
+
+ while (tx_slot_mgmnt->number_tx_in_use > 0)
+ {
+ //
+ // Update the slot usage.
+ //
+
+ tx_slot_mgmnt->number_tx_in_use--;
+
+ if (++tx_slot_mgmnt->first_tx_in_use == tx_slots)
+ {
+ tx_slot_mgmnt->first_tx_in_use = 0;
+ }
+
+ //
+ // Tell the wrapper that there is a free slot.
+ //
+
+ NdisMSendResourcesAvailable(ndisAdap->UsedInISR.MiniportHandle);
+ }
+}
+
+
+/******** End of FTK_USER.C ***********************************************/
+