diff options
Diffstat (limited to 'sys/i386/scsi/advansys.c')
-rw-r--r-- | sys/i386/scsi/advansys.c | 783 |
1 files changed, 0 insertions, 783 deletions
diff --git a/sys/i386/scsi/advansys.c b/sys/i386/scsi/advansys.c deleted file mode 100644 index e48362e..0000000 --- a/sys/i386/scsi/advansys.c +++ /dev/null @@ -1,783 +0,0 @@ -/* - * Generic driver for the Advanced Systems Inc. SCSI controllers - * Product specific probe and attach routines can be found in: - * - * i386/isa/adv_isa.c ABP5140, ABP542, ABP5150, ABP842, ABP852 - * - * Copyright (c) 1996 Justin T. Gibbs. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id$ - */ -/* - * Ported from: - * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters - * - * Copyright (c) 1995-1996 Advanced System Products, Inc. - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that redistributions of source - * code retain the above copyright notice and this comment without - * modification. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/buf.h> - -#include <machine/clock.h> - -#include <scsi/scsi_all.h> -#include <scsi/scsi_message.h> -#include <scsi/scsiconf.h> - -#include <vm/vm.h> -#include <vm/vm_param.h> -#include <vm/pmap.h> - -#include <i386/scsi/advansys.h> - -static void adv_scsi_cmd __P((struct scsi_xfer *xs)); -static void advminphys __P((struct buf *bp)); -static timeout_t - adv_timeout; -static int adv_qdone __P((struct adv_softc *adv)); -static void adv_done __P((struct adv_softc *adv, - struct adv_q_done_info *qdonep)); -static int adv_poll __P((struct adv_softc *ahc, struct scsi_xfer *xs)); - -struct adv_softc *advsoftcs[NADV]; /* XXX Config should handle this */ - -static struct scsi_adapter adv_switch = -{ - adv_scsi_cmd, - advminphys, - NULL, - NULL, - "adv" -}; - -static void -adv_scsi_cmd(xs) - struct scsi_xfer *xs; -{ - struct adv_softc *adv; - struct adv_scsi_q scsiq; - struct adv_sg_head sghead; - - SC_DEBUG(xs->sc_link, SDEV_DB2, ("adv_scsi_cmd\n")); - - adv = (struct adv_softc *)xs->sc_link->scsibus->adpt_link.adpt_softc; - - /* - * Build up the request - */ - scsiq.q1.cntl = 0; - scsiq.q1.sg_queue_cnt = 0; - scsiq.q1.status = 0; - scsiq.q1.q_no = 0; - scsiq.q1.target_id = ADV_TID_TO_TARGET_ID(xs->sc_link->target); - scsiq.q1.target_lun = xs->sc_link->lun; - scsiq.q1.sense_addr = (u_int32_t)vtophys(&xs->sense); - scsiq.q1.sense_len = sizeof(xs->sense); - scsiq.q1.data_cnt = 0; - scsiq.q1.data_addr = 0; - scsiq.q1.user_def = 0; - scsiq.q2.xs_ptr = (u_int32_t)xs; - scsiq.q2.target_ix = ADV_TIDLUN_TO_IX(xs->sc_link->target, xs->sc_link->lun); - scsiq.q2.flag = 0; - scsiq.q2.cdb_len = xs->cmdlen; - scsiq.q2.tag_code = xs->tag_type; - scsiq.q2.vm_id = 0; - scsiq.sg_head = NULL; - scsiq.cdbptr = &xs->cmd; - - if (xs->datalen) { - /* - * Determin the number of segments needed for this - * transfer. We should only use SG if we need more - * than one. - */ - int seg; - u_int32_t datalen; - vm_offset_t vaddr; - u_int32_t paddr; - u_int32_t nextpaddr; - struct adv_sg_entry *sg; - - seg = 0; - datalen = xs->datalen; - vaddr = (vm_offset_t)xs->data; - paddr = vtophys(vaddr); - sg = &sghead.sg_list[0]; - - while ((datalen > 0) && (seg < ADV_MAX_SG_LIST)) { - /* put in the base address and length */ - sg->addr = paddr; - sg->bytes = 0; - - /* do it at least once */ - nextpaddr = paddr; - - while ((datalen > 0) && (paddr == nextpaddr)) { - u_int32_t size; - /* - * This page is contiguous (physically) - * with the the last, just extend the - * length - */ - /* how far to the end of the page */ - nextpaddr = (paddr & (~PAGE_MASK)) + PAGE_SIZE; - - /* - * Compute the maximum size - */ - size = nextpaddr - paddr; - if (size > datalen) - size = datalen; - - sg->bytes += size; - vaddr += size; - datalen -= size; - if (datalen > 0) - paddr = vtophys(vaddr); - } - /* - * next page isn't contiguous, finish the seg - */ - seg++; - sg++; - } - if (seg > 1) { - scsiq.q1.cntl |= QC_SG_HEAD; - scsiq.sg_head = &sghead; - sghead.entry_cnt = sghead.entry_to_copy = seg; - sghead.res = 0; - } - scsiq.q1.data_addr = sghead.sg_list[0].addr; - scsiq.q1.data_cnt = sghead.sg_list[0].bytes; - } - - if (adv_execute_scsi_queue(adv, &scsiq) != 0) { - xs->error = XS_QUEUE_RESOURCE_SHORTAGE; - scsi_done(xs); - } else if ((xs->flags & SCSI_POLL) != 0) { - /* - * If we can't use interrupts, poll for completion - */ - int s; - - s = splbio(); - if (adv_poll(adv, xs)) { - if (!(xs->flags & SCSI_SILENT)) - printf("cmd fail\n"); - adv_timeout(xs); - } - splx(s); - } -} - - -static void -advminphys(bp) - struct buf *bp; -{ - if (bp->b_bcount > ((ADV_MAX_SG_LIST - 1) * PAGE_SIZE)) - bp->b_bcount = ((ADV_MAX_SG_LIST - 1) * PAGE_SIZE); -} - -static void -adv_timeout(arg) - void *arg; -{ - printf("adv: Ooops. Had a timeout\n"); -} - -struct adv_softc * -adv_alloc(unit, iobase) - int unit; - u_long iobase; -{ - struct adv_softc *adv; - int i; - - if (unit >= NADV) { - printf("adv: unit number (%d) too high\n", unit); - return NULL; - } - - /* - * Allocate a storage area for us - */ - if (advsoftcs[unit]) { - printf("adv%d: memory already allocated\n", unit); - return NULL; - } - - adv = malloc(sizeof(struct adv_softc), M_DEVBUF, M_NOWAIT); - if (!adv) { - printf("adv%d: cannot malloc!\n", unit); - return NULL; - } - bzero(adv, sizeof(struct adv_softc)); - advsoftcs[unit] = adv; - adv->unit = unit; - adv->iobase = iobase; - - /* Set reasonable defaults incase we can't read the EEPROM */ - adv->max_openings = ADV_DEF_MAX_TOTAL_QNG; - adv->start_motor = TARGET_BIT_VECTOR_SET; - adv->disc_enable = TARGET_BIT_VECTOR_SET; - adv->cmd_qng_enabled = TARGET_BIT_VECTOR_SET; - adv->scsi_id = 7; - - for (i = 0; i <= ADV_MAX_TID; i++) - adv->sdtr_data[i] = ADV_DEF_SDTR_OFFSET | (ADV_DEF_SDTR_INDEX << 4); - - return(adv); -} - -void -adv_free(adv) - struct adv_softc *adv; -{ - if (adv->sense_buffers != NULL) - free(adv->sense_buffers, M_DEVBUF); - free(adv, M_DEVBUF); -} - -int -adv_init(adv) - struct adv_softc *adv; -{ - struct adv_eeprom_config eeprom_config; - int checksum, i; - u_int16_t config_lsw; - u_int16_t config_msw; - - adv_get_board_type(adv); - - /* - * Stop script execution. - */ - adv_write_lram_16(adv, ADV_HALTCODE_W, 0x00FE); - adv_stop_execution(adv); - adv_reset_chip_and_scsi_bus(adv); - /* - * The generic SCSI code does a minimum delay for us - * already. - */ - /* DELAY(3 * 1000 * 1000);*/ /* 3 Second Delay */ - if (adv_is_chip_halted(adv) == 0) { - printf("adv%d: Unable to halt adapter. Initialization" - "failed\n", adv->unit); - return (1); - } - ADV_OUTW(adv, ADV_REG_PROG_COUNTER, ADV_MCODE_START_ADDR); - if (ADV_INW(adv, ADV_REG_PROG_COUNTER) != ADV_MCODE_START_ADDR) { - printf("adv%d: Unable to set program counter. Initialization" - "failed\n", adv->unit); - return (1); - } - - config_lsw = ADV_INW(adv, ADV_CONFIG_LSW); - config_msw = ADV_INW(adv, ADV_CONFIG_MSW); - -#if 0 - /* XXX Move to PCI probe code */ - if (adv->type & ADV_PCI) { -#if CC_DISABLE_PCI_PARITY_INT - config_msw &= 0xFFC0; - ADV_OUTW(adv, ADV_CONFIG_MSW, config_msw); -#endif - - if (asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_A) { - asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ADD_ONE_BYTE; - } - } -#endif - if ((config_msw & ADV_CFG_MSW_CLR_MASK) != 0) { - config_msw &= (~(ADV_CFG_MSW_CLR_MASK)); - /* - * XXX The Linux code flags this as an error, - * but what should we report to the user??? - * It seems that clearing the config register - * makes this error recoverable. - */ - ADV_OUTW(adv, ADV_CONFIG_MSW, config_msw); - } - - /* Suck in the configuration from the EEProm */ - checksum = adv_get_eeprom_config(adv, &eeprom_config); - - eeprom_config.cfg_msw &= (~(ADV_CFG_MSW_CLR_MASK)); - - if (ADV_INW(adv, ADV_CHIP_STATUS) & ADV_CSW_AUTO_CONFIG) { - /* - * XXX The Linux code sets a warning level for this - * condition, yet nothing of meaning is printed to - * the user. What does this mean??? - */ - if (adv->chip_version == 3) { - if (eeprom_config.cfg_lsw != config_lsw) { - /* XXX Yet another supposed Warning */ - eeprom_config.cfg_lsw = - ADV_INW(adv, ADV_CONFIG_LSW); - } - if (eeprom_config.cfg_msw != config_msw) { - /* XXX Yet another supposed Warning */ - eeprom_config.cfg_msw = - ADV_INW(adv, ADV_CONFIG_MSW); - } - } - } - eeprom_config.cfg_lsw |= ADV_CFG_LSW_HOST_INT_ON; - if (checksum == eeprom_config.chksum) { - if (adv_test_external_lram(adv) == 0) { - if (adv->type & ADV_PCI) { - eeprom_config.cfg_msw |= 0x0800; - config_msw |= 0x0800; - ADV_OUTW(adv, ADV_CONFIG_MSW, config_msw); - eeprom_config.max_total_qng = ADV_MAX_PCI_INRAM_TOTAL_QNG; - eeprom_config.max_tag_qng = ADV_MAX_INRAM_TAG_QNG; - } - } - /* XXX What about wide bussed cards?? */ - for (i = 0; i <= 7; i++) - adv->sdtr_data[i] = eeprom_config.sdtr_data[i]; - - /* Range/Sanity checking */ - if (eeprom_config.max_total_qng < ADV_MIN_TOTAL_QNG) { - eeprom_config.max_total_qng = ADV_MIN_TOTAL_QNG; - } - if (eeprom_config.max_total_qng > ADV_MAX_TOTAL_QNG) { - eeprom_config.max_total_qng = ADV_MAX_TOTAL_QNG; - } - if (eeprom_config.max_tag_qng > eeprom_config.max_total_qng) { - eeprom_config.max_tag_qng = eeprom_config.max_total_qng; - } - if (eeprom_config.max_tag_qng < ADV_MIN_TAG_Q_PER_DVC) { - eeprom_config.max_tag_qng = ADV_MIN_TAG_Q_PER_DVC; - } - adv->max_openings = eeprom_config.max_total_qng; - - if ((eeprom_config.use_cmd_qng & eeprom_config.disc_enable) != - eeprom_config.use_cmd_qng) { - eeprom_config.disc_enable |= eeprom_config.use_cmd_qng; - printf("adv:%d: WARNING! One or more targets with tagged " - "queuing enabled have the disconnection priveledge " - "disabled.\n" - "adv:%d: Overriding disconnection settings to " - "allow tagged queueing devices to disconnect.\n ", - adv->unit, adv->unit); - } -#if 0 - /* - * XXX We should range check our target ID - * based on the width of our bus - */ - EEPROM_SET_SCSIID(eeprom_config, - EEPROM_SCSIID(eeprom_config) & ADV_MAX_TID); -#endif - adv->initiate_sdtr = eeprom_config.init_sdtr; - adv->disc_enable = eeprom_config.disc_enable; - adv->cmd_qng_enabled = eeprom_config.use_cmd_qng; - adv->isa_dma_speed = EEPROM_DMA_SPEED(eeprom_config); - adv->scsi_id = EEPROM_SCSIID(eeprom_config); - adv->start_motor = eeprom_config.start_motor; - adv->control = eeprom_config.cntl; - adv->no_scam = eeprom_config.no_scam; - } else { - /* - * Use the defaults that adv was initialized with. - */ - /* - * XXX Fixup EEPROM with default values??? - */ - printf("adv%d: Warning EEPROM Checksum mismatch. " - "Using default device parameters\n", adv->unit); - } - -#if 0 - /* XXX Do this in the PCI probe */ - if ((adv->btype & ADV_PCI) && - !(asc_dvc->dvc_cntl & ASC_CNTL_NO_PCI_FIX_ASYN_XFER)) { - if ((asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_A) || - (asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_B)) { - asc_dvc->pci_fix_asyn_xfer = ASC_ALL_DEVICE_BIT_SET; - } - } -#endif - if (adv_set_eeprom_config(adv, &eeprom_config) != 0) - printf("adv:%d: WARNING! Failure writing to EEPROM.\n"); - - /* Allocate space for our sense buffers */ - /* XXX this should really be done by the generic SCSI layer by ensuring - * that all scsi_xfer structs are allocated below 16M if any controller - * needs to bounce. - */ - if (adv->type & ADV_ISA) { - adv->sense_buffers = (struct scsi_sense_data *)contigmalloc(sizeof(struct scsi_sense_data) * adv->max_openings, - M_DEVBUF, M_NOWAIT, 0ul, 0xfffffful, 1ul, - 0x10000ul); - if (adv->sense_buffers == NULL) { - printf("adv%d: Unable to allocate sense buffer space.\n"); - return (1); - } - - } - - if (adv_init_lram_and_mcode(adv)) - return (1); - - return (0); -} - -void -adv_intr(arg) - void *arg; -{ - struct adv_softc *adv; - u_int16_t chipstat; - u_int16_t saved_ram_addr; - u_int8_t ctrl_reg; - u_int8_t saved_ctrl_reg; - int status; - u_int8_t host_flag; - - adv = (struct adv_softc *)arg; - - ctrl_reg = ADV_INB(adv, ADV_CHIP_CTRL); - saved_ctrl_reg = ctrl_reg & (~(ADV_CC_SCSI_RESET | ADV_CC_CHIP_RESET | - ADV_CC_SINGLE_STEP | ADV_CC_DIAG | ADV_CC_TEST)); - - - if ((chipstat = ADV_INW(adv, ADV_CHIP_STATUS)) & ADV_CSW_INT_PENDING) { - - adv_ack_interrupt(adv); - - host_flag = adv_read_lram_8(adv, ADVV_HOST_FLAG_B); - adv_write_lram_8(adv, ADVV_HOST_FLAG_B, - host_flag | ADV_HOST_FLAG_IN_ISR); - saved_ram_addr = ADV_INW(adv, ADV_LRAM_ADDR); - - if ((chipstat & ADV_CSW_HALTED) - && (ctrl_reg & ADV_CC_SINGLE_STEP)) { - adv_isr_chip_halted(adv); - saved_ctrl_reg &= ~ADV_CC_HALT; - } else { - if ((adv->control & ADV_CNTL_INT_MULTI_Q) != 0) { - while (((status = adv_qdone(adv)) & 0x01) != 0) - ; - } else { - do { - status = adv_qdone(adv); - } while (status == 0x11); - } - } - ADV_OUTW(adv, ADV_LRAM_ADDR, saved_ram_addr); -#ifdef DIAGNOSTIC - if (ADV_INW(adv, ADV_LRAM_ADDR) != saved_ram_addr) - panic("adv_intr: Unable to set LRAM addr"); -#endif - adv_write_lram_8(adv, ADVV_HOST_FLAG_B, host_flag); - } - - ADV_OUTB(adv, ADV_CHIP_CTRL, saved_ctrl_reg); -} - -int -adv_qdone(adv) - struct adv_softc *adv; -{ - u_int8_t next_qp; - u_int8_t i; - u_int8_t n_q_used; - u_int8_t sg_list_qp; - u_int8_t sg_queue_cnt; - u_int8_t done_q_tail; - u_int8_t tid_no; - target_bit_vector target_id; - u_int16_t q_addr; - u_int16_t sg_q_addr; - struct adv_q_done_info scsiq_buf; - struct adv_q_done_info *scsiq; - int false_overrun; - u_int8_t tag_code; - - n_q_used = 1; - scsiq = &scsiq_buf; - done_q_tail = adv_read_lram_16(adv, ADVV_DONE_Q_TAIL_W) & 0xFF; - q_addr = ADV_QNO_TO_QADDR(done_q_tail); - next_qp = adv_read_lram_8(adv, q_addr + ADV_SCSIQ_B_FWD); - if (next_qp != ADV_QLINK_END) { - adv_write_lram_16(adv, ADVV_DONE_Q_TAIL_W, next_qp); - q_addr = ADV_QNO_TO_QADDR(next_qp); - - sg_queue_cnt = adv_copy_lram_doneq(adv, q_addr, scsiq, adv->max_dma_count); - - adv_write_lram_8(adv, q_addr + ADV_SCSIQ_B_STATUS, - scsiq->q_status & ~(QS_READY | QS_ABORTED)); - tid_no = ADV_TIX_TO_TID(scsiq->d2.target_ix); - target_id = ADV_TIX_TO_TARGET_ID(scsiq->d2.target_ix); - if ((scsiq->cntl & QC_SG_HEAD) != 0) { - sg_q_addr = q_addr; - sg_list_qp = next_qp; - for (i = 0; i < sg_queue_cnt; i++) { - sg_list_qp = adv_read_lram_8(adv, - sg_q_addr + ADV_SCSIQ_B_FWD); - sg_q_addr = ADV_QNO_TO_QADDR(sg_list_qp); -#ifdef DIAGNOSTIC - if (sg_list_qp == ASC_QLINK_END) { - panic("adv_qdone: Corrupted SG list encountered"); - } -#endif - adv_write_lram_8(adv, sg_q_addr + ADV_SCSIQ_B_STATUS, - QS_FREE); - } - - n_q_used = sg_queue_cnt + 1; - adv_write_lram_16(adv, ADVV_DONE_Q_TAIL_W, sg_list_qp); - } -#if 0 - /* XXX Fix later */ - if (adv->queue_full_or_busy & target_id) { - cur_target_qng = adv_read_lram_8(adv, - ADV_QADR_BEG + scsiq->d2.target_ix); - if (cur_target_qng < adv->max_dvc_qng[tid_no]) { - scsi_busy = adv_read_lram_8(adv, ADVV_SCSIBUSY_B); - scsi_busy &= ~target_id; - adv_write_lram_8(adv, ADVV_SCSIBUSY_B, scsi_busy); - adv->queue_full_or_busy &= ~target_id; - } - } -#endif -#ifdef DIAGNOSTIC - if (adv->cur_total_qng < n_q_used) - panic("adv_qdone: Attempting to free more queues than are active"); -#endif - adv->cur_active -= n_q_used; - - if ((scsiq->d2.xs_ptr == 0) || - ((scsiq->q_status & QS_ABORTED) != 0)) - return (0x11); - else if (scsiq->q_status == QS_DONE) { - - false_overrun = FALSE; - - if (adv->bug_fix_control & ADV_BUG_FIX_ADD_ONE_BYTE) { - tag_code = adv_read_lram_8(adv, q_addr + ADV_SCSIQ_B_TAG_CODE); - if (tag_code & ADV_TAG_FLAG_ADD_ONE_BYTE) { - if (scsiq->remain_bytes != 0) { - scsiq->remain_bytes--; - if (scsiq->remain_bytes == 0) - false_overrun = TRUE; - } - } - } - if ((scsiq->d3.done_stat == QD_WITH_ERROR) && - (scsiq->d3.host_stat == QHSTA_M_DATA_OVER_RUN)) { - if ((scsiq->cntl & (QC_DATA_IN | QC_DATA_OUT)) == 0) { - scsiq->d3.done_stat = QD_NO_ERROR; - scsiq->d3.host_stat = QHSTA_NO_ERROR; - } else if (false_overrun) { - scsiq->d3.done_stat = QD_NO_ERROR; - scsiq->d3.host_stat = QHSTA_NO_ERROR; - } - } - - if ((scsiq->cntl & QC_NO_CALLBACK) == 0) - adv_done(adv, scsiq); - else { - if ((adv_read_lram_8(adv, q_addr + ADV_SCSIQ_CDB_BEG) == - START_STOP)) { - adv->unit_not_ready &= ~target_id; - if (scsiq->d3.done_stat != QD_NO_ERROR) - adv->start_motor &= ~target_id; - } - } - return (1); - } else { - panic("adv_qdone: completed scsiq with unknown status"); -#if 0 - /* - * XXX Doesn't this simply indicate a software bug? - * What does setting the lram error code do for - * you. Would we even recover? - */ - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS); - - FATAL_ERR_QDONE: - if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { - (*asc_isr_callback) (asc_dvc, scsiq); - } - return (0x80); -#endif - } - } - return (0); -} - - -void -adv_done(adv, qdonep) - struct adv_softc *adv; - struct adv_q_done_info *qdonep; -{ - struct scsi_xfer *xs; - - xs = (struct scsi_xfer *)qdonep->d2.xs_ptr; - - xs->status = qdonep->d3.scsi_stat; - /* - * 'qdonep' contains the command's ending status. - */ - switch (qdonep->d3.done_stat) { - case QD_NO_ERROR: - switch (qdonep->d3.host_stat) { - case QHSTA_NO_ERROR: - break; - case QHSTA_M_SEL_TIMEOUT: - xs->error = XS_SELTIMEOUT; - break; - default: - /* QHSTA error occurred */ -#if 0 - /* XXX Can I get more explicit information here? */ - xs->error = XS_DRIVER_STUFFUP; -#endif - break; - } - break; - - case QD_WITH_ERROR: - switch (qdonep->d3.host_stat) { - case QHSTA_NO_ERROR: - if ((qdonep->d3.scsi_stat == STATUS_CHECK_CONDITION) - || (qdonep->d3.scsi_stat == STATUS_COMMAND_TERMINATED)) { - /* We have valid sense information to return */ - xs->error = XS_SENSE; - if (adv->sense_buffers != NULL) - /* Structure copy */ - xs->sense = adv->sense_buffers[qdonep->q_no]; - } - break; - case QHSTA_M_SEL_TIMEOUT: - xs->error = XS_SELTIMEOUT; - break; - default: -#if 0 - /* XXX Can I get more explicit information here? */ - xs->error = XS_DRIVER_STUFFUP; -#endif - break; - } - break; - - case QD_ABORTED_BY_HOST: - /* XXX Should have an explicit ABORTED error code */ - xs->error = XS_ABORTED; - break; - - default: -#if 0 - printf("adv_done: Unknown done status 0x%x\n", - qdonep->d3.done_stat); - xs->error = XS_DRIVER_STUFFUP; -#endif - break; - } - xs->flags |= SCSI_ITSDONE; - scsi_done(xs); - return; -} - -/* - * Function to poll for command completion when - * interrupts are disabled (crash dumps) - */ -static int -adv_poll(adv, xs) - struct adv_softc *adv; - struct scsi_xfer *xs; -{ - int wait; - - wait = xs->timeout; - do { - DELAY(1000); - adv_intr((void *)adv); - } while (--wait && ((xs->flags & SCSI_ITSDONE) == 0)); - if (wait == 0) { - printf("adv%d: board is not responding\n", adv->unit); - return (EIO); - } - return (0); -} - -/* - * Attach all the sub-devices we can find - */ -int -adv_attach(adv) - struct adv_softc *adv; -{ - struct scsi_bus *scbus; - struct scsi_queue *scsiq; - - scsiq = scsi_alloc_queue(adv->max_openings); - if (scsiq == NULL) - return 0; - - /* - * Prepare the scsi_bus area for the upperlevel scsi code. - */ - scbus = scsi_alloc_bus(&adv_switch, adv, adv->unit, scsiq); - if (scbus == NULL) { - scsi_free_queue(scsiq); - return 0; - } - - /* Override defaults */ - if ((adv->type & ADV_ISA) != 0) - scbus->adpt_link.adpt_flags |= SADPT_BOUNCE; - scbus->adpt_link.adpt_target = adv->scsi_id; - scbus->adpt_link.adpt_openings = 2; /* XXX Is this correct for these cards? */ - scbus->adpt_link.adpt_tagged_openings = adv->max_openings; - - /* - * ask the adapter what subunits are present - */ - if(bootverbose) - printf("adv%d: Probing SCSI bus\n", adv->unit); - - scsi_attachdevs(scbus); - - return 1; -} |