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.
 
 
 
 
 
 

1656 lines
43 KiB

/****************************************************************************
*
* DRV_INIT.C : Part of the FASTMAC TOOL-KIT (FTK)
*
* THE DRIVER MODULE (INITIALIZE / REMOVE)
*
* Copyright (c) Madge Networks Ltd. 1991-1994
*
* COMPANY CONFIDENTIAL
*
*****************************************************************************
*
* The driver module provides a simple interface to allow the use of
* Fastmac in as general a setting as possible. It handles the downloading
* of the Fastmac code and the initialization of the adapter card. It
* provides simple transmit and receive routines. It is desgined to
* quickly allow the implementation of Fastmac applications. It is not
* designed as the fastest or most memory efficient solution.
*
* The DRV_INIT.C module contains the routines necessary to initialize
* Fastmac and the adapter and remove, ie. terminate usage of, the
* adapter. Upon adapter initialization the user is returned a handle
* which is used to identify the adapter in all future accesses to the
* driver module.
*
****************************************************************************/
/*---------------------------------------------------------------------------
|
| DEFINITIONS
|
---------------------------------------------------------------------------*/
#include "ftk_defs.h"
/*---------------------------------------------------------------------------
|
| MODULE ENTRY POINTS
|
---------------------------------------------------------------------------*/
#include "ftk_intr.h" /* routines internal to FTK */
#include "ftk_extr.h" /* routines provided or used by external FTK user */
/*---------------------------------------------------------------------------
|
| LOCAL FUNCTIONS
|
---------------------------------------------------------------------------*/
local WBOOLEAN
driver_wait_for_adapter_open(
UINT * open_status,
ADAPTER * adapter
);
local WORD
driver_get_max_frame_size(
ADAPTER * adapter,
FASTMAC_INIT_PARMS * fastmac_parms
);
/*---------------------------------------------------------------------------
|
| GLOBAL VARIABLES
|
---------------------------------------------------------------------------*/
export ADAPTER * adapter_record[MAX_NUMBER_OF_ADAPTERS] = {NULL};
#ifndef FTK_NO_PROBE
/****************************************************************************
*
* driver_probe_card
* =================
*
*
* PARAMETERS :
* ============
*
* WORD adapter_card_bus_type
*
* The bus type (card family) the adapters for which to search. e.g.
* ADAPTER_CARD_ATULA_BUS_TYPE or ADAPTER_CARD_EISA_BUS_TYPE.
*
* PROBE * resources
*
* resources is an array structures used to identify and record specific
* information about adapters found.
*
* UINT length
*
* length is the number of structures pointed to by reources.
*
* WORD * valid_locations
*
* valid_locations is an array of IO locations to examine for the presence
* of an adapter. For ATULA based adapters with should be a subset of
* {0x0a20, 0x1a20, 0x2a20, 0x3a20}.
*
* UINT number_locations
*
* This is the number of IO locations in the above list.
*
* BODY :
* ======
*
* The hwi_atula_probe_card routine is called by hwi_probe_adapter. It
* probes the adapter card for information such as DMA channel, IRQ number
* etc. This information can then be supplied by the user when starting the
* adapter.
*
*
* RETURNS :
* =========
*
* The routine returns the number of adapters found, or PROBE_FAILURE
* if there's a problem.
*
****************************************************************************/
#ifdef FTK_INIT_FUNCTION
#pragma FTK_INIT_FUNCTION(driver_probe_adapter)
#endif
export UINT
driver_probe_adapter(
WORD adapter_card_bus_type,
PROBE * resources,
UINT length,
WORD * valid_locations,
UINT number_locations
)
{
return hwi_probe_adapter(
adapter_card_bus_type,
resources,
length,
valid_locations,
number_locations
);
}
/****************************************************************************
*
* driver_deprobe_adapter
* ======================
*
* PARAMETERS :
* ============
*
* PROBE * resources
*
* resources is an array structures used to identify and record specific
* information about adapters found.
*
* UINT length
*
* length is the number of structures pointed to by reources.
*
* BODY :
* ======
*
* This function frees any resources that were claimed by a call to
* driver_probe_adapter. Every valid PROBE structure returned by
* driver_probe_adapter MUST be passed to driver_deprobe adapter otherwise
* resources that were claimed from the operating system by
* driver_probe_adapter (such as PCMCIA sockets) will not be freed.
*
* RETURNS :
* =========
*
* TRUE if everything worked or FALSE if it did not.
*
****************************************************************************/
#ifdef FTK_RES_FUNCTION
#pragma FTK_RES_FUNCTION(driver_deprobe_adapter)
#endif
export WBOOLEAN
driver_deprobe_adapter(
PROBE * resources,
UINT length
)
{
return hwi_deprobe_adapter(
resources,
length
);
}
#endif
/****************************************************************************
*
* driver_prepare_adapter
* ======================
*
*
* PARAMETERS :
* ============
*
* PREPARE_ARGS * arguments
*
* This is a pointer to the arguments structure set up by the user code.
*
* ADAPTER_HANDLE * returned_adapter_handle
*
* An adapter handle is returned that is used for all subsequent calls to
* the driver to identify the particular adapter.
*
* BODY :
* ======
*
* The driver_prepare_adapter routine firstly sets up the adapter structure
* for this adapter. Then it gets memory for the status information
* structure that is filled in by driver_get_status calls. It then
* requests memory for the Fastmac transmit and receive buffers. This memory
* must be static, it must not be swapped out to disk because of DMA issues.
*
* This routine should be called once for every adapter that is to have
* Fastmac used on it.
*
* RETURNS :
* =========
*
* The routine returns TRUE if it succeeds. If this routine fails (returns
* FALSE) then a subsequent call to driver_explain_error with the returned
* adapter handle will give an explanation.
*
****************************************************************************/
#ifdef FTK_INIT_FUNCTION
#pragma FTK_INIT_FUNCTION(driver_prepare_adapter)
#endif
export WBOOLEAN
driver_prepare_adapter(
PREPARE_ARGS * arguments,
ADAPTER_HANDLE * returned_adapter_handle
)
{
ADAPTER_HANDLE adapter_handle;
ADAPTER * adapter;
FASTMAC_INIT_PARMS * fastmac_parms;
WORD i;
/*
* Set up adapter handle which is an index to an array of pointers.
* Find first a pointer not yet used.
*/
for (i = 0; i < MAX_NUMBER_OF_ADAPTERS; i++)
{
if (adapter_record[i] == NULL)
{
break;
}
}
/*
* Set up returned adapter handle ( = index to adapter structure).
* returned_adapter_handle is set up here before any failure.
* This is so can use adapter handle for call to driver_explain_error.
*/
adapter_handle = (ADAPTER_HANDLE) i;
*returned_adapter_handle = adapter_handle;
/*
* If all pointers to adapter structures are used then return error.
* Can not set up error record but see driver_explain_error.
*/
if (i == MAX_NUMBER_OF_ADAPTERS)
{
return FALSE;
}
/*
* Get memory for adapter structure.
*/
adapter_record[adapter_handle] = (ADAPTER *)
sys_alloc_adapter_structure(adapter_handle, sizeof(ADAPTER));
/*
* Check that the memory allocation was successful. Can not set up
* error record but see driver_explain_error.
*/
if (adapter_record[adapter_handle] == NULL)
{
return FALSE;
}
/*
* Remember pointer to adapter structure.
*/
adapter = adapter_record[adapter_handle];
/*
* Zero adapter structure memory.
*/
util_zero_memory((BYTE *) adapter, sizeof(ADAPTER));
/*
* Save handle, so that HWI routines that need it can find it.
*/
adapter->adapter_handle = adapter_handle;
/*
* Save the user's private information for the users sys_ functions.
*/
adapter->user_information = arguments->user_information;
#ifdef FMPLUS
/*
* Allocate memory for the FastMAC Plus to do its DMA tests.
* This is now a byte longer to allocate the byte used
* to handshake the DMA on a PCI(T) card with broken DMA.
*/
if (!sys_alloc_dma_phys_buffer(
adapter_handle,
SCB_TEST_PATTERN_LENGTH + SSB_TEST_PATTERN_LENGTH + 1,
&(adapter->dma_test_buf_phys),
&(adapter->dma_test_buf_virt)))
{
adapter->error_record.type = ERROR_TYPE_DRIVER;
adapter->error_record.value = DRIVER_E_12_FAIL_ALLOC_DMA_BUF;
return FALSE;
}
#endif
/*
* Indicate no errors have occured for this adapter yet.
*/
adapter->error_record.type = ERROR_TYPE_NONE;
/*
* Get memory for status information structure.
*/
adapter->status_info = (STATUS_INFORMATION *)
sys_alloc_status_structure(adapter_handle,sizeof(STATUS_INFORMATION));
/*
* Check that the memory allocation was successful.
*/
if (adapter->status_info == NULL)
{
adapter->error_record.type = ERROR_TYPE_DRIVER;
adapter->error_record.value = DRIVER_E_03_FAIL_ALLOC_STATUS;
return FALSE;
}
/*
* Zero status information structure memory.
*/
util_zero_memory(
(BYTE *) adapter->status_info,
sizeof(STATUS_INFORMATION)
);
/*
* Get memory for initialization block.
*/
adapter->init_block = (INITIALIZATION_BLOCK *)
sys_alloc_init_block(adapter_handle, sizeof(INITIALIZATION_BLOCK));
/*
* Check that the memory allocation was successful.
*/
if (adapter->init_block == NULL)
{
adapter->error_record.type = ERROR_TYPE_DRIVER;
adapter->error_record.value = DRIVER_E_04_FAIL_ALLOC_INIT;
return FALSE;
}
/*
* Zero initialization block memory.
*/
util_zero_memory(
(BYTE *) adapter->init_block,
sizeof(INITIALIZATION_BLOCK)
);
/*
* Get pointer to Fastmac init parameters for this adapter.
*/
fastmac_parms = &adapter->init_block->fastmac_parms;
/*
* Ensure that the fastmac_parms->features reserved bits and the
* fastmac_parms->int_flags reserved bits are zero (bits 4,11-15
* of features, and bits 3-15 of int_flags).
* (In fact they will be already from the above util_zero_memory.)
*/
/*
* Now fill in all of the hardware independant non-zero fields in the
* Fastmac part of init block.
*/
/*
* Check that the frame size requested in within the bounds
* of possibility.
*/
if (arguments->max_frame_size < MIN_FRAME_SIZE ||
arguments->max_frame_size > MAX_FRAME_SIZE_16_MBITS)
{
adapter->error_record.type = ERROR_TYPE_DRIVER;
adapter->error_record.value = DRIVER_E_13_BAD_FRAME_SIZE;
return FALSE;
}
/*
* Make a note of the maximum frame size requested.
*/
fastmac_parms->max_frame_size = arguments->max_frame_size;
#ifndef FMPLUS
/*
* Set up the header.
*/
fastmac_parms->header.length = sizeof(FASTMAC_INIT_PARMS);
fastmac_parms->header.signature = FASTMAC_INIT_HEADER_SIGNATURE;
fastmac_parms->header.version = FASTMAC_INIT_HEADER_VERSION;
/*
* Now set up the interrupt options.
*/
#ifdef FTK_TX_WITH_COMPLETION
fastmac_parms->int_flags |= INT_FLAG_TX_BUF_EMPTY;
#endif
/*
* Check have sensible value for Fastmac receive buffer size.
*/
if ((arguments->receive_buffer_byte_size < FASTMAC_MINIMUM_BUFFER_SIZE) ||
(arguments->receive_buffer_byte_size > FASTMAC_MAXIMUM_BUFFER_SIZE))
{
adapter->error_record.type = ERROR_TYPE_DRIVER;
adapter->error_record.value = DRIVER_E_0A_RX_BUF_BAD_SIZE;
return FALSE;
}
/*
* Get memory for the receive buffer.
*/
if (!sys_alloc_dma_phys_buffer(
adapter_handle,
arguments->receive_buffer_byte_size,
&adapter->rx_buffer_phys,
&adapter->rx_buffer_virt))
{
adapter->error_record.type = ERROR_TYPE_DRIVER;
adapter->error_record.value = DRIVER_E_05_FAIL_ALLOC_RX_BUF;
return FALSE;
}
fastmac_parms->rx_buf_physaddr = adapter->rx_buffer_phys;
/*
* Check that Fastmac receive buffer begins on a DWORD boundary.
*/
if ((fastmac_parms->rx_buf_physaddr & 0x00000003) != 0L)
{
adapter->error_record.type = ERROR_TYPE_DRIVER;
adapter->error_record.value = DRIVER_E_0B_RX_BUF_NOT_DWORD;
return FALSE;
}
/*
* Fill in Fastmac receive buffer size.
*/
fastmac_parms->rx_buf_size = arguments->receive_buffer_byte_size;
/*
* Check have sensible value for Fastmac transmit buffer size.
*/
if ((arguments->transmit_buffer_byte_size < FASTMAC_MINIMUM_BUFFER_SIZE) ||
(arguments->transmit_buffer_byte_size > FASTMAC_MAXIMUM_BUFFER_SIZE))
{
adapter->error_record.type = ERROR_TYPE_DRIVER;
adapter->error_record.value = DRIVER_E_0C_TX_BUF_BAD_SIZE;
return FALSE;
}
/*
* Get memory for the transmit buffer.
*/
if (!sys_alloc_dma_phys_buffer(
adapter_handle,
arguments->receive_buffer_byte_size,
&adapter->tx_buffer_phys,
&adapter->tx_buffer_virt))
{
adapter->error_record.type = ERROR_TYPE_DRIVER;
adapter->error_record.value = DRIVER_E_06_FAIL_ALLOC_TX_BUF;
return FALSE;
}
fastmac_parms->tx_buf_physaddr = adapter->tx_buffer_phys;
/*
* Check that Fastmac transmit buffer begins on a DWORD boundary.
*/
if ((fastmac_parms->tx_buf_physaddr & 0x00000003) != 0L)
{
adapter->error_record.type = ERROR_TYPE_DRIVER;
adapter->error_record.value = DRIVER_E_0D_TX_BUF_NOT_DWORD;
return FALSE;
}
/*
* Fill in Fastmac transmit buffer size.
*/
fastmac_parms->tx_buf_size = arguments->transmit_buffer_byte_size;
/*
* Mark adapter structure as containing details of initialized Fastmac
* and indicate that SRB is free.
*/
adapter->adapter_status = ADAPTER_PREPARED_FOR_START;
adapter->srb_status = SRB_FREE;
#else
/*
* Set set up the header.
*/
fastmac_parms->header.length = sizeof(FASTMAC_INIT_PARMS);
fastmac_parms->header.signature = FMPLUS_INIT_HEADER_SIGNATURE;
fastmac_parms->header.version = FMPLUS_INIT_HEADER_VERSION;
/*
* Now set up the interrupt options.
*/
#ifdef FTK_RX_OUT_OF_INTERRUPTS
fastmac_parms->int_flags |= INT_FLAG_RX;
#endif
#ifdef FTK_RX_BY_SCHEDULED_PROCESS
fastmac_parms->int_flags |= INT_FLAG_RX;
#endif
#ifdef FTK_TX_WITH_COMPLETION
fastmac_parms->int_flags |= INT_FLAG_LARGE_DMA;
#endif
/*
* Now fill in the number of slots that are required. These are user
* specified, since the numbers are host dependent (each slot must have
* a maximum frame sized buffer on the host).
*/
if (arguments->number_of_rx_slots < FMPLUS_MIN_RX_SLOTS ||
arguments->number_of_rx_slots > FMPLUS_MAX_RX_SLOTS)
{
adapter->error_record.type = ERROR_TYPE_DRIVER;
adapter->error_record.value = DRIVER_E_10_BAD_RX_SLOT_NUMBER;
return FALSE;
}
fastmac_parms->rx_slots = arguments->number_of_rx_slots;
if (arguments->number_of_tx_slots < FMPLUS_MIN_TX_SLOTS ||
arguments->number_of_tx_slots > FMPLUS_MAX_TX_SLOTS)
{
adapter->error_record.type = ERROR_TYPE_DRIVER;
adapter->error_record.value = DRIVER_E_11_BAD_TX_SLOT_NUMBER;
return FALSE;
}
fastmac_parms->tx_slots = arguments->number_of_tx_slots;
/*
* Allocate the receive slot buffers.
*/
if (!rxtx_allocate_rx_buffers(
adapter,
arguments->max_frame_size,
arguments->number_of_rx_slots
))
{
adapter->error_record.type = ERROR_TYPE_DRIVER;
adapter->error_record.value = DRIVER_E_05_FAIL_ALLOC_RX_BUF;
return FALSE;
}
/*
* Allocate the transmit slot buffers.
*/
if (!rxtx_allocate_tx_buffers(
adapter,
arguments->max_frame_size,
arguments->number_of_tx_slots
))
{
adapter->error_record.type = ERROR_TYPE_DRIVER;
adapter->error_record.value = DRIVER_E_06_FAIL_ALLOC_TX_BUF;
return FALSE;
}
/*
* Mark adapter structure as containing details of initialized Fastmac
* and indicate that SRB is free.
*/
adapter->adapter_status = ADAPTER_PREPARED_FOR_START;
adapter->srb_status = SRB_FREE;
#endif
/*
* Complete successfully.
*/
return TRUE;
}
/****************************************************************************
*
* driver_start_adapter
* ====================
*
* PARAMETERS :
* ============
*
* ADAPTER_HANDLE adapter_handle
*
* This handle identifies the adapter to be initialized. This should be a
* handle returned by a call to driver_prepare_adapter.
*
* START_ARGS * arguments
*
* This is a pointer to the arguments structure set up by the user code.
*
* NODE_ADDRESS * returned_permanent_address
*
* The node address pointed to is always filled in with the BIA PROM node
* address of the adapter. This is so the user of the FTK can fill in MAC
* headers etc. with the source node address (unless the user has supplied
* an opening address to driver_prepare_adapter which they should then use
* instead).
*
*
* BODY :
* ======
*
* The driver_start_adapter routine is called once per adapter after a call
* to driver_prepare_adapter. It takes the user supplied adapter
* information and passes it in a form usable by the HWI so that the HWI
* can install and then initialize the adapter (that is initialize
* registers on the card, download the Fastmac image and set up the IRQ and
* DMA channels if necessary). After initialization, this routine waits for
* the adapter to open if the auto-open option is enabled.
*
* RETURNS :
* =========
*
* The routine returns TRUE if it succeeds. If this routine fails (returns
* FALSE) then a subsequent call to driver_explain_error with the same
* adapter handle will give an explanation.
*
****************************************************************************/
#ifdef FTK_INIT_FUNCTION
#pragma FTK_INIT_FUNCTION(driver_start_adapter)
#endif
export WBOOLEAN
driver_start_adapter(
ADAPTER_HANDLE adapter_handle,
START_ARGS * arguments,
NODE_ADDRESS * returned_permanent_address
)
{
ADAPTER * adapter;
FASTMAC_INIT_PARMS * fastmac_parms;
WBOOLEAN init_success;
WORD max_frame_size;
UINT i;
#ifdef FMPLUS
RX_SLOT * next_rx_slot;
TX_SLOT * next_tx_slot;
RX_SLOT * * rx_slot_array;
TX_SLOT * * tx_slot_array;
UINT slot_index;
#endif
/*
* Check adapter handle and status of adapter for validity.
* If routine fails return failure (error record already filled in).
*/
if (!driver_check_adapter(
adapter_handle,
ADAPTER_PREPARED_FOR_START,
SRB_ANY_STATE
))
{
return FALSE;
}
/*
* Get pointer to adapter structure.
*/
adapter = adapter_record[adapter_handle];
/*
* Fill user supplied info into adapter structure.
*/
adapter->mmio_base_address = arguments->mmio_base_address;
adapter->adapter_card_bus_type = arguments->adapter_card_bus_type;
adapter->io_location = arguments->io_location;
adapter->dma_channel = arguments->dma_channel;
adapter->transfer_mode = arguments->transfer_mode;
adapter->interrupt_number = arguments->interrupt_number;
adapter->set_dma = arguments->set_dma_channel;
adapter->set_irq = arguments->set_interrupt_number;
adapter->set_ring_speed = arguments->set_ring_speed;
adapter->download_image = arguments->code;
adapter->pci_handle = arguments->pci_handle;
#ifdef FMPLUS
/*
* Need these values later.
*/
rx_slot_array = adapter->rx_slot_array;
tx_slot_array = adapter->tx_slot_array;
#endif
/*
* Call the HWI routine to install the adapter. This also downloads
* the Fastmac image to the adapter. If routine fails return failure
* (error record already filled in). DMA and IRQ are only enabled
* if hwi_install_adapter succeeds.
*/
/*
* WARNING: we must mark the adapter as running NOW, before downloading
* the microcode, because on AT cards in PIO mode ONLY, bring
* up diagnostics on the card fail when carrying out DMA tests.
* This occurs because the interrupt handling routine ignores
* all interrupts from the card until it is marked as running,
* but this unfortunately masks off PIO interrupts too.
*/
/*
* Mark adapter structure that adapter is now going to be running.
* Hence hwi_interrupt_entry will check adapter for interrupts
*/
adapter->adapter_status = ADAPTER_RUNNING;
if (!hwi_install_adapter(adapter, adapter->download_image))
{
/*
* Now that initial installation has failed, we can turn off the
* above indication that the card is running.
*/
adapter->adapter_status = ADAPTER_PREPARED_FOR_START;
return FALSE;
}
/*
* Get pointer to Fastmac init parameters for this adapter.
*/
fastmac_parms = &adapter->init_block->fastmac_parms;
/*
* Now fill in max frame size in init block that Fastmac should support.
* This is based on the size of the Fastmac buffers and
* max frame size supported by adapter because of ring speed. We
* put the requested max frame is into fastmac_parms->max_frame_size
* in driver_prepare_adapter.
*/
max_frame_size = driver_get_max_frame_size(adapter, fastmac_parms);
fastmac_parms->max_frame_size =
min(max_frame_size, fastmac_parms->max_frame_size);
/*
* Write the actual max frame size back up to the caller, so they know
* what it is too.
*/
arguments->max_frame_size = fastmac_parms->max_frame_size;
#ifdef FMPLUS
/*
* Set up the user selected RX/TX buffer size. This will be changed
* in hwi_gen.c if the value given is not sensible.
*/
adapter->init_block->smart_parms.rx_tx_buffer_size =
arguments->rx_tx_buffer_size;
#endif
/*
* If auto open option is on then put necessary info into init block.
*/
if (arguments->auto_open_option)
{
#ifndef FMPLUS
/*
* Use delay_rx to prevent race condition occuring whereby
* on auto-open an interrupt could occur before the host
* code has had a chance to read the location of the status
* block on the card. The other half of the code to fix this
* problem is in driver_start_adapter, where the ARB is freed.
*/
fastmac_parms->feature_flags =
FEATURE_FLAG_AUTO_OPEN | FEATURE_FLAG_DELAY_RX;
#else
fastmac_parms->feature_flags = FEATURE_FLAG_AUTO_OPEN;
#endif
fastmac_parms->open_options = arguments->open_options;
/*
* Check if auto-opening node address is set (ie. not all zeroes).
*/
for (i = 0; i < sizeof(NODE_ADDRESS); i++)
{
if (arguments->opening_node_address.byte[i] != 0)
{
break;
}
}
/*
* If opening node address not set up use BIA PROM address.
*/
if (i == sizeof(NODE_ADDRESS))
{
fastmac_parms->open_address = adapter->permanent_address;
}
else
{
fastmac_parms->open_address = arguments->opening_node_address;
}
fastmac_parms->group_address = arguments->opening_group_address;
fastmac_parms->functional_address = arguments->opening_functional_address;
}
/*
* Call the HWI routine to initialize the adapter. This downloads the
* init block to the adapter. Leaves EAGLE_SIFADRX=0x0001 so driver
* never use extended SIF regs. If routine fails return failure
* (error record already filled in).
*/
if (!hwi_initialize_adapter(adapter, adapter->init_block))
{
return FALSE;
}
/*
* At this stage the actual adapter card type is known.
* Get the IO location of the first SIF register for the adapter.
* Inform the system about the IO ports we are going to access.
*/
#ifndef FTK_NO_IO_ENABLE
macro_enable_io(adapter);
#endif
/*
* Get the DIO addresses of the Fastmac SSB and STB (ststus block).
* Only use non-extended SIF regs (EAGLE_SIFADR and EAGLE_SIFDAT_INC).
* Hence can use same code for all adapter card types.
*/
sys_outsw(adapter_handle, adapter->sif_adr, DIO_LOCATION_SRB_POINTER);
adapter->srb_dio_addr = (SRB_HEADER *) (card_t)
sys_insw(adapter_handle, adapter->sif_datinc);
sys_outsw(adapter_handle, adapter->sif_adr, DIO_LOCATION_STB_POINTER);
adapter->stb_dio_addr = (FASTMAC_STATUS_BLOCK *) (card_t)
sys_insw(adapter_handle, adapter->sif_datinc);
#ifndef FMPLUS
/*
* In the case of auto-open :
* Free the ARB to enable data to be received from here on... This only
* occurs now because it is only now that we know where to look for the
* pointers in the status block that will tell us whether data has come
* in or not.
*/
if (arguments->auto_open_option)
{
sys_outsw(adapter_handle, adapter->sif_int, EAGLE_ARB_FREE_CODE);
}
#else
/*
* Now recover the receive slot and transmit slot chains.
*/
/*
* Start with the receive slot chain. We must poll the location in the
* status block that holds the start address until it is non-zero. It
* is then safe to run down the chain finding the other slots.
*/
sys_outsw(
adapter_handle,
adapter->sif_adr,
(WORD) (card_t) &adapter->stb_dio_addr->rx_slot_start
);
/*
* Poll this address until it is non-zero.
*/
do
{
rx_slot_array[0] = (RX_SLOT *) (card_t)
sys_insw(adapter_handle, adapter->sif_dat);
}
while (rx_slot_array[0] == 0);
/*
* Recover all the other slots by running down the chain.
*/
slot_index = 0;
do
{
sys_outsw(
adapter_handle,
adapter->sif_adr,
(WORD) (card_t) &rx_slot_array[slot_index]->next_slot
);
next_rx_slot = (RX_SLOT *) (card_t)
sys_insw(adapter_handle, adapter->sif_dat);
if (next_rx_slot != rx_slot_array[0])
{
rx_slot_array[++slot_index] = next_rx_slot;
}
}
while (next_rx_slot != rx_slot_array[0]);
/*
* Now do the same for the transmit slots.
*/
sys_outsw(
adapter_handle,
adapter->sif_adr,
(WORD) (card_t) &adapter->stb_dio_addr->tx_slot_start
);
/*
* Poll this address until it is non-zero.
*/
do
{
tx_slot_array[0] = (TX_SLOT *) (card_t)
sys_insw(adapter_handle, adapter->sif_dat);
}
while (tx_slot_array[0] == 0);
/*
* Now recover all the other slots by running down the chain.
*/
slot_index = 0;
do
{
sys_outsw(
adapter_handle,
adapter->sif_adr,
(WORD) (card_t) &tx_slot_array[slot_index]->next_slot
);
next_tx_slot = (TX_SLOT *) (card_t)
sys_insw(adapter_handle, adapter->sif_dat);
if (next_tx_slot != tx_slot_array[0])
{
tx_slot_array[++slot_index] = next_tx_slot;
}
}
while (next_tx_slot != tx_slot_array[0]);
/*
* Now that we have the slot locations on the card, we can associate
* buffers with each of them. The user needs to supply a routine that
* set up the slots from the host buffers previously allocated as
* we don't enforce an organisation on the allocation of multiple
* slot buffers. We tell the user routine if it should program the
* adapter slots with physical addresses (for DMA) or virtual
* addresses (for PIO or MMIO).
*/
rxtx_setup_rx_buffers(
adapter,
(WBOOLEAN) (adapter->transfer_mode == DMA_DATA_TRANSFER_MODE),
fastmac_parms->rx_slots
);
rxtx_setup_tx_buffers(
adapter,
(WBOOLEAN) (adapter->transfer_mode == DMA_DATA_TRANSFER_MODE),
fastmac_parms->tx_slots
);
#endif
/*
* Let the system know we have finished accessing the IO ports.
*/
#ifndef FTK_NO_IO_ENABLE
macro_disable_io( adapter);
#endif
/*
* Check that Fastmac has correctly installed. Do this by reading
* node address from Fastmac status block. If routine fails return
* failure (error record already filled in). Note for EISA cards,
* this is actually first time get node address.
*/
if (!hwi_get_node_address_check(adapter))
{
return FALSE;
}
/*
* Copy permanent BIA PROM node address into user supplied node address.
*/
*returned_permanent_address = adapter->permanent_address;
/*
* If the auto open option is on then wait to see if adapter opens okay.
* Enable and disable accessing IO locations around check.
* If adapter open routine fails then error record already filled in.
*/
if (arguments->auto_open_option)
{
#ifndef FTK_NO_IO_ENABLE
macro_enable_io( adapter);
#endif
init_success = driver_wait_for_adapter_open(
&(arguments->open_status),
adapter
);
#ifndef FTK_NO_IO_ENABLE
macro_disable_io( adapter);
#endif
}
else
{
init_success = TRUE;
}
/*
* Initialization completed.
*/
return init_success;
}
#ifdef FMPLUS
/****************************************************************************
*
* driver_start_receive_process
* ============================
*
* PARAMETERS :
* ============
*
* ADAPTER_HANDLE adapter_handle
*
* This handle identifies the adapter to be initialized. This should be a
* handle returned by a call to driver_prepare_adapter.
*
* BODY :
* ======
*
* The driver_start_adapter routine is called once per adapter after a call
* to driver_start_adapter. It uses the supplied handle to identify which
* adapter it should affect : by writing a zero into the Fastmac Plus init-
* ialization block on the adapter (as specified in the manual), the card
* will start to receive frames and pass them up to the host.
*
* NOTE: If SRBs are going to be used, this MUST be called first.
*
* RETURNS :
* =========
*
* The routine returns TRUE if it succeeds. If this routine fails (returns
* FALSE) then a subsequent call to driver_explain_error with the same
* adapter handle will give an explanation.
*
****************************************************************************/
#ifdef FTK_INIT_FUNCTION
#pragma FTK_INIT_FUNCTION(driver_start_receive_process)
#endif
export WBOOLEAN
driver_start_receive_process(
ADAPTER_HANDLE adapter_handle
)
{
ADAPTER * adapter;
/*
* Adapter handle is invalid if greater than max number of adapters.
* Can not set up error record but see driver_explain_error.
*/
if (adapter_handle >= MAX_NUMBER_OF_ADAPTERS)
{
return FALSE;
}
/*
* Adapter handle is invalid when no adapter structure for handle.
* Can not set up error record but see driver_explain_error.
*/
if (adapter_record[adapter_handle] == NULL)
{
return FALSE;
}
/*
* Get pointer to adapter structure.
*/
adapter = adapter_record[adapter_handle];
/*
* Inform the system about the IO ports we are going to access.
*/
#ifndef FTK_NO_IO_ENABLE
macro_enable_io(adapter);
#endif
/*
* Let's fire off the receive process from here then...
*/
sys_outsw(
adapter_handle,
adapter->sif_adr,
(WORD) (card_t) &adapter->stb_dio_addr->rx_slot_start
);
sys_outsw(adapter_handle, adapter->sif_dat, 0);
/*
* Let the system know we have finished accessing the IO ports.
*/
#ifndef FTK_NO_IO_ENABLE
macro_disable_io(adapter);
#endif
return TRUE;
}
#endif
/****************************************************************************
*
* driver_remove_adapter
* =====================
*
* PARAMETERS :
* ============
*
* ADAPTER_HANDLE adapter_handle
*
* This handle identifies the adapter to be removed.
*
* BODY :
* ======
*
* The driver_remove_adapter routine is written such that, whatever the
* current state of the adapter, a call to driver_remove_adapter will place
* the adapter in a state whereby driver_prepare_adapter must be called to
* start using the adapter once more. Hence, on ANY fatal adapter error, a
* call to driver_remove adapter is needed before installing the adapter
* again.
*
* The routine calls the HWI to reset the required adapter if the adapter
* has been running. It also calls certain system routines in order to
* free the memory used by the Fastmac receive and transmit buffers as well
* as that used by the adapter structure. However, it only does this when
* the allocate calls were successful.
*
* RETURNS :
* =========
*
* The routine always succeeds. Even if the adapter handle is invalid then
* the routine does not fail it just does nothing.
*
****************************************************************************/
#ifdef FTK_RES_FUNCTION
#pragma FTK_RES_FUNCTION(driver_remove_adapter)
#endif
export WBOOLEAN
driver_remove_adapter(
ADAPTER_HANDLE adapter_handle
)
{
ADAPTER * adapter;
FASTMAC_INIT_PARMS * fastmac_parms;
/*
* Adapter handle is invalid if greater than max number of adapters.
* Can not set up error record but see driver_explain_error.
*/
if (adapter_handle >= MAX_NUMBER_OF_ADAPTERS)
{
return FALSE;
}
/*
* Adapter handle is invalid when no adapter structure for handle.
* Can not set up error record but see driver_explain_error.
*/
if (adapter_record[adapter_handle] == NULL)
{
return FALSE;
}
/*
* Get pointer to adapter structure.
*/
adapter = adapter_record[adapter_handle];
/*
* Call the HWI routine to kill the adapter (DMA channel, IRQ number).
* Only call it if either DMA or interrupts are enabled at adapter.
* Note in this case the actual adapter card type is known.
*/
if (adapter->interrupts_on || adapter->dma_on)
{
hwi_remove_adapter(adapter);
}
/*
* Free all memory that was allocated for handling use of this adapter.
* Includes Fastmac buffers, init block and adapter structure.
* Only free memory if allocate memory calls were successful.
*/
if (adapter->init_block != NULL)
{
/*
* Initialize variable used for freeing memory.
*/
fastmac_parms = &adapter->init_block->fastmac_parms;
#ifndef FMPLUS
/*
* Free transmit buffer space if allocated.
*/
if (adapter->tx_buffer_phys != NULL_PHYSADDR)
{
sys_free_dma_phys_buffer(
adapter_handle,
fastmac_parms->tx_buf_size,
adapter->tx_buffer_phys,
adapter->tx_buffer_virt
);
}
/*
* Free receive buffer space if allocated.
*/
if (adapter->rx_buffer_phys != NULL_PHYSADDR)
{
sys_free_dma_phys_buffer(
adapter_handle,
fastmac_parms->rx_buf_size,
adapter->rx_buffer_phys,
adapter->rx_buffer_virt
);
}
#else
/*
* Free receive buffer space if allocated.
*/
rxtx_free_rx_buffers(
adapter,
fastmac_parms->max_frame_size,
fastmac_parms->rx_slots
);
/*
* Free transmit buffer space if allocated.
*/
rxtx_free_tx_buffers(
adapter,
fastmac_parms->max_frame_size,
fastmac_parms->tx_slots
);
#endif
/*
* Free the initialization block allocated memory.
*/
sys_free_init_block(
adapter_handle,
(BYTE *) adapter->init_block,
sizeof(INITIALIZATION_BLOCK)
);
}
/*
* Free status structure if allocated.
*/
if (adapter->status_info != NULL)
{
sys_free_status_structure(
adapter_handle,
(BYTE *) adapter->status_info,
sizeof(STATUS_INFORMATION)
);
}
#ifdef FMPLUS
if (adapter->dma_test_buf_virt != 0)
{
sys_free_dma_phys_buffer(
adapter->adapter_handle,
SCB_TEST_PATTERN_LENGTH + SSB_TEST_PATTERN_LENGTH + 1,
adapter->dma_test_buf_phys,
adapter->dma_test_buf_virt
);
}
#endif
/*
* Already know adapter allocate was successful hence always free it.
*/
sys_free_adapter_structure(
adapter_handle,
(BYTE *) adapter,
sizeof(ADAPTER)
);
/*
* Clear entry in adapter pointers array.
*/
adapter_record[adapter_handle] = NULL;
/*
* Complete successfully.
*/
return TRUE;
}
/*---------------------------------------------------------------------------
|
| driver_wait_for_adapter_open
| ============================
|
| The driver_wait_for_adapter_open routine waits at least 40 seconds for
| the adapter to open. It discovers whether the adapter has opened
| successfully or not by looking in the Fastmac status block (STB). If the
| adapter fails to open then this routine fills in the adapter error
| record.
|
---------------------------------------------------------------------------*/
#ifdef FTK_INIT_FUNCTION
#pragma FTK_INIT_FUNCTION(driver_wait_for_adapter_open)
#endif
local WBOOLEAN
driver_wait_for_adapter_open(
UINT * open_status,
ADAPTER * adapter
)
{
ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
WBOOLEAN open_okay;
UINT open_error;
UINT index;
/*
* Wait at least a total of 40 seconds for adapter to open.
*/
for (index = 0; index < 160; index++)
{
/*
* Set up DIO address to open status field in STB (status block).
*/
sys_outsw(
adapter_handle,
adapter->sif_adr,
(WORD) (card_t) &adapter->stb_dio_addr->adapter_open
);
/*
* Read open status field from DIO space. If successfully
* opened then complete successfully.
*/
open_okay = (WBOOLEAN) sys_insw(
adapter_handle,
adapter->sif_datinc
);
if (open_okay)
{
*open_status = EAGLE_OPEN_ERROR_SUCCESS;
return TRUE;
}
/*
* If not opened, see if an error has occured to prevent opening.
*/
open_error = sys_insw(adapter_handle, adapter->sif_datinc);
*open_status = open_error;
if (open_error != EAGLE_OPEN_ERROR_SUCCESS)
{
adapter->error_record.type = ERROR_TYPE_AUTO_OPEN;
adapter->error_record.value = AUTO_OPEN_E_01_OPEN_ERROR;
return FALSE;
}
/*
* Opening procedure not completed. Wait at least 250 milliseconds
* before checkig again. Disable and re-enable accessing IO locations
* around wait so delay can reschedule this task and not effect others
* running.
*/
#ifndef FTK_NO_IO_ENABLE
macro_disable_io( adapter);
#endif
sys_wait_at_least_milliseconds(250);
#ifndef FTK_NO_IO_ENABLE
macro_enable_io( adapter);
#endif
}
/*
* At least 40 seconds have gone so return time out failure.
*/
adapter->error_record.type = ERROR_TYPE_AUTO_OPEN;
adapter->error_record.value = AUTO_OPEN_E_80_TIME_OUT;
return FALSE;
}
/*---------------------------------------------------------------------------
|
| driver_get_max_frame_size
| =========================
|
| The driver_get_max_frame_size routine calculates the maximum sized frame
| that can be transmitted or received. This calculation is based on the
| maximum frame size determined by ring speed alone, the size of the
| Fastmac buffers, and the fact that Fastmac pointers have to be DWORD
| aligned.
|
---------------------------------------------------------------------------*/
#ifdef FTK_INIT_FUNCTION
#pragma FTK_INIT_FUNCTION(driver_get_max_frame_size)
#endif
local WORD
driver_get_max_frame_size(
ADAPTER * adapter,
FASTMAC_INIT_PARMS * fastmac_parms
)
{
#ifdef FMPLUS
return adapter->max_frame_size;
#else
WORD tx_max_frame_size;
WORD rx_max_frame_size;
WORD max_frame_size;
/*
* Calculate max transmit frame size from size of buffer, size of
* header and knowing that one frame must leave space such that host
* and adapter ptrs into buffer are not the same.
*/
tx_max_frame_size =
fastmac_parms->tx_buf_size - macro_dword_align(
FASTMAC_BUFFER_HEADER_SIZE +
fastmac_parms->tx_buf_space +
sizeof(DWORD)
);
/*
* Calculate max receive frame size from size of buffer, size of
* header and knowing that one frame must leave space such that host
* and adapter ptrs into buffer are not the same.
*/
rx_max_frame_size =
fastmac_parms->rx_buf_size - macro_dword_align(
FASTMAC_BUFFER_HEADER_SIZE +
fastmac_parms->rx_buf_space +
sizeof(DWORD)
);
/*
* Actual max frame size is minimum of max transmit and receive frame
* sizes and max frame size for adapter (ring speed dependent).
*/
max_frame_size = util_minimum(
tx_max_frame_size,
rx_max_frame_size,
adapter->max_frame_size
);
return max_frame_size;
#endif
}
/**** End of DRV_INIT.C file ***********************************************/