#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: adwlib.c,v 1.45 2022/09/25 18:43:32 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/queue.h>
#include <sys/device.h>
#include <sys/bus.h>
#include <sys/intr.h>
#include <dev/scsipi/scsi_all.h>
#include <dev/scsipi/scsipi_all.h>
#include <dev/scsipi/scsiconf.h>
#include <dev/pci/pcidevs.h>
#include <dev/ic/adwlib.h>
#include <dev/ic/adwmcode.h>
#include <dev/ic/adw.h>
int AdwRamSelfTest(bus_space_tag_t, bus_space_handle_t, u_int8_t);
int AdwLoadMCode(bus_space_tag_t, bus_space_handle_t, u_int16_t *, u_int8_t);
int AdwASC3550Cabling(bus_space_tag_t, bus_space_handle_t, ADW_DVC_CFG *);
int AdwASC38C0800Cabling(bus_space_tag_t, bus_space_handle_t, ADW_DVC_CFG *);
int AdwASC38C1600Cabling(bus_space_tag_t, bus_space_handle_t, ADW_DVC_CFG *);
static u_int16_t AdwGetEEPROMConfig(bus_space_tag_t, bus_space_handle_t,
ADW_EEPROM *);
static void AdwSetEEPROMConfig(bus_space_tag_t, bus_space_handle_t,
ADW_EEPROM *);
static u_int16_t AdwReadEEPWord(bus_space_tag_t, bus_space_handle_t, int);
static void AdwWaitEEPCmd(bus_space_tag_t, bus_space_handle_t);
static void AdwInquiryHandling(ADW_SOFTC *, ADW_SCSI_REQ_Q *);
static void AdwSleepMilliSecond(u_int32_t);
static void AdwDelayMicroSecond(u_int32_t);
static const ADW_EEPROM adw_3550_Default_EEPROM = {
ADW_EEPROM_BIOS_ENABLE,
0x0000,
0xFFFF,
0xFFFF,
{ 0xFFFF },
0xFFFF,
0xFFFF,
0xFFFF,
0,
7,
0,
3,
0,
0,
0,
0xFFE7,
{ 0xFFFF },
{ 0 },
ADW_DEF_MAX_HOST_QNG,
ADW_DEF_MAX_DVC_QNG,
0,
{ 0 },
{ 0,0,0 },
0,
{
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
},
0,
0,
0,
0,
0,
0,
{
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0
},
0,
0,
0,
0,
{ 0,0,0,0 }
};
static const ADW_EEPROM adw_38C0800_Default_EEPROM = {
ADW_EEPROM_BIOS_ENABLE,
0x0000,
0xFFFF,
0xFFFF,
{ 0x4444 },
0xFFFF,
0xFFFF,
0xFFFF,
0,
7,
0,
3,
0,
0,
0,
0xFFE7,
{ 0x4444 },
{ 0x4444 },
ADW_DEF_MAX_HOST_QNG,
ADW_DEF_MAX_DVC_QNG,
0,
{ 0x4444 },
{ 0,0,0 },
0,
{
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
},
0,
0,
0,
0,
0,
0,
{
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0
},
0,
0,
PCI_VENDOR_ADVSYS,
PCI_PRODUCT_ADVSYS_U2W,
{ 0,0,0,0 }
};
static const ADW_EEPROM adw_38C1600_Default_EEPROM = {
ADW_EEPROM_BIOS_ENABLE,
0x0000,
0xFFFF,
0xFFFF,
{ 0x5555 },
0xFFFF,
0xFFFF,
0xFFFF,
0,
7,
0,
3,
0,
0,
0,
0xFFE7,
{ 0x5555 },
{ 0x5555 },
ADW_DEF_MAX_HOST_QNG,
ADW_DEF_MAX_DVC_QNG,
0,
{ 0x5555 },
{ 0,0,0 },
0,
{
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
},
0,
0,
0,
0,
0,
0,
{
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0
},
0,
0,
PCI_VENDOR_ADVSYS,
PCI_PRODUCT_ADVSYS_U3W,
{ 0,0,0,0 }
};
int
AdwInitFromEEPROM(ADW_SOFTC *sc)
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
ADW_EEPROM eep_config;
u_int16_t warn_code;
u_int16_t sdtr_speed = 0;
u_int8_t tid, termination;
int i, j;
warn_code = 0;
if (AdwGetEEPROMConfig(iot, ioh, &eep_config) != eep_config.check_sum) {
warn_code |= ADW_WARN_EEPROM_CHKSUM;
switch(sc->chip_type) {
case ADW_CHIP_ASC3550:
eep_config = adw_3550_Default_EEPROM;
break;
case ADW_CHIP_ASC38C0800:
eep_config = adw_38C0800_Default_EEPROM;
break;
case ADW_CHIP_ASC38C1600:
eep_config = adw_38C1600_Default_EEPROM;
#if 0
XXX TODO!!! if (ASC_PCI_ID2FUNC(sc->cfg.pci_slot_info) != 0) {
#endif
if (sc->cfg.pci_slot_info != 0) {
u_int8_t lsw_msb;
lsw_msb = eep_config.cfg_lsw >> 8;
lsw_msb &= ~(((ADW_EEPROM_BIOS_ENABLE |
ADW_EEPROM_INTAB) >> 8) & 0xFF);
ADW_WRITE_BYTE_REGISTER(iot, ioh,
IOPB_GPIO_CNTL, 0);
if (ADW_READ_BYTE_REGISTER(iot, ioh,
IOPB_GPIO_DATA) & 0x01) {
lsw_msb |= (ADW_EEPROM_INTAB >> 8)
& 0xFF;
}
eep_config.cfg_lsw &= 0x00FF;
eep_config.cfg_lsw |= lsw_msb << 8;
}
break;
}
for (i=2, j=1; i>=0; i--, j++) {
eep_config.serial_number[i] =
AdwReadEEPWord(iot, ioh, ASC_EEP_DVC_CFG_END - j);
}
AdwSetEEPROMConfig(iot, ioh, &eep_config);
}
sc->wdtr_able = eep_config.wdtr_able;
if (sc->chip_type == ADW_CHIP_ASC3550) {
sc->sdtr_able = eep_config.sdtr1.sdtr_able;
sc->ultra_able = eep_config.sdtr2.ultra_able;
} else {
sc->sdtr_speed1 = eep_config.sdtr1.sdtr_speed1;
sc->sdtr_speed2 = eep_config.sdtr2.sdtr_speed2;
sc->sdtr_speed3 = eep_config.sdtr3.sdtr_speed3;
sc->sdtr_speed4 = eep_config.sdtr4.sdtr_speed4;
}
sc->ppr_able = 0;
sc->tagqng_able = eep_config.tagqng_able;
sc->cfg.disc_enable = eep_config.disc_enable;
sc->max_host_qng = eep_config.max_host_qng;
sc->max_dvc_qng = eep_config.max_dvc_qng;
sc->chip_scsi_id = (eep_config.adapter_scsi_id & ADW_MAX_TID);
sc->start_motor = eep_config.start_motor;
sc->scsi_reset_wait = eep_config.scsi_reset_delay;
sc->bios_ctrl = eep_config.bios_ctrl;
sc->no_scam = eep_config.scam_tolerant;
sc->cfg.serial1 = eep_config.serial_number[0];
sc->cfg.serial2 = eep_config.serial_number[1];
sc->cfg.serial3 = eep_config.serial_number[2];
if (sc->chip_type == ADW_CHIP_ASC38C0800 ||
sc->chip_type == ADW_CHIP_ASC38C1600) {
sc->sdtr_able = 0;
for (tid = 0; tid <= ADW_MAX_TID; tid++) {
if (tid == 0) {
sdtr_speed = sc->sdtr_speed1;
} else if (tid == 4) {
sdtr_speed = sc->sdtr_speed2;
} else if (tid == 8) {
sdtr_speed = sc->sdtr_speed3;
} else if (tid == 12) {
sdtr_speed = sc->sdtr_speed4;
}
if (sdtr_speed & ADW_MAX_TID) {
sc->sdtr_able |= (1 << tid);
}
sdtr_speed >>= 4;
}
}
if (eep_config.max_host_qng > ADW_DEF_MAX_HOST_QNG) {
eep_config.max_host_qng = ADW_DEF_MAX_HOST_QNG;
} else if (eep_config.max_host_qng < ADW_DEF_MIN_HOST_QNG)
{
if (eep_config.max_host_qng == 0) {
eep_config.max_host_qng = ADW_DEF_MAX_HOST_QNG;
} else {
eep_config.max_host_qng = ADW_DEF_MIN_HOST_QNG;
}
}
if (eep_config.max_dvc_qng > ADW_DEF_MAX_DVC_QNG) {
eep_config.max_dvc_qng = ADW_DEF_MAX_DVC_QNG;
} else if (eep_config.max_dvc_qng < ADW_DEF_MIN_DVC_QNG) {
if (eep_config.max_dvc_qng == 0) {
eep_config.max_dvc_qng = ADW_DEF_MAX_DVC_QNG;
} else {
eep_config.max_dvc_qng = ADW_DEF_MIN_DVC_QNG;
}
}
if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
eep_config.max_dvc_qng = eep_config.max_host_qng;
}
sc->max_host_qng = eep_config.max_host_qng;
sc->max_dvc_qng = eep_config.max_dvc_qng;
switch(sc->chip_type) {
case ADW_CHIP_ASC3550:
sc->cfg.termination = 0;
switch(eep_config.termination_se) {
case 3:
sc->cfg.termination |= ADW_TERM_CTL_L;
case 2:
sc->cfg.termination |= ADW_TERM_CTL_H;
case 1:
sc->cfg.termination |= ADW_TERM_CTL_SEL;
case 0:
break;
default:
warn_code |= ADW_WARN_EEPROM_TERMINATION;
}
break;
case ADW_CHIP_ASC38C0800:
case ADW_CHIP_ASC38C1600:
switch(eep_config.termination_se) {
case 0:
termination = 0;
break;
case 1:
termination = 0;
break;
case 2:
termination = ADW_TERM_SE_HI;
break;
case 3:
termination = ADW_TERM_SE;
break;
default:
termination = 0;
warn_code |= ADW_WARN_EEPROM_TERMINATION;
}
switch(eep_config.termination_lvd) {
case 0:
sc->cfg.termination = termination;
break;
case 1:
sc->cfg.termination = termination;
break;
case 2:
sc->cfg.termination = termination | ADW_TERM_LVD_HI;
break;
case 3:
sc->cfg.termination = termination | ADW_TERM_LVD;
break;
default:
sc->cfg.termination = termination;
warn_code |= ADW_WARN_EEPROM_TERMINATION;
}
break;
}
return warn_code;
}
int
AdwInitDriver(ADW_SOFTC *sc)
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
u_int16_t error_code;
int word;
int i;
u_int16_t bios_mem[ADW_MC_BIOSLEN/2];
u_int16_t wdtr_able = 0, sdtr_able, tagqng_able;
u_int8_t max_cmd[ADW_MAX_TID + 1];
u_int8_t tid;
error_code = 0;
for (i = 0; i < ADW_MC_BIOSLEN/2; i++) {
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_BIOSMEM+(2*i), bios_mem[i]);
}
switch (sc->chip_type) {
case ADW_CHIP_ASC3550:
if (bios_mem[(ADW_MC_BIOS_SIGNATURE-ADW_MC_BIOSMEM)/2]==0x55AA){
u_int16_t bios_version, major, minor;
bios_version = bios_mem[(ADW_MC_BIOS_VERSION -
ADW_MC_BIOSMEM) / 2];
major = (bios_version >> 12) & 0xF;
minor = (bios_version >> 8) & 0xF;
if (major < 3 || (major == 3 && minor == 1)) {
ADW_READ_WORD_LRAM(iot, ioh, 0x120, wdtr_able);
} else {
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_WDTR_ABLE,
wdtr_able);
}
}
break;
case ADW_CHIP_ASC38C1600:
case ADW_CHIP_ASC38C0800:
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_WDTR_ABLE, wdtr_able);
break;
}
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_SDTR_ABLE, sdtr_able);
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_TAGQNG_ABLE, tagqng_able);
for (tid = 0; tid <= ADW_MAX_TID; tid++) {
ADW_READ_BYTE_LRAM(iot, ioh, ADW_MC_NUMBER_OF_MAX_CMD + tid,
max_cmd[tid]);
}
if((error_code = AdwRamSelfTest(iot, ioh, sc->chip_type))) {
return error_code;
}
;
if((error_code = AdwLoadMCode(iot, ioh, bios_mem, sc->chip_type))) {
return error_code;
}
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_VERSION_DATE, sc->cfg.mcode_date);
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_VERSION_NUM, sc->cfg.mcode_version);
if (sc->cfg.control_flag & CONTROL_FLAG_IGNORE_PERR) {
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_CONTROL_FLAG, word);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_CONTROL_FLAG,
word | CONTROL_FLAG_IGNORE_PERR);
}
switch (sc->chip_type) {
case ADW_CHIP_ASC3550:
ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_DMA_CFG0,
START_CTL_EMFU | READ_CMD_MRM);
break;
case ADW_CHIP_ASC38C0800:
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_SCSI_CFG1,
ADW_READ_WORD_REGISTER(iot, ioh, IOPW_SCSI_CFG1)
| ADW_DIS_TERM_DRV);
ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_DMA_CFG0,
BC_THRESH_ENB | FIFO_THRESH_80B
| START_CTL_TH | READ_CMD_MRM);
break;
case ADW_CHIP_ASC38C1600:
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_SCSI_CFG1,
ADW_READ_WORD_REGISTER(iot, ioh, IOPW_SCSI_CFG1)
| ADW_DIS_TERM_DRV);
if ((sc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) {
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_CONTROL_FLAG, word);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_CONTROL_FLAG,
word | CONTROL_FLAG_ENABLE_AIPP);
}
ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_DMA_CFG0,
FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM);
break;
}
if ((sc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_WDTR_ABLE, sc->wdtr_able);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_ABLE, sc->sdtr_able);
}
switch (sc->chip_type) {
case ADW_CHIP_ASC3550:
word = 0;
for (tid = 0; tid <= ADW_MAX_TID; tid++) {
if (ADW_TID_TO_TIDMASK(tid) & sc->ultra_able) {
word |= (0x3 << (4 * (tid % 4)));
} else {
word |= (0x2 << (4 * (tid % 4)));
}
if (tid == 3) {
ADW_WRITE_WORD_LRAM(iot, ioh,
ADW_MC_SDTR_SPEED1, word);
word = 0;
} else if (tid == 7) {
ADW_WRITE_WORD_LRAM(iot, ioh,
ADW_MC_SDTR_SPEED2, word);
word = 0;
} else if (tid == 11) {
ADW_WRITE_WORD_LRAM(iot, ioh,
ADW_MC_SDTR_SPEED3, word);
word = 0;
} else if (tid == 15) {
ADW_WRITE_WORD_LRAM(iot, ioh,
ADW_MC_SDTR_SPEED4, word);
}
}
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DISC_ENABLE,
sc->cfg.disc_enable);
break;
case ADW_CHIP_ASC38C0800:
case ADW_CHIP_ASC38C1600:
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DISC_ENABLE,
sc->cfg.disc_enable);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_SPEED1,
sc->sdtr_speed1);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_SPEED2,
sc->sdtr_speed2);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_SPEED3,
sc->sdtr_speed3);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_SPEED4,
sc->sdtr_speed4);
break;
}
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DEFAULT_SCSI_CFG0,
ADW_PARITY_EN | ADW_QUEUE_128 | ADW_SEL_TMO_LONG |
ADW_OUR_ID_EN | sc->chip_scsi_id);
switch(sc->chip_type) {
case ADW_CHIP_ASC3550:
error_code = AdwASC3550Cabling(iot, ioh, &sc->cfg);
break;
case ADW_CHIP_ASC38C0800:
error_code = AdwASC38C0800Cabling(iot, ioh, &sc->cfg);
break;
case ADW_CHIP_ASC38C1600:
error_code = AdwASC38C1600Cabling(iot, ioh, &sc->cfg);
break;
}
if(error_code) {
return error_code;
}
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DEFAULT_SEL_MASK,
ADW_TID_TO_TIDMASK(sc->chip_scsi_id));
sc->carr_freelist = AdwInitCarriers(sc->sc_dmamap_carrier,
sc->sc_control->carriers);
if ((sc->icq_sp = sc->carr_freelist) == NULL) {
return ADW_IERR_NO_CARRIER;
}
sc->carr_freelist = ADW_CARRIER_VADDR(sc,
ASC_GET_CARRP(sc->icq_sp->next_ba));
sc->icq_sp->next_ba = htole32(ASC_CQ_STOPPER);
ADW_WRITE_DWORD_LRAM(iot, ioh, ADW_MC_ICQ, le32toh(sc->icq_sp->carr_ba));
if(sc->chip_type == ADW_CHIP_ASC38C1600) {
ADW_WRITE_DWORD_REGISTER(iot, ioh, IOPDW_COMMA,
le32toh(sc->icq_sp->carr_ba));
}
if ((sc->irq_sp = sc->carr_freelist) == NULL) {
return ADW_IERR_NO_CARRIER;
}
sc->carr_freelist = ADW_CARRIER_VADDR(sc,
ASC_GET_CARRP(sc->irq_sp->next_ba));
sc->irq_sp->next_ba = htole32(ASC_CQ_STOPPER);
ADW_WRITE_DWORD_LRAM(iot, ioh, ADW_MC_IRQ, le32toh(sc->irq_sp->carr_ba));
sc->carr_pending_cnt = 0;
ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_INTR_ENABLES,
(ADW_INTR_ENABLE_HOST_INTR | ADW_INTR_ENABLE_GLOBAL_INTR));
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_CODE_BEGIN_ADDR, word);
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_PC, word);
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_RISC_CSR, ADW_RISC_CSR_RUN);
if (sc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS)
{
if (bios_mem[(ADW_MC_BIOS_SIGNATURE - ADW_MC_BIOSMEM)/2] ==
0x55AA) {
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_WDTR_ABLE,
wdtr_able);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_ABLE,
sdtr_able);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_TAGQNG_ABLE,
tagqng_able);
for (tid = 0; tid <= ADW_MAX_TID; tid++) {
ADW_WRITE_BYTE_LRAM(iot, ioh,
ADW_MC_NUMBER_OF_MAX_CMD + tid,
max_cmd[tid]);
}
} else {
if (AdwResetCCB(sc) != ADW_TRUE) {
error_code = ADW_WARN_BUSRESET_ERROR;
}
}
}
return error_code;
}
int
AdwRamSelfTest(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t chip_type)
{
int i;
u_int8_t byte;
if ((chip_type == ADW_CHIP_ASC38C0800) ||
(chip_type == ADW_CHIP_ASC38C1600)) {
for (i = 0; i < 2; i++) {
ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_RAM_BIST,
PRE_TEST_MODE);
AdwSleepMilliSecond(10);
byte = ADW_READ_BYTE_REGISTER(iot, ioh, IOPB_RAM_BIST);
if ((byte & RAM_TEST_DONE) == 0 || (byte & 0x0F) !=
PRE_TEST_VALUE) {
return ADW_IERR_BIST_PRE_TEST;
}
ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_RAM_BIST,
NORMAL_MODE);
AdwSleepMilliSecond(10);
if (ADW_READ_BYTE_REGISTER(iot, ioh, IOPB_RAM_BIST)
!= NORMAL_VALUE) {
return ADW_IERR_BIST_PRE_TEST;
}
}
ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_RAM_BIST, RAM_TEST_MODE);
AdwSleepMilliSecond(10);
byte = ADW_READ_BYTE_REGISTER(iot, ioh, IOPB_RAM_BIST);
if ((byte & RAM_TEST_DONE)==0 || (byte & RAM_TEST_STATUS)!=0) {
return ADW_IERR_BIST_RAM_TEST;
}
ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_RAM_BIST, NORMAL_MODE);
}
return 0;
}
int
AdwLoadMCode(bus_space_tag_t iot, bus_space_handle_t ioh, u_int16_t *bios_mem, u_int8_t chip_type)
{
const u_int8_t *mcode_data;
u_int32_t mcode_chksum;
u_int16_t mcode_size;
u_int32_t sum;
u_int16_t code_sum;
int begin_addr;
int end_addr;
int word;
int adw_memsize;
int adw_mcode_expanded_size;
int i, j;
switch(chip_type) {
case ADW_CHIP_ASC3550:
mcode_data = (const u_int8_t *)adw_asc3550_mcode_data.mcode_data;
mcode_chksum = (u_int32_t)adw_asc3550_mcode_data.mcode_chksum;
mcode_size = (u_int16_t)adw_asc3550_mcode_data.mcode_size;
adw_memsize = ADW_3550_MEMSIZE;
break;
case ADW_CHIP_ASC38C0800:
mcode_data = (const u_int8_t *)adw_asc38C0800_mcode_data.mcode_data;
mcode_chksum =(u_int32_t)adw_asc38C0800_mcode_data.mcode_chksum;
mcode_size = (u_int16_t)adw_asc38C0800_mcode_data.mcode_size;
adw_memsize = ADW_38C0800_MEMSIZE;
break;
case ADW_CHIP_ASC38C1600:
mcode_data = (const u_int8_t *)adw_asc38C1600_mcode_data.mcode_data;
mcode_chksum =(u_int32_t)adw_asc38C1600_mcode_data.mcode_chksum;
mcode_size = (u_int16_t)adw_asc38C1600_mcode_data.mcode_size;
adw_memsize = ADW_38C1600_MEMSIZE;
break;
default:
return (EINVAL);
}
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_RAM_ADDR, 0);
word = 0;
for (i = 253 * 2; i < mcode_size; i++) {
if (mcode_data[i] == 0xff) {
for (j = 0; j < mcode_data[i + 1]; j++) {
ADW_WRITE_WORD_AUTO_INC_LRAM(iot, ioh,
(((u_int16_t)mcode_data[i + 3] << 8) |
mcode_data[i + 2]));
word++;
}
i += 3;
} else if (mcode_data[i] == 0xfe) {
ADW_WRITE_WORD_AUTO_INC_LRAM(iot, ioh,
(((u_int16_t)mcode_data[i + 2] << 8) |
mcode_data[i + 1]));
i += 2;
word++;
} else {
ADW_WRITE_WORD_AUTO_INC_LRAM(iot, ioh, (((u_int16_t)
mcode_data[(mcode_data[i] * 2) + 1] <<8) |
mcode_data[mcode_data[i] * 2]));
word++;
}
}
word *= 2;
adw_mcode_expanded_size = word;
for (; word < adw_memsize; word += 2) {
ADW_WRITE_WORD_AUTO_INC_LRAM(iot, ioh, 0);
}
sum = 0;
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_RAM_ADDR, 0);
for (word = 0; word < adw_mcode_expanded_size; word += 2) {
sum += ADW_READ_WORD_AUTO_INC_LRAM(iot, ioh);
}
if (sum != mcode_chksum) {
return ADW_IERR_MCODE_CHKSUM;
}
for (i = 0; i < ADW_MC_BIOSLEN/2; i++) {
if(chip_type == ADW_CHIP_ASC3550) {
ADW_WRITE_BYTE_LRAM(iot, ioh, ADW_MC_BIOSMEM + (2 * i),
bios_mem[i]);
} else {
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_BIOSMEM + (2 * i),
bios_mem[i]);
}
}
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_CODE_BEGIN_ADDR, begin_addr);
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_CODE_END_ADDR, end_addr);
code_sum = 0;
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_RAM_ADDR, begin_addr);
for (word = begin_addr; word < end_addr; word += 2) {
code_sum += ADW_READ_WORD_AUTO_INC_LRAM(iot, ioh);
}
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_CODE_CHK_SUM, code_sum);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_CHIP_TYPE, chip_type);
return 0;
}
int
AdwASC3550Cabling(bus_space_tag_t iot, bus_space_handle_t ioh, ADW_DVC_CFG *cfg)
{
u_int16_t scsi_cfg1;
scsi_cfg1 = ADW_READ_WORD_REGISTER(iot, ioh, IOPW_SCSI_CFG1);
if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
(scsi_cfg1 & CABLE_ILLEGAL_B) == 0) {
return ADW_IERR_ILLEGAL_CONNECTION;
}
if ((ADW_READ_WORD_REGISTER(iot,ioh, IOPW_SCSI_CTRL) & 0x3F07)==0x3F07){
return ADW_IERR_REVERSED_CABLE;
}
if ((scsi_cfg1 & ADW_DIFF_MODE) &&
(scsi_cfg1 & ADW_DIFF_SENSE) == 0) {
return ADW_IERR_SINGLE_END_DEVICE;
}
if (cfg->termination == 0) {
cfg->termination |= ADW_TERM_CTL_SEL;
switch(scsi_cfg1 & ADW_CABLE_DETECT) {
case 0x3: case 0x7: case 0xB:
case 0xD: case 0xE: case 0xF:
cfg->termination |=
(ADW_TERM_CTL_H | ADW_TERM_CTL_L);
break;
case 0x1: case 0x5: case 0x9:
case 0xA: case 0xC:
cfg->termination |= ADW_TERM_CTL_H;
break;
case 0x2: case 0x6:
break;
}
}
scsi_cfg1 &= ~ADW_TERM_CTL;
scsi_cfg1 |= (ADW_TERM_CTL_SEL | (~cfg->termination & ADW_TERM_CTL));
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DEFAULT_SCSI_CFG1,
ADW_FLTR_DISABLE | scsi_cfg1);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DEFAULT_MEM_CFG,
ADW_BIOS_EN | ADW_RAM_SZ_8KB);
return 0;
}
int
AdwASC38C0800Cabling(bus_space_tag_t iot, bus_space_handle_t ioh, ADW_DVC_CFG *cfg)
{
u_int16_t scsi_cfg1;
scsi_cfg1 = ADW_READ_WORD_REGISTER(iot, ioh, IOPW_SCSI_CFG1);
if ((ADW_READ_WORD_REGISTER(iot,ioh, IOPW_SCSI_CTRL) & 0x3F07)==0x3F07){
return ADW_IERR_REVERSED_CABLE;
}
if (scsi_cfg1 & ADW_HVD) {
return ADW_IERR_HVD_DEVICE;
}
if ((cfg->termination & ADW_TERM_SE) == 0) {
switch(scsi_cfg1 & ADW_C_DET_SE) {
case 0x1: case 0x2: case 0x3:
cfg->termination |= ADW_TERM_SE;
break;
case 0x0:
cfg->termination |= ADW_TERM_SE_HI;
break;
}
}
if ((cfg->termination & ADW_TERM_LVD) == 0) {
switch(scsi_cfg1 & ADW_C_DET_LVD) {
case 0x4: case 0x8: case 0xC:
cfg->termination |= ADW_TERM_LVD;
break;
case 0x0:
break;
}
}
scsi_cfg1 &= (~ADW_TERM_SE & ~ADW_TERM_LVD);
scsi_cfg1 |= (~cfg->termination & 0xF0);
scsi_cfg1 &= (~ADW_BIG_ENDIAN & ~ADW_DIS_TERM_DRV &
~ADW_TERM_POL & ~ADW_HVD_LVD_SE);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DEFAULT_MEM_CFG,
ADW_BIOS_EN | ADW_RAM_SZ_16KB);
return 0;
}
int
AdwASC38C1600Cabling(bus_space_tag_t iot, bus_space_handle_t ioh, ADW_DVC_CFG *cfg)
{
u_int16_t scsi_cfg1;
scsi_cfg1 = ADW_READ_WORD_REGISTER(iot, ioh, IOPW_SCSI_CFG1);
if ((ADW_READ_WORD_REGISTER(iot,ioh, IOPW_SCSI_CTRL) & 0x3F07)==0x3F07){
return ADW_IERR_REVERSED_CABLE;
}
if (scsi_cfg1 & ADW_HVD) {
return ADW_IERR_HVD_DEVICE;
}
if ((cfg->termination & ADW_TERM_SE) == 0) {
switch(scsi_cfg1 & ADW_C_DET_SE) {
case 0x1: case 0x2: case 0x3:
cfg->termination |= ADW_TERM_SE;
break;
case 0x0:
#if 0
if (ASC_PCI_ID2FUNC(cfg->pci_slot_info) == 0) {
}
else
#endif
{
cfg->termination |= ADW_TERM_SE_HI;
}
break;
}
}
scsi_cfg1 &= ~ADW_TERM_SE;
scsi_cfg1 |= (~cfg->termination & ADW_TERM_SE);
scsi_cfg1 &= (~ADW_BIG_ENDIAN & ~ADW_DIS_TERM_DRV & ~ADW_TERM_POL);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_DEFAULT_MEM_CFG,
ADW_BIOS_EN | ADW_RAM_SZ_32KB);
return 0;
}
static u_int16_t
AdwGetEEPROMConfig(bus_space_tag_t iot, bus_space_handle_t ioh, ADW_EEPROM *cfg_buf)
{
u_int16_t wval, chksum;
u_int16_t *wbuf;
int eep_addr;
wbuf = (u_int16_t *) cfg_buf;
chksum = 0;
for (eep_addr = ASC_EEP_DVC_CFG_BEGIN;
eep_addr < ASC_EEP_DVC_CFG_END;
eep_addr++, wbuf++) {
wval = AdwReadEEPWord(iot, ioh, eep_addr);
chksum += wval;
*wbuf = wval;
}
*wbuf = AdwReadEEPWord(iot, ioh, eep_addr);
wbuf++;
for (eep_addr = ASC_EEP_DVC_CTL_BEGIN;
eep_addr < ASC_EEP_MAX_WORD_ADDR;
eep_addr++, wbuf++) {
*wbuf = AdwReadEEPWord(iot, ioh, eep_addr);
}
return chksum;
}
static u_int16_t
AdwReadEEPWord(bus_space_tag_t iot, bus_space_handle_t ioh, int eep_word_addr)
{
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_CMD,
ASC_EEP_CMD_READ | eep_word_addr);
AdwWaitEEPCmd(iot, ioh);
return ADW_READ_WORD_REGISTER(iot, ioh, IOPW_EE_DATA);
}
static void
AdwWaitEEPCmd(bus_space_tag_t iot, bus_space_handle_t ioh)
{
int eep_delay_ms;
for (eep_delay_ms = 0; eep_delay_ms < ASC_EEP_DELAY_MS; eep_delay_ms++){
if (ADW_READ_WORD_REGISTER(iot, ioh, IOPW_EE_CMD) &
ASC_EEP_CMD_DONE) {
break;
}
AdwSleepMilliSecond(1);
}
(void)ADW_READ_WORD_REGISTER(iot, ioh, IOPW_EE_CMD);
}
static void
AdwSetEEPROMConfig(bus_space_tag_t iot, bus_space_handle_t ioh, ADW_EEPROM *cfg_buf)
{
u_int16_t *wbuf;
u_int16_t addr, chksum;
wbuf = (u_int16_t *) cfg_buf;
chksum = 0;
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
AdwWaitEEPCmd(iot, ioh);
for (addr = ASC_EEP_DVC_CFG_BEGIN;
addr < ASC_EEP_DVC_CFG_END; addr++, wbuf++) {
chksum += *wbuf;
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_DATA, *wbuf);
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_CMD,
ASC_EEP_CMD_WRITE | addr);
AdwWaitEEPCmd(iot, ioh);
AdwSleepMilliSecond(ASC_EEP_DELAY_MS);
}
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_DATA, chksum);
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_CMD,
ASC_EEP_CMD_WRITE | addr);
AdwWaitEEPCmd(iot, ioh);
wbuf++;
for (addr = ASC_EEP_DVC_CTL_BEGIN;
addr < ASC_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_DATA, *wbuf);
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_CMD,
ASC_EEP_CMD_WRITE | addr);
AdwWaitEEPCmd(iot, ioh);
}
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_EE_CMD,
ASC_EEP_CMD_WRITE_DISABLE);
AdwWaitEEPCmd(iot, ioh);
return;
}
int
AdwExeScsiQueue(ADW_SOFTC *sc, ADW_SCSI_REQ_Q *scsiq)
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
ADW_CCB *ccb;
u_int32_t req_paddr;
ADW_CARRIER *new_carrp;
if (scsiq->target_id > ADW_MAX_TID) {
scsiq->host_status = QHSTA_M_INVALID_DEVICE;
scsiq->done_status = QD_WITH_ERROR;
return ADW_ERROR;
}
ccb = adw_ccb_phys_kv(sc, scsiq->ccb_ptr);
if ((new_carrp = sc->carr_freelist) == NULL) {
return ADW_BUSY;
}
sc->carr_freelist = ADW_CARRIER_VADDR(sc,
ASC_GET_CARRP(new_carrp->next_ba));
sc->carr_pending_cnt++;
new_carrp->next_ba = htole32(ASC_CQ_STOPPER);
req_paddr = sc->sc_dmamap_control->dm_segs[0].ds_addr +
ADW_CCB_OFF(ccb) + offsetof(struct adw_ccb, scsiq);
scsiq->scsiq_rptr = htole32(req_paddr);
scsiq->carr_ba = sc->icq_sp->carr_ba;
scsiq->carr_va = sc->icq_sp->carr_ba;
sc->icq_sp->areq_ba = htole32(req_paddr);
sc->icq_sp->next_ba = new_carrp->carr_ba;
#if ADW_DEBUG
printf("icq 0x%x, 0x%x, 0x%x, 0x%x\n",
sc->icq_sp->carr_id,
sc->icq_sp->carr_ba,
sc->icq_sp->areq_ba,
sc->icq_sp->next_ba);
#endif
sc->icq_sp = new_carrp;
if (sc->chip_type == ADW_CHIP_ASC3550 ||
sc->chip_type == ADW_CHIP_ASC38C0800) {
ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_TICKLE, ADW_TICKLE_A);
if (sc->chip_type == ADW_CHIP_ASC3550) {
ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_TICKLE,
ADW_TICKLE_NOP);
}
} else if (sc->chip_type == ADW_CHIP_ASC38C1600) {
ADW_WRITE_DWORD_REGISTER(iot, ioh, IOPDW_COMMA,
le32toh(new_carrp->carr_ba));
}
return ADW_SUCCESS;
}
void
AdwResetChip(bus_space_tag_t iot, bus_space_handle_t ioh)
{
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_CTRL_REG,
ADW_CTRL_REG_CMD_RESET);
AdwSleepMilliSecond(100);
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_CTRL_REG,
ADW_CTRL_REG_CMD_WR_IO_REG);
}
int
AdwResetCCB(ADW_SOFTC *sc)
{
int status;
status = AdwSendIdleCmd(sc, (u_int16_t) IDLE_CMD_SCSI_RESET_START, 0L);
if (status != ADW_TRUE) {
return status;
}
AdwDelayMicroSecond((u_int16_t) ASC_SCSI_RESET_HOLD_TIME_US);
status = AdwSendIdleCmd(sc, (u_int16_t) IDLE_CMD_SCSI_RESET_END, 0L);
if (status != ADW_TRUE) {
return status;
}
AdwSleepMilliSecond((u_int32_t) sc->scsi_reset_wait * 1000);
return status;
}
int
AdwResetSCSIBus(ADW_SOFTC *sc)
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
int status;
u_int16_t wdtr_able, sdtr_able, tagqng_able;
u_int16_t ppr_able = 0;
u_int8_t tid, max_cmd[ADW_MAX_TID + 1];
u_int16_t bios_sig;
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_WDTR_ABLE, wdtr_able);
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_SDTR_ABLE, sdtr_able);
if (sc->chip_type == ADW_CHIP_ASC38C1600) {
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_PPR_ABLE, ppr_able);
}
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_TAGQNG_ABLE, tagqng_able);
for (tid = 0; tid <= ADW_MAX_TID; tid++) {
ADW_READ_BYTE_LRAM(iot, ioh, ADW_MC_NUMBER_OF_MAX_CMD + tid,
max_cmd[tid]);
}
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_BIOS_SIGNATURE, bios_sig);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_BIOS_SIGNATURE, 0);
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_RISC_CSR, ADW_RISC_CSR_STOP);
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_CTRL_REG,
ADW_CTRL_REG_CMD_RESET);
AdwSleepMilliSecond(100);
ADW_WRITE_WORD_REGISTER(iot, ioh, IOPW_CTRL_REG,
ADW_CTRL_REG_CMD_WR_IO_REG);
status = (AdwInitDriver(sc) == 0)? ADW_TRUE : ADW_FALSE;
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_BIOS_SIGNATURE, bios_sig);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_WDTR_ABLE, wdtr_able);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_ABLE, sdtr_able);
if (sc->chip_type == ADW_CHIP_ASC38C1600) {
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_PPR_ABLE, ppr_able);
}
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_TAGQNG_ABLE, tagqng_able);
for (tid = 0; tid <= ADW_MAX_TID; tid++) {
ADW_WRITE_BYTE_LRAM(iot, ioh, ADW_MC_NUMBER_OF_MAX_CMD + tid,
max_cmd[tid]);
}
return status;
}
int
AdwISR(ADW_SOFTC *sc)
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
u_int8_t int_stat;
ADW_CARRIER *free_carrp;
u_int32_t irq_next_pa;
ADW_SCSI_REQ_Q *scsiq;
ADW_CCB *ccb;
int s;
s = splbio();
int_stat = ADW_READ_BYTE_REGISTER(iot, ioh, IOPB_INTR_STATUS_REG);
if ((int_stat & (ADW_INTR_STATUS_INTRA | ADW_INTR_STATUS_INTRB |
ADW_INTR_STATUS_INTRC)) == 0) {
splx(s);
return ADW_FALSE;
}
if (int_stat & ADW_INTR_STATUS_INTRB) {
u_int8_t intrb_code;
ADW_READ_BYTE_LRAM(iot, ioh, ADW_MC_INTRB_CODE, intrb_code);
if (sc->chip_type == ADW_CHIP_ASC3550 ||
sc->chip_type == ADW_CHIP_ASC38C0800) {
if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE &&
sc->carr_pending_cnt != 0) {
ADW_WRITE_BYTE_REGISTER(iot, ioh,
IOPB_TICKLE, ADW_TICKLE_A);
if (sc->chip_type == ADW_CHIP_ASC3550) {
ADW_WRITE_BYTE_REGISTER(iot, ioh,
IOPB_TICKLE, ADW_TICKLE_NOP);
}
}
}
if (sc->async_callback != 0) {
(*sc->async_callback)(sc, intrb_code);
}
}
while (((le32toh(irq_next_pa = sc->irq_sp->next_ba)) & ASC_RQ_DONE) != 0)
{
#if ADW_DEBUG
printf("irq 0x%x, 0x%x, 0x%x, 0x%x\n",
sc->irq_sp->carr_id,
sc->irq_sp->carr_ba,
sc->irq_sp->areq_ba,
sc->irq_sp->next_ba);
#endif
ccb = adw_ccb_phys_kv(sc, sc->irq_sp->areq_ba);
scsiq = &ccb->scsiq;
scsiq->ccb_ptr = sc->irq_sp->areq_ba;
if ((le32toh(irq_next_pa) & ASC_RQ_GOOD) != 0) {
scsiq->done_status = QD_NO_ERROR;
scsiq->host_status = scsiq->scsi_status = 0;
scsiq->data_cnt = 0L;
}
free_carrp = sc->irq_sp;
sc->irq_sp = ADW_CARRIER_VADDR(sc, ASC_GET_CARRP(irq_next_pa));
free_carrp->next_ba = (sc->carr_freelist == NULL) ? 0
: sc->carr_freelist->carr_ba;
sc->carr_freelist = free_carrp;
sc->carr_pending_cnt--;
scsiq->cntl = 0;
if (scsiq->done_status == QD_NO_ERROR &&
scsiq->cdb[0] == INQUIRY &&
scsiq->target_lun == 0) {
AdwInquiryHandling(sc, scsiq);
}
(*sc->isr_callback)(sc, scsiq);
}
splx(s);
return ADW_TRUE;
}
int
AdwSendIdleCmd(ADW_SOFTC *sc, u_int16_t idle_cmd, u_int32_t idle_cmd_parameter)
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
u_int16_t result;
u_int32_t i, j, s;
s = splbio();
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_IDLE_CMD_STATUS, (u_int16_t) 0);
ADW_WRITE_DWORD_LRAM(iot, ioh, ADW_MC_IDLE_CMD_PARAMETER,
idle_cmd_parameter);
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_IDLE_CMD, idle_cmd);
ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_TICKLE, ADW_TICKLE_B);
if (sc->chip_type == ADW_CHIP_ASC3550) {
ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_TICKLE, ADW_TICKLE_NOP);
}
for (i = 0; i < SCSI_WAIT_100_MSEC; i++) {
for (j = 0; j < SCSI_US_PER_MSEC; j++) {
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_IDLE_CMD_STATUS,
result);
if (result != 0) {
splx(s);
return result;
}
AdwDelayMicroSecond(1);
}
}
splx(s);
return ADW_ERROR;
}
static void
AdwInquiryHandling(ADW_SOFTC *sc, ADW_SCSI_REQ_Q *scsiq)
{
#ifndef FAILSAFE
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
u_int8_t tid;
struct scsipi_inquiry_data *inq;
u_int16_t tidmask;
u_int16_t cfg_word;
if (scsiq->cdb[4] < 8 || (scsiq->cdb[4] - scsiq->data_cnt) < 8) {
return;
}
tid = scsiq->target_id;
inq = (struct scsipi_inquiry_data *) scsiq->vdata_addr;
if (((inq->response_format & SID_RespDataFmt) < 2) &&
((inq->version & SID_ANSII) < 2)) {
return;
} else {
tidmask = ADW_TID_TO_TIDMASK(tid);
#ifdef SCSI_ADW_WDTR_DISABLE
if(!(tidmask & SCSI_ADW_WDTR_DISABLE))
#endif
if ((sc->wdtr_able & tidmask) && (inq->flags3 & SID_WBus16)) {
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_WDTR_ABLE,
cfg_word);
if ((cfg_word & tidmask) == 0) {
cfg_word |= tidmask;
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_WDTR_ABLE,
cfg_word);
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_SDTR_DONE,
cfg_word);
cfg_word &= ~tidmask;
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_DONE,
cfg_word);
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_WDTR_DONE,
cfg_word);
cfg_word &= ~tidmask;
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_WDTR_DONE,
cfg_word);
}
}
#ifdef SCSI_ADW_SDTR_DISABLE
if(!(tidmask & SCSI_ADW_SDTR_DISABLE))
#endif
if ((sc->sdtr_able & tidmask) && (inq->flags3 & SID_Sync)) {
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_SDTR_ABLE,cfg_word);
if ((cfg_word & tidmask) == 0) {
cfg_word |= tidmask;
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_ABLE,
cfg_word);
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_SDTR_DONE,
cfg_word);
cfg_word &= ~tidmask;
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_SDTR_DONE,
cfg_word);
}
}
if (sc->chip_type == ADW_CHIP_ASC38C1600 &&
(scsiq->cdb[4] >= 57 ||
(scsiq->cdb[4] - scsiq->data_cnt) >= 57)) {
if((inq->flags4 & SID_Clocking) & SID_CLOCKING_DT_ONLY){
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_PPR_ABLE,
sc->ppr_able);
sc->ppr_able |= tidmask;
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_PPR_ABLE,
sc->ppr_able);
}
}
#ifdef SCSI_ADW_TAGQ_DISABLE
if(!(tidmask & SCSI_ADW_TAGQ_DISABLE))
#endif
if ((sc->tagqng_able & tidmask) && (inq->flags3 & SID_CmdQue)) {
ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_TAGQNG_ABLE,
cfg_word);
cfg_word |= tidmask;
ADW_WRITE_WORD_LRAM(iot, ioh, ADW_MC_TAGQNG_ABLE,
cfg_word);
ADW_WRITE_BYTE_LRAM(iot, ioh,
ADW_MC_NUMBER_OF_MAX_CMD + tid,
sc->max_dvc_qng);
}
}
#endif
}
static void
AdwSleepMilliSecond(u_int32_t n)
{
DELAY(n * 1000);
}
static void
AdwDelayMicroSecond(u_int32_t n)
{
DELAY(n);
}