summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/madge/driver/drv_init.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/ndis/madge/driver/drv_init.c1656
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 ***********************************************/