diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/ndis/madge/driver/drv_init.c | 1656 |
1 files changed, 1656 insertions, 0 deletions
diff --git a/private/ntos/ndis/madge/driver/drv_init.c b/private/ntos/ndis/madge/driver/drv_init.c new file mode 100644 index 000000000..28539f67c --- /dev/null +++ b/private/ntos/ndis/madge/driver/drv_init.c @@ -0,0 +1,1656 @@ +/**************************************************************************** +* +* 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 ***********************************************/ |