diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/ndis/madge/driver/hwi_sm16.c | 1191 |
1 files changed, 1191 insertions, 0 deletions
diff --git a/private/ntos/ndis/madge/driver/hwi_sm16.c b/private/ntos/ndis/madge/driver/hwi_sm16.c new file mode 100644 index 000000000..75c637c21 --- /dev/null +++ b/private/ntos/ndis/madge/driver/hwi_sm16.c @@ -0,0 +1,1191 @@ +/**************************************************************************** +* +* HWI_SM16.C : Part of the FASTMAC TOOL-KIT (FTK) +* +* HARDWARE INTERFACE MODULE FOR SMART 16 CARDS +* +* Copyright (c) Madge Networks Ltd. 1994 +* +* COMPANY CONFIDENTIAL +* +* +***************************************************************************** +* +* The purpose of the Hardware Interface (HWI) is to supply an adapter card +* independent interface to any driver. It performs nearly all of the +* functions that involve affecting SIF registers on the adapter cards. +* This includes downloading code to, initializing, and removing adapters. +* +* The HWI_SM16.C module contains the routines specific to the Smart16 card +* which are necessary to install an adapter, to initialize an adapter, to +* remove an adapter, and to handle interrupts on an adapter. +* +/***************************************************************************/ + +/*--------------------------------------------------------------------------- +| +| 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 */ + +#ifndef FTK_NO_SMART16 + +/*--------------------------------------------------------------------------- +| +| LOCAL PROCEDURES +| +---------------------------------------------------------------------------*/ + +local WBOOLEAN +hwi_smart16_read_node_address( + ADAPTER * adapter + ); + +local WBOOLEAN +hwi_smart16_valid_io_location( + WORD io_location + ); + +local WBOOLEAN +hwi_smart16_valid_transfer_mode( + UINT transfer_mode + ); + +#ifndef FTK_NO_PROBE + +local WBOOLEAN +hwi_smart16_check_for_card( + WORD io_location + ); + +#endif + +local WBOOLEAN +hwi_smart16_valid_irq_channel( + ADAPTER * adapter + ); + +#ifndef FTK_NO_PROBE +/**************************************************************************** +* +* hwi_smart16_probe_card +* ====================== +* +* +* PARAMETERS (passed by hwi_probe_adapter) : +* ========================================== +* +* 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 smart 16 adapters with should be a subset of +* {0x4a20, 0x4e20, 0x6a20, 0x6e20}. +* +* UINT number_locations +* +* This is the number of IO locations in the above list. +* +* BODY : +* ====== +* +* The hwi_smart16_probe_card routine is called by hwi_probe_adapter. It +* checks for the existence of a card by reading its node address. This is +* about all we can do for a smart 16. +* +* +* 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(hwi_smart16_probe_card) +#endif + +export UINT +hwi_smart16_probe_card( + PROBE * resources, + UINT length, + WORD * valid_locations, + UINT number_locations + ) +{ + WORD control_1; + WORD control_2; + UINT i; + UINT j; + + /* + * Check the bounds are sensible. + */ + + if(length <= 0 || number_locations <= 0) + { + return PROBE_FAILURE; + } + + /* + * Range check the IO locations. + */ + + for(i = 0; i < number_locations; i++) + { + if(!hwi_smart16_valid_io_location(valid_locations[i])) + { + return PROBE_FAILURE; + } + } + + /* + * j is the number of adapters found. + */ + + j = 0; + + for(i = 0; i < number_locations; i++) + { + /* + * Check we aren't out of PROBE structures. + */ + + if(j >= length) + { + return j; + } + + /* + * Set up the control register locations. + */ + + control_1 = valid_locations[i] + SMART16_CONTROL_REGISTER_1; + control_2 = valid_locations[i] + SMART16_CONTROL_REGISTER_2; + +#ifndef FTK_NO_IO_ENABLE + macro_probe_enable_io(valid_locations[i], SMART16_IO_RANGE); +#endif + /* + * Reset the card. + */ + + sys_probe_outsb(control_1, 0); + + if (hwi_smart16_check_for_card(valid_locations[i])) + { + + /* + * We have obviously found a valid smart 16 by this point so + * set up some values. + */ + + resources[j].adapter_card_bus_type = ADAPTER_CARD_SMART16_BUS_TYPE; + resources[j].adapter_card_type = ADAPTER_CARD_TYPE_SMART_16; + resources[j].adapter_card_revision = ADAPTER_CARD_SMART_16; + resources[j].adapter_ram_size = 128; + resources[j].io_location = valid_locations[i]; + resources[j].interrupt_number = SMART16_DEFAULT_INTERRUPT; + resources[j].dma_channel = 0; + resources[j].transfer_mode = PIO_DATA_TRANSFER_MODE; + + /* + * And increment j to point at the next free PROBE structure. + */ + + j++; + } + +#ifndef FTK_NO_IO_ENABLE + macro_probe_disable_io(resources->io_location, SMART16_IO_RANGE); +#endif + + } + + return j; +} +#endif + +/**************************************************************************** +* +* hwi_smart16_install_card +* ======================== +* +* +* PARAMETERS (passed by hwi_install_adapter) : +* ============================================ +* +* ADAPTER * adapter +* +* This structure is used to identify and record specific information about +* the required adapter. +* +* DOWNLOAD_IMAGE * download_image +* +* This is the code to be downloaded to the adapter. The image must be of +* the correct type i.e. must be downloadable into the adapter. If the +* pointer is 0 downloading is not done. +* +* +* BODY : +* ====== +* +* hwi_smart16_install_card is called by hwi_install_adapter. It sets up +* the adapter card and downloads the required code to it. Firstly, it +* checks there is a valid adapter at the required IO address by reading +* the node address from the BIA PROM. It then sets up and checks various +* on-board registers for correct operation. +* +* Then, it halts the EAGLE, downloads the code, restarts the EAGLE and +* waits up to 3 seconds for a valid bring-up code. If interrupts are +* required, these are enabled by operating system specific calls. +* The adapter is set up for Eagle Pseudo-DMA, since real DMA is not used. +* +* +* RETURNS : +* ========= +* +* The routine returns TRUE if it succeeds. If this routine fails (returns +* FALSE) then a subsequent call to driver_explain_error, with the adapter +* handle corresponding to the adapter parameter used here, will give an +* explanation. +* +****************************************************************************/ + +#ifdef FTK_INIT_FUNCTION +#pragma FTK_INIT_FUNCTION(hwi_smart16_install_card) +#endif + +export WBOOLEAN +hwi_smart16_install_card( + ADAPTER * adapter, + DOWNLOAD_IMAGE * download_image + ) +{ + ADAPTER_HANDLE adapter_handle = adapter->adapter_handle; + WORD control_1 = adapter->io_location + + SMART16_CONTROL_REGISTER_1; + WORD control_2 = adapter->io_location + + SMART16_CONTROL_REGISTER_2; + WORD sif_base; + + /* + * Check the IO location is valid. + */ + + if(!hwi_smart16_valid_io_location(adapter->io_location)) + { + adapter->error_record.type = ERROR_TYPE_HWI; + adapter->error_record.value = HWI_E_02_BAD_IO_LOCATION; + + return FALSE; + } + + /* + * Check the transfer mode is valid. + */ + + if(!hwi_smart16_valid_transfer_mode(adapter->transfer_mode)) + { + adapter->error_record.type = ERROR_TYPE_HWI; + adapter->error_record.value = HWI_E_02_BAD_IO_LOCATION; + + return FALSE; + } + + if (!hwi_smart16_valid_irq_channel(adapter)) + { + return FALSE; + } + + /* + * Record the locations of the SIF registers. + */ + + sif_base = adapter->io_location + SMART16_FIRST_SIF_REGISTER; + + adapter->sif_dat = sif_base + EAGLE_SIFDAT; + adapter->sif_datinc = sif_base + EAGLE_SIFDAT_INC; + adapter->sif_adr = sif_base + EAGLE_SIFADR; + adapter->sif_int = sif_base + EAGLE_SIFINT; + adapter->sif_acl = sif_base + EAGLE_SIFACL; + adapter->sif_adr2 = sif_base + EAGLE_SIFADR; + adapter->sif_adx = sif_base + EAGLE_SIFADX; + adapter->sif_dmalen = sif_base + EAGLE_DMALEN; + adapter->sif_sdmadat = sif_base + EAGLE_SDMADAT; + adapter->sif_sdmaadr = sif_base + EAGLE_SDMAADR; + adapter->sif_sdmaadx = sif_base + EAGLE_SDMAADX; + + adapter->io_range = SMART16_IO_RANGE; + +#ifndef FTK_NO_IO_ENABLE + macro_enable_io(adapter); +#endif + + /* + * You might want to check that we have not already checked for a card + * at this address (or its rev3/4 equivalent). + */ + + /* + * Reset adapter (SMART16_CTRL1_SRESET = 0). This is necessary for + * reading the BIA. + */ + + sys_outsb(adapter_handle, control_1, 0); + + /* + * Read the node address for the specified IO location. This will check + * that it is a valid Madge address, which is the only way we have of + * identifying the card. + */ + + if (!hwi_smart16_read_node_address(adapter)) + { + /* + * Fill in error record and return + */ + + adapter->error_record.type = ERROR_TYPE_HWI; + adapter->error_record.value = HWI_E_05_ADAPTER_NOT_FOUND; + +#ifndef FTK_NO_IO_ENABLE + macro_disable_io(adapter); +#endif + + return FALSE; + } + + /* + * Make sure that SCS bit is zero (see below where we bring card out of + * reset). + */ + + sys_outsb(adapter_handle, control_1, 0); + + /* + * nselout_bits are needed to select the IRQ on the card. + */ + + switch (adapter->interrupt_number) + { + case 2 : + adapter->nselout_bits = SMART16_IRQ_2; + break; + case 3 : + adapter->nselout_bits = SMART16_IRQ_3; + break; + case 7 : + adapter->nselout_bits = SMART16_IRQ_7; + break; + default : + break; + + } + + /* + * These things can all be assumed for the smart16. + */ + + adapter->adapter_card_type = ADAPTER_CARD_TYPE_SMART_16; + adapter->adapter_card_revision = ADAPTER_CARD_SMART_16; + adapter->adapter_ram_size = 128; + adapter->edge_triggered_ints = TRUE; + adapter->EaglePsDMA = TRUE; + adapter->max_frame_size = MAX_FRAME_SIZE_16_MBITS; + adapter->ring_speed = 16; + + /* + * Bring adapter out of reset state (ensure that SCS is zero before + * doing this). + */ + + sys_outsb(adapter_handle, control_1, 1); + + /* + * Halt the Eagle prior to downloading the MAC code - this will also + * write the interrupt bits into the SIFACL register, where the MAC can + * find them. + */ + + hwi_halt_eagle(adapter); + + /* + * Download code to adapter. + * View download image as a sequence of download records. Pass address + * of routine to set up DIO addresses on ATULA cards. + * If routine fails return failure (error record already filled in). + */ + + if (!hwi_download_code(adapter, + (DOWNLOAD_RECORD *) download_image, + hwi_smart16_set_dio_address)) + { +#ifndef FTK_NO_IO_ENABLE + macro_disable_io(adapter); +#endif + return FALSE; + } + + /* + * Restart the Eagle to initiate bring up diagnostics. + */ + + hwi_start_eagle(adapter); + + /* + * Wait for a valid bring up code, may wait 3 seconds. + * If routine fails return failure (error record already filled in). + */ + + if (!hwi_get_bring_up_code(adapter)) + { +#ifndef FTK_NO_IO_ENABLE + macro_disable_io(adapter); +#endif + return FALSE; + } + + /* + * Set DIO address to point to EAGLE DATA page 0x10000L. + */ + + hwi_smart16_set_dio_address(adapter, DIO_LOCATION_EAGLE_DATA_PAGE); + + /* + * If not in polling mode then set up interrupts. + * Interrupts_on field is used when disabling interrupts for adapter. + */ + + if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE) + { + adapter->interrupts_on = + sys_enable_irq_channel(adapter_handle, adapter->interrupt_number); + + /* + * If fail enable irq channel then fill in error record and return. + */ + + if (!adapter->interrupts_on) + { + adapter->error_record.type = ERROR_TYPE_HWI; + adapter->error_record.value = HWI_E_0B_FAIL_IRQ_ENABLE; +#ifndef FTK_NO_IO_ENABLE + macro_disable_io(adapter); +#endif + return FALSE; + } + } + else + { + adapter->interrupts_on = TRUE; + } + + /* return successfully */ + +#ifndef FTK_NO_IO_ENABLE + macro_disable_io(adapter); +#endif + return TRUE; + +} + + +/**************************************************************************** +* +* hwi_smart16_interrupt_handler +* ============================= +* +* +* PARAMETERS (passed by hwi_interrupt_entry) : +* ============================================ +* +* ADAPTER * adapter +* +* This structure is used to identify and record specific information about +* the required adapter. +* +* +* BODY : +* ====== +* +* The hwi_smart16_interrupt_handler routine is called, when an interrupt +* occurs, by hwi_interrupt_entry. It checks to see if a particular card +* has interrupted. The interrupt could be generated by the SIF for either +* a PIO data transfer or a normal condition (received frame, SRB complete, +* ARB indication etc). Note it could in fact be the case that no interrupt +* has occured on the particular adapter being checked. +* +* On normal SIF interrupts, the interrupt is acknowledged and cleared. The +* value in the SIF interrupt register is recorded in order to pass it to +* the driver_interrupt_entry routine (along with the adapter details). +* +* On PseudoDMA interrupts, the length, direction and physical address of +* the transfer is determined. A system provided routine is called to do +* the data transfer itself. +* +* +* RETURNS : +* ========= +* +* The routine always successfully completes. +* +****************************************************************************/ + +#ifdef FTK_IRQ_FUNCTION +#pragma FTK_IRQ_FUNCTION(hwi_smart16_interrupt_handler) +#endif + +export void +hwi_smart16_interrupt_handler( + ADAPTER * adapter + ) +{ + ADAPTER_HANDLE adapter_handle = adapter->adapter_handle; + WORD sifacl_value; + WORD sifint_value; + WORD sifint_tmp; + WBOOLEAN sifint_occurred = FALSE; + WBOOLEAN pioint_occurred = FALSE; + WORD pio_len_bytes; + WBOOLEAN pio_from_adapter; + BYTE FAR * pio_address; + WORD lo_word; + DWORD hi_word; + + /* + * Inform system about the IO ports we are going to access. + */ + +#ifndef FTK_NO_IO_ENABLE + macro_enable_io(adapter); +#endif + + /* + * Check for SIF interrupt or PIO interrupt. + */ + + /* + * Mask off any further interrupts while we read SIFINT (note that this + * does not mask off Pseudo DMA interrupts). + */ + + macro_clearw_bit( + adapter_handle, + adapter->sif_acl, + EAGLE_SIFACL_SINTEN + ); + + sifint_value = sys_insw(adapter_handle, adapter->sif_int); + do + { + sifint_tmp = sifint_value; + sifint_value = sys_insw( + adapter_handle, + adapter->sif_int + ); + } + while (sifint_tmp != sifint_value); + + if ((sifint_value & EAGLE_SIFINT_SYSTEM) != 0) + { + /* + * SIF interrupt has occurred. + * SRB free, adapter check or received frame interrupt. + */ + + sifint_occurred = TRUE; + + /* + * Clear EAGLE_SIFINT_HOST_IRQ to acknowledge interrupt at SIF. + */ + + sys_outsw( adapter_handle, adapter->sif_int, 0); + + } + + sifacl_value = sys_insw(adapter_handle, adapter->sif_acl); + + if ((sifacl_value & EAGLE_SIFACL_SWHRQ) != 0) + { + /* + * PIO interrupt has occurred. + * Data transfer to/from adapter interrupt. + */ + + pioint_occurred = TRUE; + + macro_setw_bit( + adapter_handle, + adapter->sif_acl, + EAGLE_SIFACL_SWHLDA + ); + + /* + * Determine what direction the data transfer is to take place in. + */ + + pio_from_adapter = sys_insw( + adapter_handle, + adapter->sif_acl + ) & EAGLE_SIFACL_SWDDIR; + + pio_len_bytes = sys_insw( + adapter_handle, + adapter->sif_dmalen + ); + + lo_word = sys_insw( + adapter_handle, + adapter->sif_sdmaadr + ); + + hi_word = (DWORD) sys_insw( + adapter_handle, + adapter->sif_sdmaadx + ); + + pio_address = (BYTE FAR *) ((hi_word << 16) | ((DWORD) lo_word)); + + /* + * Do the actual data transfer. + * Note that Fastmac only copies whole UINTs to DWORD boundaries. + * FastmacPlus, however, can transfer any length to any address. + */ + + if (pio_from_adapter) + { + /* + * Transfer into host memory from adapter. + * First, check if host address is on an odd byte boundary. + */ + + if ((card_t)pio_address % 2) + { + pio_len_bytes--; + *(pio_address++) = + sys_insb(adapter_handle, + (WORD) (adapter->sif_sdmadat + 1)); + } + + /* + * Now transfer the bulk of the data. + */ + + sys_rep_insw( + adapter_handle, + adapter->sif_sdmadat, + pio_address, + (WORD) (pio_len_bytes >> 1)); + + /* + * Finally transfer any trailing byte. + */ + + if (pio_len_bytes % 2) + { + *(pio_address+pio_len_bytes-1) = + sys_insb(adapter_handle, + adapter->sif_sdmadat); + } + } + else + { + /* + * Transfer into adapter memory from the host. + */ + + if ((card_t)pio_address % 2) + { + pio_len_bytes--; + sys_outsb( + adapter_handle, + (WORD) (adapter->sif_sdmadat + 1), + *(pio_address++) + ); + } + + sys_rep_outsw( + adapter_handle, + adapter->sif_sdmadat, + pio_address, + (WORD) (pio_len_bytes >> 1) + ); + + if (pio_len_bytes % 2) + { + sys_outsb( + adapter_handle, + adapter->sif_sdmadat, + *(pio_address+pio_len_bytes-1) + ); + } + } + } + +#ifndef FTK_NO_CLEAR_IRQ + + if (sifint_occurred || pioint_occurred) + { + /* + * Acknowledge/clear interrupt at interrupt controller. + */ + sys_clear_controller_interrupt( + adapter_handle, + adapter->interrupt_number); + } + +#endif + + if (sifint_occurred) + { + /* + * Call driver with details of SIF interrupt. + */ + + driver_interrupt_entry( + adapter_handle, + adapter, + sifint_value); + } + + /* + * Read SIFACL until the SWHLDA bit has cleared. + */ + + do + { + sifacl_value = sys_insw(adapter_handle, adapter->sif_acl); + } + while ((sifacl_value & EAGLE_SIFACL_SWHLDA) != 0); + + /* + * Now set SINTEN in SIFACL to regenerate interrupts. + */ + + sys_outsw( + adapter_handle, + adapter->sif_acl, + (WORD) (sifacl_value | EAGLE_SIFACL_SINTEN) + ); + + /* + * Let system know we have finished accessing the IO ports. + */ + +#ifndef FTK_NO_IO_ENABLE + macro_disable_io( adapter); +#endif +} + + +/**************************************************************************** +* +* hwi_smart16_remove_card +* ======================= +* +* +* PARAMETERS (passed by hwi_remove_adapter) : +* =========================================== +* +* ADAPTER * adapter +* +* This structure is used to identify and record specific information about +* the required adapter. +* +* +* BODY : +* ====== +* +* The hwi_smart16_remove_card routine is called by hwi_remove_adapter. It +* disables interrupts if they are being used. It also resets the adapter. +* +* +* RETURNS : +* ========= +* +* The routine always successfully completes. +* +****************************************************************************/ + +#ifdef FTK_RES_FUNCTION +#pragma FTK_RES_FUNCTION(hwi_smart16_remove_card) +#endif + +export void +hwi_smart16_remove_card( + ADAPTER * adapter + ) +{ + ADAPTER_HANDLE adapter_handle = adapter->adapter_handle; + WORD control_1 = adapter->io_location + + SMART16_CONTROL_REGISTER_1; + WORD sifacl_value; + + /* + * Interrupt must be disabled at adapter before unpatching interrupt. + * Even in polling mode we must turn off interrupts at adapter. + */ + +#ifndef FTK_NO_IO_ENABLE + macro_enable_io(adapter); +#endif + + sifacl_value = sys_insw(adapter_handle, adapter->sif_acl); + sifacl_value = (sifacl_value & ~(EAGLE_SIFACL_PSDMAEN | EAGLE_SIFACL_SINTEN)); + sys_outsw( + adapter_handle, + adapter->sif_acl, + sifacl_value); + + if (adapter->interrupts_on) + { + if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE) + { + sys_disable_irq_channel( + adapter_handle, + adapter->interrupt_number); + } + + adapter->interrupts_on = FALSE; + } + + /* + * perform adapter reset, set BALD_EAGLE_CTRL1_NSRESET low + */ + + sys_outsb(adapter_handle, control_1, 0); + +#ifndef FTK_NO_IO_ENABLE + macro_disable_io(adapter); +#endif +} + + +/**************************************************************************** +* +* hwi_smart16_set_dio_address +* =========================== +* +* The hwi_smart16_set_dio_address routine is used, with Smart16 cards, for +* putting a 32 bit DIO address into the SIF DIO address and extended DIO +* address registers. Note that the extended address register should be +* loaded first. +* +****************************************************************************/ + +#ifdef FTK_INIT_FUNCTION +#pragma FTK_INIT_FUNCTION(hwi_smart16_set_dio_address) +#endif + +export void +hwi_smart16_set_dio_address( + ADAPTER * adapter, + DWORD dio_address + ) +{ + ADAPTER_HANDLE adapter_handle = adapter->adapter_handle; + WORD sif_dio_adr = adapter->sif_adr; + WORD sif_dio_adrx = adapter->sif_adx; + + /* + * Load extended DIO address register with top 16 bits of address. + * Always load extended address register first. + */ + sys_outsw( + adapter_handle, + sif_dio_adrx, + (WORD)(dio_address >> 16)); + + /* + * Load DIO address register with low 16 bits of address. + */ + + sys_outsw( + adapter_handle, + sif_dio_adr, + (WORD)(dio_address & 0x0000FFFF)); + +} + + +/*--------------------------------------------------------------------------- +| +| LOCAL PROCEDURES +| +---------------------------------------------------------------------------*/ + +#ifndef FTK_NO_PROBE +/*--------------------------------------------------------------------------- +| +| hwi_smart16_check_for_card +| ========================== +| +| The hwi_smart16_check_for_card routine reads in the node address from +| the BIA, and checks that it is a valid Madge node address. Basically +| it's just the same as hwi_smart16_read_node_address. +| +---------------------------------------------------------------------------*/ + +#ifdef FTK_INIT_FUNCTION +#pragma FTK_INIT_FUNCTION(hwi_smart16_check_for_card) +#endif + +local WBOOLEAN +hwi_smart16_check_for_card( + WORD io_location + ) +{ + WORD control_2 = io_location + SMART16_CONTROL_REGISTER_2; + WORD port; + BYTE i; + BYTE j; + BYTE two_bits; + DWORD node_address = 0; + + for (i = 0; i < 4; i++) + { + sys_probe_outsb(control_2, i); + + /* + * Read the 8 bit node address 2 bits at a time. + */ + + port = io_location; + + for (j = 0; j < 4; j++) + { + two_bits = (BYTE)(sys_probe_insb(port) & 3); + node_address = (node_address << 2) | two_bits; + port += 8; + } + } + + /* + * If we find that the high byte is not f6 then we know we haven't + * got a valid card so we fail. + */ + + return (((node_address >> 24) & 0x000000ffL) == 0x000000f6L && + (node_address & 0x00ffffffL) != 0x00ffffffL && + (node_address & 0x00ffffffL) != 0x00000000L); +} +#endif + +/*--------------------------------------------------------------------------- +| +| hwi_smart16_read_node_address +| ============================= +| +| The hwi_smart16_read_node_address routine reads in the node address from +| the BIA, and checks that it is a valid Madge node address. +| +---------------------------------------------------------------------------*/ + +#ifdef FTK_INIT_FUNCTION +#pragma FTK_INIT_FUNCTION(hwi_smart16_read_node_address) +#endif + +local WBOOLEAN +hwi_smart16_read_node_address( + ADAPTER * adapter + ) +{ + WORD control_2 = adapter->io_location + + SMART16_CONTROL_REGISTER_2; + WORD port; + BYTE i; + BYTE j; + BYTE two_bits; + DWORD node_address = 0; + + for (i = 0; i < 4; i++) + { + sys_outsb( + adapter->adapter_handle, + control_2, + i); + + /* + * Read the 8 bit node address 2 bits at a time. + */ + + port = adapter->io_location; + + for (j = 0; j < 4; j++) + { + two_bits = (BYTE)(sys_insb(adapter->adapter_handle, port) & 3); + node_address = (node_address << 2) | two_bits; + port += 8; + } + } + + adapter->permanent_address.byte[0] = 0; + adapter->permanent_address.byte[1] = 0; + + for (i = 0; i < 4; i++) + { + adapter->permanent_address.byte[5-i] + = (BYTE)((node_address >> (8 * i)) & 0x0ff); + } + + return (adapter->permanent_address.byte[2] == MADGE_NODE_BYTE_2); +} + + +/*--------------------------------------------------------------------------- +| +| hwi_smart16_valid_io_location +| ============================= +| +| The hwi_smart16_valid_io_location routine checks to see if the user has +| supplied a valid IO location for a smart 16 adapter card. +| +---------------------------------------------------------------------------*/ + +#ifdef FTK_INIT_FUNCTION +#pragma FTK_INIT_FUNCTION(hwi_smart16_valid_io_location) +#endif + +local WBOOLEAN +hwi_smart16_valid_io_location( + WORD io_location + ) +{ + WBOOLEAN io_valid; + + switch (io_location & ~SMART16_REV3) + { + + case 0x4A20 : + case 0x4E20 : + case 0x6A20 : + case 0x6E20 : + + /* + * These are the valid user supplied io locations. + */ + + io_valid = TRUE; + break; + + + default : + + /* + * Anything else is invalid. + */ + + io_valid = FALSE; + + break; + } + + return(io_valid); +} + + +/*--------------------------------------------------------------------------- +| +| hwi_smart16_valid_transfer_mode +| =============================== +| +| The hwi_smart16_valid_transfer_mode routine checks to see if the user has +| supplied a valid transfer mode for a smart 16 adapter card (that's PIO to +| you and me). +| +---------------------------------------------------------------------------*/ + +#ifdef FTK_INIT_FUNCTION +#pragma FTK_INIT_FUNCTION(hwi_smart16_valid_transfer_mode) +#endif + +local WBOOLEAN +hwi_smart16_valid_transfer_mode( + UINT transfer_mode + ) +{ + return(transfer_mode == PIO_DATA_TRANSFER_MODE); +} + + +/*--------------------------------------------------------------------------- +| +| hwi_smart16_valid_irq_channel +| ============================= +| +| The hwi_smart16_valid_irq_channel routine checks to see if the user has +| supplied a valid interrupt number for a Smart16 adapter card. +| +---------------------------------------------------------------------------*/ + +#ifdef FTK_INIT_FUNCTION +#pragma FTK_INIT_FUNCTION(hwi_smart16_valid_irq_channel) +#endif + +local WBOOLEAN +hwi_smart16_valid_irq_channel( + ADAPTER * adapter + ) +{ + WBOOLEAN int_valid; + + /* + * Assume that interrupt number is valid. + */ + + int_valid = TRUE; + + /* + * No need to do any check on interrupt number if in polling mode. + */ + + if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE) + { + switch (adapter->interrupt_number) + { + case 2 : + case 3 : + case 7 : + break; + + default : + int_valid = FALSE; + break; + + } + } + + if (!int_valid) + { + adapter->error_record.type = ERROR_TYPE_HWI; + adapter->error_record.value = HWI_E_03_BAD_INTERRUPT_NUMBER; + } + + return int_valid; +} + +#endif + +/******** End of HWI_SM16.C file *******************************************/ + |