/**************************************************************************** * * 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 #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 ***********************************************/