diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/ndis/madge/driver/ftk_user.c | 2187 |
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 ***********************************************/ + |