Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2187 lines
62 KiB

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