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