mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2206 lines
59 KiB
2206 lines
59 KiB
/****************************************************************************
|
|
*
|
|
* HWI_AT.C : Part of the FASTMAC TOOL-KIT (FTK)
|
|
*
|
|
* HARDWARE INTERFACE MODULE FOR ATULA CARDS
|
|
*
|
|
* Copyright (c) Madge Networks Ltd. 1990-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_AT.C module contains the routines specific to 16/4 PC and 16/4
|
|
* AT cards 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_ATULA
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| LOCAL PROCEDURES
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
local void
|
|
hwi_atula_read_node_address(
|
|
ADAPTER * adapter
|
|
);
|
|
|
|
local WBOOLEAN
|
|
hwi_atula_valid_io_location(
|
|
WORD io_location
|
|
);
|
|
|
|
#ifndef FTK_NO_PROBE
|
|
|
|
local WORD
|
|
hwi_atula_get_irq_channel(
|
|
WORD io_location,
|
|
UINT adapter_revision
|
|
);
|
|
|
|
local WORD
|
|
hwi_atula_get_dma_channel(
|
|
WORD io_location,
|
|
UINT adapter_revsion
|
|
);
|
|
|
|
#endif
|
|
|
|
local WORD
|
|
hwi_atula_valid_transfer_mode(
|
|
ADAPTER * adapter
|
|
);
|
|
|
|
local WORD
|
|
hwi_atula_valid_irq_channel(
|
|
ADAPTER * adapter
|
|
);
|
|
|
|
local WORD
|
|
hwi_atula_valid_dma_channel(
|
|
ADAPTER * adapter
|
|
);
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| LOCAL VARIABLES
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
local BYTE atp_irq_select_table[16] =
|
|
{
|
|
0xff, /* 0 Unused */
|
|
0xff, /* 1 Unused */
|
|
0x07, /* 2 */
|
|
0x06, /* 3 */
|
|
0xff, /* 4 Unused */
|
|
0x05, /* 5 */
|
|
0xff, /* 6 Unused */
|
|
0x04, /* 7 */
|
|
0xff, /* 8 Unused */
|
|
0x07, /* 9 */
|
|
0x03, /* 10 */
|
|
0x02, /* 11 */
|
|
0x01, /* 12 */
|
|
0xff, /* 13 Unused */
|
|
0xff, /* 14 Unused */
|
|
0x00 /* 15 */
|
|
};
|
|
|
|
local BYTE atp_dma_select_table[7] =
|
|
{
|
|
0xff, /* 0 Unused */
|
|
0xff, /* 1 Unused */
|
|
0xff, /* 2 Unused */
|
|
0x08, /* 3 */
|
|
0xff, /* 4 Unused */
|
|
0x10, /* 5 */
|
|
0x18 /* 6 */
|
|
};
|
|
|
|
local WORD adapter_card_at_rmsz_lut[7] =
|
|
{
|
|
128, /* 16/4 AT */
|
|
128, /* 16/4 AT */
|
|
256, /* 16/4 AT */
|
|
256, /* 16/4 Fibre AT */
|
|
256, /* 16/4 AT Bridgenode */
|
|
128, /* 16/4 ISA Client */
|
|
512 /* 16/4 AT Plus */
|
|
};
|
|
|
|
#ifndef FTK_NO_PROBE
|
|
/****************************************************************************
|
|
*
|
|
* hwi_atula_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 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(hwi_atula_probe_card)
|
|
#endif
|
|
|
|
export UINT
|
|
hwi_atula_probe_card(
|
|
PROBE * resources,
|
|
UINT length,
|
|
WORD * valid_locations,
|
|
UINT number_locations
|
|
)
|
|
{
|
|
WBOOLEAN card_found;
|
|
WORD control_1;
|
|
WORD control_2;
|
|
WORD status;
|
|
WORD control_6;
|
|
WORD control_7;
|
|
WORD bia_prom;
|
|
WORD bia_prom_id;
|
|
WORD bia_prom_adap;
|
|
WORD bia_prom_rev;
|
|
WORD bia_prom_hwf;
|
|
BYTE bia_temp_bd;
|
|
BYTE bia_temp_rev;
|
|
BYTE bia_temp_hwf;
|
|
UINT i;
|
|
UINT j;
|
|
|
|
/*
|
|
* Sanity check the bounds.
|
|
*/
|
|
|
|
if (length <= 0 || number_locations <= 0)
|
|
{
|
|
return PROBE_FAILURE;
|
|
}
|
|
|
|
/*
|
|
* Validate the IO locations.
|
|
*/
|
|
|
|
for (i = 0; i < number_locations; i++)
|
|
{
|
|
if (!hwi_atula_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++)
|
|
{
|
|
/*
|
|
* Make sure that we haven't run out of PROBE structures.
|
|
*/
|
|
|
|
if (j >= length)
|
|
{
|
|
return j;
|
|
}
|
|
|
|
/*
|
|
* Set up the ATULA control IO locations.
|
|
*/
|
|
|
|
control_1 = valid_locations[i] + ATULA_CONTROL_REGISTER_1;
|
|
control_2 = valid_locations[i] + ATULA_CONTROL_REGISTER_2;
|
|
status = valid_locations[i] + ATULA_STATUS_REGISTER;
|
|
control_6 = valid_locations[i] + ATULA_CONTROL_REGISTER_6;
|
|
control_7 = valid_locations[i] + ATULA_CONTROL_REGISTER_7;
|
|
bia_prom = valid_locations[i] + ATULA_BIA_PROM;
|
|
bia_prom_id = bia_prom + BIA_PROM_ID_BYTE;
|
|
bia_prom_adap = bia_prom + BIA_PROM_ADAPTER_BYTE;
|
|
bia_prom_rev = bia_prom + BIA_PROM_REVISION_BYTE;
|
|
bia_prom_hwf = bia_prom + BIA_PROM_FEATURES_BYTE;
|
|
|
|
#ifndef FTK_NO_IO_ENABLE
|
|
macro_probe_enable_io(valid_locations[i], ATULA_IO_RANGE);
|
|
#endif
|
|
|
|
/*
|
|
* Reset adapter (ATULA_CTRL1_NRESET = 0).
|
|
*/
|
|
|
|
sys_probe_outsb(control_1, 0);
|
|
|
|
/*
|
|
* Page in first page of BIA PROM.
|
|
* set ATULA_CTRL7_PAGE = 0 and ATULA_CTRL7_SIFSEL = 0.
|
|
*/
|
|
|
|
sys_probe_outsb(control_7, 0);
|
|
|
|
/*
|
|
* Check we have a functioning adapter at the given IO location by
|
|
* checking the BIA PROM for an 'M' id byte and also by checking that
|
|
* the BIA adapter card byte is for a supported card type.
|
|
*/
|
|
|
|
/*
|
|
* At the moment there are four major board types that are acceptable
|
|
* AT, PC, MAXY, and ATP.
|
|
*/
|
|
|
|
card_found = FALSE;
|
|
|
|
if (sys_probe_insb(bia_prom_id) == 'M')
|
|
{
|
|
bia_temp_bd = sys_probe_insb(bia_prom_adap);
|
|
bia_temp_rev = sys_probe_insb(bia_prom_rev);
|
|
bia_temp_hwf = sys_probe_insb(bia_prom_hwf);
|
|
|
|
if (bia_temp_bd == BIA_PROM_TYPE_16_4_PC)
|
|
{
|
|
resources[j].adapter_card_revision = ADAPTER_CARD_16_4_PC;
|
|
resources[j].adapter_ram_size = 128;
|
|
card_found = TRUE;
|
|
}
|
|
else if (bia_temp_bd == BIA_PROM_TYPE_16_4_MAXY)
|
|
{
|
|
resources[j].adapter_card_revision = ADAPTER_CARD_16_4_MAXY;
|
|
resources[j].adapter_ram_size = 256;
|
|
card_found = TRUE;
|
|
}
|
|
else if (bia_temp_bd == BIA_PROM_TYPE_16_4_AT)
|
|
{
|
|
if (bia_temp_rev <= MAX_ADAPTER_CARD_AT_REV)
|
|
{
|
|
resources[j].adapter_ram_size = adapter_card_at_rmsz_lut[bia_temp_rev];
|
|
}
|
|
else
|
|
{
|
|
resources[j].adapter_ram_size = 128;
|
|
}
|
|
|
|
if (bia_temp_rev < ADAPTER_CARD_16_4_AT)
|
|
{
|
|
resources[j].adapter_card_revision = ADAPTER_CARD_16_4_AT;
|
|
}
|
|
else
|
|
{
|
|
resources[j].adapter_card_revision = bia_temp_rev;
|
|
}
|
|
card_found = TRUE;
|
|
}
|
|
else if (bia_temp_bd == BIA_PROM_TYPE_16_4_AT_P)
|
|
{
|
|
resources[j].adapter_ram_size = 512;
|
|
|
|
switch(bia_temp_rev)
|
|
{
|
|
case ADAPTER_CARD_16_4_FIBRE:
|
|
resources[j].adapter_card_revision = ADAPTER_CARD_16_4_FIBRE_P;
|
|
break;
|
|
case ADAPTER_CARD_16_4_ISA_C:
|
|
resources[j].adapter_card_revision = ADAPTER_CARD_16_4_ISA_C_P;
|
|
resources[j].adapter_ram_size = 128;
|
|
break;
|
|
case ADAPTER_CARD_16_4_AT_P_REV:
|
|
resources[j].adapter_card_revision = ADAPTER_CARD_16_4_AT_P;
|
|
break;
|
|
default:
|
|
resources[j].adapter_card_revision = ADAPTER_CARD_UNKNOWN;
|
|
break;
|
|
}
|
|
|
|
card_found = TRUE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Check for the features byte - if it is non-zero, it may override our
|
|
* RAM size calculations.
|
|
*/
|
|
|
|
if (bia_temp_hwf)
|
|
{
|
|
UINT dram = (bia_temp_hwf & BIA_PROM_FEATURE_DRAM_MASK) * DRAM_MULT;
|
|
|
|
if (dram)
|
|
{
|
|
resources[j].adapter_ram_size = dram;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If we've found an adapter then we need to make a note of
|
|
* the IO location and attempt to determine the interrupt
|
|
* number and DMA channel.
|
|
*/
|
|
|
|
if (card_found)
|
|
{
|
|
resources[j].io_location = valid_locations[i];
|
|
resources[j].adapter_card_bus_type = ADAPTER_CARD_ATULA_BUS_TYPE;
|
|
resources[j].adapter_card_type = ADAPTER_CARD_TYPE_16_4_AT;
|
|
|
|
resources[j].dma_channel = hwi_atula_get_dma_channel(
|
|
valid_locations[i],
|
|
resources[j].adapter_card_revision
|
|
);
|
|
|
|
/*
|
|
* If we get a DMA channel of 0 back then we can't use DMA so
|
|
* default the transfer mode to PIO. Otherwise we'll set the
|
|
* transfer mode to DMA.
|
|
*/
|
|
|
|
if (resources[j].dma_channel == 0)
|
|
{
|
|
resources[j].transfer_mode = PIO_DATA_TRANSFER_MODE;
|
|
}
|
|
else
|
|
{
|
|
resources[j].transfer_mode = DMA_DATA_TRANSFER_MODE;
|
|
}
|
|
|
|
resources[j].interrupt_number = hwi_atula_get_irq_channel(
|
|
valid_locations[i],
|
|
resources[j].adapter_card_revision
|
|
);
|
|
|
|
/*
|
|
* And note that we've found an adapter.
|
|
*/
|
|
|
|
j++;
|
|
}
|
|
|
|
#ifndef FTK_NO_IO_ENABLE
|
|
macro_probe_disable_io(valid_locations[i], ATULA_IO_RANGE);
|
|
#endif
|
|
}
|
|
|
|
return j;
|
|
}
|
|
#endif /* FTK_NO_PROBE */
|
|
|
|
#ifndef FTK_NO_DETECT
|
|
/****************************************************************************/
|
|
/* */
|
|
/* hwi_atula_read_rate_error */
|
|
/* ========================= */
|
|
/* */
|
|
/* */
|
|
/* PARAMETERS : */
|
|
/* ============ */
|
|
/* */
|
|
/* adapter : The ubiqitous adapter structure. */
|
|
/* */
|
|
/* BODY : */
|
|
/* ====== */
|
|
/* */
|
|
/* The hwi_atula_read_rate_error reads the NRATE_ERR signal from the */
|
|
/* adapter DIO space. This is read from chapter 0 address 0. */
|
|
/* */
|
|
/* RETURNS : */
|
|
/* ========= */
|
|
/* */
|
|
/* The routine returns RATE_ERROR if there is a rate error, 0 if there is no*/
|
|
/* error, and NOT_SUPP if the card doesn't support this. */
|
|
/* */
|
|
|
|
#ifdef FTK_INIT_FUNCTION
|
|
#pragma FTK_INIT_FUNCTION(hwi_atula_read_rate_error)
|
|
#endif
|
|
|
|
export WORD hwi_atula_read_rate_error( ADAPTER * adapter
|
|
)
|
|
{
|
|
WBOOLEAN ret_code;
|
|
WORD error_word;
|
|
|
|
#ifndef FTK_NO_IO_ENABLE
|
|
macro_enable_io( adapter );
|
|
#endif
|
|
|
|
if (adapter->speed_detect == TRUE)
|
|
{
|
|
hwi_atula_set_dio_address( adapter, 0x00000000L);
|
|
|
|
sys_outsw( adapter->adapter_handle, adapter->sif_adr, 0x0);
|
|
|
|
|
|
error_word = sys_insw( adapter->adapter_handle, adapter->sif_dat) & 0x0080;
|
|
|
|
hwi_atula_set_dio_address( adapter, DIO_LOCATION_EAGLE_DATA_PAGE);
|
|
|
|
if (error_word & 0x0080)
|
|
{
|
|
ret_code = 0;
|
|
}
|
|
else
|
|
{
|
|
ret_code = RATE_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ret_code = NOT_SUPP;
|
|
}
|
|
|
|
#ifndef FTK_NO_IO_ENABLE
|
|
macro_disable_io( adapter );
|
|
#endif
|
|
|
|
return ret_code;
|
|
}
|
|
#endif /* FTK_NO_DETECT */
|
|
|
|
/****************************************************************************
|
|
*
|
|
* hwi_atula_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 :
|
|
* ======
|
|
*
|
|
* The hwi_atula_install_card routine 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. If so it
|
|
* reads the node address from the BIA PROM and sets up and checks numerous
|
|
* 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.
|
|
* Similarly, operating system calls are used to enable DMA if required. If
|
|
* DMA is not used then the adapter is set up for PIO.
|
|
*
|
|
* 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_atula_install_card)
|
|
#endif
|
|
|
|
export WBOOLEAN
|
|
hwi_atula_install_card(
|
|
ADAPTER * adapter,
|
|
DOWNLOAD_IMAGE * download_image
|
|
)
|
|
{
|
|
WBOOLEAN is_soft_prog = FALSE;
|
|
ADAPTER_HANDLE handle = adapter->adapter_handle;
|
|
WORD control_1 = adapter->io_location + ATULA_CONTROL_REGISTER_1;
|
|
WORD control_2 = adapter->io_location + ATULA_CONTROL_REGISTER_2;
|
|
WORD status = adapter->io_location + ATULA_STATUS_REGISTER;
|
|
WORD control_6 = adapter->io_location + ATULA_CONTROL_REGISTER_6;
|
|
WORD control_7 = adapter->io_location + ATULA_CONTROL_REGISTER_7;
|
|
WORD bia_prom = adapter->io_location + ATULA_BIA_PROM;
|
|
WORD bia_prom_id = bia_prom + BIA_PROM_ID_BYTE;
|
|
WORD bia_prom_adap = bia_prom + BIA_PROM_ADAPTER_BYTE;
|
|
WORD bia_prom_rev = bia_prom + BIA_PROM_REVISION_BYTE;
|
|
WORD bia_prom_hwf = bia_prom + BIA_PROM_FEATURES_BYTE;
|
|
WORD bia_prom_hwf2 = bia_prom + BIA_PROM_HWF2;
|
|
WORD bia_prom_hwf3 = bia_prom + BIA_PROM_HWF3;
|
|
BYTE control_6_out;
|
|
BYTE dummy_sifdat;
|
|
BYTE bia_temp_bd = 0;
|
|
BYTE bia_temp_rev = 0;
|
|
BYTE bia_temp_hwf = 0;
|
|
BYTE bia_temp_hwf2 = 0;
|
|
BYTE bia_temp_hwf3 = 0;
|
|
WBOOLEAN card_found;
|
|
WORD sif_base;
|
|
|
|
/*
|
|
* Check that the IO location is valid.
|
|
*/
|
|
|
|
if (!hwi_atula_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;
|
|
}
|
|
|
|
/*
|
|
* Record the locations of the SIF registers.
|
|
*/
|
|
|
|
sif_base = adapter->io_location + ATULA_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 + ATULA_EAGLE_SIFACL;
|
|
adapter->sif_adr2 = sif_base + ATULA_EAGLE_SIFADR_2;
|
|
adapter->sif_adx = sif_base + ATULA_EAGLE_SIFADX;
|
|
adapter->sif_dmalen = sif_base + ATULA_EAGLE_DMALEN;
|
|
|
|
adapter->io_range = ATULA_IO_RANGE;
|
|
|
|
#ifndef FTK_NO_IO_ENABLE
|
|
macro_enable_io(adapter);
|
|
#endif
|
|
|
|
/*
|
|
* Enable adapter card interrupts.
|
|
*/
|
|
|
|
sys_outsb(handle, control_2, ATULA_CTRL2_INTEN);
|
|
|
|
/*
|
|
* Reset adapter (ATULA_CTRL1_NRESET = 0).
|
|
*/
|
|
|
|
sys_outsb(handle, control_1, 0);
|
|
|
|
/*
|
|
* Page in first page of BIA PROM.
|
|
* Set ATULA_CTRL7_PAGE = 0 and ATULA_CTRL7_SIFSEL = 0.
|
|
*/
|
|
|
|
sys_outsb(handle, control_7, 0);
|
|
|
|
/*
|
|
* Check we have a functioning adapter at the given IO location by
|
|
* checking the BIA PROM for an 'M' id byte and also by checking that
|
|
* the BIA adapter card byte is for a supported card type.
|
|
*/
|
|
|
|
/*
|
|
* At the moment there are four major board types that are acceptable
|
|
* AT, PC, MAXY, and ATP.
|
|
*/
|
|
|
|
card_found = FALSE;
|
|
|
|
if (sys_insb(handle, bia_prom_id) == 'M')
|
|
{
|
|
bia_temp_bd = sys_insb(handle, bia_prom_adap);
|
|
bia_temp_rev = sys_insb(handle, bia_prom_rev);
|
|
bia_temp_hwf = sys_insb(handle, bia_prom_hwf);
|
|
bia_temp_hwf2 = sys_insb(handle, bia_prom_hwf2);
|
|
bia_temp_hwf3 = sys_insb(handle, bia_prom_hwf3);
|
|
|
|
if (bia_temp_bd == BIA_PROM_TYPE_16_4_PC)
|
|
{
|
|
adapter->adapter_card_revision = ADAPTER_CARD_16_4_PC;
|
|
adapter->adapter_ram_size = 128;
|
|
card_found = TRUE;
|
|
}
|
|
else if (bia_temp_bd == BIA_PROM_TYPE_16_4_MAXY)
|
|
{
|
|
adapter->adapter_card_revision = ADAPTER_CARD_16_4_MAXY;
|
|
adapter->adapter_ram_size = 256;
|
|
card_found = TRUE;
|
|
}
|
|
else if (bia_temp_bd == BIA_PROM_TYPE_16_4_AT)
|
|
{
|
|
if (bia_temp_rev <= MAX_ADAPTER_CARD_AT_REV)
|
|
{
|
|
adapter->adapter_ram_size = adapter_card_at_rmsz_lut[bia_temp_rev];
|
|
}
|
|
else
|
|
{
|
|
adapter->adapter_ram_size = 128;
|
|
}
|
|
|
|
if (bia_temp_rev < ADAPTER_CARD_16_4_AT)
|
|
{
|
|
adapter->adapter_card_revision = ADAPTER_CARD_16_4_AT;
|
|
}
|
|
else
|
|
{
|
|
adapter->adapter_card_revision = bia_temp_rev;
|
|
}
|
|
|
|
card_found = TRUE;
|
|
}
|
|
else if (bia_temp_bd == BIA_PROM_TYPE_16_4_AT_P)
|
|
{
|
|
adapter->adapter_ram_size = 512;
|
|
|
|
switch(bia_temp_rev)
|
|
{
|
|
case ADAPTER_CARD_16_4_FIBRE:
|
|
adapter->adapter_card_revision = ADAPTER_CARD_16_4_FIBRE_P;
|
|
break;
|
|
case ADAPTER_CARD_16_4_ISA_C:
|
|
adapter->adapter_card_revision = ADAPTER_CARD_16_4_ISA_C_P;
|
|
adapter->adapter_ram_size = 128;
|
|
adapter->mc32_config = MC_AND_ISACP_USE_PIO;
|
|
break;
|
|
case ADAPTER_CARD_16_4_AT_P_REV:
|
|
adapter->adapter_card_revision = ADAPTER_CARD_16_4_AT_P;
|
|
break;
|
|
default:
|
|
adapter->adapter_card_revision = ADAPTER_CARD_UNKNOWN;
|
|
break;
|
|
}
|
|
|
|
card_found = TRUE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If no ATULA card found then fill in error record and return.
|
|
*/
|
|
|
|
if (!card_found)
|
|
{
|
|
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;
|
|
}
|
|
|
|
/*
|
|
* Sanity check the interrupt number and DMA channel. The checking
|
|
* routines fill in the error record in the adapter structure.
|
|
*/
|
|
|
|
if (!hwi_atula_valid_irq_channel(adapter) ||
|
|
!hwi_atula_valid_transfer_mode(adapter) ||
|
|
!hwi_atula_valid_dma_channel(adapter))
|
|
{
|
|
#ifndef FTK_NO_IO_ENABLE
|
|
macro_disable_io(adapter);
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Note the major card type.
|
|
*/
|
|
|
|
adapter->adapter_card_type = ADAPTER_CARD_TYPE_16_4_AT;
|
|
|
|
/*
|
|
* If this card has a C30 on board and the ring speed bit is set then
|
|
* we support ring speed detect.
|
|
*/
|
|
|
|
if (((bia_temp_hwf2 & 0x3) == C30 ) && (bia_temp_hwf3 & RSPEED_DETECT))
|
|
{
|
|
adapter->speed_detect = TRUE;
|
|
}
|
|
|
|
/*
|
|
* Now we need to check for AT/P cards - these need special processing.
|
|
*/
|
|
|
|
if (bia_temp_bd == BIA_PROM_TYPE_16_4_AT_P ||
|
|
bia_temp_rev == ADAPTER_CARD_16_4_AT_P_REV)
|
|
{
|
|
WORD atp_eisa_rev2 = adapter->io_location + AT_P_EISA_REV2_CTRL_REG;
|
|
BYTE eisa_rev2_byte = 0;
|
|
|
|
if (bia_temp_bd == BIA_PROM_TYPE_16_4_AT_P)
|
|
{
|
|
eisa_rev2_byte |= ATP_RSCTRL;
|
|
}
|
|
|
|
if ((bia_temp_hwf & BIA_PROM_FEATURE_CLKDIV_MASK) ||
|
|
(bia_temp_rev == ADAPTER_CARD_16_4_ISA_C))
|
|
{
|
|
eisa_rev2_byte |= ATP_CLKDIV;
|
|
}
|
|
|
|
sys_outsb(handle, atp_eisa_rev2, eisa_rev2_byte);
|
|
|
|
is_soft_prog = TRUE;
|
|
}
|
|
|
|
/*
|
|
* Check for the features byte - if it is non-zero, it may override our
|
|
* RAM size calculations.
|
|
*/
|
|
|
|
if (bia_temp_hwf)
|
|
{
|
|
UINT dram = (bia_temp_hwf & BIA_PROM_FEATURE_DRAM_MASK) * DRAM_MULT;
|
|
|
|
if (dram)
|
|
{
|
|
adapter->adapter_ram_size = dram;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* The user might have asked to override the card configuration with
|
|
* the values supplied - this only works for ATPs and ISA/C/Ps.
|
|
*/
|
|
|
|
if (is_soft_prog)
|
|
{
|
|
WORD atp_sw_config = adapter->io_location + AT_P_SW_CONFIG_REG;
|
|
BYTE config_byte;
|
|
UINT int_num = adapter->interrupt_number;
|
|
UINT dma_chan = adapter->dma_channel;
|
|
|
|
if (adapter->set_irq || adapter->set_dma || adapter->set_ring_speed)
|
|
{
|
|
config_byte = sys_insb(handle, atp_sw_config);
|
|
|
|
/*
|
|
* Override the interrupt number.
|
|
*/
|
|
|
|
if (adapter->set_irq &&
|
|
int_num < sizeof(atp_irq_select_table) &&
|
|
atp_irq_select_table[int_num] != 0xff)
|
|
{
|
|
config_byte = (config_byte & ~ATP_INTSEL) |
|
|
atp_irq_select_table[int_num];
|
|
}
|
|
|
|
/*
|
|
* Override the DMA channel.
|
|
*/
|
|
|
|
if (adapter->set_dma &&
|
|
dma_chan < sizeof(atp_dma_select_table) &&
|
|
atp_dma_select_table[dma_chan] != 0xff)
|
|
{
|
|
config_byte = (config_byte & ~ATP_DMA) |
|
|
atp_dma_select_table[dma_chan];
|
|
}
|
|
|
|
/*
|
|
* Set the ring speed.
|
|
*/
|
|
|
|
if (adapter->set_ring_speed == 16)
|
|
{
|
|
config_byte = (config_byte & ~ATP_S4N16);
|
|
}
|
|
else if (adapter->set_ring_speed == 4)
|
|
{
|
|
config_byte = (config_byte | ATP_S4N16);
|
|
}
|
|
|
|
sys_outsb(handle, atp_sw_config, config_byte);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* May have changed from software running in bus master to PIO.
|
|
* Hence get spurious data at ?a28 cos of DLATCH bug in ATULA hardware
|
|
* so get next read data as if doing PIO data transfer.
|
|
* Hence do extra read from ?a28 to fix bug.
|
|
*/
|
|
|
|
dummy_sifdat = sys_insb(handle, adapter->sif_dat);
|
|
|
|
/*
|
|
* Check here to see if we have to force card to 16 Mb/s for a none
|
|
* soft programmable card.
|
|
*/
|
|
|
|
if (!is_soft_prog && adapter->set_ring_speed == 16)
|
|
{
|
|
macro_setb_bit(handle, control_1, ATULA_CTRL1_4_16_SEL);
|
|
}
|
|
|
|
/*
|
|
* Interrupts for ATULA cards are always edge triggered.
|
|
*/
|
|
|
|
adapter->edge_triggered_ints = TRUE;
|
|
|
|
/*
|
|
* Machine reset does not affect speed or media setting of ATULA cards.
|
|
*/
|
|
|
|
/*
|
|
* Find the adapter card node address.
|
|
*/
|
|
|
|
hwi_atula_read_node_address(adapter);
|
|
|
|
/*
|
|
* If have REV3 adapter type then must set up special bus timings
|
|
* must do this before any SIF register access
|
|
* on 16/4 PC doing this is not necessary but has no effect
|
|
*/
|
|
|
|
if ((sys_insb(handle, control_7) & ATULA_CTRL7_REV_4) == 0)
|
|
{
|
|
/*
|
|
* Note that a sys_outsb here will clear the INTEN bit that was set
|
|
* earlier on. This does not matter, however, because we have found
|
|
* the interrupt vector by this stage. If this does become a problem,
|
|
* use macro_setb_bit().
|
|
*/
|
|
|
|
sys_outsb(handle, control_2, ATULA_CTRL2_CS16DLY);
|
|
}
|
|
|
|
/*
|
|
* Set control register 6 for normal or synchronous bus operation.
|
|
* Use status register to get bus operation mode. On 16/4 PC will always
|
|
* in fact have normal bus operation.
|
|
*/
|
|
|
|
control_6_out = 0;
|
|
|
|
if ((sys_insb(handle, status) & ATULA_STATUS_ASYN_BUS) != 0)
|
|
{
|
|
control_6_out |= ATULA_CTRL6_CLKSEL_ON_BOARD;
|
|
}
|
|
else
|
|
{
|
|
control_6_out |= ATULA_CTRL6_CLKSEL_HOST;
|
|
}
|
|
|
|
/*
|
|
* If want to use DMA, need a 16 bit slot.
|
|
* Note that 16/4 PC will always be in an 8 bit slot.
|
|
*/
|
|
|
|
if ((adapter->transfer_mode == DMA_DATA_TRANSFER_MODE) &&
|
|
((sys_insb(handle, status) & ATULA_STATUS_BUS8) != 0))
|
|
{
|
|
adapter->error_record.type = ERROR_TYPE_HWI;
|
|
adapter->error_record.value = HWI_E_06_CANNOT_USE_DMA;
|
|
|
|
#ifndef FTK_NO_IO_ENABLE
|
|
macro_disable_io(adapter);
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Set up transfer mode now that we know we are in a valid slot.
|
|
*/
|
|
|
|
if (adapter->transfer_mode == DMA_DATA_TRANSFER_MODE)
|
|
{
|
|
control_6_out |= ATULA_CTRL6_MODE_BUS_MASTER;
|
|
}
|
|
else
|
|
{
|
|
control_6_out |= ATULA_CTRL6_MODE_PIO;
|
|
}
|
|
|
|
/*
|
|
* Now output to control register 6 the required value we have set up.
|
|
*/
|
|
|
|
sys_outsb(handle, control_6, control_6_out);
|
|
|
|
/*
|
|
* Wait at least 10 milliseconds and bring adapter out of reset state.
|
|
* 10ms is the minimum time must hold ATULA_CTRL1_NRESET low after
|
|
* changing ATULA_CTRL6_CLKSEL bits. 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(10);
|
|
|
|
#ifndef FTK_NO_IO_ENABLE
|
|
macro_enable_io(adapter);
|
|
#endif
|
|
|
|
macro_setb_bit( handle, control_1, ATULA_CTRL1_NSRESET);
|
|
|
|
/*
|
|
* Get extended SIF registers, halt EAGLE, then get normal SIF regs.
|
|
*/
|
|
|
|
macro_setb_bit(handle, control_7, ATULA_CTRL7_SIFSEL);
|
|
macro_setb_bit(handle, control_1, ATULA_CTRL1_SRSX);
|
|
|
|
hwi_halt_eagle(adapter);
|
|
|
|
macro_clearb_bit(handle, control_1, ATULA_CTRL1_SRSX);
|
|
|
|
/*
|
|
* 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_atula_set_dio_address
|
|
))
|
|
{
|
|
#ifndef FTK_NO_IO_ENABLE
|
|
macro_disable_io(adapter);
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Get extended SIF registers, start EAGLE, then get normal SIF regs.
|
|
*/
|
|
|
|
macro_setb_bit(handle, control_1, ATULA_CTRL1_SRSX);
|
|
|
|
hwi_start_eagle(adapter);
|
|
|
|
macro_clearb_bit(handle, control_1, ATULA_CTRL1_SRSX);
|
|
|
|
/*
|
|
* 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_atula_set_dio_address(adapter, DIO_LOCATION_EAGLE_DATA_PAGE);
|
|
|
|
/*
|
|
* Set maximum frame size from the ring speed.
|
|
*/
|
|
|
|
adapter->max_frame_size = hwi_get_max_frame_size(adapter);
|
|
adapter->ring_speed = hwi_get_ring_speed(adapter);
|
|
|
|
/*
|
|
* 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(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;
|
|
}
|
|
|
|
/*
|
|
* Enable interrupts at adapter (do this even in polling mode).
|
|
* Hence when polling still 'using' interrupt channel.
|
|
* So do not use card interrupt switch setting shared by other devices.
|
|
*/
|
|
|
|
macro_setb_bit( handle, control_1, ATULA_CTRL1_SINTREN);
|
|
macro_setb_bit( handle, control_2, ATULA_CTRL2_INTEN);
|
|
|
|
/*
|
|
* Set up PIO or DMA as required.
|
|
*/
|
|
|
|
if (adapter->transfer_mode == DMA_DATA_TRANSFER_MODE)
|
|
{
|
|
/*
|
|
* Bus master DMA. This is not possible for 16/4 PC adapters.
|
|
* Enable DMA at adapter and then call system service routine.
|
|
* Must enable DMA at adapter before enable DMA channel
|
|
* otherwise machine will 'crash'. Also important that DMA
|
|
* channel is correct for same reason. dma_on field is used
|
|
* when disabling DMA for adapter.
|
|
*/
|
|
|
|
macro_setb_bit(handle, control_6, ATULA_CTRL6_DMAEN);
|
|
|
|
adapter->dma_on = sys_enable_dma_channel(handle, adapter->dma_channel);
|
|
|
|
/*
|
|
* If we fail to enable dma channel then fill in error record
|
|
* and return also disable DMA at adapter because of failure.
|
|
*/
|
|
|
|
if (!adapter->dma_on)
|
|
{
|
|
macro_clearb_bit(handle, control_6, ATULA_CTRL6_DMAEN);
|
|
|
|
adapter->error_record.type = ERROR_TYPE_HWI;
|
|
adapter->error_record.value = HWI_E_0C_FAIL_DMA_ENABLE;
|
|
|
|
#ifndef FTK_NO_IO_ENABLE
|
|
macro_disable_io(adapter);
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* PIO mode. This is only data transfer mode possible for
|
|
* 16/4 PC adapters. Enable PIO interrupt.
|
|
*/
|
|
|
|
macro_setb_bit(handle, control_2, ATULA_CTRL2_SHRQEN);
|
|
}
|
|
|
|
#ifndef FTK_NO_IO_ENABLE
|
|
macro_disable_io(adapter);
|
|
#endif
|
|
|
|
/*
|
|
* Return successfully.
|
|
*/
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* hwi_atula_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_atula_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 or by the
|
|
* ATULA in order to do a PIO data transfer. Note it could in fact be the
|
|
* case that no interrupt has occured on the particular adapter being
|
|
* checked.
|
|
*
|
|
* On 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 PIO interrupts, the length, direction and physical address of the
|
|
* transfer is determined. A system provided routine is called to do the
|
|
* data transfer itself. Note the EAGLE thinks it is doing a DMA transfer
|
|
* - it is the ATULA which allows us to do it via in/out instructions. Also
|
|
* note that the IO location for the PIO is mapped onto the location of the
|
|
* EAGLE SIFDAT register - the PIO does not actually use the SIFDAT
|
|
* register so it's value is not effected by this routine.
|
|
*
|
|
* RETURNS :
|
|
* =========
|
|
*
|
|
* The routine always successfully completes.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#ifdef FTK_IRQ_FUNCTION
|
|
#pragma FTK_IRQ_FUNCTION(hwi_atula_interrupt_handler)
|
|
#endif
|
|
|
|
export void
|
|
hwi_atula_interrupt_handler(
|
|
ADAPTER * adapter
|
|
)
|
|
{
|
|
ADAPTER_HANDLE handle = adapter->adapter_handle;
|
|
WORD control_1 = adapter->io_location + ATULA_CONTROL_REGISTER_1;
|
|
WORD control_2 = adapter->io_location + ATULA_CONTROL_REGISTER_2;
|
|
WORD status = adapter->io_location + ATULA_STATUS_REGISTER;
|
|
WORD control_7 = adapter->io_location + ATULA_CONTROL_REGISTER_7;
|
|
WORD sifadr = adapter->sif_adr;
|
|
WORD sifdat = adapter->sif_dat;
|
|
WORD sifint = adapter->sif_int;
|
|
WORD sifint_value;
|
|
WORD sifint_tmp;
|
|
BYTE FAR * pio_virtaddr;
|
|
WORD pio_len_bytes;
|
|
WBOOLEAN pio_from_adapter;
|
|
WORD saved_sifadr;
|
|
UINT dummy;
|
|
DWORD dma_high_word;
|
|
WORD dma_low_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.
|
|
*/
|
|
|
|
if ((sys_insb(handle, control_7) & ATULA_CTRL7_SINTR) != 0)
|
|
{
|
|
/*
|
|
* SIF interrupt has occurred. SRB free, adapter check
|
|
* or received frame interrupt.
|
|
*/
|
|
|
|
/*
|
|
* Toggle SIF interrupt enable to acknowledge interrupt at ATULA.
|
|
*/
|
|
|
|
macro_clearb_bit(handle, control_1, ATULA_CTRL1_SINTREN);
|
|
macro_setb_bit(handle, control_1, ATULA_CTRL1_SINTREN);
|
|
|
|
/*
|
|
* Clear EAGLE_SIFINT_HOST_IRQ to acknowledge interrupt at SIF.
|
|
*/
|
|
|
|
/*
|
|
* WARNING: Do NOT reorder the clearing of the SIFINT register with
|
|
* the reading of it. If SIFINT is cleared after reading it, any
|
|
* interrupts raised after reading it will be lost. Admittedly
|
|
* this is a small time frame, but it is important.
|
|
*/
|
|
|
|
sys_outsw(handle, sifint, 0);
|
|
|
|
/*
|
|
* Record the EAGLE SIF interrupt register value.
|
|
*/
|
|
|
|
/*
|
|
* WARNING: Continue to read the SIFINT register until it is stable
|
|
* because of a potential problem involving the host reading the
|
|
* register after the adapter has written the low byte of it, but
|
|
* before it has written the high byte. Failure to wait for the
|
|
* SIFINT register to settle can cause spurious interrupts.
|
|
*/
|
|
|
|
sifint_value = sys_insw(handle, sifint);
|
|
do
|
|
{
|
|
sifint_tmp = sifint_value;
|
|
sifint_value = sys_insw(handle, sifint);
|
|
}
|
|
while (sifint_tmp != sifint_value);
|
|
|
|
/*
|
|
* Acknowledge/clear interrupt at interrupt controller.
|
|
*/
|
|
|
|
#ifndef FTK_NO_CLEAR_IRQ
|
|
sys_clear_controller_interrupt(handle, adapter->interrupt_number);
|
|
#endif
|
|
|
|
/*
|
|
* Toggle interrupt enable bit to regenerate any lost interrupts.
|
|
* Need do this because using edge triggered interrupts.
|
|
*/
|
|
|
|
macro_clearb_bit(handle, control_2, ATULA_CTRL2_INTEN);
|
|
macro_setb_bit(handle, control_2, ATULA_CTRL2_INTEN);
|
|
|
|
/*
|
|
* Call driver with details of SIF interrupt.
|
|
*/
|
|
driver_interrupt_entry(handle, adapter, sifint_value);
|
|
}
|
|
else if ((sys_insb(handle, control_2) & ATULA_CTRL2_SHRQ) != 0)
|
|
{
|
|
/*
|
|
* PIO interrupt has occurred. Data transfer to/from adapter
|
|
* interrupt.
|
|
*/
|
|
|
|
/*
|
|
* Toggle PIO interrupt enable to acknowledge interrupt at ATULA.
|
|
*/
|
|
|
|
macro_clearb_bit(handle, control_2, ATULA_CTRL2_SHRQEN);
|
|
macro_setb_bit(handle, control_2, ATULA_CTRL2_SHRQEN);
|
|
|
|
/*
|
|
* We must preserve the value of SIF address in case we have
|
|
* interrupted someone who relies on it not chaning.
|
|
*/
|
|
|
|
saved_sifadr = sys_insw(handle, adapter->sif_adr);
|
|
|
|
/*
|
|
* Read the virtual address for the PIO through DIO space from the
|
|
* SIF registers. Because the SIF thinks that it is doing real DMA,
|
|
* the SDMAADR/SDMAADX registers cannot be paged in, so they must
|
|
* be read from their memory mapped locations in Eagle memory.
|
|
*/
|
|
|
|
sys_outsw(handle, sifadr, DIO_LOCATION_EXT_DMA_ADDR);
|
|
dma_high_word = (DWORD) sys_insw(handle, sifdat);
|
|
|
|
sys_outsw(handle, sifadr, DIO_LOCATION_DMA_ADDR);
|
|
dma_low_word = sys_insw(handle, sifdat);
|
|
|
|
pio_virtaddr = (BYTE FAR *) ((dma_high_word << 16) | ((DWORD) dma_low_word));
|
|
|
|
/*
|
|
* Read the DMA length from the extended SIF register.
|
|
*/
|
|
|
|
macro_setb_bit(handle, control_1, ATULA_CTRL1_SRSX);
|
|
pio_len_bytes = sys_insw(handle, adapter->sif_dmalen);
|
|
macro_clearb_bit( handle, control_1, ATULA_CTRL1_SRSX);
|
|
|
|
/*
|
|
* If we are talking to the ISA Client/P, we need to use software
|
|
* handshaking across the PIO. Start by writing zero to a magic
|
|
* location on the adapter.
|
|
*/
|
|
|
|
if (adapter->adapter_card_revision == ADAPTER_CARD_16_4_ISA_C_P)
|
|
{
|
|
sys_outsw(handle, sifadr, DIO_LOCATION_DMA_CONTROL);
|
|
sys_outsw(handle, sifdat, 0);
|
|
}
|
|
|
|
/*
|
|
* Start what the SIF thinks is a DMA but is PIO instead.
|
|
*/
|
|
|
|
macro_setb_bit(handle, control_2, ATULA_CTRL2_SHLDA);
|
|
|
|
/*
|
|
* Determine what direction the data transfer is to take place in.
|
|
*/
|
|
|
|
pio_from_adapter = sys_insb(handle, status) & ATULA_STATUS_SDDIR;
|
|
|
|
/*
|
|
* Do the actual data transfer. Note that Fastmac only copies whole
|
|
* WORDs 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_virtaddr % 2)
|
|
{
|
|
pio_len_bytes--;
|
|
*(pio_virtaddr++) =
|
|
sys_insb(handle, (WORD) (sifdat + ATULA_PIO_IO_LOC + 1));
|
|
}
|
|
|
|
/*
|
|
* Now transfer the bulk of the data.
|
|
*/
|
|
|
|
sys_rep_insw(
|
|
handle,
|
|
(WORD) (sifdat + ATULA_PIO_IO_LOC),
|
|
pio_virtaddr,
|
|
(WORD) (pio_len_bytes >> 1)
|
|
);
|
|
|
|
/*
|
|
* Finally transfer any trailing byte.
|
|
*/
|
|
|
|
if (pio_len_bytes % 2)
|
|
{
|
|
*(pio_virtaddr + pio_len_bytes - 1) =
|
|
sys_insb(handle, (WORD) (sifdat + ATULA_PIO_IO_LOC));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Transfer into adapter memory from the host.
|
|
*/
|
|
|
|
/*
|
|
* If we are talking to an ISA Client/P card, we need to assert
|
|
* the -CLKDIV signal to prevent dips in one of the signals to
|
|
* the ATULA. This is only needed for ISA/C/P transmits.
|
|
*/
|
|
|
|
if (adapter->adapter_card_revision == ADAPTER_CARD_16_4_ISA_C_P &&
|
|
pio_len_bytes > 13)
|
|
{
|
|
/*
|
|
* Need to write ATP_RSCTRL to ATP_EISA_REV2_CTRL reg.
|
|
*/
|
|
|
|
sys_outsb(
|
|
handle,
|
|
(WORD) (adapter->io_location + AT_P_EISA_REV2_CTRL_REG),
|
|
ATP_RSCTRL
|
|
);
|
|
}
|
|
|
|
/*
|
|
* First, check if host address is on an odd byte boundary.
|
|
*/
|
|
|
|
if ((card_t) pio_virtaddr % 2)
|
|
{
|
|
pio_len_bytes--;
|
|
sys_outsb(
|
|
handle,
|
|
(WORD) (sifdat + ATULA_PIO_IO_LOC + 1),
|
|
*(pio_virtaddr++)
|
|
);
|
|
}
|
|
|
|
/*
|
|
* Now transfer the bulk of the data.
|
|
*/
|
|
|
|
sys_rep_outsw(
|
|
handle,
|
|
(WORD) (sifdat + ATULA_PIO_IO_LOC),
|
|
pio_virtaddr,
|
|
(WORD) (pio_len_bytes >> 1)
|
|
);
|
|
|
|
/*
|
|
* Finally transfer any trailing byte.
|
|
*/
|
|
|
|
if (pio_len_bytes % 2)
|
|
{
|
|
sys_outsb(
|
|
handle,
|
|
(WORD) (sifdat + ATULA_PIO_IO_LOC),
|
|
*(pio_virtaddr + pio_len_bytes - 1)
|
|
);
|
|
}
|
|
|
|
/*
|
|
* If we are talking to an ISA Client/P card, we need to remove
|
|
* the -CLKDIV signal that we asserted above.
|
|
*/
|
|
|
|
if (adapter->adapter_card_revision == ADAPTER_CARD_16_4_ISA_C_P &&
|
|
pio_len_bytes > 13)
|
|
{
|
|
/*
|
|
* Deassert the -CLKDIV signal that we asserted up above.
|
|
*/
|
|
|
|
sys_outsb(
|
|
handle,
|
|
(WORD) (adapter->io_location + AT_P_EISA_REV2_CTRL_REG),
|
|
ATP_RSCTRL | ATP_CLKDIV
|
|
);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If we are talking to an ISA Client/P card, we now finish off the
|
|
* software handshake process that we started at the beginning.
|
|
*/
|
|
|
|
if (adapter->adapter_card_revision == ADAPTER_CARD_16_4_ISA_C_P)
|
|
{
|
|
/*
|
|
* Do a read first - otherwise the write might fail.
|
|
*/
|
|
|
|
sys_outsw(handle, sifadr, DIO_LOCATION_DMA_CONTROL);
|
|
dummy = sys_insw(handle, sifdat);
|
|
|
|
sys_outsw(handle, sifadr, DIO_LOCATION_DMA_CONTROL);
|
|
sys_outsw(handle, sifdat, 0xFFFF);
|
|
}
|
|
|
|
/*
|
|
* Restore the SIF address.
|
|
*/
|
|
|
|
sys_outsw(handle, adapter->sif_adr, saved_sifadr);
|
|
|
|
/*
|
|
* Acknowledge/clear interrupt at interrupt controller.
|
|
*/
|
|
|
|
#ifndef FTK_NO_CLEAR_IRQ
|
|
sys_clear_controller_interrupt(handle, adapter->interrupt_number);
|
|
#endif
|
|
|
|
/*
|
|
* Toggle interrupt enable bit to regenerate any lost interrupts.
|
|
*/
|
|
|
|
macro_clearb_bit(handle, control_2, ATULA_CTRL2_INTEN);
|
|
macro_setb_bit(handle, control_2, ATULA_CTRL2_INTEN);
|
|
}
|
|
|
|
/*
|
|
* Let system know we have finished accessing the IO ports.
|
|
*/
|
|
|
|
#ifndef FTK_NO_IO_ENABLE
|
|
macro_disable_io(adapter);
|
|
#endif
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* hwi_atula_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_atula_remove_card routine is called by hwi_remove_adapter. It
|
|
* disables DMA and 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_atula_remove_card)
|
|
#endif
|
|
|
|
export void
|
|
hwi_atula_remove_card(
|
|
ADAPTER * adapter
|
|
)
|
|
{
|
|
ADAPTER_HANDLE handle = adapter->adapter_handle;
|
|
WORD control_1 = adapter->io_location + ATULA_CONTROL_REGISTER_1;
|
|
WORD control_2 = adapter->io_location + ATULA_CONTROL_REGISTER_2;
|
|
WORD control_6 = adapter->io_location + ATULA_CONTROL_REGISTER_6;
|
|
|
|
/*
|
|
* Disable DMA if successfully enabled. DMA will only be on if not
|
|
* in PIO mode. DMA channel must be disabled before disabling DMA
|
|
* at adapter otherwise machine will 'crash'.
|
|
*/
|
|
|
|
#ifndef FTK_NO_IO_ENABLE
|
|
macro_enable_io(adapter);
|
|
#endif
|
|
|
|
if (adapter->dma_on)
|
|
{
|
|
sys_disable_dma_channel(handle, adapter->dma_channel);
|
|
|
|
macro_clearb_bit(handle, control_6, ATULA_CTRL6_DMAEN);
|
|
|
|
adapter->dma_on = FALSE;
|
|
}
|
|
|
|
/*
|
|
* Disable interrupts being generated. Only need to do this if
|
|
* interrupts successfully enabled. Interrupt must be disabled at
|
|
* adapter before unpatching interrupt. Even in polling mode we
|
|
* must turn off interrupts at adapter.
|
|
*/
|
|
|
|
if (adapter->interrupts_on)
|
|
{
|
|
macro_clearb_bit(handle, control_2, ATULA_CTRL2_INTEN);
|
|
|
|
if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
|
|
{
|
|
sys_disable_irq_channel(handle, adapter->interrupt_number);
|
|
}
|
|
|
|
adapter->interrupts_on = FALSE;
|
|
}
|
|
|
|
/*
|
|
* Perform adapter reset, set ATULA_CTRL1_NSRESET low.
|
|
*/
|
|
|
|
sys_outsb(handle, control_1, 0);
|
|
|
|
#ifndef FTK_NO_IO_ENABLE
|
|
macro_disable_io(adapter);
|
|
#endif
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* hwi_atula_set_dio_address
|
|
* =========================
|
|
* PARAMETERS :
|
|
* ============
|
|
*
|
|
* ADAPTER * adapter
|
|
*
|
|
* This structure is used to identify and record specific information about
|
|
* the required adapter.
|
|
*
|
|
* DWORD dio_address
|
|
*
|
|
* The 32 bit DIO address to select.
|
|
*
|
|
* BODY :
|
|
* ======
|
|
*
|
|
* The hwi_atula_set_dio_address routine is used, with ATULA 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_atula_set_dio_address)
|
|
#endif
|
|
|
|
export void
|
|
hwi_atula_set_dio_address(
|
|
ADAPTER * adapter,
|
|
DWORD dio_address
|
|
)
|
|
{
|
|
ADAPTER_HANDLE handle = adapter->adapter_handle;
|
|
WORD control_1 = adapter->io_location + ATULA_CONTROL_REGISTER_1;
|
|
WORD sif_dio_adr = adapter->sif_adr;
|
|
WORD sif_dio_adrx = adapter->sif_adx;
|
|
|
|
/*
|
|
* Page in extended SIF registers.
|
|
*/
|
|
|
|
macro_setb_bit(handle, control_1, ATULA_CTRL1_SRSX);
|
|
|
|
/*
|
|
* Load extended DIO address register with top 16 bits of address.
|
|
* Always load extended address register first.
|
|
*/
|
|
|
|
sys_outsw(handle, sif_dio_adrx, (WORD) (dio_address >> 16));
|
|
|
|
/*
|
|
* Return to having normal SIF registers paged in.
|
|
*/
|
|
|
|
macro_clearb_bit(handle, control_1, ATULA_CTRL1_SRSX);
|
|
|
|
/*
|
|
* Load DIO address register with low 16 bits of address.
|
|
*/
|
|
|
|
sys_outsw(handle, sif_dio_adr, (WORD) (dio_address & 0x0000FFFF));
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| LOCAL PROCEDURES
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| hwi_atula_valid_io_location
|
|
| ===========================
|
|
|
|
|
| The hwi_atula_valid_io_location routine checks to see if the user has
|
|
| supplied a valid IO location for an ATULA based adapter card.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
#ifdef FTK_INIT_FUNCTION
|
|
#pragma FTK_INIT_FUNCTION(hwi_atula_valid_io_location)
|
|
#endif
|
|
|
|
local WBOOLEAN
|
|
hwi_atula_valid_io_location(
|
|
WORD io_location
|
|
)
|
|
{
|
|
WBOOLEAN io_valid;
|
|
|
|
switch (io_location)
|
|
{
|
|
case 0x0A20 :
|
|
case 0x1A20 :
|
|
case 0x2A20 :
|
|
case 0x3A20 :
|
|
|
|
/*
|
|
* 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_atula_read_node_address
|
|
| ===========================
|
|
|
|
|
| The hwi_atula_read_node_address routine reads in the node address that
|
|
| is stored in the second page of the BIA PROM on ATULA cards.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
#ifdef FTK_INIT_FUNCTION
|
|
#pragma FTK_INIT_FUNCTION(hwi_atula_read_node_address)
|
|
#endif
|
|
|
|
local void
|
|
hwi_atula_read_node_address(
|
|
ADAPTER * adapter
|
|
)
|
|
{
|
|
ADAPTER_HANDLE handle = adapter->adapter_handle;
|
|
WORD control_7 = adapter->io_location + ATULA_CONTROL_REGISTER_7;
|
|
WORD bia_prom = adapter->io_location + ATULA_BIA_PROM;
|
|
WORD bia_prom_address = bia_prom + BIA_PROM_NODE_ADDRESS;
|
|
WORD index;
|
|
|
|
/*
|
|
* Page in second page of BIA PROM containing node address.
|
|
*/
|
|
|
|
macro_setb_bit(handle, control_7, ATULA_CTRL7_PAGE);
|
|
|
|
/*
|
|
* Read node address from BIA PROM.
|
|
*/
|
|
|
|
for (index = 0; index < 6; index++)
|
|
{
|
|
adapter->permanent_address.byte[index] =
|
|
sys_insb(handle, (WORD) (bia_prom_address + index));
|
|
}
|
|
|
|
/*
|
|
* Restore first page of BIA PROM.
|
|
*/
|
|
|
|
macro_clearb_bit(handle, control_7, ATULA_CTRL7_PAGE);
|
|
}
|
|
|
|
|
|
#ifndef FTK_NO_PROBE
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| hwi_atula_get_irq_channel
|
|
| =========================
|
|
|
|
|
| The hwi_atula_get_irq_channel routine attempts to determine the
|
|
| interrupt number that an ATULA card is using. It does this by calling
|
|
| system provided routine. It does not always succeed in finding the
|
|
| interrupt number being used.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
#ifdef FTK_INIT_FUNCTION
|
|
#pragma FTK_INIT_FUNCTION(hwi_atula_get_irq_channel)
|
|
#endif
|
|
|
|
local WORD
|
|
hwi_atula_get_irq_channel(
|
|
WORD io_location,
|
|
UINT adapter_revision
|
|
)
|
|
{
|
|
WORD control_2 = io_location + ATULA_CONTROL_REGISTER_2;
|
|
WORD control_7 = io_location + ATULA_CONTROL_REGISTER_7;
|
|
BYTE original_ctrl7;
|
|
BYTE irq_off;
|
|
BYTE irq_on;
|
|
WORD irq;
|
|
|
|
/*
|
|
* Enable interrupts at adapter card temporarily.
|
|
*/
|
|
|
|
macro_probe_setb_bit(control_2, ATULA_CTRL2_INTEN);
|
|
|
|
/*
|
|
* Save contents of ATULA control register 7.
|
|
*/
|
|
|
|
original_ctrl7 = sys_probe_insb(control_7);
|
|
|
|
/*
|
|
* Current contents of control register 7 does not generate interrupt.
|
|
*/
|
|
|
|
irq_off = original_ctrl7;
|
|
|
|
/*
|
|
* If set user interrupt bit then will generate interrupt.
|
|
*/
|
|
|
|
irq_on = irq_off | ATULA_CTRL7_UINT;
|
|
|
|
/*
|
|
* Call system provided routine to attempt to dicover interrupt number.
|
|
* Routine returns FTK_NOT_DETERMINED if not get interrupt number.
|
|
*/
|
|
|
|
irq = sys_atula_find_irq_channel(control_7, irq_on, irq_off);
|
|
|
|
/*
|
|
* Restore original contents of ATULA control register 7.
|
|
*/
|
|
|
|
sys_probe_outsb(control_7, original_ctrl7);
|
|
|
|
/*
|
|
* Disable interrupts at adapter card.
|
|
*/
|
|
|
|
macro_probe_clearb_bit( control_2, ATULA_CTRL2_INTEN);
|
|
|
|
/*
|
|
* Return discovered interrupt number (could be FTK_NOT_DETERMINED).
|
|
*/
|
|
|
|
return irq;
|
|
}
|
|
#endif
|
|
|
|
#ifndef FTK_NO_PROBE
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| hwi_atula_get_dma_channel
|
|
| =========================
|
|
|
|
|
| The hwi_atula_get_dma_channel routine attempts to determine the DMA
|
|
| channel that an ATULA card is using. It does this by calling a system
|
|
| provided routine.
|
|
|
|
|
| It may be that the system routine does not always succeed in finding the
|
|
| DMA channel being used. However, if the provided system routine is used,
|
|
| then PIO mode is chosen if the DMA channel can not be determined. Hence,
|
|
| in this case, the value FTK_NOT_DETERMINED will never be returned by the
|
|
| hwi_atula_get_dma_channel routine.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
#ifdef FTK_INIT_FUNCTION
|
|
#pragma FTK_INIT_FUNCTION(hwi_atula_get_dma_channel)
|
|
#endif
|
|
|
|
local WORD
|
|
hwi_atula_get_dma_channel(
|
|
WORD io_location ,
|
|
UINT adapter_revision
|
|
)
|
|
{
|
|
WORD control_6 = io_location + ATULA_CONTROL_REGISTER_6;
|
|
WORD bia_prom = io_location + ATULA_BIA_PROM;
|
|
WORD bia_prom_adap = bia_prom + BIA_PROM_ADAPTER_BYTE;
|
|
BYTE original_ctrl6;
|
|
BYTE dma_off;
|
|
BYTE dma_on;
|
|
WORD dma;
|
|
|
|
/*
|
|
* Check to see if an adapter that doesn't support DMA is being used.
|
|
*/
|
|
|
|
if (adapter_revision == ADAPTER_CARD_16_4_PC ||
|
|
adapter_revision == ADAPTER_CARD_16_4_ISA_C ||
|
|
adapter_revision == ADAPTER_CARD_16_4_ISA_C_P)
|
|
{
|
|
dma = 0;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* For the 16/4 AT card, save the contents of control register 6.
|
|
*/
|
|
|
|
original_ctrl6 = sys_probe_insb(control_6);
|
|
|
|
/*
|
|
* Need to enable DMA for bus master.
|
|
*/
|
|
|
|
dma_off = original_ctrl6 |
|
|
ATULA_CTRL6_MODE_BUS_MASTER |
|
|
ATULA_CTRL6_DMAEN;
|
|
|
|
/*
|
|
* Set user generate DMA request bit for turning DMA signal on.
|
|
*/
|
|
|
|
dma_on = dma_off | ATULA_CTRL6_UDRQ;
|
|
|
|
/*
|
|
* Call system provided routine to attempt to dicover DMA channel.
|
|
* Provided routine returns PIO_DATA_TRANSFER_MODE if not find.
|
|
*/
|
|
|
|
dma = sys_atula_find_dma_channel(control_6, dma_on, dma_off);
|
|
|
|
/*
|
|
* Restore original contents of ATULA control register 6.
|
|
*/
|
|
|
|
sys_probe_outsb(control_6, original_ctrl6);
|
|
}
|
|
|
|
/*
|
|
* Return discovered DMA channel details.
|
|
*/
|
|
|
|
return dma;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| hwi_atula_valid_transfer_mode
|
|
| =============================
|
|
|
|
|
| The hwi_atula_valid_transfer mode routine checks to see if the user has
|
|
| supplied a valid transfer mode for an ATULA based adapter card.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
#ifdef FTK_INIT_FUNCTION
|
|
#pragma FTK_INIT_FUNCTION(hwi_atula_valid_transfer_mode)
|
|
#endif
|
|
|
|
local WBOOLEAN
|
|
hwi_atula_valid_transfer_mode(
|
|
ADAPTER * adapter
|
|
)
|
|
{
|
|
WBOOLEAN mode_valid;
|
|
|
|
/*
|
|
* Assume that transfer mode is valid.
|
|
*/
|
|
|
|
mode_valid = TRUE;
|
|
|
|
/*
|
|
* MMIO is always invalid.
|
|
*/
|
|
|
|
if (adapter->transfer_mode == MMIO_DATA_TRANSFER_MODE)
|
|
{
|
|
mode_valid = FALSE;
|
|
}
|
|
|
|
/*
|
|
* PIO is always valid but DMA may not be.
|
|
*/
|
|
|
|
else if (adapter->transfer_mode == DMA_DATA_TRANSFER_MODE)
|
|
{
|
|
if (adapter->adapter_card_revision == ADAPTER_CARD_16_4_PC ||
|
|
adapter->adapter_card_revision == ADAPTER_CARD_16_4_ISA_C ||
|
|
adapter->adapter_card_revision == ADAPTER_CARD_16_4_ISA_C_P)
|
|
{
|
|
mode_valid = FALSE;
|
|
}
|
|
}
|
|
|
|
if (!mode_valid)
|
|
{
|
|
adapter->error_record.type = ERROR_TYPE_HWI;
|
|
adapter->error_record.value = HWI_E_17_BAD_TRANSFER_MODE;
|
|
}
|
|
|
|
return mode_valid;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| hwi_atula_valid_irq_channel
|
|
| ===========================
|
|
|
|
|
| The hwi_atula_valid_irq_channel routine checks to see if the user has
|
|
| supplied a valid interrupt number for an ATULA based adapter card.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
#ifdef FTK_INIT_FUNCTION
|
|
#pragma FTK_INIT_FUNCTION(hwi_atula_valid_irq_channel)
|
|
#endif
|
|
|
|
local WBOOLEAN
|
|
hwi_atula_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)
|
|
{
|
|
/*
|
|
* Check the interrupt number based on adapter type.
|
|
*/
|
|
|
|
if (adapter->adapter_card_revision == ADAPTER_CARD_16_4_PC)
|
|
{
|
|
switch (adapter->interrupt_number)
|
|
{
|
|
case 2 :
|
|
case 3 :
|
|
case 5 :
|
|
case 7 :
|
|
case 9 :
|
|
break;
|
|
|
|
default :
|
|
int_valid = FALSE;
|
|
break;
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (adapter->interrupt_number)
|
|
{
|
|
case 2 :
|
|
case 3 :
|
|
case 5 :
|
|
case 7 :
|
|
case 9 :
|
|
case 10 :
|
|
case 11 :
|
|
case 12 :
|
|
case 15 :
|
|
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;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| hwi_atula_valid_dma_channel
|
|
| ===========================
|
|
|
|
|
| The hwi_atula_valid_dma_channel routine checks to see if the user has
|
|
| supplied a valid DMA channel for an ATULA based adapter card.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
#ifdef FTK_INIT_FUNCTION
|
|
#pragma FTK_INIT_FUNCTION(hwi_atula_valid_dma_channel)
|
|
#endif
|
|
|
|
local WBOOLEAN
|
|
hwi_atula_valid_dma_channel(
|
|
ADAPTER * adapter
|
|
)
|
|
{
|
|
WBOOLEAN dma_valid;
|
|
|
|
/*
|
|
* Assume that DMA channel is valid.
|
|
*/
|
|
|
|
dma_valid = TRUE;
|
|
|
|
/*
|
|
* Only need to check on DMA channel in DMA mode.
|
|
*/
|
|
|
|
if (adapter->transfer_mode == DMA_DATA_TRANSFER_MODE)
|
|
{
|
|
/*
|
|
* Some adapters do not support DMA.
|
|
*/
|
|
|
|
if (adapter->adapter_card_revision == ADAPTER_CARD_16_4_PC ||
|
|
adapter->adapter_card_revision == ADAPTER_CARD_16_4_ISA_C ||
|
|
adapter->adapter_card_revision == ADAPTER_CARD_16_4_ISA_C_P)
|
|
{
|
|
dma_valid = FALSE;
|
|
}
|
|
else if (adapter->adapter_card_revision == ADAPTER_CARD_16_4_AT_P ||
|
|
adapter->adapter_card_revision == ADAPTER_CARD_16_4_FIBRE_P)
|
|
{
|
|
switch (adapter->dma_channel)
|
|
{
|
|
case 3 :
|
|
case 5 :
|
|
case 6 :
|
|
break;
|
|
|
|
default :
|
|
dma_valid = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (adapter->dma_channel)
|
|
{
|
|
case 1 :
|
|
case 3 :
|
|
case 5 :
|
|
case 6 :
|
|
break;
|
|
|
|
default :
|
|
dma_valid = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!dma_valid)
|
|
{
|
|
adapter->error_record.type = ERROR_TYPE_HWI;
|
|
adapter->error_record.value = HWI_E_04_BAD_DMA_CHANNEL;
|
|
}
|
|
|
|
return dma_valid;
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
/**** End of HWI_AT.C file *************************************************/
|