From 97631c912c65111eb5a6f32972ae8674df2c7b1e Mon Sep 17 00:00:00 2001 From: jsg Date: Mon, 7 Mar 2022 23:40:53 +0000 Subject: [PATCH] remove WD33C93 SCSI code used by wdsc on sgi (removed in 2021) ok krw@ --- sys/conf/files | 6 +- sys/dev/ic/wd33c93.c | 2386 --------------------------------------- sys/dev/ic/wd33c93reg.h | 518 --------- sys/dev/ic/wd33c93var.h | 261 ----- 4 files changed, 1 insertion(+), 3170 deletions(-) delete mode 100644 sys/dev/ic/wd33c93.c delete mode 100644 sys/dev/ic/wd33c93reg.h delete mode 100644 sys/dev/ic/wd33c93var.h diff --git a/sys/conf/files b/sys/conf/files index 17681eebce9..57af5b5b476 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.711 2022/03/06 08:40:34 jsg Exp $ +# $OpenBSD: files,v 1.712 2022/03/07 23:40:53 jsg Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -229,10 +229,6 @@ file dev/ic/osiop.c osiop & (osiop_gsc | osiop_eisa | osiop_mc | osiop_pcctwo) device oosiop: scsi file dev/ic/oosiop.c oosiop -# Western Digital WD33C93 SCSI controllers -define wd33c93ctrl -file dev/ic/wd33c93.c wd33c93ctrl - # 3Com Etherlink-III Ethernet controller device ep: ether, ifnet, ifmedia, mii file dev/ic/elink3.c ep diff --git a/sys/dev/ic/wd33c93.c b/sys/dev/ic/wd33c93.c deleted file mode 100644 index af3dca55464..00000000000 --- a/sys/dev/ic/wd33c93.c +++ /dev/null @@ -1,2386 +0,0 @@ -/* $OpenBSD: wd33c93.c,v 1.20 2022/01/09 05:42:42 jsg Exp $ */ -/* $NetBSD: wd33c93.c,v 1.24 2010/11/13 13:52:02 uebayasi Exp $ */ - -/* - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Van Jacobson of Lawrence Berkeley Laboratory. - * - * 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, 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. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - * - * @(#)scsi.c 7.5 (Berkeley) 5/4/91 - */ - -/* - * Changes Copyright (c) 2001 Wayne Knowles - * Changes Copyright (c) 1996 Steve Woodford - * Original Copyright (c) 1994 Christian E. Hopps - * - * This code is derived from software contributed to Berkeley by - * Van Jacobson of Lawrence Berkeley Laboratory. - * - * 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, 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - * - * @(#)scsi.c 7.5 (Berkeley) 5/4/91 - */ - -/* - * This version of the driver is pretty well generic, so should work with - * any flavour of WD33C93 chip. - */ - -#include -#include -#include -#include /* For hz */ -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include - -/* - * SCSI delays - * In u-seconds, primarily for state changes on the SPC. - */ -#define SBIC_CMD_WAIT 200000 /* wait per step of 'immediate' cmds */ -#define SBIC_DATA_WAIT 200000 /* wait per data in/out step */ - -#define STATUS_UNKNOWN 0xff /* uninitialized status */ - -/* - * Convenience macro for waiting for a particular wd33c93 event - */ -#define SBIC_WAIT(regs, until, timeo) wd33c93_wait(regs, until, timeo, __LINE__) - -void wd33c93_init(struct wd33c93_softc *); -void wd33c93_reset(struct wd33c93_softc *); -int wd33c93_loop(struct wd33c93_softc *, u_char, u_char); -int wd33c93_go(struct wd33c93_softc *, struct wd33c93_acb *); -int wd33c93_dmaok(struct wd33c93_softc *, struct scsi_xfer *); -int wd33c93_wait(struct wd33c93_softc *, u_char, int , int); -u_char wd33c93_selectbus(struct wd33c93_softc *, struct wd33c93_acb *); -ssize_t wd33c93_xfout(struct wd33c93_softc *, ssize_t, void *); -ssize_t wd33c93_xfin(struct wd33c93_softc *, ssize_t, void *); -int wd33c93_poll(struct wd33c93_softc *, struct wd33c93_acb *); -int wd33c93_nextstate(struct wd33c93_softc *, struct wd33c93_acb *, - u_char, u_char); -int wd33c93_abort(struct wd33c93_softc *, struct wd33c93_acb *, - const char *); -void wd33c93_xferdone(struct wd33c93_softc *); -void wd33c93_error(struct wd33c93_softc *, struct wd33c93_acb *); -void wd33c93_scsidone(struct wd33c93_softc *, struct wd33c93_acb *, int); -void wd33c93_sched(struct wd33c93_softc *); -void wd33c93_dequeue(struct wd33c93_softc *, struct wd33c93_acb *); -void wd33c93_dma_stop(struct wd33c93_softc *); -void wd33c93_dma_setup(struct wd33c93_softc *, int); -int wd33c93_msgin_phase(struct wd33c93_softc *, int); -void wd33c93_msgin(struct wd33c93_softc *, u_char *, int); -void wd33c93_reselect(struct wd33c93_softc *, int, int, int, int); -void wd33c93_sched_msgout(struct wd33c93_softc *, u_short); -void wd33c93_msgout(struct wd33c93_softc *); -void wd33c93_timeout(void *arg); -void wd33c93_watchdog(void *arg); -u_char wd33c93_stp2syn(struct wd33c93_softc *, struct wd33c93_tinfo *); -void wd33c93_setsync(struct wd33c93_softc *, struct wd33c93_tinfo *); - -struct pool wd33c93_pool; /* Adapter Control Blocks */ -struct scsi_iopool wd33c93_iopool; -int wd33c93_pool_initialized = 0; - -void * wd33c93_io_get(void *); -void wd33c93_io_put(void *, void *); - -/* - * Timeouts - */ -int wd33c93_cmd_wait = SBIC_CMD_WAIT; -int wd33c93_data_wait = SBIC_DATA_WAIT; - -int wd33c93_nodma = 0; /* Use polled IO transfers */ -int wd33c93_nodisc = 0; /* Allow command queues */ -int wd33c93_notags = 0; /* No Tags */ - -/* - * Some useful stuff for debugging purposes - */ -#ifdef SBICDEBUG - -#define QPRINTF(a) SBIC_DEBUG(MISC, a) - -int wd33c93_debug = 0; /* Debug flags */ - -void wd33c93_print_csr (u_char); -void wd33c93_hexdump (u_char *, int); - -#else -#define QPRINTF(a) /* */ -#endif - -static const char *wd33c93_chip_names[] = SBIC_CHIP_LIST; - -/* - * Attach instance of driver and probe for sub devices - */ -void -wd33c93_attach(struct wd33c93_softc *sc, struct scsi_adapter *adapter) -{ - struct scsibus_attach_args saa; - - sc->sc_cfflags = sc->sc_dev.dv_cfdata->cf_flags; - timeout_set(&sc->sc_watchdog, wd33c93_watchdog, sc); - wd33c93_init(sc); - - printf(": %s, %d.%d MHz, %s\n", - wd33c93_chip_names[sc->sc_chip], - sc->sc_clkfreq / 10, sc->sc_clkfreq % 10, - (sc->sc_dmamode == SBIC_CTL_DMA) ? "DMA" : - (sc->sc_dmamode == SBIC_CTL_DBA_DMA) ? "DBA" : - (sc->sc_dmamode == SBIC_CTL_BURST_DMA) ? "burst DMA" : "PIO"); - if (sc->sc_chip == SBIC_CHIP_WD33C93B) { - printf("%s: microcode revision 0x%02x", - sc->sc_dev.dv_xname, sc->sc_rev); - if (sc->sc_minsyncperiod < 50) - printf(", fast SCSI"); - printf("\n"); - } - - saa.saa_adapter_softc = sc; - saa.saa_adapter_target = sc->sc_id; - saa.saa_adapter_buswidth = SBIC_NTARG; - saa.saa_adapter = adapter; - saa.saa_luns = SBIC_NLUN; - saa.saa_openings = 2; - saa.saa_pool = &wd33c93_iopool; - saa.saa_quirks = saa.saa_flags = 0; - saa.saa_wwpn = saa.saa_wwnn = 0; - - config_found(&sc->sc_dev, &saa, scsiprint); - timeout_add_sec(&sc->sc_watchdog, 60); -} - -/* - * Initialize driver-private structures - */ -void -wd33c93_init(struct wd33c93_softc *sc) -{ - u_int i; - - timeout_del(&sc->sc_watchdog); - - if (!wd33c93_pool_initialized) { - /* All instances share the same pool */ - pool_init(&wd33c93_pool, sizeof(struct wd33c93_acb), 0, - IPL_BIO, 0, "wd33c93_acb", NULL); - scsi_iopool_init(&wd33c93_iopool, NULL, - wd33c93_io_get, wd33c93_io_put); - ++wd33c93_pool_initialized; - } - - if (sc->sc_state == 0) { - TAILQ_INIT(&sc->ready_list); - - sc->sc_nexus = NULL; - sc->sc_disc = 0; - memset(sc->sc_tinfo, 0, sizeof(sc->sc_tinfo)); - } else { - /* XXX cancel all active commands */ - panic("wd33c93: reinitializing driver!"); - } - - sc->sc_flags = 0; - sc->sc_state = SBIC_IDLE; - wd33c93_reset(sc); - - for (i = 0; i < SBIC_NTARG; i++) { - struct wd33c93_tinfo *ti = &sc->sc_tinfo[i]; - /* - * cf_flags = 0xTTSSRR - * - * TT = Bitmask to disable Tagged Queues - * SS = Bitmask to disable Sync negotiation - * RR = Bitmask to disable disconnect/reselect - */ - ti->flags = T_NEED_RESET; - if (CFFLAGS_NOSYNC(sc->sc_cfflags, i)) - ti->flags |= T_NOSYNC; - if (CFFLAGS_NODISC(sc->sc_cfflags, i) || wd33c93_nodisc) - ti->flags |= T_NODISC; - ti->period = sc->sc_minsyncperiod; - ti->offset = 0; - } -} - -void -wd33c93_reset(struct wd33c93_softc *sc) -{ - u_int my_id, s, div, i; - u_char csr, reg; - - SET_SBIC_cmd(sc, SBIC_CMD_ABORT); - WAIT_CIP(sc); - - s = splbio(); - - if (sc->sc_reset != NULL) - (*sc->sc_reset)(sc); - - my_id = sc->sc_id & SBIC_ID_MASK; - - /* Enable advanced features and really(!) advanced features */ -#if 1 - my_id |= (SBIC_ID_EAF | SBIC_ID_RAF); /* XXX - MD Layer */ -#endif - - SET_SBIC_myid(sc, my_id); - - /* Reset the chip */ - SET_SBIC_cmd(sc, SBIC_CMD_RESET); - DELAY(25); - SBIC_WAIT(sc, SBIC_ASR_INT, 0); - - /* Set up various chip parameters */ - SET_SBIC_control(sc, SBIC_CTL_EDI | SBIC_CTL_IDI); - - GET_SBIC_csr(sc, csr); /* clears interrupt also */ - GET_SBIC_cdb1(sc, sc->sc_rev); /* valid with RAF on wd33c93b */ - - switch (csr) { - case SBIC_CSR_RESET: - sc->sc_chip = SBIC_CHIP_WD33C93; - break; - case SBIC_CSR_RESET_AM: - SET_SBIC_queue_tag(sc, 0x55); - GET_SBIC_queue_tag(sc, reg); - sc->sc_chip = (reg == 0x55) ? - SBIC_CHIP_WD33C93B : SBIC_CHIP_WD33C93A; - SET_SBIC_queue_tag(sc, 0x0); - break; - default: - sc->sc_chip = SBIC_CHIP_UNKNOWN; - } - - /* - * Choose a suitable clock divisor and work out the resulting - * sync transfer periods in 4ns units. - */ - if (sc->sc_clkfreq < 110) { - my_id |= SBIC_ID_FS_8_10; - div = 2; - } else if (sc->sc_clkfreq < 160) { - my_id |= SBIC_ID_FS_12_15; - div = 3; - } else if (sc->sc_clkfreq < 210) { - my_id |= SBIC_ID_FS_16_20; - div = 4; - } else - panic("wd33c93: invalid clock speed %d", sc->sc_clkfreq); - - for (i = 0; i < 7; i++) - sc->sc_syncperiods[i] = - (i + 2) * div * 1250 / sc->sc_clkfreq; - sc->sc_minsyncperiod = sc->sc_syncperiods[0]; - SBIC_DEBUG(SYNC, ("available sync periods: %d %d %d %d %d %d %d\n", - sc->sc_syncperiods[0], sc->sc_syncperiods[1], - sc->sc_syncperiods[2], sc->sc_syncperiods[3], - sc->sc_syncperiods[4], sc->sc_syncperiods[5], - sc->sc_syncperiods[6])); - - if (sc->sc_clkfreq >= 160 && sc->sc_chip == SBIC_CHIP_WD33C93B) { - for (i = 0; i < 3; i++) - sc->sc_fsyncperiods[i] = - (i + 2) * 2 * 1250 / sc->sc_clkfreq; - SBIC_DEBUG(SYNC, ("available fast sync periods: %d %d %d\n", - sc->sc_fsyncperiods[0], sc->sc_fsyncperiods[1], - sc->sc_fsyncperiods[2])); - sc->sc_minsyncperiod = sc->sc_fsyncperiods[0]; - } - - /* Max Sync Offset */ - if (sc->sc_chip == SBIC_CHIP_WD33C93A || - sc->sc_chip == SBIC_CHIP_WD33C93B) - sc->sc_maxoffset = SBIC_SYN_93AB_MAX_OFFSET; - else - sc->sc_maxoffset = SBIC_SYN_93_MAX_OFFSET; - - /* - * don't allow Selection (SBIC_RID_ES) - * until we can handle target mode!! - */ - SET_SBIC_rselid(sc, SBIC_RID_ER); - - /* Asynchronous for now */ - SET_SBIC_syn(sc, 0); - - sc->sc_flags = 0; - sc->sc_state = SBIC_IDLE; - - splx(s); -} - -void -wd33c93_error(struct wd33c93_softc *sc, struct wd33c93_acb *acb) -{ - struct scsi_xfer *xs = acb->xs; - - KASSERT(xs); - - if (xs->flags & SCSI_SILENT) - return; - - sc_print_addr(xs->sc_link); - printf("SCSI Error\n"); -} - -/* - * Determine an appropriate value for the synchronous transfer register - * given the period and offset values in *ti. - */ -u_char -wd33c93_stp2syn(struct wd33c93_softc *sc, struct wd33c93_tinfo *ti) -{ - unsigned i; - - /* see if we can handle fast scsi (100-200ns) first */ - if (ti->period < 50 && sc->sc_minsyncperiod < 50) { - for (i = 0; i < 3; i++) - if (sc->sc_fsyncperiods[i] >= ti->period) - return (SBIC_SYN(ti->offset, i + 2, 1)); - } - - for (i = 0; i < 7; i++) { - if (sc->sc_syncperiods[i] >= ti->period) { - if (i == 6) - return (SBIC_SYN(0, 0, 0)); - else - return (SBIC_SYN(ti->offset, i + 2, 0)); - } - } - - /* XXX - can't handle it; do async */ - return (SBIC_SYN(0, 0, 0)); -} - -/* - * Setup sync mode for given target - */ -void -wd33c93_setsync(struct wd33c93_softc *sc, struct wd33c93_tinfo *ti) -{ - u_char syncreg; - - if (ti->flags & T_SYNCMODE) - syncreg = wd33c93_stp2syn(sc, ti); - else - syncreg = SBIC_SYN(0, 0, 0); - - SBIC_DEBUG(SYNC, ("wd33c93_setsync: sync reg = 0x%02x\n", syncreg)); - SET_SBIC_syn(sc, syncreg); -} - -/* - * Check if current operation can be done using DMA - * - * returns 1 if DMA OK, 0 for polled I/O transfer - */ -int -wd33c93_dmaok(struct wd33c93_softc *sc, struct scsi_xfer *xs) -{ - if (wd33c93_nodma || sc->sc_dmamode == SBIC_CTL_NO_DMA || - (xs->flags & SCSI_POLL) || xs->datalen == 0) - return (0); - return(1); -} - -/* - * Setup for DMA transfer - */ -void -wd33c93_dma_setup(struct wd33c93_softc *sc, int datain) -{ - struct wd33c93_acb *acb = sc->sc_nexus; - int s; - - sc->sc_daddr = acb->daddr; - sc->sc_dleft = acb->dleft; - - s = splbio(); - /* Indicate that we're in DMA mode */ - if (sc->sc_dleft) { - sc->sc_dmasetup(sc, &sc->sc_daddr, &sc->sc_dleft, - datain, &sc->sc_dleft); - } - splx(s); - return; -} - - -/* - * Save DMA pointers. Take into account partial transfer. Shut down DMA. - */ -void -wd33c93_dma_stop(struct wd33c93_softc *sc) -{ - ssize_t count; - int asr; - - /* Wait until WD chip is idle */ - do { - GET_SBIC_asr(sc, asr); /* XXX */ - if (asr & SBIC_ASR_DBR) { - printf("%s: %s: asr %02x cancelled!\n", - sc->sc_dev.dv_xname, __func__, asr); - break; - } - } while (asr & (SBIC_ASR_BSY|SBIC_ASR_CIP)); - - /* Only need to save pointers if DMA was active */ - if (sc->sc_flags & SBICF_INDMA) { - int s = splbio(); - - /* Shut down DMA and flush FIFO's */ - sc->sc_dmastop(sc); - - /* Fetch the residual count */ - SBIC_TC_GET(sc, count); - - /* Work out how many bytes were actually transferred */ - count = sc->sc_tcnt - count; - - if (sc->sc_dleft < count) { - if (sc->sc_nexus && sc->sc_nexus->xs) - sc_print_addr(sc->sc_nexus->xs->sc_link); - else - printf("%s: ", sc->sc_dev.dv_xname); - printf("xfer too large: dleft=%zd resid=%zd\n", - sc->sc_dleft, count); - } - - /* Fixup partial xfers */ - sc->sc_daddr = (char *)sc->sc_daddr + count; - sc->sc_dleft -= count; - sc->sc_tcnt = 0; - sc->sc_flags &= ~SBICF_INDMA; - splx(s); - SBIC_DEBUG(DMA, ("dma_stop\n")); - } - /* - * Ensure the WD chip is back in polled I/O mode, with nothing to - * transfer. - */ - SBIC_TC_PUT(sc, 0); - SET_SBIC_control(sc, SBIC_CTL_EDI | SBIC_CTL_IDI); -} - - -/* - * Handle new request from scsi layer - */ -void -wd33c93_scsi_cmd(struct scsi_xfer *xs) -{ - struct scsi_link *sc_link = xs->sc_link; - struct wd33c93_softc *sc = sc_link->bus->sb_adapter_softc; - struct wd33c93_acb *acb; - int flags, s; - - SBIC_DEBUG(MISC, ("wd33c93_scsi_cmd\n")); - - /* - * The original 33C93 expects commands not in groups 0, 1 and 5 - * to be six bytes long. - */ - if (sc->sc_chip <= SBIC_CHIP_WD33C93) { - switch (xs->cmd.opcode >> 5) { - case 0: - case 1: - case 5: - break; - default: - if (xs->cmdlen == 6) - break; - memset(&xs->sense, 0, sizeof(xs->sense)); - /* sense data borrowed from gdt(4) */ - xs->sense.error_code = SSD_ERRCODE_VALID | - SSD_ERRCODE_CURRENT; - xs->sense.flags = SKEY_ILLEGAL_REQUEST; - xs->sense.add_sense_code = 0x20; /* illcmd */ - xs->error = XS_SENSE; - scsi_done(xs); - return; - } - } - - /* - * None of the 33C93 are documented to support the START_STOP - * command, and it turns out the chip takes some significant - * time to recover when the target powers down (the fewer - * targets on the bus, the larger the time needed to recover). - */ - if (xs->cmd.opcode == START_STOP && - ((struct scsi_start_stop *)&xs->cmd)->how == SSS_STOP) { - if (xs->timeout < 30000) - xs->timeout = 30000; - } - - flags = xs->flags; - - if (sc->sc_nexus && (flags & SCSI_POLL)) - panic("wd33c93_scsicmd: busy"); - - acb = xs->io; - memset(acb, 0, sizeof(*acb)); - acb->flags = ACB_ACTIVE; - acb->xs = xs; - acb->timeout = xs->timeout; - timeout_set(&acb->to, wd33c93_timeout, acb); - - memcpy(&acb->cmd, &xs->cmd, xs->cmdlen); - acb->clen = xs->cmdlen; - acb->daddr = xs->data; - acb->dleft = xs->datalen; - - if (flags & SCSI_POLL) { - /* - * Complete currently active command(s) before - * issuing an immediate command - */ - while (sc->sc_nexus) - wd33c93_poll(sc, sc->sc_nexus); - } - - s = splbio(); - TAILQ_INSERT_TAIL(&sc->ready_list, acb, chain); - acb->flags |= ACB_READY; - - /* If nothing is active, try to start it now. */ - if (sc->sc_state == SBIC_IDLE) - wd33c93_sched(sc); - splx(s); - - if ((flags & SCSI_POLL) == 0) - return; - - if (wd33c93_poll(sc, acb)) { - wd33c93_timeout(acb); - if (wd33c93_poll(sc, acb)) /* 2nd retry for ABORT */ - wd33c93_timeout(acb); - } -} - -/* - * attempt to start the next available command - */ -void -wd33c93_sched(struct wd33c93_softc *sc) -{ - struct scsi_link *sc_link; - struct wd33c93_acb *acb; - struct wd33c93_tinfo *ti; - struct wd33c93_linfo *li; - int lun, tag, flags; - int s; - - if (sc->sc_state != SBIC_IDLE) - return; - - KASSERT(sc->sc_nexus == NULL); - - /* Loop through the ready list looking for work to do... */ - TAILQ_FOREACH(acb, &sc->ready_list, chain) { - sc_link = acb->xs->sc_link; - lun = sc_link->lun; - ti = &sc->sc_tinfo[sc_link->target]; - - KASSERT(acb->flags & ACB_READY); - - /* Select type of tag for this command */ - if ((ti->flags & T_NODISC) != 0) - tag = 0; - else if ((ti->flags & T_TAG) == 0) - tag = 0; - else if ((acb->flags & ACB_SENSE) != 0) - tag = 0; - else if (acb->xs->flags & SCSI_POLL) - tag = 0; /* No tags for polled commands */ - else - tag = MSG_SIMPLE_Q_TAG; - - s = splbio(); - li = TINFO_LUN(ti, lun); - if (li == NULL) { - /* Initialize LUN info and add to list. */ - li = malloc(sizeof(*li), M_DEVBUF, M_NOWAIT | M_ZERO); - if (li == NULL) { - splx(s); - continue; - } - li->lun = lun; - if (lun < SBIC_NLUN) - ti->lun[lun] = li; - } - li->last_used = getuptime(); - - /* - * We've found a potential command, but is the target/lun busy? - */ - - if (tag == 0 && li->untagged == NULL) - li->untagged = acb; /* Issue untagged */ - - if (li->untagged != NULL) { - tag = 0; - if ((li->state != L_STATE_BUSY) && li->used == 0) { - /* Issue this untagged command now */ - acb = li->untagged; - sc_link = acb->xs->sc_link; - } else{ - /* Not ready yet */ - splx(s); - continue; - } - } - - acb->tag_type = tag; - if (tag != 0) { - int i; - - /* Allocate a tag */ - if (li->used == 255) { - /* no free tags */ - splx(s); - continue; - } - /* Start from the last used location */ - for (i = li->avail; i < 256; i++) { - if (li->queued[i] == NULL) - break; - } - /* Couldn't find one, start again from the beginning */ - if (i == 256) { - for (i = 0; i < 256; i++) { - if (li->queued[i] == NULL) - break; - } - } -#ifdef DIAGNOSTIC - if (i == 256) - panic("%s: tag alloc failure", __func__); -#endif - - /* Save where to start next time. */ - li->avail = i + 1; - li->used++; - li->queued[i] = acb; - acb->tag_id = i; - } - splx(s); - if (li->untagged != NULL && (li->state != L_STATE_BUSY)) { - li->state = L_STATE_BUSY; - break; - } - if (li->untagged == NULL && tag != 0) { - break; - } else { - sc_print_addr(sc_link); - printf(" busy\n"); - } - } - - if (acb == NULL) { - SBIC_DEBUG(ACBS, ("wd33c93sched: no work\n")); - return; /* did not find an available command */ - } - - SBIC_DEBUG(ACBS, ("wd33c93_sched(%d,%d)\n", sc_link->target, - sc_link->lun)); - - TAILQ_REMOVE(&sc->ready_list, acb, chain); - acb->flags &= ~ACB_READY; - - flags = acb->xs->flags; - if (flags & SCSI_RESET) - wd33c93_reset(sc); - - /* XXX - Implicitly call scsidone on select timeout */ - if (wd33c93_go(sc, acb) != 0 || acb->xs->error == XS_SELTIMEOUT) { - acb->dleft = sc->sc_dleft; - wd33c93_scsidone(sc, acb, sc->sc_status); - return; - } -} - -void -wd33c93_scsidone(struct wd33c93_softc *sc, struct wd33c93_acb *acb, int status) -{ - struct scsi_xfer *xs = acb->xs; - struct scsi_link *sc_link = xs->sc_link; - struct wd33c93_tinfo *ti; - struct wd33c93_linfo *li; - -#ifdef DIAGNOSTIC - KASSERT(sc->target == sc_link->target); - KASSERT(sc->lun == sc_link->lun); - KASSERT(acb->flags != ACB_FREE); -#endif - - SBIC_DEBUG(ACBS, ("scsidone: (%d,%d)->(%d,%d)%02x\n", - sc_link->target, sc_link->lun, sc->target, sc->lun, status)); - - timeout_del(&acb->to); - - if (xs->error == XS_NOERROR) { - xs->status = status & SCSI_STATUS_MASK; - xs->resid = acb->dleft; - - switch (xs->status) { - case SCSI_CHECK: - case SCSI_TERMINATED: - /* XXX Need to read sense - return busy for now */ - /*FALLTHROUGH*/ - case SCSI_QUEUE_FULL: - case SCSI_BUSY: - xs->error = XS_BUSY; - break; - } - } - - ti = &sc->sc_tinfo[sc_link->target]; - li = TINFO_LUN(ti, sc_link->lun); - ti->cmds++; - if (xs->error == XS_SELTIMEOUT) { - /* Selection timeout -- discard this LUN if empty */ - if (li->untagged == NULL && li->used == 0) { - if (sc_link->lun < SBIC_NLUN) - ti->lun[sc_link->lun] = NULL; - free(li, M_DEVBUF, 0); - li = NULL; - } - } - - if (li != NULL) - wd33c93_dequeue(sc, acb); - if (sc->sc_nexus == acb) { - sc->sc_state = SBIC_IDLE; - sc->sc_nexus = NULL; - sc->sc_flags = 0; - - if (!TAILQ_EMPTY(&sc->ready_list)) - wd33c93_sched(sc); - } - - scsi_done(xs); -} - -void -wd33c93_dequeue(struct wd33c93_softc *sc, struct wd33c93_acb *acb) -{ - struct wd33c93_tinfo *ti = &sc->sc_tinfo[acb->xs->sc_link->target]; - struct wd33c93_linfo *li; - int lun = acb->xs->sc_link->lun; - - li = TINFO_LUN(ti, lun); -#ifdef DIAGNOSTIC - if (li == NULL || li->lun != lun) - panic("wd33c93_dequeue: lun %d for ecb %p does not exist", - lun, acb); -#endif - if (li->untagged == acb) { - li->state = L_STATE_IDLE; - li->untagged = NULL; - } - if (acb->tag_type && li->queued[acb->tag_id] != NULL) { -#ifdef DIAGNOSTIC - if (li->queued[acb->tag_id] != NULL && - (li->queued[acb->tag_id] != acb)) - panic("wd33c93_dequeue: slot %d for lun %d has %p " - "instead of acb %p\n", acb->tag_id, - lun, li->queued[acb->tag_id], acb); -#endif - li->queued[acb->tag_id] = NULL; - li->used--; - } -} - - -int -wd33c93_wait(struct wd33c93_softc *sc, u_char until, int timeo, int line) -{ - u_char val; - - if (timeo == 0) - timeo = 1000000; /* some large value.. */ - GET_SBIC_asr(sc, val); - while ((val & until) == 0) { - if (timeo-- == 0) { - int csr; - GET_SBIC_csr(sc, csr); -#ifdef SBICDEBUG - printf("wd33c93_wait: TIMEO @%d with asr=0x%x csr=0x%x\n", - line, val, csr); -#ifdef DDB - db_enter(); -#endif -#endif - return(val); /* Maybe I should abort */ - break; - } - DELAY(1); - GET_SBIC_asr(sc, val); - } - return(val); -} - -int -wd33c93_abort(struct wd33c93_softc *sc, struct wd33c93_acb *acb, - const char *where) -{ - u_char csr, asr; - - GET_SBIC_asr(sc, asr); - GET_SBIC_csr(sc, csr); - - sc_print_addr(acb->xs->sc_link); - printf("ABORT in %s: csr=0x%02x, asr=0x%02x\n", where, csr, asr); - - acb->timeout = SBIC_ABORT_TIMEOUT; - acb->flags |= ACB_ABORT; - - /* - * Clean up chip itself - */ - if (sc->sc_nexus == acb) { - /* Reschedule timeout. */ - if ((acb->xs->flags & SCSI_POLL) == 0) - timeout_add_msec(&acb->to, acb->timeout); - - while (asr & SBIC_ASR_DBR) { - /* - * wd33c93 is jammed w/data. need to clear it - * But we don't know what direction it needs to go - */ - GET_SBIC_data(sc, asr); - sc_print_addr(acb->xs->sc_link); - printf("abort %s: clearing data buffer 0x%02x\n", - where, asr); - GET_SBIC_asr(sc, asr); - if (asr & SBIC_ASR_DBR) /* Not the read direction */ - SET_SBIC_data(sc, asr); - GET_SBIC_asr(sc, asr); - } - - sc_print_addr(acb->xs->sc_link); - printf("sending ABORT command\n"); - - WAIT_CIP(sc); - SET_SBIC_cmd(sc, SBIC_CMD_ABORT); - WAIT_CIP(sc); - - GET_SBIC_asr(sc, asr); - - sc_print_addr(acb->xs->sc_link); - if (asr & (SBIC_ASR_BSY|SBIC_ASR_LCI)) { - /* - * ok, get more drastic.. - */ - printf("Resetting bus\n"); - wd33c93_reset(sc); - } else { - printf("sending DISCONNECT to target\n"); - SET_SBIC_cmd(sc, SBIC_CMD_DISC); - WAIT_CIP(sc); - - do { - SBIC_WAIT (sc, SBIC_ASR_INT, 0); - GET_SBIC_asr(sc, asr); - GET_SBIC_csr(sc, csr); - SBIC_DEBUG(MISC, ("csr: 0x%02x, asr: 0x%02x\n", - csr, asr)); - } while ((csr != SBIC_CSR_DISC) && - (csr != SBIC_CSR_DISC_1) && - (csr != SBIC_CSR_CMD_INVALID)); - } - sc->sc_state = SBIC_ERROR; - sc->sc_flags = 0; - } - return SBIC_STATE_ERROR; -} - - -/* - * select the bus, return when selected or error. - * - * Returns the current CSR following selection and optionally MSG out phase. - * i.e. the returned CSR *should* indicate CMD phase... - * If the return value is 0, some error happened. - */ -u_char -wd33c93_selectbus(struct wd33c93_softc *sc, struct wd33c93_acb *acb) -{ - struct scsi_xfer *xs = acb->xs; - struct scsi_link *sc_link = xs->sc_link; - struct wd33c93_tinfo *ti; - u_char target, lun, asr, csr, id; - - KASSERT(sc->sc_state == SBIC_IDLE); - - target = sc_link->target; - lun = sc_link->lun; - ti = &sc->sc_tinfo[target]; - - sc->sc_state = SBIC_SELECTING; - sc->target = target; - sc->lun = lun; - - SBIC_DEBUG(PHASE, ("wd33c93_selectbus %d: ", target)); - - if ((xs->flags & SCSI_POLL) == 0) - timeout_add_msec(&acb->to, acb->timeout); - - /* - * issue select - */ - SBIC_TC_PUT(sc, 0); - SET_SBIC_selid(sc, target); - SET_SBIC_timeo(sc, SBIC_TIMEOUT(250, sc->sc_clkfreq)); - - GET_SBIC_asr(sc, asr); - if (asr & (SBIC_ASR_INT|SBIC_ASR_BSY)) { - /* This means we got ourselves reselected upon */ - SBIC_DEBUG(PHASE, ("WD busy (reselect?) ASR=%02x\n", asr)); - return 0; - } - - SET_SBIC_cmd(sc, SBIC_CMD_SEL_ATN); - WAIT_CIP(sc); - - /* - * wait for select (merged from separate function may need - * cleanup) - */ - do { - asr = SBIC_WAIT(sc, SBIC_ASR_INT | SBIC_ASR_LCI, 0); - if (asr & SBIC_ASR_LCI) { - QPRINTF(("late LCI: asr %02x\n", asr)); - return 0; - } - - /* Clear interrupt */ - GET_SBIC_csr (sc, csr); - - /* Reselected from under our feet? */ - if (csr == SBIC_CSR_RSLT_NI || csr == SBIC_CSR_RSLT_IFY) { - SBIC_DEBUG(PHASE, ("got reselected, asr %02x\n", asr)); - /* - * We need to handle this now so we don't lock up later - */ - wd33c93_nextstate(sc, acb, csr, asr); - return 0; - } - - /* Whoops! */ - if (csr == SBIC_CSR_SLT || csr == SBIC_CSR_SLT_ATN) { - panic("wd33c93_selectbus: target issued select!"); - return 0; - } - - } while (csr != (SBIC_CSR_MIS_2 | MESG_OUT_PHASE) && - csr != (SBIC_CSR_MIS_2 | CMD_PHASE) && - csr != SBIC_CSR_SEL_TIMEO); - - /* Anyone at home? */ - if (csr == SBIC_CSR_SEL_TIMEO) { - xs->error = XS_SELTIMEOUT; - SBIC_DEBUG(PHASE, ("-- Selection Timeout\n")); - return 0; - } - - SBIC_DEBUG(PHASE, ("Selection Complete\n")); - - /* Assume we're now selected */ - GET_SBIC_selid(sc, id); - if (id != target) { - /* Something went wrong - wrong target was select */ - sc_print_addr(sc_link); - printf("%s: wrong target selected; WANTED %d GOT %d", - __func__, target, id); - return 0; /* XXX: Need to call nexstate to handle? */ - } - - sc->sc_flags |= SBICF_SELECTED; - sc->sc_state = SBIC_CONNECTED; - - /* setup correct sync mode for this target */ - wd33c93_setsync(sc, ti); - - if (ti->flags & T_NODISC && sc->sc_disc == 0) - SET_SBIC_rselid (sc, 0); /* Not expecting a reselect */ - else - SET_SBIC_rselid (sc, SBIC_RID_ER); - - /* - * We only really need to do anything when the target goes to MSG out - * If the device ignored ATN, it's probably old and brain-dead, - * but we'll try to support it anyhow. - * If it doesn't support message out, it definitely doesn't - * support synchronous transfers, so no point in even asking... - */ - if (csr == (SBIC_CSR_MIS_2 | MESG_OUT_PHASE)) { - if (ti->flags & T_NEGOTIATE) { - /* Initiate a SDTR message */ - SBIC_DEBUG(SYNC, ("Sending SDTR to target %d\n", id)); - if (ti->flags & T_WANTSYNC) { - ti->period = sc->sc_minsyncperiod; - ti->offset = sc->sc_maxoffset; - } else { - ti->period = 0; - ti->offset = 0; - } - /* Send Sync negotiation message */ - sc->sc_omsg[0] = MSG_IDENTIFY(lun, 0); /* No Disc */ - sc->sc_omsg[1] = MSG_EXTENDED; - sc->sc_omsg[2] = MSG_EXT_SDTR_LEN; - sc->sc_omsg[3] = MSG_EXT_SDTR; - if (ti->flags & T_WANTSYNC) { - sc->sc_omsg[4] = sc->sc_minsyncperiod; - sc->sc_omsg[5] = sc->sc_maxoffset; - } else { - sc->sc_omsg[4] = 0; - sc->sc_omsg[5] = 0; - } - wd33c93_xfout(sc, 6, sc->sc_omsg); - sc->sc_msgout |= SEND_SDTR; /* may be rejected */ - sc->sc_flags |= SBICF_SYNCNEGO; - } else { - if (sc->sc_nexus->tag_type != 0) { - /* Use TAGS */ - SBIC_DEBUG(TAGS, ("