summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2004-08-03 21:46:59 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2004-08-03 21:46:59 +0000
commite710973823a9bbc5e904b1e829a0707e61ff21c5 (patch)
treeb089733d9e628b19e64a9e7909e96308a3f8877f /sys
parent64d5018aaa427d0e10165c038e59678b058e4f55 (diff)
Replace the old 4.4BSD scsi code used on hp300 with a ``real'' driver
interfaced with the MI scsi code. Adapted from NetBSD with some changes (especially to get tape and old cd-rom drives to not cause the driver to spin during probe). Tested by millert@ and I, ok millert@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/hp300/conf/GENERIC14
-rw-r--r--sys/arch/hp300/conf/RAMDISK11
-rw-r--r--sys/arch/hp300/conf/files.hp30033
-rw-r--r--sys/arch/hp300/dev/ac.c507
-rw-r--r--sys/arch/hp300/dev/acioctl.h85
-rw-r--r--sys/arch/hp300/dev/acvar.h96
-rw-r--r--sys/arch/hp300/dev/hp98265reg.h (renamed from sys/arch/hp300/dev/sdvar.h)87
-rw-r--r--sys/arch/hp300/dev/mb89352.c2025
-rw-r--r--sys/arch/hp300/dev/mb89352reg.h238
-rw-r--r--sys/arch/hp300/dev/mb89352var.h217
-rw-r--r--sys/arch/hp300/dev/scsi.c1541
-rw-r--r--sys/arch/hp300/dev/scsireg.h477
-rw-r--r--sys/arch/hp300/dev/scsivar.h91
-rw-r--r--sys/arch/hp300/dev/sd.c1271
-rw-r--r--sys/arch/hp300/dev/spc.c276
-rw-r--r--sys/arch/hp300/dev/st.c1413
-rw-r--r--sys/arch/hp300/dev/stvar.h220
-rw-r--r--sys/arch/hp300/hp300/autoconf.c131
-rw-r--r--sys/arch/hp300/hp300/conf.c25
19 files changed, 2881 insertions, 5877 deletions
diff --git a/sys/arch/hp300/conf/GENERIC b/sys/arch/hp300/conf/GENERIC
index c68b4a85fa6..9ea6c96e91c 100644
--- a/sys/arch/hp300/conf/GENERIC
+++ b/sys/arch/hp300/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.30 2001/12/06 01:03:42 miod Exp $
+# $OpenBSD: GENERIC,v 1.31 2004/08/03 21:46:54 miod Exp $
# $NetBSD: GENERIC,v 1.23 1997/01/31 06:12:57 thorpej Exp $
#
# Generic kernel - one size fits all.
@@ -110,8 +110,12 @@ ct* at hpibbus? slave ? punit ? # HP-IB cartridge tapes
mt* at hpibbus? slave ? punit ? # HP-IB 9-track tape
ppi0 at hpibbus0 slave 5 punit 0 # HP-IB plotter
-oscsi* at dio? scode ? # Old HP SCSI
+spc* at dio? scode ? # SCSI controller
+scsibus* at spc?
-sd* at oscsi? target ? lun ? # SCSI disks
-st* at oscsi? target ? lun ? # SCSI tapes
-ac* at oscsi? target ? lun ? # SCSI changers
+sd* at scsibus? target ? lun ? # SCSI disks
+st* at scsibus? target ? lun ? # SCSI tapes
+cd* at scsibus? target ? lun ? # SCSI CD-ROMs
+ch* at scsibus? target ? lun ? # SCSI changer devices
+ss* at scsibus? target ? lun ? # SCSI scanners
+uk* at scsibus? target ? lun ? # unknown SCSI devices
diff --git a/sys/arch/hp300/conf/RAMDISK b/sys/arch/hp300/conf/RAMDISK
index f295f330e13..f98fb63c77f 100644
--- a/sys/arch/hp300/conf/RAMDISK
+++ b/sys/arch/hp300/conf/RAMDISK
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK,v 1.15 2001/11/25 23:23:45 miod Exp $
+# $OpenBSD: RAMDISK,v 1.16 2004/08/03 21:46:54 miod Exp $
#
# Ram disk kernel.
#
@@ -117,11 +117,12 @@ hd* at hpibbus? slave ? punit ? # HP-IB disks
ct* at hpibbus? slave ? punit ? # HP-IB cartridge tapes
mt* at hpibbus? slave ? punit ? # HP-IB 9-track tape
-oscsi* at dio? scode ? # Old HP SCSI
+spc* at dio? scode ? # SCSI controller
+scsibus* at spc?
-sd* at oscsi? target ? lun ? # SCSI disks
-st* at oscsi? target ? lun ? # SCSI tapes
-ac* at oscsi? target ? lun ? # SCSI changers
+sd* at scsibus? target ? lun ? # SCSI disks
+st* at scsibus? target ? lun ? # SCSI tapes
+cd* at scsibus? target ? lun ? # SCSI CD-ROMs
pseudo-device loop 1 # network loopback
pseudo-device pty 16 # pseudo-terminals
diff --git a/sys/arch/hp300/conf/files.hp300 b/sys/arch/hp300/conf/files.hp300
index fa24df6bebe..025e4098110 100644
--- a/sys/arch/hp300/conf/files.hp300
+++ b/sys/arch/hp300/conf/files.hp300
@@ -1,4 +1,4 @@
-# $OpenBSD: files.hp300,v 1.21 2004/07/10 03:40:32 deraadt Exp $
+# $OpenBSD: files.hp300,v 1.22 2004/08/03 21:46:54 miod Exp $
# $NetBSD: files.hp300,v 1.28 1997/05/12 08:23:28 thorpej Exp $
#
# hp300-specific configuration info
@@ -8,9 +8,6 @@ maxpartitions 16
maxusers 2 8 64
-# NOTE! The order of these lines is significant! Don't change them
-# unless you absolutely know what you're doing!
-
#
# Mainbus
#
@@ -130,12 +127,10 @@ file arch/hp300/dev/hpib.c hpibbus
device ct: tape
attach ct at hpibbus
file arch/hp300/dev/ct.c ct needs-flag
-major {ct = 0}
device mt: tape
attach mt at hpibbus
file arch/hp300/dev/mt.c mt needs-flag
-major {mt = 1}
device hd: disk
attach hd at hpibbus
@@ -149,24 +144,16 @@ file arch/hp300/dev/ppi.c ppi needs-flag
# RAM disk
major {rd = 8}
-# Old HP SCSI layer
-device oscsi { target = -1, lun = -1 }
-attach oscsi at dio
-file arch/hp300/dev/scsi.c oscsi
-
-# Old HP SCSI devices
-device sd: disk
-attach sd at oscsi
-file arch/hp300/dev/sd.c sd needs-flag
-major {sd = 4}
+# SCSI devices
+include "scsi/files.scsi"
-device st: tape
-attach st at oscsi
-file arch/hp300/dev/st.c st needs-flag
+device spc: scsi
+attach spc at dio
+file arch/hp300/dev/spc.c spc needs-flag
+file arch/hp300/dev/mb89352.c spc
-device ac
-attach ac at oscsi
-file arch/hp300/dev/ac.c ac needs-flag
+major {sd = 4}
+major {cd = 9}
# Human (Hilarious) Interface Loop
# XXX should be a real device
@@ -198,8 +185,6 @@ file arch/hp300/dev/dma.c
file dev/cons.c
file dev/cninit.c
-major {vnd = 6}
-
#
# HP-UX binary compatibility
#
diff --git a/sys/arch/hp300/dev/ac.c b/sys/arch/hp300/dev/ac.c
deleted file mode 100644
index 79afe6b15cf..00000000000
--- a/sys/arch/hp300/dev/ac.c
+++ /dev/null
@@ -1,507 +0,0 @@
-/* $OpenBSD: ac.c,v 1.13 2003/06/02 23:27:44 millert Exp $ */
-/* $NetBSD: ac.c,v 1.9 1997/04/02 22:37:21 scottr Exp $ */
-
-/*
- * Copyright (c) 1996, 1997 Jason R. Thorpe. All rights reserved.
- * Copyright (c) 1991 University of Utah.
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * the Systems Programming Group of the University of Utah Computer
- * Science Department.
- *
- * 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.
- *
- * from: Utah $Hdr: ac.c 1.5 92/01/21$
- *
- * @(#)ac.c 8.2 (Berkeley) 1/12/94
- */
-
-/*
- * SCSI driver for MO autochanger.
- *
- * Very crude. Because of the lack of connect/disconnect support in the
- * scsi driver, this driver can tie up the SCSI bus for a long time. It
- * also grabs a DMA channel and holds it for the duration even though it
- * never uses it.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/device.h>
-#include <sys/errno.h>
-#include <sys/ioctl.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-
-#include <sys/conf.h>
-
-#include <hp300/dev/scsireg.h>
-#include <hp300/dev/scsivar.h>
-#include <hp300/dev/acioctl.h>
-#include <hp300/dev/acvar.h>
-
-bdev_decl(ac);
-cdev_decl(ac);
-
-static int acmatch(struct device *, void *, void *);
-static void acattach(struct device *, struct device *, void *);
-
-struct cfattach ac_ca = {
- sizeof(struct ac_softc), acmatch, acattach
-};
-
-struct cfdriver ac_cd = {
- NULL, "ac", DV_DULL
-};
-
-void acstart(void *);
-void acgo(void *);
-void acintr(void *, int);
-
-#ifdef DEBUG
-int ac_debug = 0x0000;
-#define ACD_FOLLOW 0x0001
-#define ACD_OPEN 0x0002
-#endif
-
-static int
-acmatch(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- struct oscsi_attach_args *osa = aux;
-
- if (osa->osa_inqbuf->type != 8 || osa->osa_inqbuf->qual != 0x80 ||
- osa->osa_inqbuf->version != 2)
- return (0);
-
- return (1);
-}
-
-static void
-acattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
-{
- struct ac_softc *sc = (struct ac_softc *)self;
- struct oscsi_attach_args *osa = aux;
-
- printf("\n");
-
- sc->sc_target = osa->osa_target;
- sc->sc_lun = osa->osa_lun;
-
- /* Initialize SCSI queue entry. */
- sc->sc_sq.sq_softc = sc;
- sc->sc_sq.sq_target = sc->sc_target;
- sc->sc_sq.sq_lun = sc->sc_lun;
- sc->sc_sq.sq_start = acstart;
- sc->sc_sq.sq_go = acgo;
- sc->sc_sq.sq_intr = acintr;
-
- sc->sc_bp = (struct buf *)malloc(sizeof(struct buf),
- M_DEVBUF, M_NOWAIT);
- sc->sc_cmd = (struct scsi_fmt_cdb *)malloc(sizeof(struct scsi_fmt_cdb),
- M_DEVBUF, M_NOWAIT);
-
- if (sc->sc_bp == NULL || sc->sc_cmd == NULL) {
- printf("%s: memory allocation failed\n", sc->sc_dev.dv_xname);
- return;
- }
-
- sc->sc_flags = ACF_ALIVE;
-}
-
-/*ARGSUSED*/
-int
-acopen(dev, flag, mode, p)
- dev_t dev;
- int flag, mode;
- struct proc *p;
-{
- int unit = minor(dev);
- struct ac_softc *sc;
-
- if (unit >= ac_cd.cd_ndevs ||
- (sc = ac_cd.cd_devs[unit]) == NULL ||
- (sc->sc_flags & ACF_ALIVE) == 0)
- return (ENXIO);
-
- if (sc->sc_flags & ACF_OPEN)
- return (EBUSY);
-
- /*
- * Since acgeteinfo can block we mark the changer open now.
- */
- sc->sc_flags |= ACF_OPEN;
- if (acgeteinfo(dev)) {
- sc->sc_flags &= ~ACF_OPEN;
- return(EIO);
- }
- return (0);
-}
-
-/*ARGSUSED*/
-int
-acclose(dev, flag, mode, p)
- dev_t dev;
- int flag, mode;
- struct proc *p;
-{
- struct ac_softc *sc = ac_cd.cd_devs[minor(dev)];
-
- sc->sc_flags &= ~ACF_OPEN;
- return (0);
-}
-
-#define ACRESLEN(ep) \
- (8 + (ep)->nmte*12 + (ep)->nse*12 + (ep)->niee*12 + (ep)->ndte*20)
-
-/*ARGSUSED*/
-int
-acioctl(dev, cmd, data, flag, p)
- dev_t dev;
- u_long cmd;
- caddr_t data;
- int flag;
- struct proc *p;
-{
- struct ac_softc *sc = ac_cd.cd_devs[minor(dev)];
- char *dp;
- int dlen, error = 0;
-
- switch (cmd) {
-
- default:
- return (EINVAL);
-
- /* perform an init element status and mode sense to reset state */
- case ACIOCINIT:
- error = accommand(dev, ACCMD_INITES, (caddr_t)0, 0);
- if (!error)
- error = acgeteinfo(dev);
- break;
-
- /* copy internal element information */
- case ACIOCGINFO:
- *(struct acinfo *)data = sc->sc_einfo;
- break;
-
- case ACIOCRAWES:
- {
- struct acbuffer *acbp = (struct acbuffer *)data;
-
- dlen = ACRESLEN(&sc->sc_einfo);
- dp = (char *) malloc(dlen, M_DEVBUF, M_WAITOK);
- error = accommand(dev, ACCMD_READES, dp, dlen);
- if (!error) {
- dlen = *(int *)&dp[4] + 8;
- if (dlen > acbp->buflen)
- dlen = acbp->buflen;
- error = copyout(dp, acbp->bufptr, dlen);
- }
- break;
- }
-
- case ACIOCGSTAT:
- {
- struct acbuffer *acbp = (struct acbuffer *)data;
-
- dlen = ACRESLEN(&sc->sc_einfo);
- dp = (char *) malloc(dlen, M_DEVBUF, M_WAITOK);
- error = accommand(dev, ACCMD_READES, dp, dlen);
- if (!error) {
- int ne;
- char *tbuf;
-
- ne = sc->sc_einfo.nmte + sc->sc_einfo.nse +
- sc->sc_einfo.niee + sc->sc_einfo.ndte;
- dlen = ne * sizeof(struct aceltstat);
- tbuf = (char *) malloc(dlen, M_DEVBUF, M_WAITOK);
- acconvert(dp, tbuf, ne);
- if (dlen > acbp->buflen)
- dlen = acbp->buflen;
- error = copyout(tbuf, acbp->bufptr, dlen);
- free(tbuf, M_DEVBUF);
- }
- free(dp, M_DEVBUF);
- break;
- }
-
- case ACIOCMOVE:
- error = accommand(dev, ACCMD_MOVEM, data,
- sizeof(struct acmove));
- break;
- }
- return(error);
-}
-
-int
-accommand(dev, command, bufp, buflen)
- dev_t dev;
- int command;
- char *bufp;
- int buflen;
-{
- int unit = minor(dev);
- struct ac_softc *sc = ac_cd.cd_devs[unit];
- struct buf *bp = sc->sc_bp;
- struct scsi_fmt_cdb *cmd = sc->sc_cmd;
- int error;
-
-#ifdef DEBUG
- if (ac_debug & ACD_FOLLOW)
- printf("accommand(dev=%x, cmd=%x, buf=%p, buflen=%x)\n",
- dev, command, bufp, buflen);
-#endif
- if (sc->sc_flags & ACF_ACTIVE)
- panic("accommand: active!");
-
- sc->sc_flags |= ACF_ACTIVE;
- bzero((caddr_t)cmd->cdb, sizeof(cmd->cdb));
- cmd->cdb[0] = command;
-
- switch (command) {
- case ACCMD_INITES:
- cmd->len = 6;
- break;
- case ACCMD_READES:
- cmd->len = 12;
- *(short *)&cmd->cdb[2] = 0;
- *(short *)&cmd->cdb[4] =
- sc->sc_einfo.nmte + sc->sc_einfo.nse +
- sc->sc_einfo.niee + sc->sc_einfo.ndte;
- cmd->cdb[7] = buflen >> 16;
- cmd->cdb[8] = buflen >> 8;
- cmd->cdb[9] = buflen;
- break;
- case ACCMD_MODESENSE:
- cmd->len = 6;
- cmd->cdb[2] = 0x3F; /* all pages */
- cmd->cdb[4] = buflen;
- break;
- case ACCMD_MOVEM:
- cmd->len = 12;
- *(short *)&cmd->cdb[2] = sc->sc_picker;
- *(short *)&cmd->cdb[4] = *(short *)&bufp[0];
- *(short *)&cmd->cdb[6] = *(short *)&bufp[2];
- if (*(short *)&bufp[4] & AC_INVERT)
- cmd->cdb[10] = 1;
- bufp = 0;
- buflen = 0;
- break;
- default:
- panic("accommand: bad command");
- }
- bp->b_flags = B_BUSY|B_READ;
- bp->b_dev = dev;
- bp->b_un.b_addr = bufp;
- bp->b_bcount = buflen;
- bp->b_resid = 0;
- bp->b_blkno = 0;
- bp->b_error = 0;
- LIST_INIT(&bp->b_dep);
- if (scsireq(sc->sc_dev.dv_parent, &sc->sc_sq))
- acstart(sc);
- error = biowait(bp);
- sc->sc_flags &= ~ACF_ACTIVE;
- return (error);
-}
-
-void
-acstart(arg)
- void *arg;
-{
- struct ac_softc *sc = arg;
-
-#ifdef DEBUG
- if (ac_debug & ACD_FOLLOW)
- printf("acstart(unit=%x)\n", sc->sc_dev.dv_unit);
-#endif
- if (scsiustart(sc->sc_dev.dv_parent->dv_unit))
- acgo(arg);
-}
-
-void
-acgo(arg)
- void *arg;
-{
- struct ac_softc *sc = arg;
- struct buf *bp = sc->sc_bp;
- int stat;
- int s;
-
-#ifdef DEBUG
- if (ac_debug & ACD_FOLLOW)
- printf("acgo(unit=%x): ", sc->sc_dev.dv_unit);
-#endif
- stat = scsigo(sc->sc_dev.dv_parent->dv_unit, sc->sc_target,
- sc->sc_lun, bp, sc->sc_cmd, 0);
-#ifdef DEBUG
- if (ac_debug & ACD_FOLLOW)
- printf("scsigo returns %x\n", stat);
-#endif
- if (stat) {
- bp->b_error = EIO;
- bp->b_flags |= B_ERROR;
- s = splbio();
- biodone(bp);
- splx(s);
- scsifree(sc->sc_dev.dv_parent, &sc->sc_sq);
- }
-}
-
-void
-acintr(arg, stat)
- void *arg;
- int stat;
-{
- struct ac_softc *sc = arg;
- struct buf *bp = sc->sc_bp;
- u_char sensebuf[78];
- struct scsi_xsense *sp;
-
-#ifdef DEBUG
- if (ac_debug & ACD_FOLLOW)
- printf("acintr(unit=%x, stat=%x)\n", sc->sc_dev.dv_unit, stat);
-#endif
- switch (stat) {
- case 0:
- bp->b_resid = 0;
- break;
- case STS_CHECKCOND:
- scsi_request_sense(sc->sc_dev.dv_parent->dv_unit,
- sc->sc_target, sc->sc_lun, sensebuf, sizeof sensebuf);
- sp = (struct scsi_xsense *)sensebuf;
- printf("%s: acintr sense key=%x, ac=%x, acq=%x\n",
- sc->sc_dev.dv_xname, sp->key, sp->info4, sp->len);
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- break;
- default:
- printf("%s: acintr unknown status 0x%x\n", sc->sc_dev.dv_xname,
- stat);
- break;
- }
- biodone(sc->sc_bp);
- scsifree(sc->sc_dev.dv_parent, &sc->sc_sq);
-}
-
-int
-acgeteinfo(dev)
- dev_t dev;
-{
- struct ac_softc *sc = ac_cd.cd_devs[minor(dev)];
- char *bp;
- char msbuf[48];
- int error;
-
- bzero(msbuf, sizeof msbuf);
- error = accommand(dev, ACCMD_MODESENSE, msbuf, sizeof msbuf);
- if (error)
- return(error);
- bp = &msbuf[4];
- while (bp < &msbuf[48]) {
- switch (bp[0] & 0x3F) {
- case 0x1D:
- sc->sc_einfo = *(struct acinfo *)&bp[2];
- sc->sc_picker = sc->sc_einfo.fmte; /* XXX */
- return(0);
- case 0x1E:
- bp += 4;
- break;
- case 0x1F:
- bp += 20;
- break;
- default:
- printf("acgeteinfo: bad page type %x\n", bp[0]);
- return(EIO);
- }
- }
- return(EIO);
-}
-
-void
-acconvert(sbuf, dbuf, ne)
- char *sbuf, *dbuf;
- int ne;
-{
- struct aceltstat *ep = (struct aceltstat *)dbuf;
- struct ac_restatphdr *phdr;
- struct ac_restatdb *dbp;
- struct ac_restathdr *hdr;
-#ifdef DEBUG
- int bcount;
-#endif
-
- hdr = (struct ac_restathdr *)&sbuf[0];
- sbuf += sizeof *hdr;
-#ifdef DEBUG
- if (ac_debug & ACD_FOLLOW)
- printf("element status: first=%d, num=%d, len=%ld\n",
- hdr->ac_felt, hdr->ac_nelt, hdr->ac_bcount);
- if (hdr->ac_nelt != ne) {
- printf("acconvert: # of elements, %d != %d\n",
- hdr->ac_nelt, ne);
- if (hdr->ac_nelt < ne)
- ne = hdr->ac_nelt;
- }
- bcount = hdr->ac_bcount;
-#endif
- while (ne) {
- phdr = (struct ac_restatphdr *)sbuf;
- sbuf += sizeof *phdr;
-#ifdef DEBUG
- bcount -= sizeof *phdr;
-#endif
- dbp = (struct ac_restatdb *)sbuf;
- sbuf += phdr->ac_bcount;
-#ifdef DEBUG
- bcount -= phdr->ac_bcount;
-#endif
- while (dbp < (struct ac_restatdb *)sbuf) {
- ep->type = phdr->ac_type;
- ep->eaddr = dbp->ac_eaddr;
- ep->flags = 0;
- if (dbp->ac_full)
- ep->flags |= AC_FULL;
- if (dbp->ac_exc)
- ep->flags |= AC_ERROR;
- if (dbp->ac_acc)
- ep->flags |= AC_ACCESS;
- dbp = (struct ac_restatdb *)
- ((char *)dbp + phdr->ac_dlen);
- ep++;
- ne--;
- }
-#ifdef DEBUG
- if (ne < 0 || bcount < 0)
- panic("acconvert: inconsistent");
-#endif
- }
-}
diff --git a/sys/arch/hp300/dev/acioctl.h b/sys/arch/hp300/dev/acioctl.h
deleted file mode 100644
index ac7c7d29bed..00000000000
--- a/sys/arch/hp300/dev/acioctl.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* $OpenBSD: acioctl.h,v 1.4 2003/11/07 10:16:45 jmc Exp $ */
-/* $NetBSD: acioctl.h,v 1.2 1994/10/26 07:23:25 cgd Exp $ */
-
-/*
- * Copyright (c) 1991 University of Utah.
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * the Systems Programming Group of the University of Utah Computer
- * Science Department.
- *
- * 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.
- *
- * from: Utah $Hdr: acioctl.h 1.1 91/06/19$
- *
- * @(#)acioctl.h 8.1 (Berkeley) 6/10/93
- */
-
-struct acinfo {
- short fmte; /* 1st medium transport elt (picker) */
- short nmte; /* # medium transport elts */
- short fse; /* 1st storage elt (slot) */
- short nse; /* # storage elts */
- short fiee; /* 1st import/export elt (mailslot) */
- short niee; /* # import/export elts */
- short fdte; /* 1st data transport elt (drive) */
- short ndte; /* # data transport elts */
-};
-
-struct aceltstat {
- short eaddr; /* element address */
- char type; /* type of element */
- char flags; /* flags */
-};
-
-/* types */
-#define AC_MTE 0x01 /* picker */
-#define AC_SE 0x02 /* slot */
-#define AC_IEE 0x03 /* mailslot */
-#define AC_DTE 0x04 /* drive */
-/* flags */
-#define AC_FULL 0x01 /* media present */
-#define AC_ERROR 0x04 /* error accessing element */
-#define AC_ACCESS 0x08 /* element accessible */
-#define AC_INVERT 0x80 /* media inverted prior to insertion */
-
-struct acmove {
- short srcelem;
- short dstelem;
- short flags;
-};
-
-struct acbuffer {
- char *bufptr;
- int buflen;
-};
-
-#define ACIOCINIT _IO('A', 0x1) /* init elt status */
-#define ACIOCGINFO _IOR('A', 0x2, struct acinfo) /* mode sense */
-#define ACIOCGSTAT _IOW('A', 0x3, struct acbuffer) /* read elem status */
-#define ACIOCMOVE _IOW('A', 0x4, struct acmove) /* move elem */
-#define ACIOCRAWES _IOW('A', 0x5, struct acbuffer) /* raw element stat */
diff --git a/sys/arch/hp300/dev/acvar.h b/sys/arch/hp300/dev/acvar.h
deleted file mode 100644
index 2680fbd05f5..00000000000
--- a/sys/arch/hp300/dev/acvar.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* $OpenBSD: acvar.h,v 1.6 2003/06/02 23:27:44 millert Exp $ */
-/* $NetBSD: acvar.h,v 1.4 1997/03/31 07:32:15 scottr Exp $ */
-
-/*
- * Copyright (c) 1991 University of Utah.
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * the Systems Programming Group of the University of Utah Computer
- * Science Department.
- *
- * 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.
- *
- * from: Utah $Hdr: acvar.h 1.1 91/06/19$
- *
- * @(#)acvar.h 8.1 (Berkeley) 6/10/93
- */
-
-struct ac_softc {
- struct device sc_dev;
- int sc_target;
- int sc_lun;
- int sc_flags;
- struct buf *sc_bp;
- struct scsi_fmt_cdb *sc_cmd;
- struct acinfo sc_einfo;
- short sc_picker;
- struct scsiqueue sc_sq;
-};
-
-#define ACF_ALIVE 0x01
-#define ACF_OPEN 0x02
-#define ACF_ACTIVE 0x04
-
-#define ACCMD_INITES 0x07
-#define ACCMD_MODESENSE 0x1A
-#define ACCMD_READES 0xB8
-#define ACCMD_MOVEM 0xA5
-
-struct ac_restathdr {
- short ac_felt; /* first element reported */
- short ac_nelt; /* number of elements reported */
- long ac_bcount; /* length of report (really only 24 bits) */
-};
-
-struct ac_restatphdr {
- char ac_type; /* type code */
- char ac_res;
- short ac_dlen; /* element descriptor length */
- long ac_bcount; /* byte count (really only 24 bits) */
-};
-
-struct ac_restatdb {
- short ac_eaddr; /* element address */
- u_int ac_res1:2,
- ac_ie:1, /* import enabled (IEE only) */
- ac_ee:1, /* export enabled (IEE only) */
- ac_acc:1, /* accessible from MTE */
- ac_exc:1, /* element in abnormal state */
- ac_imp:1, /* 1 == user inserted medium (IEE only) */
- ac_full:1; /* element contains media */
-};
-
-#ifdef _KERNEL
-int accommand(dev_t, int, char *, int);
-
-void acstart(void *);
-void acgo(void *);
-void acintr(void *, int);
-
-int acgeteinfo(dev_t);
-void acconvert(char *, char *, int);
-#endif /* _KERNEL */
diff --git a/sys/arch/hp300/dev/sdvar.h b/sys/arch/hp300/dev/hp98265reg.h
index e74377b04e3..f8b6dbcf00b 100644
--- a/sys/arch/hp300/dev/sdvar.h
+++ b/sys/arch/hp300/dev/hp98265reg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: sdvar.h,v 1.12 2003/06/02 23:27:45 millert Exp $ */
-/* $NetBSD: sdvar.h,v 1.7 1997/03/31 07:40:07 scottr Exp $ */
+/* $OpenBSD: hp98265reg.h,v 1.1 2004/08/03 21:46:56 miod Exp $ */
+/* $NetBSD: hp98265reg.h,v 1.1 2003/08/01 01:18:45 tsutsui Exp $ */
/*
* Copyright (c) 1990, 1993
@@ -32,63 +32,40 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)sdvar.h 8.1 (Berkeley) 6/10/93
+ * @(#)scsireg.h 8.1 (Berkeley) 6/10/93
*/
-struct sdstats {
- long sdresets;
- long sdtransfers;
- long sdpartials;
-};
-
-struct sd_softc {
- struct device sc_dev;
- struct disk sc_dkdev;
- struct scsiqueue sc_sq;
- int sc_format_pid; /* process using "format" mode */
- short sc_flags;
- short sc_type; /* drive type */
- int sc_target; /* SCSI target */
- int sc_lun; /* SCSI lun */
- u_short sc_bshift; /* convert device blocks to DEV_BSIZE blks */
- u_int sc_blks; /* number of blocks on device */
- int sc_blksize; /* device block size in bytes */
- u_int sc_heads; /* number of heads (tracks) */
- u_int sc_cyls; /* number of cylinders */
- struct buf sc_tab; /* buffer queue */
- struct sdstats sc_stats; /* debugging stats */
- struct scsi_fmt_cdb sc_cmdstore;
- struct scsi_fmt_sense sc_sensestore;
-};
-
-/* sc_flags values */
-#define SDF_ALIVE 0x01
-#define SDF_OPENING 0x02
-#define SDF_CLOSING 0x04
-#define SDF_WANTED 0x08
-#define SDF_WLABEL 0x10
-#define SDF_RMEDIA 0x20
-#define SDF_ERROR 0x40
-
-#define SDUNIT(x) DISKUNIT(x)
-#define SDPART(x) DISKPART(x)
-#define SDLABELDEV(d) MAKEDISKDEV(major(d), SDUNIT(d), RAW_PART)
-
-#define b_cylin b_resid
+/*
+ * HP 98265A SCSI Interface Hardware Description.
+ */
-#define SDRETRY 2
+#define SPC_OFFSET 32
+#define SPC_SIZE (32 * 2) /* XXX */
-#ifdef _KERNEL
-/* sd.c */
-void sdustart(int);
+#define HPSCSI_ID 0x00
+#define ID_MASK 0x1f
+#define SCSI_ID 0x07
+#define ID_WORD_DMA 0x20
-void sdstart(void *);
-void sdgo(void *);
-void sdintr(void *, int);
+#define HPSCSI_CSR 0x01
+#define CSR_IE 0x80
+#define CSR_IR 0x40
+#define SCSI_IPL(csr) ((((csr) >> 4) & 3) + 3)
+#define CSR_DMA32 0x08
+#define CSR_DMAIN 0x04
+#define CSR_DE1 0x02
+#define CSR_DE0 0x01
-int sdgetcapacity(struct sd_softc *, dev_t);
-int sdgetinfo(dev_t, struct sd_softc *, struct disklabel *, int);
+#define HPSCSI_WRAP 0x02
+#define WRAP_REQ 0x80
+#define WRAP_ACK 0x40
+#define WRAP_BSY 0x08
+#define WRAP_MSG 0x04
+#define WRAP_CD 0x02
+#define WRAP_IO 0x01
-/* sd_compat.c */
-void sdmakedisklabel(int, struct disklabel *);
-#endif /* _KERNEL */
+#define HPSCSI_HCONF 0x03
+#define HCONF_TP 0x80
+#define SCSI_SYNC_XFER(hconf) (((hconf) >> 5) & 3)
+#define HCONF_SD 0x10
+#define HCONF_PARITY 0x08
diff --git a/sys/arch/hp300/dev/mb89352.c b/sys/arch/hp300/dev/mb89352.c
new file mode 100644
index 00000000000..5f9cdff8258
--- /dev/null
+++ b/sys/arch/hp300/dev/mb89352.c
@@ -0,0 +1,2025 @@
+/* $OpenBSD: mb89352.c,v 1.1 2004/08/03 21:46:56 miod Exp $ */
+/* $NetBSD: mb89352.c,v 1.5 2000/03/23 07:01:31 thorpej Exp $ */
+/* NecBSD: mb89352.c,v 1.4 1998/03/14 07:31:20 kmatsuda Exp */
+
+/*-
+ * Copyright (c) 1996,97,98,99 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum, Masaru Oki and Kouichi Matsuda.
+ *
+ * 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 Charles M. Hannum.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Copyright (c) 1994 Jarle Greipsland
+ * 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, 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 ``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 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.
+ */
+/*
+ * [NetBSD for NEC PC-98 series]
+ * Copyright (c) 1996, 1997, 1998
+ * NetBSD/pc98 porting staff. All rights reserved.
+ * Copyright (c) 1996, 1997, 1998
+ * Kouichi Matsuda. All rights reserved.
+ */
+
+/*
+ * Acknowledgements: Many of the algorithms used in this driver are
+ * inspired by the work of Julian Elischer (julian@tfs.com) and
+ * Charles Hannum (mycroft@duality.gnu.ai.mit.edu). Thanks a million!
+ */
+
+/*
+ * A few customizable items:
+ */
+
+/* Synchronous data transfers? */
+#define SPC_USE_SYNCHRONOUS 0
+#define SPC_SYNC_REQ_ACK_OFS 8
+
+/* Wide data transfers? */
+#define SPC_USE_WIDE 0
+#define SPC_MAX_WIDTH 0
+
+/* Max attempts made to transmit a message */
+#define SPC_MSG_MAX_ATTEMPT 3 /* Not used now XXX */
+
+/*
+ * Some spin loop parameters (essentially how long to wait some places)
+ * The problem(?) is that sometimes we expect either to be able to transmit a
+ * byte or to get a new one from the SCSI bus pretty soon. In order to avoid
+ * returning from the interrupt just to get yanked back for the next byte we
+ * may spin in the interrupt routine waiting for this byte to come. How long?
+ * This is really (SCSI) device and processor dependent. Tuneable, I guess.
+ */
+#define SPC_MSGIN_SPIN 1 /* Will spinwait upto ?ms for a new msg byte */
+#define SPC_MSGOUT_SPIN 1
+
+/*
+ * Include debug functions? At the end of this file there are a bunch of
+ * functions that will print out various information regarding queued SCSI
+ * commands, driver state and chip contents. You can call them from the
+ * kernel debugger. If you set SPC_DEBUG to 0 they are not included (the
+ * kernel uses less memory) but you lose the debugging facilities.
+ */
+/* #define SPC_DEBUG */
+
+#define SPC_ABORT_TIMEOUT 2000 /* time to wait for abort */
+
+/* threshold length for DMA transfer */
+#define SPC_MIN_DMA_LEN 32
+
+/* End of customizable parameters */
+
+/*
+ * MB89352 SCSI Protocol Controller (SPC) routines.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/queue.h>
+
+#include <machine/intr.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsi_message.h>
+#include <scsi/scsiconf.h>
+
+#include <hp300/dev/mb89352reg.h>
+#include <hp300/dev/mb89352var.h>
+
+#ifdef SPC_DEBUG
+int spc_debug = 0x00; /* SPC_SHOWSTART|SPC_SHOWMISC|SPC_SHOWTRACE; */
+#endif
+
+void spc_done (struct spc_softc *, struct spc_acb *);
+void spc_dequeue (struct spc_softc *, struct spc_acb *);
+int spc_scsi_cmd (struct scsi_xfer *);
+int spc_poll (struct spc_softc *, struct scsi_xfer *, int);
+void spc_sched_msgout(struct spc_softc *, u_char);
+void spc_setsync(struct spc_softc *, struct spc_tinfo *);
+void spc_select (struct spc_softc *, struct spc_acb *);
+void spc_timeout (void *);
+void spc_scsi_reset (struct spc_softc *);
+void spc_reset (struct spc_softc *);
+void spc_free_acb (struct spc_softc *, struct spc_acb *, int);
+struct spc_acb* spc_get_acb(struct spc_softc *, int);
+int spc_reselect (struct spc_softc *, int);
+void spc_sense (struct spc_softc *, struct spc_acb *);
+void spc_msgin (struct spc_softc *);
+void spc_abort (struct spc_softc *, struct spc_acb *);
+void spc_msgout (struct spc_softc *);
+int spc_dataout_pio (struct spc_softc *, u_char *, int);
+int spc_datain_pio (struct spc_softc *, u_char *, int);
+void spc_process_intr(void *, u_char);
+#ifdef SPC_DEBUG
+void spc_print_acb (struct spc_acb *);
+void spc_dump_driver (struct spc_softc *);
+void spc_dump89352 (struct spc_softc *);
+void spc_show_scsi_cmd(struct spc_acb *);
+void spc_print_active_acb(void);
+#endif
+
+extern struct cfdriver spc_cd;
+
+struct scsi_device spc_dev = {
+ NULL, /* Use default error handler */
+ NULL, /* have a queue, served by this */
+ NULL, /* have no async handler */
+ NULL, /* Use default 'done' routine */
+};
+
+struct scsi_adapter spc_switch = {
+ spc_scsi_cmd,
+ minphys,
+ NULL,
+ NULL
+};
+
+/*
+ * INITIALIZATION ROUTINES (probe, attach ++)
+ */
+
+void
+spc_attach(struct spc_softc *sc)
+{
+ SPC_TRACE(("spc_attach "));
+ sc->sc_state = SPC_INIT;
+
+ sc->sc_freq = 20; /* XXX Assume 20 MHz. */
+
+#if SPC_USE_SYNCHRONOUS
+ /*
+ * These are the bounds of the sync period, based on the frequency of
+ * the chip's clock input and the size and offset of the sync period
+ * register.
+ *
+ * For a 20MHz clock, this gives us 25, or 100nS, or 10MB/s, as a
+ * maximum transfer rate, and 112.5, or 450nS, or 2.22MB/s, as a
+ * minimum transfer rate.
+ */
+ sc->sc_minsync = (2 * 250) / sc->sc_freq;
+ sc->sc_maxsync = (9 * 250) / sc->sc_freq;
+#endif
+
+ spc_init(sc); /* Init chip and driver */
+
+ /*
+ * Fill in the adapter.
+ */
+ sc->sc_link.adapter_softc = sc;
+ sc->sc_link.adapter_target = sc->sc_initiator;
+ sc->sc_link.adapter = &spc_switch;
+ sc->sc_link.device = &spc_dev;
+ sc->sc_link.openings = 2;
+
+ /*
+ * ask the adapter what subunits are present
+ */
+ config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
+}
+
+/*
+ * Initialize MB89352 chip itself
+ * The following conditions should hold:
+ * spc_isa_probe should have succeeded, i.e. the iobase address in spc_softc
+ * must be valid.
+ */
+void
+spc_reset(struct spc_softc *sc)
+{
+ SPC_TRACE(("spc_reset "));
+ /*
+ * Disable interrupts then reset the FUJITSU chip.
+ */
+ spc_write(SCTL, SCTL_DISABLE | SCTL_CTRLRST);
+ spc_write(SCMD, 0);
+ spc_write(TMOD, 0);
+ spc_write(PCTL, 0);
+ spc_write(TEMP, 0);
+ spc_write(TCH, 0);
+ spc_write(TCM, 0);
+ spc_write(TCL, 0);
+ spc_write(INTS, 0);
+ spc_write(SCTL,
+ SCTL_DISABLE | SCTL_ABRT_ENAB | SCTL_PARITY_ENAB | SCTL_RESEL_ENAB);
+ spc_write(BDID, sc->sc_initiator);
+ delay(400);
+ spc_write(SCTL, spc_read(SCTL) & ~SCTL_DISABLE);
+}
+
+
+/*
+ * Pull the SCSI RST line for 500us.
+ */
+void
+spc_scsi_reset(struct spc_softc *sc)
+{
+ SPC_TRACE(("spc_scsi_reset "));
+ spc_write(SCMD, spc_read(SCMD) | SCMD_RST);
+ delay(500);
+ spc_write(SCMD, spc_read(SCMD) & ~SCMD_RST);
+ delay(50);
+}
+
+/*
+ * Initialize spc SCSI driver.
+ */
+void
+spc_init(struct spc_softc *sc)
+{
+ struct spc_acb *acb;
+ int r;
+
+ SPC_TRACE(("spc_init "));
+ spc_reset(sc);
+ spc_scsi_reset(sc);
+ spc_reset(sc);
+
+ if (sc->sc_state == SPC_INIT) {
+ /* First time through; initialize. */
+ TAILQ_INIT(&sc->ready_list);
+ TAILQ_INIT(&sc->nexus_list);
+ TAILQ_INIT(&sc->free_list);
+ sc->sc_nexus = NULL;
+ acb = sc->sc_acb;
+ bzero(acb, sizeof(sc->sc_acb));
+ for (r = 0; r < sizeof(sc->sc_acb) / sizeof(*acb); r++) {
+ TAILQ_INSERT_TAIL(&sc->free_list, acb, chain);
+ acb++;
+ }
+ bzero(&sc->sc_tinfo, sizeof(sc->sc_tinfo));
+ } else {
+ /* Cancel any active commands. */
+ sc->sc_state = SPC_CLEANING;
+ if ((acb = sc->sc_nexus) != NULL) {
+ acb->xs->error = XS_DRIVER_STUFFUP;
+ timeout_del(&acb->xs->stimeout);
+ spc_done(sc, acb);
+ }
+ while ((acb = TAILQ_FIRST(&sc->nexus_list)) != NULL) {
+ acb->xs->error = XS_DRIVER_STUFFUP;
+ timeout_del(&acb->xs->stimeout);
+ spc_done(sc, acb);
+ }
+ }
+
+ sc->sc_prevphase = PH_INVALID;
+ for (r = 0; r < 8; r++) {
+ struct spc_tinfo *ti = &sc->sc_tinfo[r];
+
+ ti->flags = 0;
+#if SPC_USE_SYNCHRONOUS
+ ti->flags |= DO_SYNC;
+ ti->period = sc->sc_minsync;
+ ti->offset = SPC_SYNC_REQ_ACK_OFS;
+#else
+ ti->period = ti->offset = 0;
+#endif
+#if SPC_USE_WIDE
+ ti->flags |= DO_WIDE;
+ ti->width = SPC_MAX_WIDTH;
+#else
+ ti->width = 0;
+#endif
+ }
+
+ sc->sc_state = SPC_IDLE;
+ spc_write(SCTL, spc_read(SCTL) | SCTL_INTR_ENAB);
+}
+
+void
+spc_free_acb(struct spc_softc *sc, struct spc_acb *acb, int flags)
+{
+ int s;
+
+ SPC_TRACE(("spc_free_acb "));
+ s = splbio();
+
+ acb->flags = 0;
+ TAILQ_INSERT_HEAD(&sc->free_list, acb, chain);
+
+ /*
+ * If there were none, wake anybody waiting for one to come free,
+ * starting with queued entries.
+ */
+ if (acb->chain.tqe_next == 0)
+ wakeup(&sc->free_list);
+
+ splx(s);
+}
+
+struct spc_acb *
+spc_get_acb(struct spc_softc *sc, int flags)
+{
+ struct spc_acb *acb;
+ int s;
+
+ SPC_TRACE(("spc_get_acb "));
+ s = splbio();
+
+ while ((acb = TAILQ_FIRST(&sc->free_list)) == NULL &&
+ (flags & SCSI_NOSLEEP) == 0)
+ tsleep(&sc->free_list, PRIBIO, "spcacb", 0);
+ if (acb) {
+ TAILQ_REMOVE(&sc->free_list, acb, chain);
+ acb->flags |= ACB_ALLOC;
+ }
+
+ splx(s);
+ return acb;
+}
+
+/*
+ * DRIVER FUNCTIONS CALLABLE FROM HIGHER LEVEL DRIVERS
+ */
+
+/*
+ * Expected sequence:
+ * 1) Command inserted into ready list
+ * 2) Command selected for execution
+ * 3) Command won arbitration and has selected target device
+ * 4) Send message out (identify message, eventually also sync.negotiations)
+ * 5) Send command
+ * 5a) Receive disconnect message, disconnect.
+ * 5b) Reselected by target
+ * 5c) Receive identify message from target.
+ * 6) Send or receive data
+ * 7) Receive status
+ * 8) Receive message (command complete etc.)
+ * 9) If status == SCSI_CHECK construct a synthetic request sense SCSI cmd.
+ * Repeat 2-8 (no disconnects please...)
+ */
+
+/*
+ * Start a SCSI-command
+ * This function is called by the higher level SCSI-driver to queue/run
+ * SCSI-commands.
+ */
+int
+spc_scsi_cmd(struct scsi_xfer *xs)
+{
+ struct scsi_link *sc_link = xs->sc_link;
+ struct spc_softc *sc = sc_link->adapter_softc;
+ struct spc_acb *acb;
+ int s, flags;
+
+ SPC_TRACE(("spc_scsi_cmd "));
+ SPC_CMDS(("[0x%x, %d]->%d ", (int)xs->cmd->opcode, xs->cmdlen,
+ sc_link->target));
+
+ flags = xs->flags;
+ if ((acb = spc_get_acb(sc, flags)) == NULL) {
+ xs->error = XS_DRIVER_STUFFUP;
+ return TRY_AGAIN_LATER;
+ }
+
+ /* Initialize acb */
+ acb->xs = xs;
+ acb->timeout = xs->timeout;
+
+ if (xs->flags & SCSI_RESET) {
+ acb->flags |= ACB_RESET;
+ acb->scsi_cmd_length = 0;
+ acb->data_length = 0;
+ } else {
+ bcopy(xs->cmd, &acb->scsi_cmd, xs->cmdlen);
+ acb->scsi_cmd_length = xs->cmdlen;
+ acb->data_addr = xs->data;
+ acb->data_length = xs->datalen;
+ }
+ acb->target_stat = 0;
+
+ s = splbio();
+
+ TAILQ_INSERT_TAIL(&sc->ready_list, acb, chain);
+ /*
+ * Start scheduling unless a queue process is in progress.
+ */
+ if (sc->sc_state == SPC_IDLE)
+ spc_sched(sc);
+ /*
+ * After successful sending, check if we should return just now.
+ * If so, return SUCCESSFULLY_QUEUED.
+ */
+
+ splx(s);
+
+ if ((flags & SCSI_POLL) == 0)
+ return SUCCESSFULLY_QUEUED;
+
+ /* Not allowed to use interrupts, use polling instead */
+ s = splbio();
+ if (spc_poll(sc, xs, acb->timeout)) {
+ spc_timeout(acb);
+ if (spc_poll(sc, xs, acb->timeout))
+ spc_timeout(acb);
+ }
+ splx(s);
+ return COMPLETE;
+}
+
+/*
+ * Used when interrupt driven I/O isn't allowed, e.g. during boot.
+ */
+int
+spc_poll(struct spc_softc *sc, struct scsi_xfer *xs, int count)
+{
+ u_char intr;
+
+ SPC_TRACE(("spc_poll "));
+ while (count) {
+ /*
+ * If we had interrupts enabled, would we
+ * have got an interrupt?
+ */
+ intr = spc_read(INTS);
+ if (intr != 0)
+ spc_process_intr(sc, intr);
+ if ((xs->flags & ITSDONE) != 0)
+ return 0;
+ delay(1000);
+ count--;
+ }
+ return 1;
+}
+
+/*
+ * LOW LEVEL SCSI UTILITIES
+ */
+
+void
+spc_sched_msgout(struct spc_softc *sc, u_char m)
+{
+ SPC_TRACE(("spc_sched_msgout "));
+ if (sc->sc_msgpriq == 0)
+ spc_write(SCMD, SCMD_SET_ATN);
+ sc->sc_msgpriq |= m;
+}
+
+/*
+ * Set synchronous transfer offset and period.
+ */
+void
+spc_setsync(struct spc_softc *sc, struct spc_tinfo *ti)
+{
+#if SPC_USE_SYNCHRONOUS
+ SPC_TRACE(("spc_setsync "));
+ if (ti->offset != 0)
+ spc_write(TMOD,
+ ((ti->period * sc->sc_freq) / 250 - 2) << 4 | ti->offset);
+ else
+ spc_write(TMOD, 0);
+#endif
+}
+
+/*
+ * Start a selection. This is used by spc_sched() to select an idle target,
+ * and by spc_done() to immediately reselect a target to get sense information.
+ */
+void
+spc_select(struct spc_softc *sc, struct spc_acb *acb)
+{
+ struct scsi_link *sc_link = acb->xs->sc_link;
+ int target = sc_link->target;
+ struct spc_tinfo *ti = &sc->sc_tinfo[target];
+
+ SPC_TRACE(("spc_select "));
+ spc_setsync(sc, ti);
+
+#if 0
+ spc_write(SCMD, SCMD_SET_ATN);
+#endif
+
+ spc_write(PCTL, 0);
+ spc_write(TEMP, (1 << sc->sc_initiator) | (1 << target));
+
+#ifdef hp300
+ /* Select timeout hardcoded to 2ms */
+ spc_write(TCH, 15);
+ spc_write(TCM, 32);
+ spc_write(TCL, 4);
+#else
+ /*
+ * Setup BSY timeout (selection timeout).
+ * 250ms according to the SCSI specification.
+ * T = (X * 256 + 15) * Tclf * 2 (Tclf = 200ns on x68k)
+ * To setup 256ms timeout,
+ * 128000ns/200ns = X * 256 + 15
+ * 640 - 15 = X * 256
+ * X = 625 / 256
+ * X = 2 + 113 / 256
+ * ==> tch = 2, tcm = 113 (correct?)
+ */
+ /* Time to the information transfer phase start. */
+ /* XXX These values should be calculated from sc_freq */
+ spc_write(TCH, 2);
+ spc_write(TCM, 113);
+ spc_write(TCL, 3);
+#endif
+ spc_write(SCMD, SCMD_SELECT);
+
+ sc->sc_state = SPC_SELECTING;
+}
+
+int
+spc_reselect(struct spc_softc *sc, int message)
+{
+ u_char selid, target, lun;
+ struct spc_acb *acb;
+ struct scsi_link *sc_link;
+ struct spc_tinfo *ti;
+
+ SPC_TRACE(("spc_reselect "));
+ /*
+ * The SCSI chip made a snapshot of the data bus while the reselection
+ * was being negotiated. This enables us to determine which target did
+ * the reselect.
+ */
+ selid = sc->sc_selid & ~(1 << sc->sc_initiator);
+ if (selid & (selid - 1)) {
+ printf("%s: reselect with invalid selid %02x; "
+ "sending DEVICE RESET\n", sc->sc_dev.dv_xname, selid);
+ SPC_BREAK();
+ goto reset;
+ }
+
+ /*
+ * Search wait queue for disconnected cmd
+ * The list should be short, so I haven't bothered with
+ * any more sophisticated structures than a simple
+ * singly linked list.
+ */
+ target = ffs(selid) - 1;
+ lun = message & 0x07;
+ TAILQ_FOREACH(acb, &sc->nexus_list, chain) {
+ sc_link = acb->xs->sc_link;
+ if (sc_link->target == target &&
+ sc_link->lun == lun)
+ break;
+ }
+ if (acb == NULL) {
+ printf("%s: reselect from target %d lun %d with no nexus; "
+ "sending ABORT\n", sc->sc_dev.dv_xname, target, lun);
+ SPC_BREAK();
+ goto abort;
+ }
+
+ /* Make this nexus active again. */
+ TAILQ_REMOVE(&sc->nexus_list, acb, chain);
+ sc->sc_state = SPC_CONNECTED;
+ sc->sc_nexus = acb;
+ ti = &sc->sc_tinfo[target];
+ ti->lubusy |= (1 << lun);
+ spc_setsync(sc, ti);
+
+ if (acb->flags & ACB_RESET)
+ spc_sched_msgout(sc, SEND_DEV_RESET);
+ else if (acb->flags & ACB_ABORT)
+ spc_sched_msgout(sc, SEND_ABORT);
+
+ /* Do an implicit RESTORE POINTERS. */
+ sc->sc_dp = acb->data_addr;
+ sc->sc_dleft = acb->data_length;
+ sc->sc_cp = (u_char *)&acb->scsi_cmd;
+ sc->sc_cleft = acb->scsi_cmd_length;
+
+ return (0);
+
+reset:
+ spc_sched_msgout(sc, SEND_DEV_RESET);
+ return (1);
+
+abort:
+ spc_sched_msgout(sc, SEND_ABORT);
+ return (1);
+}
+
+/*
+ * Schedule a SCSI operation. This has now been pulled out of the interrupt
+ * handler so that we may call it from spc_scsi_cmd and spc_done. This may
+ * save us an unnecessary interrupt just to get things going. Should only be
+ * called when state == SPC_IDLE and at bio pl.
+ */
+void
+spc_sched(struct spc_softc *sc)
+{
+ struct spc_acb *acb;
+ struct scsi_link *sc_link;
+ struct spc_tinfo *ti;
+
+ /* missing the hw, just return and wait for our hw */
+ if (sc->sc_flags & SPC_INACTIVE)
+ return;
+ SPC_TRACE(("spc_sched "));
+ /*
+ * Find first acb in ready queue that is for a target/lunit pair that
+ * is not busy.
+ */
+ TAILQ_FOREACH(acb, &sc->ready_list, chain) {
+ sc_link = acb->xs->sc_link;
+ ti = &sc->sc_tinfo[sc_link->target];
+ if ((ti->lubusy & (1 << sc_link->lun)) == 0) {
+ SPC_MISC(("selecting %d:%d ",
+ sc_link->target, sc_link->lun));
+ TAILQ_REMOVE(&sc->ready_list, acb, chain);
+ sc->sc_nexus = acb;
+ spc_select(sc, acb);
+ return;
+ } else
+ SPC_MISC(("%d:%d busy\n",
+ sc_link->target, sc_link->lun));
+ }
+ SPC_MISC(("idle "));
+ /* Nothing to start; just enable reselections and wait. */
+}
+
+void
+spc_sense(struct spc_softc *sc, struct spc_acb *acb)
+{
+ struct scsi_xfer *xs = acb->xs;
+ struct scsi_link *sc_link = xs->sc_link;
+ struct spc_tinfo *ti = &sc->sc_tinfo[sc_link->target];
+ struct scsi_sense *ss = (void *)&acb->scsi_cmd;
+
+ SPC_MISC(("requesting sense "));
+ /* Next, setup a request sense command block */
+ bzero(ss, sizeof(*ss));
+ ss->opcode = REQUEST_SENSE;
+ ss->byte2 = sc_link->lun << 5;
+ ss->length = sizeof(struct scsi_sense_data);
+ acb->scsi_cmd_length = sizeof(*ss);
+ acb->data_addr = (char *)&xs->sense;
+ acb->data_length = sizeof(struct scsi_sense_data);
+ acb->flags |= ACB_SENSE;
+ ti->senses++;
+ if (acb->flags & ACB_NEXUS)
+ ti->lubusy &= ~(1 << sc_link->lun);
+ if (acb == sc->sc_nexus) {
+ spc_select(sc, acb);
+ } else {
+ spc_dequeue(sc, acb);
+ TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain);
+ if (sc->sc_state == SPC_IDLE)
+ spc_sched(sc);
+ }
+}
+
+/*
+ * POST PROCESSING OF SCSI_CMD (usually current)
+ */
+void
+spc_done(struct spc_softc *sc, struct spc_acb *acb)
+{
+ struct scsi_xfer *xs = acb->xs;
+ struct scsi_link *sc_link = xs->sc_link;
+ struct spc_tinfo *ti = &sc->sc_tinfo[sc_link->target];
+
+ SPC_TRACE(("spc_done "));
+
+ /*
+ * Now, if we've come here with no error code, i.e. we've kept the
+ * initial XS_NOERROR, and the status code signals that we should
+ * check sense, we'll need to set up a request sense cmd block and
+ * push the command back into the ready queue *before* any other
+ * commands for this target/lunit, else we lose the sense info.
+ * We don't support chk sense conditions for the request sense cmd.
+ */
+ if (xs->error == XS_NOERROR) {
+ if (acb->flags & ACB_ABORT) {
+ xs->error = XS_DRIVER_STUFFUP;
+ } else if (acb->flags & ACB_SENSE) {
+ xs->error = XS_SENSE;
+ } else {
+ switch (acb->target_stat) {
+ case SCSI_CHECK:
+ /* First, save the return values */
+ xs->resid = acb->data_length;
+ xs->status = acb->target_stat;
+ spc_sense(sc, acb);
+ return;
+ case SCSI_BUSY:
+ xs->error = XS_BUSY;
+ break;
+ case SCSI_OK:
+ xs->resid = acb->data_length;
+ break;
+ default:
+ xs->error = XS_DRIVER_STUFFUP;
+#ifdef SPC_DEBUG
+ printf("%s: spc_done: bad stat 0x%x\n",
+ sc->sc_dev.dv_xname, acb->target_stat);
+#endif
+ break;
+ }
+ }
+ }
+
+ xs->flags |= ITSDONE;
+
+#ifdef SPC_DEBUG
+ if ((spc_debug & SPC_SHOWMISC) != 0) {
+ if (xs->resid != 0)
+ printf("resid=%d ", xs->resid);
+ if (xs->error == XS_SENSE)
+ printf("sense=0x%02x\n", xs->sense.error_code);
+ else
+ printf("error=%d\n", xs->error);
+ }
+#endif
+
+ /*
+ * Remove the ACB from whatever queue it happens to be on.
+ */
+ if (acb->flags & ACB_NEXUS)
+ ti->lubusy &= ~(1 << sc_link->lun);
+ if (acb == sc->sc_nexus) {
+ sc->sc_nexus = NULL;
+ sc->sc_state = SPC_IDLE;
+ spc_sched(sc);
+ } else
+ spc_dequeue(sc, acb);
+
+ spc_free_acb(sc, acb, xs->flags);
+ ti->cmds++;
+ scsi_done(xs);
+}
+
+void
+spc_dequeue(struct spc_softc *sc, struct spc_acb *acb)
+{
+ SPC_TRACE(("spc_dequeue "));
+ if (acb->flags & ACB_NEXUS)
+ TAILQ_REMOVE(&sc->nexus_list, acb, chain);
+ else
+ TAILQ_REMOVE(&sc->ready_list, acb, chain);
+}
+
+/*
+ * INTERRUPT/PROTOCOL ENGINE
+ */
+
+#define IS1BYTEMSG(m) (((m) != 0x01 && (m) < 0x20) || (m) >= 0x80)
+#define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20)
+#define ISEXTMSG(m) ((m) == 0x01)
+
+/*
+ * Precondition:
+ * The SCSI bus is already in the MSGI phase and there is a message byte
+ * on the bus, along with an asserted REQ signal.
+ */
+void
+spc_msgin(struct spc_softc *sc)
+{
+ int n;
+ u_int8_t msg;
+
+ SPC_TRACE(("spc_msgin "));
+
+ if (sc->sc_prevphase == PH_MSGIN) {
+ /* This is a continuation of the previous message. */
+ n = sc->sc_imp - sc->sc_imess;
+ goto nextbyte;
+ }
+
+ /* This is a new MESSAGE IN phase. Clean up our state. */
+ sc->sc_flags &= ~SPC_DROP_MSGIN;
+
+nextmsg:
+ n = 0;
+ sc->sc_imp = &sc->sc_imess[n];
+
+nextbyte:
+ /*
+ * Read a whole message, but don't ack the last byte. If we reject the
+ * message, we have to assert ATN during the message transfer phase
+ * itself.
+ */
+ for (;;) {
+ if (spc_read(INTS) != 0) {
+ /*
+ * Target left MESSAGE IN, probably because it
+ * a) noticed our ATN signal, or
+ * b) ran out of messages.
+ */
+ goto out;
+ }
+ /* If parity error, just dump everything on the floor. */
+ if ((spc_read(SERR) & (SERR_SCSI_PAR|SERR_SPC_PAR)) != 0) {
+ sc->sc_flags |= SPC_DROP_MSGIN;
+ spc_sched_msgout(sc, SEND_PARITY_ERROR);
+ }
+
+ /* send TRANSFER command. */
+ spc_write(TCH, 0);
+ spc_write(TCM, 0);
+ spc_write(TCL, 1);
+ spc_write(PCTL, sc->sc_phase | PCTL_BFINT_ENAB);
+ spc_write(SCMD, SCMD_XFR | SCMD_PROG_XFR); /* XXX */
+
+ for (;;) {
+ if ((spc_read(SSTS) & SSTS_DREG_EMPTY) == 0)
+ break;
+ if (spc_read(INTS) != 0)
+ goto out;
+ }
+
+ /* Gather incoming message bytes if needed. */
+ if ((sc->sc_flags & SPC_DROP_MSGIN) == 0) {
+ if (n >= SPC_MAX_MSG_LEN) {
+ msg = spc_read(DREG);
+ sc->sc_flags |= SPC_DROP_MSGIN;
+ spc_sched_msgout(sc, SEND_REJECT);
+ } else {
+ *sc->sc_imp++ = spc_read(DREG);
+ n++;
+ /*
+ * This testing is suboptimal, but most
+ * messages will be of the one byte variety, so
+ * it should not affect performance
+ * significantly.
+ */
+ if (n == 1 && IS1BYTEMSG(sc->sc_imess[0]))
+ break;
+ if (n == 2 && IS2BYTEMSG(sc->sc_imess[0]))
+ break;
+ if (n >= 3 && ISEXTMSG(sc->sc_imess[0]) &&
+ n == sc->sc_imess[1] + 2)
+ break;
+ }
+ } else
+ msg = spc_read(DREG);
+
+ /*
+ * If we reach this spot we're either:
+ * a) in the middle of a multi-byte message, or
+ * b) dropping bytes.
+ */
+
+ /* Ack the last byte read. */
+#if 0
+ spc_write(SCMD, SCMD_RST_ACK);
+#endif
+ }
+
+ SPC_MISC(("n=%d imess=0x%02x ", n, sc->sc_imess[0]));
+
+ /* We now have a complete message. Parse it. */
+ switch (sc->sc_state) {
+ struct spc_acb *acb;
+ struct scsi_link *sc_link;
+ struct spc_tinfo *ti;
+
+ case SPC_CONNECTED:
+ SPC_ASSERT(sc->sc_nexus != NULL);
+ acb = sc->sc_nexus;
+ ti = &sc->sc_tinfo[acb->xs->sc_link->target];
+
+ switch (sc->sc_imess[0]) {
+ case MSG_CMDCOMPLETE:
+ if (sc->sc_dleft < 0) {
+ sc_link = acb->xs->sc_link;
+ printf("%s: %d extra bytes from %d:%d\n",
+ sc->sc_dev.dv_xname, -sc->sc_dleft,
+ sc_link->target, sc_link->lun);
+ sc->sc_dleft = 0;
+ }
+ acb->xs->resid = acb->data_length = sc->sc_dleft;
+ sc->sc_state = SPC_CMDCOMPLETE;
+ break;
+
+ case MSG_PARITY_ERROR:
+ /* Resend the last message. */
+ spc_sched_msgout(sc, sc->sc_lastmsg);
+ break;
+
+ case MSG_MESSAGE_REJECT:
+ SPC_MISC(("message rejected %02x ", sc->sc_lastmsg));
+ switch (sc->sc_lastmsg) {
+#if SPC_USE_SYNCHRONOUS + SPC_USE_WIDE
+ case SEND_IDENTIFY:
+ ti->flags &= ~(DO_SYNC | DO_WIDE);
+ ti->period = ti->offset = 0;
+ spc_setsync(sc, ti);
+ ti->width = 0;
+ break;
+#endif
+#if SPC_USE_SYNCHRONOUS
+ case SEND_SDTR:
+ ti->flags &= ~DO_SYNC;
+ ti->period = ti->offset = 0;
+ spc_setsync(sc, ti);
+ break;
+#endif
+#if SPC_USE_WIDE
+ case SEND_WDTR:
+ ti->flags &= ~DO_WIDE;
+ ti->width = 0;
+ break;
+#endif
+ case SEND_INIT_DET_ERR:
+ spc_sched_msgout(sc, SEND_ABORT);
+ break;
+ }
+ break;
+
+ case MSG_NOOP:
+ break;
+
+ case MSG_DISCONNECT:
+ ti->dconns++;
+ sc->sc_state = SPC_DISCONNECT;
+ break;
+
+ case MSG_SAVEDATAPOINTER:
+ acb->data_addr = sc->sc_dp;
+ acb->data_length = sc->sc_dleft;
+ break;
+
+ case MSG_RESTOREPOINTERS:
+ sc->sc_dp = acb->data_addr;
+ sc->sc_dleft = acb->data_length;
+ sc->sc_cp = (u_char *)&acb->scsi_cmd;
+ sc->sc_cleft = acb->scsi_cmd_length;
+ break;
+
+ case MSG_EXTENDED:
+ switch (sc->sc_imess[2]) {
+#if SPC_USE_SYNCHRONOUS
+ case MSG_EXT_SDTR:
+ if (sc->sc_imess[1] != 3)
+ goto reject;
+ ti->period = sc->sc_imess[3];
+ ti->offset = sc->sc_imess[4];
+ ti->flags &= ~DO_SYNC;
+ if (ti->offset == 0) {
+ } else if (ti->period < sc->sc_minsync ||
+ ti->period > sc->sc_maxsync ||
+ ti->offset > 8) {
+ ti->period = ti->offset = 0;
+ spc_sched_msgout(sc, SEND_SDTR);
+ } else {
+ sc_print_addr(acb->xs->sc_link);
+ printf("sync, offset %d, "
+ "period %dnsec\n",
+ ti->offset, ti->period * 4);
+ }
+ spc_setsync(sc, ti);
+ break;
+#endif
+
+#if SPC_USE_WIDE
+ case MSG_EXT_WDTR:
+ if (sc->sc_imess[1] != 2)
+ goto reject;
+ ti->width = sc->sc_imess[3];
+ ti->flags &= ~DO_WIDE;
+ if (ti->width == 0) {
+ } else if (ti->width > SPC_MAX_WIDTH) {
+ ti->width = 0;
+ spc_sched_msgout(sc, SEND_WDTR);
+ } else {
+ sc_print_addr(acb->xs->sc_link);
+ printf("wide, width %d\n",
+ 1 << (3 + ti->width));
+ }
+ break;
+#endif
+
+ default:
+ printf("%s: unrecognized MESSAGE EXTENDED; "
+ "sending REJECT\n", sc->sc_dev.dv_xname);
+ SPC_BREAK();
+ goto reject;
+ }
+ break;
+
+ default:
+ printf("%s: unrecognized MESSAGE; sending REJECT\n",
+ sc->sc_dev.dv_xname);
+ SPC_BREAK();
+ reject:
+ spc_sched_msgout(sc, SEND_REJECT);
+ break;
+ }
+ break;
+
+ case SPC_RESELECTED:
+ if (!MSG_ISIDENTIFY(sc->sc_imess[0])) {
+ printf("%s: reselect without IDENTIFY; "
+ "sending DEVICE RESET\n", sc->sc_dev.dv_xname);
+ SPC_BREAK();
+ goto reset;
+ }
+
+ (void) spc_reselect(sc, sc->sc_imess[0]);
+ break;
+
+ default:
+ printf("%s: unexpected MESSAGE IN; sending DEVICE RESET\n",
+ sc->sc_dev.dv_xname);
+ SPC_BREAK();
+ reset:
+ spc_sched_msgout(sc, SEND_DEV_RESET);
+ break;
+
+#ifdef notdef
+ abort:
+ spc_sched_msgout(sc, SEND_ABORT);
+ break;
+#endif
+ }
+
+ /* Ack the last message byte. */
+#if 0
+ spc_write(SCMD, SCMD_RST_ACK);
+#endif
+
+ /* Go get the next message, if any. */
+ goto nextmsg;
+
+out:
+ spc_write(SCMD, SCMD_RST_ACK);
+ SPC_MISC(("n=%d imess=0x%02x ", n, sc->sc_imess[0]));
+
+ while ((spc_read(SSTS) & SSTS_ACTIVE) == SSTS_INITIATOR)
+ ; /* XXX needs timeout */
+}
+
+/*
+ * Send the highest priority, scheduled message.
+ */
+void
+spc_msgout(struct spc_softc *sc)
+{
+#if SPC_USE_SYNCHRONOUS
+ struct spc_tinfo *ti;
+#endif
+ int n;
+
+ SPC_TRACE(("spc_msgout "));
+
+ if (sc->sc_prevphase == PH_MSGOUT) {
+ if (sc->sc_omp == sc->sc_omess) {
+ /*
+ * This is a retransmission.
+ *
+ * We get here if the target stayed in MESSAGE OUT
+ * phase. Section 5.1.9.2 of the SCSI 2 spec indicates
+ * that all of the previously transmitted messages must
+ * be sent again, in the same order. Therefore, we
+ * requeue all the previously transmitted messages, and
+ * start again from the top. Our simple priority
+ * scheme keeps the messages in the right order.
+ */
+ SPC_MISC(("retransmitting "));
+ sc->sc_msgpriq |= sc->sc_msgoutq;
+ /*
+ * Set ATN. If we're just sending a trivial 1-byte
+ * message, we'll clear ATN later on anyway.
+ */
+ spc_write(SCMD, SCMD_SET_ATN); /* XXX? */
+ } else {
+ /* This is a continuation of the previous message. */
+ n = sc->sc_omp - sc->sc_omess;
+ goto nextbyte;
+ }
+ }
+
+ /* No messages transmitted so far. */
+ sc->sc_msgoutq = 0;
+ sc->sc_lastmsg = 0;
+
+nextmsg:
+ /* Pick up highest priority message. */
+ sc->sc_currmsg = sc->sc_msgpriq & -sc->sc_msgpriq;
+ sc->sc_msgpriq &= ~sc->sc_currmsg;
+ sc->sc_msgoutq |= sc->sc_currmsg;
+
+ /* Build the outgoing message data. */
+ switch (sc->sc_currmsg) {
+ case SEND_IDENTIFY:
+ SPC_ASSERT(sc->sc_nexus != NULL);
+ sc->sc_omess[0] =
+ MSG_IDENTIFY(sc->sc_nexus->xs->sc_link->lun, 1);
+ n = 1;
+ break;
+
+#if SPC_USE_SYNCHRONOUS
+ case SEND_SDTR:
+ SPC_ASSERT(sc->sc_nexus != NULL);
+ ti = &sc->sc_tinfo[sc->sc_nexus->xs->sc_link->target];
+ sc->sc_omess[4] = MSG_EXTENDED;
+ sc->sc_omess[3] = MSG_EXT_SDTR_LEN;
+ sc->sc_omess[2] = MSG_EXT_SDTR;
+ sc->sc_omess[1] = ti->period >> 2;
+ sc->sc_omess[0] = ti->offset;
+ n = 5;
+ break;
+#endif
+
+#if SPC_USE_WIDE
+ case SEND_WDTR:
+ SPC_ASSERT(sc->sc_nexus != NULL);
+ ti = &sc->sc_tinfo[sc->sc_nexus->xs->sc_link->target];
+ sc->sc_omess[3] = MSG_EXTENDED;
+ sc->sc_omess[2] = MSG_EXT_WDTR_LEN;
+ sc->sc_omess[1] = MSG_EXT_WDTR;
+ sc->sc_omess[0] = ti->width;
+ n = 4;
+ break;
+#endif
+
+ case SEND_DEV_RESET:
+ sc->sc_flags |= SPC_ABORTING;
+ sc->sc_omess[0] = MSG_BUS_DEV_RESET;
+ n = 1;
+ break;
+
+ case SEND_REJECT:
+ sc->sc_omess[0] = MSG_MESSAGE_REJECT;
+ n = 1;
+ break;
+
+ case SEND_PARITY_ERROR:
+ sc->sc_omess[0] = MSG_PARITY_ERROR;
+ n = 1;
+ break;
+
+ case SEND_INIT_DET_ERR:
+ sc->sc_omess[0] = MSG_INITIATOR_DET_ERR;
+ n = 1;
+ break;
+
+ case SEND_ABORT:
+ sc->sc_flags |= SPC_ABORTING;
+ sc->sc_omess[0] = MSG_ABORT;
+ n = 1;
+ break;
+
+ default:
+ printf("%s: unexpected MESSAGE OUT; sending NOOP\n",
+ sc->sc_dev.dv_xname);
+ SPC_BREAK();
+ sc->sc_omess[0] = MSG_NOOP;
+ n = 1;
+ break;
+ }
+ sc->sc_omp = &sc->sc_omess[n];
+
+nextbyte:
+ /* Send message bytes. */
+ /* send TRANSFER command. */
+ spc_write(TCH, n >> 16);
+ spc_write(TCM, n >> 8);
+ spc_write(TCL, n);
+ spc_write(PCTL, sc->sc_phase | PCTL_BFINT_ENAB);
+ spc_write(SCMD, SCMD_XFR | SCMD_PROG_XFR | SCMD_ICPT_XFR);
+ for (;;) {
+ if ((spc_read(SSTS) & SSTS_BUSY) != 0)
+ break;
+ if (spc_read(INTS) != 0)
+ goto out;
+ }
+ for (;;) {
+#if 0
+ for (;;) {
+ if ((spc_read(PSNS) & PSNS_REQ) != 0)
+ break;
+ /* Wait for REQINIT. XXX Need timeout. */
+ }
+#endif
+ if (spc_read(INTS) != 0) {
+ /*
+ * Target left MESSAGE OUT, possibly to reject
+ * our message.
+ *
+ * If this is the last message being sent, then we
+ * deassert ATN, since either the target is going to
+ * ignore this message, or it's going to ask for a
+ * retransmission via MESSAGE PARITY ERROR (in which
+ * case we reassert ATN anyway).
+ */
+#if 0
+ if (sc->sc_msgpriq == 0)
+ spc_write(SCMD, SCMD_RST_ATN);
+#endif
+ goto out;
+ }
+
+#if 0
+ /* Clear ATN before last byte if this is the last message. */
+ if (n == 1 && sc->sc_msgpriq == 0)
+ spc_write(SCMD, SCMD_RST_ATN);
+#endif
+
+ while ((spc_read(SSTS) & SSTS_DREG_FULL) != 0)
+ ;
+ /* Send message byte. */
+ spc_write(DREG, *--sc->sc_omp);
+ --n;
+ /* Keep track of the last message we've sent any bytes of. */
+ sc->sc_lastmsg = sc->sc_currmsg;
+#if 0
+ /* Wait for ACK to be negated. XXX Need timeout. */
+ while ((spc_read(PSNS) & ACKI) != 0)
+ ;
+#endif
+
+ if (n == 0)
+ break;
+ }
+
+ /* We get here only if the entire message has been transmitted. */
+ if (sc->sc_msgpriq != 0) {
+ /* There are more outgoing messages. */
+ goto nextmsg;
+ }
+
+ /*
+ * The last message has been transmitted. We need to remember the last
+ * message transmitted (in case the target switches to MESSAGE IN phase
+ * and sends a MESSAGE REJECT), and the list of messages transmitted
+ * this time around (in case the target stays in MESSAGE OUT phase to
+ * request a retransmit).
+ */
+
+out:
+ /* Disable REQ/ACK protocol. */
+ return;
+}
+
+/*
+ * spc_dataout_pio: perform a data transfer using the FIFO datapath in the spc
+ * Precondition: The SCSI bus should be in the DOUT phase, with REQ asserted
+ * and ACK deasserted (i.e. waiting for a data byte).
+ *
+ * This new revision has been optimized (I tried) to make the common case fast,
+ * and the rarer cases (as a result) somewhat more complex.
+ */
+int
+spc_dataout_pio(struct spc_softc *sc, u_char *p, int n)
+{
+ u_char intstat = 0;
+ int out = 0;
+#define DOUTAMOUNT 8 /* Full FIFO */
+
+ SPC_TRACE(("spc_dataout_pio "));
+ /* send TRANSFER command. */
+ spc_write(TCH, n >> 16);
+ spc_write(TCM, n >> 8);
+ spc_write(TCL, n);
+ spc_write(PCTL, sc->sc_phase | PCTL_BFINT_ENAB);
+ spc_write(SCMD, SCMD_XFR | SCMD_PROG_XFR | SCMD_ICPT_XFR); /* XXX */
+ for (;;) {
+ if ((spc_read(SSTS) & SSTS_BUSY) != 0)
+ break;
+ if (spc_read(INTS) != 0)
+ break;
+ }
+
+ /*
+ * I have tried to make the main loop as tight as possible. This
+ * means that some of the code following the loop is a bit more
+ * complex than otherwise.
+ */
+ while (n > 0) {
+ int xfer;
+
+ for (;;) {
+ intstat = spc_read(INTS);
+ /* Wait till buffer is empty. */
+ if ((spc_read(SSTS) & SSTS_DREG_EMPTY) != 0)
+ break;
+ /* Break on interrupt. */
+ if (intstat != 0)
+ goto phasechange;
+ }
+
+ xfer = min(DOUTAMOUNT, n);
+
+ SPC_MISC(("%d> ", xfer));
+
+ n -= xfer;
+ out += xfer;
+
+ while (xfer-- > 0)
+ spc_write(DREG, *p++);
+ }
+
+ if (out == 0) {
+ for (;;) {
+ if (spc_read(INTS) != 0)
+ break;
+ }
+ SPC_MISC(("extra data "));
+ } else {
+ /* See the bytes off chip */
+ for (;;) {
+ /* Wait till buffer is empty. */
+ if ((spc_read(SSTS) & SSTS_DREG_EMPTY) != 0)
+ break;
+ intstat = spc_read(INTS);
+ /* Break on interrupt. */
+ if (intstat != 0)
+ goto phasechange;
+ }
+ }
+
+phasechange:
+ /* Stop the FIFO data path. */
+
+ if (intstat != 0) {
+ /* Some sort of phase change. */
+ int amount;
+
+ amount = ((spc_read(TCH) << 16) |
+ (spc_read(TCM) << 8) | spc_read(TCL));
+ if (amount > 0) {
+ out -= amount;
+ SPC_MISC(("+%d ", amount));
+ }
+ }
+
+ return out;
+}
+
+/*
+ * spc_datain_pio: perform data transfers using the FIFO datapath in the spc
+ * Precondition: The SCSI bus should be in the DIN phase, with REQ asserted
+ * and ACK deasserted (i.e. at least one byte is ready).
+ *
+ * For now, uses a pretty dumb algorithm, hangs around until all data has been
+ * transferred. This, is OK for fast targets, but not so smart for slow
+ * targets which don't disconnect or for huge transfers.
+ */
+int
+spc_datain_pio(struct spc_softc *sc, u_char *p, int n)
+{
+ int in = 0;
+ u_int8_t intstat, sstat;
+#define DINAMOUNT 8 /* Full FIFO */
+
+ SPC_TRACE(("spc_datain_pio "));
+ /* send TRANSFER command. */
+ spc_write(TCH, n >> 16);
+ spc_write(TCM, n >> 8);
+ spc_write(TCL, n);
+ spc_write(PCTL, sc->sc_phase | PCTL_BFINT_ENAB);
+ spc_write(SCMD, SCMD_XFR | SCMD_PROG_XFR); /* XXX */
+ for (;;) {
+ if ((spc_read(SSTS) & SSTS_BUSY) != 0)
+ break;
+ if (spc_read(INTS) != 0)
+ goto phasechange;
+ }
+
+ /*
+ * We leave this loop if one or more of the following is true:
+ * a) phase != PH_DATAIN && FIFOs are empty
+ * b) reset has occurred or busfree is detected.
+ */
+ while (n > 0) {
+ int xfer;
+
+ /* Wait for fifo half full or phase mismatch */
+ for (;;) {
+ /* XXX needs timeout */
+ intstat = spc_read(INTS);
+ sstat = spc_read(SSTS);
+ if (intstat != 0 ||
+ (sstat & SSTS_DREG_FULL) != 0 ||
+ (sstat & SSTS_DREG_EMPTY) == 0)
+ break;
+ }
+
+ if (intstat != 0)
+ goto phasechange;
+
+ if (sstat & SSTS_DREG_FULL) {
+ xfer = DINAMOUNT;
+ n -= xfer;
+ in += xfer;
+ while (xfer-- > 0)
+ *p++ = spc_read(DREG);
+ }
+ while (n > 0 && (spc_read(SSTS) & SSTS_DREG_EMPTY) == 0) {
+ n--;
+ in++;
+ *p++ = spc_read(DREG);
+ }
+ }
+
+ /*
+ * Some SCSI-devices are rude enough to transfer more data than what
+ * was requested, e.g. 2048 bytes from a CD-ROM instead of the
+ * requested 512. Test for progress, i.e. real transfers. If no real
+ * transfers have been performed (n is probably already zero) and the
+ * FIFO is not empty, waste some bytes....
+ */
+ if (in == 0) {
+ for (;;) {
+ /* XXX needs timeout */
+ if (spc_read(INTS) != 0)
+ break;
+ }
+ SPC_MISC(("extra data "));
+ }
+
+phasechange:
+ /* Stop the FIFO data path. */
+
+ return in;
+}
+
+/*
+ * Catch an interrupt from the adaptor
+ */
+/*
+ * This is the workhorse routine of the driver.
+ * Deficiencies (for now):
+ * 1) always uses programmed I/O
+ */
+int
+spc_intr(void *arg)
+{
+ struct spc_softc *sc = arg;
+ u_char ints;
+
+ SPC_TRACE(("spc_intr "));
+
+ /*
+ * Disable interrupt.
+ */
+ spc_write(SCTL, spc_read(SCTL) & ~SCTL_INTR_ENAB);
+
+ ints = spc_read(INTS);
+ if (ints != 0)
+ spc_process_intr(arg, ints);
+else printf("spc_intr: 0\n");
+
+ spc_write(SCTL, spc_read(SCTL) | SCTL_INTR_ENAB);
+ return 1;
+}
+
+void
+spc_process_intr(void *arg, u_char ints)
+{
+ struct spc_softc *sc = arg;
+ struct spc_acb *acb;
+ struct scsi_link *sc_link;
+ struct spc_tinfo *ti;
+ int n;
+
+ SPC_TRACE(("spc_process_intr "));
+
+ if (sc->sc_dma_done != NULL &&
+ sc->sc_state == SPC_CONNECTED &&
+ (sc->sc_flags & SPC_DOINGDMA) != 0 &&
+ (sc->sc_phase == PH_DATAOUT || sc->sc_phase == PH_DATAIN)) {
+ (*sc->sc_dma_done)(sc);
+ }
+
+ goto start;
+
+loop:
+ /*
+ * Loop until transfer completion.
+ */
+ /*
+ * First check for abnormal conditions, such as reset.
+ */
+ ints = spc_read(INTS);
+start:
+ SPC_MISC(("ints = 0x%x ", ints));
+
+ if ((ints & INTS_RST) != 0) {
+ printf("%s: SCSI bus reset\n", sc->sc_dev.dv_xname);
+ goto reset;
+ }
+
+ /*
+ * Check for less serious errors.
+ */
+ if ((spc_read(SERR) & (SERR_SCSI_PAR|SERR_SPC_PAR))
+ != 0) {
+ printf("%s: SCSI bus parity error\n", sc->sc_dev.dv_xname);
+ if (sc->sc_prevphase == PH_MSGIN) {
+ sc->sc_flags |= SPC_DROP_MSGIN;
+ spc_sched_msgout(sc, SEND_PARITY_ERROR);
+ } else
+ spc_sched_msgout(sc, SEND_INIT_DET_ERR);
+ }
+
+ /*
+ * If we're not already busy doing something test for the following
+ * conditions:
+ * 1) We have been reselected by something
+ * 2) We have selected something successfully
+ * 3) Our selection process has timed out
+ * 4) This is really a bus free interrupt just to get a new command
+ * going?
+ * 5) Spurious interrupt?
+ */
+ switch (sc->sc_state) {
+ case SPC_IDLE:
+ case SPC_SELECTING:
+ SPC_MISC(("ints:0x%02x ", ints));
+
+ if ((ints & INTS_SEL) != 0) {
+ /*
+ * We don't currently support target mode.
+ */
+ printf("%s: target mode selected; going to BUS FREE\n",
+ sc->sc_dev.dv_xname);
+
+ goto sched;
+ } else if ((ints & INTS_RESEL) != 0) {
+ SPC_MISC(("reselected "));
+
+ /*
+ * If we're trying to select a target ourselves,
+ * push our command back into the ready list.
+ */
+ if (sc->sc_state == SPC_SELECTING) {
+ SPC_MISC(("backoff selector "));
+ SPC_ASSERT(sc->sc_nexus != NULL);
+ acb = sc->sc_nexus;
+ sc->sc_nexus = NULL;
+ TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain);
+ }
+
+ /* Save reselection ID. */
+ sc->sc_selid = spc_read(TEMP);
+
+ sc->sc_state = SPC_RESELECTED;
+ } else if ((ints & INTS_CMD_DONE) != 0) {
+ SPC_MISC(("selected "));
+
+ /*
+ * We have selected a target. Things to do:
+ * a) Determine what message(s) to send.
+ * b) Verify that we're still selecting the target.
+ * c) Mark device as busy.
+ */
+ if (sc->sc_state != SPC_SELECTING) {
+ printf("%s: selection out while idle; "
+ "resetting\n", sc->sc_dev.dv_xname);
+ SPC_BREAK();
+ goto reset;
+ }
+ SPC_ASSERT(sc->sc_nexus != NULL);
+ acb = sc->sc_nexus;
+ sc_link = acb->xs->sc_link;
+ ti = &sc->sc_tinfo[sc_link->target];
+
+ sc->sc_msgpriq = SEND_IDENTIFY;
+ if (acb->flags & ACB_RESET)
+ sc->sc_msgpriq |= SEND_DEV_RESET;
+ else if (acb->flags & ACB_ABORT)
+ sc->sc_msgpriq |= SEND_ABORT;
+ else {
+#if SPC_USE_SYNCHRONOUS
+ if ((ti->flags & DO_SYNC) != 0)
+ sc->sc_msgpriq |= SEND_SDTR;
+#endif
+#if SPC_USE_WIDE
+ if ((ti->flags & DO_WIDE) != 0)
+ sc->sc_msgpriq |= SEND_WDTR;
+#endif
+ }
+
+ acb->flags |= ACB_NEXUS;
+ ti->lubusy |= (1 << sc_link->lun);
+
+ /* Do an implicit RESTORE POINTERS. */
+ sc->sc_dp = acb->data_addr;
+ sc->sc_dleft = acb->data_length;
+ sc->sc_cp = (u_char *)&acb->scsi_cmd;
+ sc->sc_cleft = acb->scsi_cmd_length;
+
+ /* On our first connection, schedule a timeout. */
+ if ((acb->xs->flags & SCSI_POLL) == 0) {
+ timeout_set(&acb->xs->stimeout, spc_timeout,
+ acb);
+ timeout_add(&acb->xs->stimeout,
+ (acb->timeout * hz) / 1000);
+ }
+ sc->sc_state = SPC_CONNECTED;
+ } else if ((ints & INTS_TIMEOUT) != 0) {
+ SPC_MISC(("selection timeout "));
+
+ if (sc->sc_state != SPC_SELECTING) {
+ printf("%s: selection timeout while idle; "
+ "resetting\n", sc->sc_dev.dv_xname);
+ SPC_BREAK();
+ goto reset;
+ }
+ SPC_ASSERT(sc->sc_nexus != NULL);
+ acb = sc->sc_nexus;
+
+ delay(250);
+
+ acb->xs->error = XS_SELTIMEOUT;
+ goto finish;
+ } else {
+ if (sc->sc_state != SPC_IDLE) {
+ printf("%s: BUS FREE while not idle; "
+ "state=%d\n",
+ sc->sc_dev.dv_xname, sc->sc_state);
+ SPC_BREAK();
+ goto out;
+ }
+
+ goto sched;
+ }
+
+ /*
+ * Turn off selection stuff, and prepare to catch bus free
+ * interrupts, parity errors, and phase changes.
+ */
+
+ sc->sc_flags = 0;
+ sc->sc_prevphase = PH_INVALID;
+ goto dophase;
+ }
+
+ if ((ints & INTS_DISCON) != 0) {
+ /* disable disconnect interrupt */
+ spc_write(PCTL, spc_read(PCTL) & ~PCTL_BFINT_ENAB);
+ /* XXX reset interrput */
+ spc_write(INTS, ints);
+
+ switch (sc->sc_state) {
+ case SPC_RESELECTED:
+ goto sched;
+
+ case SPC_CONNECTED:
+ SPC_ASSERT(sc->sc_nexus != NULL);
+ acb = sc->sc_nexus;
+
+#if SPC_USE_SYNCHRONOUS + SPC_USE_WIDE
+ if (sc->sc_prevphase == PH_MSGOUT) {
+ /*
+ * If the target went to BUS FREE phase during
+ * or immediately after sending a SDTR or WDTR
+ * message, disable negotiation.
+ */
+ sc_link = acb->xs->sc_link;
+ ti = &sc->sc_tinfo[sc_link->target];
+ switch (sc->sc_lastmsg) {
+#if SPC_USE_SYNCHRONOUS
+ case SEND_SDTR:
+ ti->flags &= ~DO_SYNC;
+ ti->period = ti->offset = 0;
+ break;
+#endif
+#if SPC_USE_WIDE
+ case SEND_WDTR:
+ ti->flags &= ~DO_WIDE;
+ ti->width = 0;
+ break;
+#endif
+ }
+ }
+#endif
+
+ if ((sc->sc_flags & SPC_ABORTING) == 0) {
+ /*
+ * Section 5.1.1 of the SCSI 2 spec suggests
+ * issuing a REQUEST SENSE following an
+ * unexpected disconnect. Some devices go into
+ * a contingent allegiance condition when
+ * disconnecting, and this is necessary to
+ * clean up their state.
+ */
+ printf("%s: unexpected disconnect; "
+ "sending REQUEST SENSE\n",
+ sc->sc_dev.dv_xname);
+ SPC_BREAK();
+ spc_sense(sc, acb);
+ goto out;
+ }
+
+ acb->xs->error = XS_DRIVER_STUFFUP;
+ goto finish;
+
+ case SPC_DISCONNECT:
+ SPC_ASSERT(sc->sc_nexus != NULL);
+ acb = sc->sc_nexus;
+ TAILQ_INSERT_HEAD(&sc->nexus_list, acb, chain);
+ sc->sc_nexus = NULL;
+ goto sched;
+
+ case SPC_CMDCOMPLETE:
+ SPC_ASSERT(sc->sc_nexus != NULL);
+ acb = sc->sc_nexus;
+ goto finish;
+ }
+ }
+ else if ((ints & INTS_CMD_DONE) != 0 &&
+ sc->sc_prevphase == PH_MSGIN &&
+ sc->sc_state != SPC_CONNECTED)
+ goto out;
+
+dophase:
+#if 0
+ if ((spc_read(PSNS) & PSNS_REQ) == 0) {
+ /* Wait for REQINIT. */
+ goto out;
+ }
+#else
+ spc_write(INTS, ints);
+ while ((spc_read(PSNS) & PSNS_REQ) == 0)
+ delay(1); /* need timeout XXX */
+#endif
+
+ /*
+ * State transition.
+ */
+ sc->sc_phase = spc_read(PSNS) & PH_MASK;
+#if 0
+ spc_write(PCTL, sc->sc_phase);
+#endif
+
+ SPC_MISC(("phase=%d\n", sc->sc_phase));
+ switch (sc->sc_phase) {
+ case PH_MSGOUT:
+ if (sc->sc_state != SPC_CONNECTED &&
+ sc->sc_state != SPC_RESELECTED)
+ break;
+ spc_msgout(sc);
+ sc->sc_prevphase = PH_MSGOUT;
+ goto loop;
+
+ case PH_MSGIN:
+ if (sc->sc_state != SPC_CONNECTED &&
+ sc->sc_state != SPC_RESELECTED)
+ break;
+ spc_msgin(sc);
+ sc->sc_prevphase = PH_MSGIN;
+ goto loop;
+
+ case PH_CMD:
+ if (sc->sc_state != SPC_CONNECTED)
+ break;
+#ifdef SPC_DEBUG
+ if ((spc_debug & SPC_SHOWMISC) != 0) {
+ SPC_ASSERT(sc->sc_nexus != NULL);
+ acb = sc->sc_nexus;
+ printf("cmd=0x%02x+%d ",
+ acb->scsi_cmd.opcode, acb->scsi_cmd_length - 1);
+ }
+#endif
+ n = spc_dataout_pio(sc, sc->sc_cp, sc->sc_cleft);
+ sc->sc_cp += n;
+ sc->sc_cleft -= n;
+ sc->sc_prevphase = PH_CMD;
+ goto loop;
+
+ case PH_DATAOUT:
+ if (sc->sc_state != SPC_CONNECTED)
+ break;
+ SPC_MISC(("dataout dleft=%d ", sc->sc_dleft));
+ if (sc->sc_dma_start != NULL &&
+ sc->sc_dleft > SPC_MIN_DMA_LEN) {
+ (*sc->sc_dma_start)(sc, sc->sc_dp, sc->sc_dleft, 0);
+ sc->sc_prevphase = PH_DATAOUT;
+ goto out;
+ }
+ n = spc_dataout_pio(sc, sc->sc_dp, sc->sc_dleft);
+ sc->sc_dp += n;
+ sc->sc_dleft -= n;
+ sc->sc_prevphase = PH_DATAOUT;
+ goto loop;
+
+ case PH_DATAIN:
+ if (sc->sc_state != SPC_CONNECTED)
+ break;
+ SPC_MISC(("datain "));
+ if (sc->sc_dma_start != NULL &&
+ sc->sc_dleft > SPC_MIN_DMA_LEN) {
+ (*sc->sc_dma_start)(sc, sc->sc_dp, sc->sc_dleft, 1);
+ sc->sc_prevphase = PH_DATAIN;
+ goto out;
+ }
+ n = spc_datain_pio(sc, sc->sc_dp, sc->sc_dleft);
+ sc->sc_dp += n;
+ sc->sc_dleft -= n;
+ sc->sc_prevphase = PH_DATAIN;
+ goto loop;
+
+ case PH_STAT:
+ if (sc->sc_state != SPC_CONNECTED)
+ break;
+ SPC_ASSERT(sc->sc_nexus != NULL);
+ acb = sc->sc_nexus;
+ spc_datain_pio(sc, &acb->target_stat, 1);
+
+ SPC_MISC(("target_stat=0x%02x ", acb->target_stat));
+ sc->sc_prevphase = PH_STAT;
+ goto loop;
+ }
+
+ printf("%s: unexpected bus phase; resetting\n", sc->sc_dev.dv_xname);
+ SPC_BREAK();
+reset:
+ spc_init(sc);
+ return;
+
+finish:
+ timeout_del(&acb->xs->stimeout);
+ spc_write(INTS, ints);
+ ints = 0;
+ spc_done(sc, acb);
+ return;
+
+sched:
+ sc->sc_state = SPC_IDLE;
+ spc_sched(sc);
+ goto out;
+
+out:
+ if (ints != 0)
+ spc_write(INTS, ints);
+}
+
+void
+spc_abort(struct spc_softc *sc, struct spc_acb *acb)
+{
+ /* 2 secs for the abort */
+ acb->timeout = SPC_ABORT_TIMEOUT;
+ acb->flags |= ACB_ABORT;
+
+ if (acb == sc->sc_nexus) {
+ /*
+ * If we're still selecting, the message will be scheduled
+ * after selection is complete.
+ */
+ if (sc->sc_state == SPC_CONNECTED)
+ spc_sched_msgout(sc, SEND_ABORT);
+ } else {
+ spc_dequeue(sc, acb);
+ TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain);
+ if (sc->sc_state == SPC_IDLE)
+ spc_sched(sc);
+ }
+}
+
+void
+spc_timeout(void *arg)
+{
+ struct spc_acb *acb = arg;
+ struct scsi_xfer *xs = acb->xs;
+ struct scsi_link *sc_link = xs->sc_link;
+ struct spc_softc *sc = sc_link->adapter_softc;
+ int s;
+
+ sc_print_addr(sc_link);
+ printf("timed out");
+
+ s = splbio();
+
+ if (acb->flags & ACB_ABORT) {
+ /* abort timed out */
+ printf(" AGAIN\n");
+ /* XXX Must reset! */
+ } else {
+ /* abort the operation that has timed out */
+ printf("\n");
+ acb->xs->error = XS_TIMEOUT;
+ spc_abort(sc, acb);
+ }
+
+ splx(s);
+}
+
+#ifdef SPC_DEBUG
+/*
+ * The following functions are mostly used for debugging purposes, either
+ * directly called from the driver or from the kernel debugger.
+ */
+
+void
+spc_show_scsi_cmd(struct spc_acb *acb)
+{
+ u_char *b = (u_char *)&acb->scsi_cmd;
+ struct scsi_link *sc_link = acb->xs->sc_link;
+ int i;
+
+ sc_print_addr(sc_link);
+ if ((acb->xs->flags & SCSI_RESET) == 0) {
+ for (i = 0; i < acb->scsi_cmd_length; i++) {
+ if (i)
+ printf(",");
+ printf("%x", b[i]);
+ }
+ printf("\n");
+ } else
+ printf("RESET\n");
+}
+
+void
+spc_print_acb(struct spc_acb *acb)
+{
+ printf("acb@%p xs=%p flags=%x", acb, acb->xs, acb->flags);
+ printf(" dp=%p dleft=%d target_stat=%x\n",
+ acb->data_addr, acb->data_length, acb->target_stat);
+ spc_show_scsi_cmd(acb);
+}
+
+void
+spc_print_active_acb(void)
+{
+ struct spc_acb *acb;
+ struct spc_softc *sc = spc_cd.cd_devs[0]; /* XXX */
+
+ printf("ready list:\n");
+ TAILQ_FOREACH(acb, &sc->ready_list, chain)
+ spc_print_acb(acb);
+ printf("nexus:\n");
+ if (sc->sc_nexus != NULL)
+ spc_print_acb(sc->sc_nexus);
+ printf("nexus list:\n");
+ TAILQ_FOREACH(acb, &sc->nexus_list, chain)
+ spc_print_acb(acb);
+}
+
+void
+spc_dump89352(struct spc_softc *sc)
+{
+ printf("mb89352: BDID=%x SCTL=%x SCMD=%x TMOD=%x\n",
+ spc_read(BDID), spc_read(SCTL), spc_read(SCMD), spc_read(TMOD));
+ printf(" INTS=%x PSNS=%x SSTS=%x SERR=%x PCTL=%x\n",
+ spc_read(INTS), spc_read(PSNS), spc_read(SSTS), spc_read(SERR),
+ spc_read(PCTL));
+ printf(" MBC=%x DREG=%x TEMP=%x TCH=%x TCM=%x\n",
+ spc_read(MBC),
+#if 0
+ spc_read(DREG),
+#else
+ 0,
+#endif
+ spc_read(TEMP), spc_read(TCH), spc_read(TCM));
+ printf(" TCL=%x EXBF=%x\n", spc_read(TCL), spc_read(EXBF));
+}
+
+void
+spc_dump_driver(struct spc_softc *sc)
+{
+ struct spc_tinfo *ti;
+ int i;
+
+ printf("nexus=%p prevphase=%x\n", sc->sc_nexus, sc->sc_prevphase);
+ printf("state=%x msgin=%x msgpriq=%x msgoutq=%x lastmsg=%x "
+ "currmsg=%x\n", sc->sc_state, sc->sc_imess[0],
+ sc->sc_msgpriq, sc->sc_msgoutq, sc->sc_lastmsg, sc->sc_currmsg);
+ for (i = 0; i < 7; i++) {
+ ti = &sc->sc_tinfo[i];
+ printf("tinfo%d: %d cmds %d disconnects %d timeouts",
+ i, ti->cmds, ti->dconns, ti->touts);
+ printf(" %d senses flags=%x\n", ti->senses, ti->flags);
+ }
+}
+#endif
diff --git a/sys/arch/hp300/dev/mb89352reg.h b/sys/arch/hp300/dev/mb89352reg.h
new file mode 100644
index 00000000000..3c24aca2b25
--- /dev/null
+++ b/sys/arch/hp300/dev/mb89352reg.h
@@ -0,0 +1,238 @@
+/* $OpenBSD: mb89352reg.h,v 1.1 2004/08/03 21:46:56 miod Exp $ */
+/* $NetBSD: mb89352reg.h,v 1.3 2003/08/07 16:31:02 agc Exp $ */
+/* NecBSD: mb89352reg.h,v 1.3 1998/03/14 07:04:34 kmatsuda Exp */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum, Masaru Oki and Kouichi Matsuda.
+ *
+ * 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.
+ *
+ * @(#)scsireg.h 8.1 (Berkeley) 6/10/93
+ */
+
+/*-
+ * Copyright (c) 1996,97,98,99 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum, Masaru Oki and Kouichi Matsuda.
+ *
+ * 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.
+ *
+ * @(#)scsireg.h 8.1 (Berkeley) 6/10/93
+ */
+/*
+ * [NetBSD for NEC PC-98 series]
+ * Copyright (c) 1996, 1997, 1998
+ * NetBSD/pc98 porting staff. All rights reserved.
+ * Copyright (c) 1996, 1997, 1998
+ * Kouichi Matsuda. All rights reserved.
+ */
+
+/*
+ * FUJITSU MB89352A SCSI Protocol Controller Hardware Description.
+ */
+
+/* Definitions, most of them has turned out to be unneccesary, but here they
+ * are anyway.
+ */
+
+#define BDID 0x00 /* Bus Device ID (R/W) */
+#define SCTL 0x01 /* SPC Control register (R/W) */
+#define SCMD 0x02 /* Command Register (R/W) */
+#define TMOD 0x03 /* Transmit Mode Register (synch models) */
+#define INTS 0x04 /* Interrupt sense (R); Interrupt Reset (W) */
+#define PSNS 0x05 /* Phase Sense (R); SPC Diagnostic Control (W) */
+#define SSTS 0x06 /* SPC status (R/O) */
+#define SERR 0x07 /* SPC error status (R/O) */
+#define PCTL 0x08 /* Phase Control (R/W) */
+#define MBC 0x09 /* Modified Byte Counter (R/O) */
+#define DREG 0x0a /* Data Register (R/W) */
+#define TEMP 0x0b /* Temporary Register (R/W) */
+#define TCH 0x0c /* Transfer Counter High (R/W) */
+#define TCM 0x0d /* Transfer Counter Middle (R/W) */
+#define TCL 0x0e /* Transfer Counter Low (R/W) */
+#define EXBF 0x0f /* External Buffer (synch models) */
+
+/* What all the bits do */
+
+/* SCSI_BDID */
+/* SCSI selection/reselection ID (both target *and* initiator) */
+#define SELID7 0x80
+#define SELID6 0x40
+#define SELID5 0x20
+#define SELID4 0x10
+#define SELID3 0x08
+#define SELID2 0x04
+#define SELID1 0x02
+#define SELID0 0x01
+
+/* SCSI_SCTL */
+#define SCTL_DISABLE 0x80
+#define SCTL_CTRLRST 0x40
+#define SCTL_DIAG 0x20
+#define SCTL_ABRT_ENAB 0x10
+#define SCTL_PARITY_ENAB 0x08
+#define SCTL_SEL_ENAB 0x04
+#define SCTL_RESEL_ENAB 0x02
+#define SCTL_INTR_ENAB 0x01
+
+/* SCSI_SCMD */
+#define SCMD_RST 0x10
+#define SCMD_ICPT_XFR 0x08
+#define SCMD_PROG_XFR 0x04
+#define SCMD_PAD 0x01 /* if initiator */
+#define SCMD_PERR_STOP 0x01 /* if target */
+ /* command codes */
+#define SCMD_BUS_REL 0x00
+#define SCMD_SELECT 0x20
+#define SCMD_RST_ATN 0x40
+#define SCMD_SET_ATN 0x60
+#define SCMD_XFR 0x80
+#define SCMD_XFR_PAUSE 0xa0
+#define SCMD_RST_ACK 0xc0
+#define SCMD_SET_ACK 0xe0
+
+/* SCSI_TMOD */
+#define TMOD_SYNC 0x80
+
+/* SCSI_INTS */
+#define INTS_SEL 0x80
+#define INTS_RESEL 0x40
+#define INTS_DISCON 0x20
+#define INTS_CMD_DONE 0x10
+#define INTS_SRV_REQ 0x08
+#define INTS_TIMEOUT 0x04
+#define INTS_HARD_ERR 0x02
+#define INTS_RST 0x01
+
+/* SCSI_PSNS */
+#define PSNS_REQ 0x80
+#define PSNS_ACK 0x40
+#define PSNS_ATN 0x20
+#define PSNS_SEL 0x10
+#define PSNS_BSY 0x08
+
+/* PSNS */
+#define REQI 0x80
+#define ACKI 0x40
+#define ATNI 0x20
+#define SELI 0x10
+#define BSYI 0x08
+#define MSGI 0x04
+#define CDI 0x02
+#define IOI 0x01
+
+/* Important! The 3 most significant bits of this register, in initiator mode,
+ * represents the "expected" SCSI bus phase and can be used to trigger phase
+ * mismatch and phase change interrupts. But more important: If there is a
+ * phase mismatch the chip will not transfer any data! This is actually a nice
+ * feature as it gives us a bit more control over what is happening when we are
+ * bursting data (in) through the FIFOs and the phase suddenly changes from
+ * DATA IN to STATUS or MESSAGE IN. The transfer will stop and wait for the
+ * proper phase to be set in this register instead of dumping the bits into the
+ * FIFOs.
+ */
+#if 0
+#define REQO 0x80
+#define ACKO 0x40
+#define ATNO 0x20
+#define SELO 0x10
+#define BSYO 0x08
+#endif
+/* PCTL */
+#define MSGO 0x04
+#define CDO 0x02
+#define IOO 0x01
+
+/* Information transfer phases */
+#define PH_DATAOUT (0)
+#define PH_DATAIN (IOI)
+#define PH_CMD (CDI)
+#define PH_STAT (CDI | IOI)
+#define PH_MSGOUT (MSGI | CDI)
+#define PH_MSGIN (MSGI | CDI | IOI)
+
+#define PH_MASK (MSGI | CDI | IOI)
+
+#define PH_INVALID 0xff
+
+/* SCSI_SSTS */
+#define SSTS_INITIATOR 0x80
+#define SSTS_TARGET 0x40
+#define SSTS_BUSY 0x20
+#define SSTS_XFR 0x10
+#define SSTS_ACTIVE (SSTS_INITIATOR|SSTS_XFR)
+#define SSTS_RST 0x08
+#define SSTS_TCZERO 0x04
+#define SSTS_DREG_FULL 0x02
+#define SSTS_DREG_EMPTY 0x01
+
+/* SCSI_SERR */
+#define SERR_SCSI_PAR 0x80
+#define SERR_SPC_PAR 0x40
+#define SERR_TC_PAR 0x08
+#define SERR_PHASE_ERR 0x04
+#define SERR_SHORT_XFR 0x02
+#define SERR_OFFSET 0x01
+
+/* SCSI_PCTL */
+#define PCTL_BFINT_ENAB 0x80
diff --git a/sys/arch/hp300/dev/mb89352var.h b/sys/arch/hp300/dev/mb89352var.h
new file mode 100644
index 00000000000..2cbd8df450d
--- /dev/null
+++ b/sys/arch/hp300/dev/mb89352var.h
@@ -0,0 +1,217 @@
+/* $OpenBSD: mb89352var.h,v 1.1 2004/08/03 21:46:56 miod Exp $ */
+/* $NetBSD: mb89352var.h,v 1.6 2003/08/02 12:48:09 tsutsui Exp $ */
+/* NecBSD: mb89352var.h,v 1.4 1998/03/14 07:31:22 kmatsuda Exp */
+
+/*-
+ * Copyright (c) 1996,97,98,99 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum, Masaru Oki and Kouichi Matsuda.
+ *
+ * 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 Charles M. Hannum.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Copyright (c) 1994 Jarle Greipsland
+ * 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, 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 ``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 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.
+ */
+/*
+ * [NetBSD for NEC PC-98 series]
+ * Copyright (c) 1996, 1997, 1998
+ * NetBSD/pc98 porting staff. All rights reserved.
+ * Copyright (c) 1996, 1997, 1998
+ * Kouich Matsuda. All rights reserved.
+ */
+
+#ifndef _MB89352VAR_H_
+#define _MB89352VAR_H_
+
+/*
+ * ACB. Holds additional information for each SCSI command Comments: We
+ * need a separate scsi command block because we may need to overwrite it
+ * with a request sense command. Basicly, we refrain from fiddling with
+ * the scsi_xfer struct (except do the expected updating of return values).
+ * We'll generally update: xs->{flags,resid,error,sense,status} and
+ * occasionally xs->retries.
+ */
+struct spc_acb {
+ struct scsi_generic scsi_cmd;
+ int scsi_cmd_length;
+ u_char *data_addr; /* Saved data pointer */
+ int data_length; /* Residue */
+
+ u_char target_stat; /* SCSI status byte */
+
+#ifdef notdef
+ struct spc_dma_seg dma[SPC_NSEG]; /* Physical addresses+len */
+#endif
+
+ TAILQ_ENTRY(spc_acb) chain;
+ struct scsi_xfer *xs; /* SCSI xfer ctrl block from above */
+ int flags;
+#define ACB_ALLOC 0x01
+#define ACB_NEXUS 0x02
+#define ACB_SENSE 0x04
+#define ACB_ABORT 0x40
+#define ACB_RESET 0x80
+ int timeout;
+};
+
+/*
+ * Some info about each (possible) target on the SCSI bus. This should
+ * probably have been a "per target+lunit" structure, but we'll leave it at
+ * this for now.
+ */
+struct spc_tinfo {
+ int cmds; /* #commands processed */
+ int dconns; /* #disconnects */
+ int touts; /* #timeouts */
+ int perrs; /* #parity errors */
+ int senses; /* #request sense commands sent */
+ ushort lubusy; /* What local units/subr. are busy? */
+ u_char flags;
+#define DO_SYNC 0x01 /* (Re)Negotiate synchronous options */
+#define DO_WIDE 0x02 /* (Re)Negotiate wide options */
+ u_char period; /* Period suggestion */
+ u_char offset; /* Offset suggestion */
+ u_char width; /* Width suggestion */
+};
+
+struct spc_softc {
+ struct device sc_dev;
+
+ volatile u_int8_t *sc_regs;
+
+ struct scsi_link sc_link; /* prototype for subdevs */
+
+ TAILQ_HEAD(, spc_acb) free_list, ready_list, nexus_list;
+ struct spc_acb *sc_nexus; /* current command */
+ struct spc_acb sc_acb[8];
+ struct spc_tinfo sc_tinfo[8];
+
+ /* Data about the current nexus (updated for every cmd switch) */
+ u_char *sc_dp; /* Current data pointer */
+ size_t sc_dleft; /* Data bytes left to transfer */
+ u_char *sc_cp; /* Current command pointer */
+ size_t sc_cleft; /* Command bytes left to transfer */
+
+ /* Adapter state */
+ u_char sc_phase; /* Current bus phase */
+ u_char sc_prevphase; /* Previous bus phase */
+ u_char sc_state; /* State applicable to the adapter */
+#define SPC_INIT 0
+#define SPC_IDLE 1
+#define SPC_SELECTING 2 /* SCSI command is arbiting */
+#define SPC_RESELECTED 3 /* Has been reselected */
+#define SPC_CONNECTED 4 /* Actively using the SCSI bus */
+#define SPC_DISCONNECT 5 /* MSG_DISCONNECT received */
+#define SPC_CMDCOMPLETE 6 /* MSG_CMDCOMPLETE received */
+#define SPC_CLEANING 7
+ u_char sc_flags;
+#define SPC_DROP_MSGIN 0x01 /* Discard all msgs (parity err detected) */
+#define SPC_ABORTING 0x02 /* Bailing out */
+#define SPC_DOINGDMA 0x04 /* doing DMA */
+#define SPC_INACTIVE 0x80 /* The FIFO data path is active! */
+ u_char sc_selid; /* Reselection ID */
+
+ /* Message stuff */
+ u_char sc_msgpriq; /* Messages we want to send */
+ u_char sc_msgoutq; /* Messages sent during last MESSAGE OUT */
+ u_char sc_lastmsg; /* Message last transmitted */
+ u_char sc_currmsg; /* Message currently ready to transmit */
+#define SEND_DEV_RESET 0x01
+#define SEND_PARITY_ERROR 0x02
+#define SEND_INIT_DET_ERR 0x04
+#define SEND_REJECT 0x08
+#define SEND_IDENTIFY 0x10
+#define SEND_ABORT 0x20
+#define SEND_SDTR 0x40
+#define SEND_WDTR 0x80
+#define SPC_MAX_MSG_LEN 8
+ u_char sc_omess[SPC_MAX_MSG_LEN];
+ u_char *sc_omp; /* Outgoing message pointer */
+ u_char sc_imess[SPC_MAX_MSG_LEN];
+ u_char *sc_imp; /* Incoming message pointer */
+
+ /* Hardware stuff */
+ int sc_initiator; /* Our scsi id */
+ int sc_freq; /* Clock frequency in MHz */
+ int sc_minsync; /* Minimum sync period / 4 */
+ int sc_maxsync; /* Maximum sync period / 4 */
+
+ /* DMA function set from MD code */
+ void (*sc_dma_start)(struct spc_softc *, void *, size_t, int);
+ void (*sc_dma_done)(struct spc_softc *);
+};
+
+#ifdef SPC_DEBUG
+#define SPC_SHOWACBS 0x01
+#define SPC_SHOWINTS 0x02
+#define SPC_SHOWCMDS 0x04
+#define SPC_SHOWMISC 0x08
+#define SPC_SHOWTRACE 0x10
+#define SPC_SHOWSTART 0x20
+#define SPC_DOBREAK 0x40
+extern int spc_debug; /* SPC_SHOWSTART|SPC_SHOWMISC|SPC_SHOWTRACE; */
+#define SPC_PRINT(b, s) do {if ((spc_debug & (b)) != 0) printf s;} while (0)
+#define SPC_BREAK() do {if ((spc_debug & SPC_DOBREAK) != 0) Debugger();} while (0)
+#define SPC_ASSERT(x) do {if (x) {} else {printf("%s at line %d: assertion failed\n", sc->sc_dev.dv_xname, __LINE__); Debugger();}} while (0)
+#else
+#define SPC_PRINT(b, s)
+#define SPC_BREAK()
+#define SPC_ASSERT(x)
+#endif
+
+#define SPC_ACBS(s) SPC_PRINT(SPC_SHOWACBS, s)
+#define SPC_INTS(s) SPC_PRINT(SPC_SHOWINTS, s)
+#define SPC_CMDS(s) SPC_PRINT(SPC_SHOWCMDS, s)
+#define SPC_MISC(s) SPC_PRINT(SPC_SHOWMISC, s)
+#define SPC_TRACE(s) SPC_PRINT(SPC_SHOWTRACE, s)
+#define SPC_START(s) SPC_PRINT(SPC_SHOWSTART, s)
+
+void spc_attach(struct spc_softc *);
+int spc_intr(void *);
+void spc_init(struct spc_softc *);
+void spc_sched(struct spc_softc *);
+int spc_scsi_cmd(struct scsi_xfer *);
+void spc_minphys(struct buf *);
+
+#define SPC_ADDRESS(o) (sc->sc_regs + ((o) << 1) + 1)
+#define spc_read(o) *(volatile u_int8_t *)(SPC_ADDRESS(o))
+#define spc_write(o, v) *(volatile u_int8_t *)(SPC_ADDRESS(o)) = (v)
+
+#endif /* _MB89352VAR_H_ */
diff --git a/sys/arch/hp300/dev/scsi.c b/sys/arch/hp300/dev/scsi.c
deleted file mode 100644
index 2492ba758d0..00000000000
--- a/sys/arch/hp300/dev/scsi.c
+++ /dev/null
@@ -1,1541 +0,0 @@
-/* $OpenBSD: scsi.c,v 1.16 2003/10/26 15:07:25 jmc Exp $ */
-/* $NetBSD: scsi.c,v 1.21 1997/05/05 21:08:26 thorpej Exp $ */
-
-/*
- * Copyright (c) 1996, 1997 Jason R. Thorpe. All rights reserved.
- * Copyright (c) 1990, 1993
- * 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 8.2 (Berkeley) 1/12/94
- */
-
-/*
- * HP 9000/3xx 98658 SCSI host adaptor driver.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/device.h>
-
-#include <machine/autoconf.h>
-#include <machine/cpu.h>
-#include <machine/intr.h>
-#include <machine/hp300spu.h>
-
-#include <hp300/dev/dioreg.h>
-#include <hp300/dev/diovar.h>
-#include <hp300/dev/diodevs.h>
-
-#include <hp300/dev/dmavar.h>
-
-#include <hp300/dev/scsireg.h>
-#include <hp300/dev/scsivar.h>
-
-struct scsi_softc {
- struct device sc_dev; /* generic device glue */
- volatile struct scsidevice *sc_regs; /* card registers */
- struct dmaqueue sc_dq; /* our entry in DMA job queue */
- TAILQ_HEAD(, scsiqueue) sc_queue; /* job queue */
- u_char sc_flags;
- u_char sc_sync;
- u_char sc_scsi_addr;
- u_char sc_scsiid; /* XXX unencoded copy of sc_scsi_addr */
- u_char sc_stat[2];
- u_char sc_msg[7];
-};
-
-/* sc_flags */
-#define SCSI_IO 0x80 /* DMA I/O in progress */
-#define SCSI_DMA32 0x40 /* 32-bit DMA should be used */
-#define SCSI_HAVEDMA 0x04 /* controller has DMA channel */
-#ifdef DEBUG
-#define SCSI_PAD 0x02 /* 'padded' transfer in progress */
-#endif
-#define SCSI_ALIVE 0x01 /* controller initialized */
-
-/*
- * SCSI delays
- * In u-seconds, primarily for state changes on the SPC.
- */
-#define SCSI_CMD_WAIT 10000 /* wait per step of 'immediate' cmds */
-#define SCSI_DATA_WAIT 10000 /* wait per data in/out step */
-#define SCSI_INIT_WAIT 50000 /* wait per step (both) during init */
-
-static void scsiabort(int, struct scsi_softc *,
- volatile struct scsidevice *, char *);
-static void scsierror(struct scsi_softc *,
- volatile struct scsidevice *, u_char);
-static int issue_select(volatile struct scsidevice *,
- u_char, u_char);
-static int wait_for_select(volatile struct scsidevice *);
-static int ixfer_start(volatile struct scsidevice *,
- int, u_char, int);
-static int ixfer_out(volatile struct scsidevice *, int, u_char *);
-static void ixfer_in(volatile struct scsidevice *, int, u_char *);
-static int mxfer_in(volatile struct scsidevice *,
- int, u_char *, u_char);
-static int scsiicmd(struct scsi_softc *, int, u_char *, int,
- u_char *, int, u_char);
-static void finishxfer(struct scsi_softc *,
- volatile struct scsidevice *, int);
-
-int scsimatch(struct device *, void *, void *);
-void scsiattach(struct device *, struct device *, void *);
-void scsi_attach_children(struct scsi_softc *);
-int scsisubmatch(struct device *, void *, void *);
-
-struct cfattach oscsi_ca = {
- sizeof(struct scsi_softc), scsimatch, scsiattach
-};
-
-struct cfdriver oscsi_cd = {
- NULL, "oscsi", DV_DULL
-};
-
-int scsi_cmd_wait = SCSI_CMD_WAIT;
-int scsi_data_wait = SCSI_DATA_WAIT;
-int scsi_init_wait = SCSI_INIT_WAIT;
-
-int scsi_nosync = 1; /* inhibit sync xfers if 1 */
-int scsi_pridma = 0; /* use "priority" dma */
-
-#ifdef DEBUG
-int scsi_debug = 0;
-#define WAITHIST
-#endif
-
-#ifdef WAITHIST
-#define MAXWAIT 1022
-u_int ixstart_wait[MAXWAIT+2];
-u_int ixin_wait[MAXWAIT+2];
-u_int ixout_wait[MAXWAIT+2];
-u_int mxin_wait[MAXWAIT+2];
-u_int mxin2_wait[MAXWAIT+2];
-u_int cxin_wait[MAXWAIT+2];
-u_int fxfr_wait[MAXWAIT+2];
-u_int sgo_wait[MAXWAIT+2];
-#define HIST(h,w) (++h[((w)>MAXWAIT? MAXWAIT : ((w) < 0 ? -1 : (w))) + 1]);
-#else
-#define HIST(h,w)
-#endif
-
-#define b_cylin b_resid
-
-static void
-scsiabort(target, hs, hd, where)
- int target;
- struct scsi_softc *hs;
- volatile struct scsidevice *hd;
- char *where;
-{
- int len;
- int maxtries; /* XXX - kludge till I understand whats *supposed* to happen */
- int startlen; /* XXX - kludge till I understand whats *supposed* to happen */
- u_char junk;
-
- printf("%s: ", hs->sc_dev.dv_xname);
- if (target != -1)
- printf("targ %d ", target);
- printf("abort from %s: phase=0x%x, ssts=0x%x, ints=0x%x\n",
- where, hd->scsi_psns, hd->scsi_ssts, hd->scsi_ints);
-
- hd->scsi_ints = hd->scsi_ints;
- hd->scsi_csr = 0;
- if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0)
- /* no longer connected to scsi target */
- return;
-
- /* get the number of bytes remaining in current xfer + fudge */
- len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl;
-
- /* for that many bus cycles, try to send an abort msg */
- for (startlen = (len += 1024); (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) {
- hd->scsi_scmd = SCMD_SET_ATN;
- maxtries = 1000;
- while ((hd->scsi_psns & PSNS_REQ) == 0) {
- if (! (hd->scsi_ssts & SSTS_INITIATOR))
- goto out;
- DELAY(1);
- if (--maxtries == 0) {
- printf("-- scsiabort gave up after 1000 tries (startlen = %d len = %d)\n",
- startlen, len);
- goto out2;
- }
-
- }
-out2:
- if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE)
- hd->scsi_scmd = SCMD_RST_ATN;
- hd->scsi_pctl = hd->scsi_psns & PHASE;
- if (hd->scsi_psns & PHASE_IO) {
- /* one of the input phases - read & discard a byte */
- hd->scsi_scmd = SCMD_SET_ACK;
- if (hd->scsi_tmod == 0)
- while (hd->scsi_psns & PSNS_REQ)
- DELAY(1);
- junk = hd->scsi_temp;
- } else {
- /* one of the output phases - send an abort msg */
- hd->scsi_temp = MSG_ABORT;
- hd->scsi_scmd = SCMD_SET_ACK;
- if (hd->scsi_tmod == 0)
- while (hd->scsi_psns & PSNS_REQ)
- DELAY(1);
- }
- hd->scsi_scmd = SCMD_RST_ACK;
- }
-out:
- /*
- * Either the abort was successful & the bus is disconnected or
- * the device didn't listen. If the latter, announce the problem.
- * Either way, reset the card & the SPC.
- */
- if (len < 0 && hs)
- printf("%s: abort failed. phase=0x%x, ssts=0x%x\n",
- hs->sc_dev.dv_xname, hd->scsi_psns, hd->scsi_ssts);
-
- if (! ((junk = hd->scsi_ints) & INTS_RESEL)) {
- hd->scsi_sctl |= SCTL_CTRLRST;
- DELAY(2);
- hd->scsi_sctl &=~ SCTL_CTRLRST;
- hd->scsi_hconf = 0;
- hd->scsi_ints = hd->scsi_ints;
- }
-}
-
-/*
- * XXX Set/reset long delays.
- *
- * if delay == 0, reset default delays
- * if delay < 0, set both delays to default long initialization values
- * if delay > 0, set both delays to this value
- *
- * Used when a devices is expected to respond slowly (e.g. during
- * initialization).
- */
-void
-scsi_delay(delay)
- int delay;
-{
- static int saved_cmd_wait, saved_data_wait;
-
- if (delay) {
- saved_cmd_wait = scsi_cmd_wait;
- saved_data_wait = scsi_data_wait;
- if (delay > 0)
- scsi_cmd_wait = scsi_data_wait = delay;
- else
- scsi_cmd_wait = scsi_data_wait = scsi_init_wait;
- } else {
- scsi_cmd_wait = saved_cmd_wait;
- scsi_data_wait = saved_data_wait;
- }
-}
-
-int
-scsimatch(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- struct dio_attach_args *da = aux;
-
- switch (da->da_id) {
- case DIO_DEVICE_ID_SCSI0:
- case DIO_DEVICE_ID_SCSI1:
- case DIO_DEVICE_ID_SCSI2:
- case DIO_DEVICE_ID_SCSI3:
- return (1);
- }
-
- return (0);
-}
-
-void
-scsiattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
-{
- struct scsi_softc *hs = (struct scsi_softc *)self;
- struct dio_attach_args *da = aux;
- struct scsidevice *hd;
- int ipl, unit = self->dv_unit;
-
- /*
- * Set up DMA job queue entry.
- */
- hs->sc_dq.dq_softc = hs;
- hs->sc_dq.dq_start = scsistart;
- hs->sc_dq.dq_done = scsidone;
-
- /* Initialize request queue. */
- TAILQ_INIT(&hs->sc_queue);
-
- /* Map the device. */
- hd = (struct scsidevice *)iomap(dio_scodetopa(da->da_scode),
- da->da_size);
- if (hd == NULL) {
- printf("\n%s: can't map registers\n", self->dv_xname);
- return;
- }
- ipl = DIO_IPL(hd);
-
- printf(" ipl %d", ipl);
-
- hs->sc_regs = hd;
-
- /* Establish the interrupt handler. */
- (void) dio_intr_establish(scsiintr, hs, ipl, IPL_BIO);
-
- /* Reset the controller. */
- scsireset(unit);
-
- /*
- * Print information about what we've found.
- */
- printf(":");
- if (hs->sc_flags & SCSI_DMA32)
- printf(" 32 bit dma, ");
-
- switch (hs->sc_sync) {
- case 0:
- printf("async");
- break;
-
- case (TMOD_SYNC | 0x3e):
- printf("250ns sync");
- break;
-
- case (TMOD_SYNC | 0x5e):
- printf("375ns sync");
- break;
-
- case (TMOD_SYNC | 0x7d):
- printf("500ns sync");
- break;
-
- default:
- panic("scsiattach: unknown sync param 0x%x", hs->sc_sync);
- }
-
- if ((hd->scsi_hconf & HCONF_PARITY) == 0)
- printf(", no parity");
-
- printf(", scsi id %d\n", hs->sc_scsiid);
-
- /*
- * XXX scale initialization wait according to CPU speed.
- * Should we do this for all wait? Should we do this at all?
- */
- scsi_init_wait *= (cpuspeed / 8);
-
- /*
- * Find and attach devices on the SCSI bus.
- */
- scsi_attach_children(hs);
-}
-
-void
-scsi_attach_children(sc)
- struct scsi_softc *sc;
-{
- struct oscsi_attach_args osa;
- struct scsi_inquiry inqbuf;
- int target, lun;
-
- /*
- * Look for devices on the SCSI bus.
- */
-
- for (target = 0; target < 8; target++) {
- /* Skip target used by controller. */
- if (target == sc->sc_scsiid)
- continue;
-
- for (lun = 0; lun < 1 /* XXX */; lun++) {
- bzero(&inqbuf, sizeof(inqbuf));
- if (scsi_probe_device(sc->sc_dev.dv_unit,
- target, lun, &inqbuf, sizeof(inqbuf))) {
- /*
- * XXX First command on some tapes
- * XXX always fails. (Or, at least,
- * XXX that's what the old Utah "st"
- * XXX driver claimed.)
- */
- bzero(&inqbuf, sizeof(inqbuf));
- if (scsi_probe_device(sc->sc_dev.dv_unit,
- target, lun, &inqbuf, sizeof(inqbuf)))
- continue;
- }
-
- /*
- * There is a device here; find a driver
- * to match it.
- */
- osa.osa_target = target;
- osa.osa_lun = lun;
- osa.osa_inqbuf = &inqbuf;
- (void)config_found_sm(&sc->sc_dev, &osa,
- scsi_print, scsisubmatch);
- }
- }
-}
-
-int
-scsisubmatch(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- struct cfdata *cf = match;
- struct oscsi_attach_args *osa = aux;
-
- if (cf->cf_loc[0] != -1 &&
- cf->cf_loc[0] != osa->osa_target)
- return (0);
-
- if (cf->cf_loc[1] != -1 &&
- cf->cf_loc[1] != osa->osa_lun)
- return (0);
-
- return ((*cf->cf_attach->ca_match)(parent, match, aux));
-}
-
-int
-scsi_print(aux, pnp)
- void *aux;
- const char *pnp;
-{
- struct oscsi_attach_args *osa = aux;
- struct scsi_inquiry *inqbuf = osa->osa_inqbuf;
- char vendor[9], product[17], revision[5];
-
- if (pnp == NULL)
- printf(" targ %d lun %d: ", osa->osa_target, osa->osa_lun);
-
- bzero(vendor, sizeof(vendor));
- bzero(product, sizeof(product));
- bzero(revision, sizeof(revision));
- switch (inqbuf->version) {
- case 1:
- case 2:
- scsi_str(inqbuf->vendor_id, vendor, sizeof(inqbuf->vendor_id));
- scsi_str(inqbuf->product_id, product,
- sizeof(inqbuf->product_id));
- scsi_str(inqbuf->rev, revision, sizeof(inqbuf->rev));
- printf("<%s, %s, %s>", vendor, product, revision);
- if (inqbuf->version == 2)
- printf(" (SCSI-2)");
- break;
- default:
- printf("type 0x%x, qual 0x%x, ver %d",
- inqbuf->type, inqbuf->qual, inqbuf->version);
- }
- if (pnp != NULL)
- printf(" at %s targ %d lun %d",
- pnp, osa->osa_target, osa->osa_lun);
-
- return (UNCONF);
-}
-
-void
-scsireset(unit)
- int unit;
-{
- struct scsi_softc *hs = oscsi_cd.cd_devs[unit];
- volatile struct scsidevice *hd = hs->sc_regs;
- u_int i;
-
- if (hs->sc_flags & SCSI_ALIVE)
- scsiabort(-1, hs, hd, "reset");
-
- hd->scsi_id = 0xFF;
- DELAY(100);
- /*
- * Disable interrupts then reset the FUJI chip.
- */
- hd->scsi_csr = 0;
- hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST;
- hd->scsi_scmd = 0;
- hd->scsi_tmod = 0;
- hd->scsi_pctl = 0;
- hd->scsi_temp = 0;
- hd->scsi_tch = 0;
- hd->scsi_tcm = 0;
- hd->scsi_tcl = 0;
- hd->scsi_ints = 0;
-
- if ((hd->scsi_id & ID_WORD_DMA) == 0)
- hs->sc_flags |= SCSI_DMA32;
-
- /* Determine Max Synchronous Transfer Rate */
- if (scsi_nosync)
- i = 3;
- else
- i = SCSI_SYNC_XFER(hd->scsi_hconf);
- switch (i) {
- case 0:
- hs->sc_sync = TMOD_SYNC | 0x3e; /* 250 nsecs */
- break;
- case 1:
- hs->sc_sync = TMOD_SYNC | 0x5e; /* 375 nsecs */
- break;
- case 2:
- hs->sc_sync = TMOD_SYNC | 0x7d; /* 500 nsecs */
- break;
- case 3:
- hs->sc_sync = 0;
- break;
- }
-
- /*
- * Configure the FUJI chip with its SCSI address, all
- * interrupts enabled & appropriate parity.
- */
- i = (~hd->scsi_hconf) & 0x7;
- hs->sc_scsi_addr = 1 << i;
- hd->scsi_bdid = i;
- hs->sc_scsiid = i;
- if (hd->scsi_hconf & HCONF_PARITY)
- hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB |
- SCTL_SEL_ENAB | SCTL_RESEL_ENAB |
- SCTL_INTR_ENAB | SCTL_PARITY_ENAB;
- else
- hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB |
- SCTL_SEL_ENAB | SCTL_RESEL_ENAB |
- SCTL_INTR_ENAB;
-
- hd->scsi_sctl &=~ SCTL_DISABLE;
- hs->sc_flags |= SCSI_ALIVE;
-}
-
-static void
-scsierror(hs, hd, ints)
- struct scsi_softc *hs;
- volatile struct scsidevice *hd;
- u_char ints;
-{
- char *sep = "";
-
- printf("%s: ", hs->sc_dev.dv_xname);
- if (ints & INTS_RST) {
- DELAY(100);
- if (hd->scsi_hconf & HCONF_SD)
- printf("spurious RST interrupt");
- else
- printf("hardware error - check fuse");
- sep = ", ";
- }
- if ((ints & INTS_HARD_ERR) || hd->scsi_serr) {
- if (hd->scsi_serr & SERR_SCSI_PAR) {
- printf("%sparity err", sep);
- sep = ", ";
- }
- if (hd->scsi_serr & SERR_SPC_PAR) {
- printf("%sSPC parity err", sep);
- sep = ", ";
- }
- if (hd->scsi_serr & SERR_TC_PAR) {
- printf("%sTC parity err", sep);
- sep = ", ";
- }
- if (hd->scsi_serr & SERR_PHASE_ERR) {
- printf("%sphase err", sep);
- sep = ", ";
- }
- if (hd->scsi_serr & SERR_SHORT_XFR) {
- printf("%ssync short transfer err", sep);
- sep = ", ";
- }
- if (hd->scsi_serr & SERR_OFFSET) {
- printf("%ssync offset error", sep);
- sep = ", ";
- }
- }
- if (ints & INTS_TIMEOUT)
- printf("%sSPC select timeout error", sep);
- if (ints & INTS_SRV_REQ)
- printf("%sspurious SRV_REQ interrupt", sep);
- if (ints & INTS_CMD_DONE)
- printf("%sspurious CMD_DONE interrupt", sep);
- if (ints & INTS_DISCON)
- printf("%sspurious disconnect interrupt", sep);
- if (ints & INTS_RESEL)
- printf("%sspurious reselect interrupt", sep);
- if (ints & INTS_SEL)
- printf("%sspurious select interrupt", sep);
- printf("\n");
-}
-
-static int
-issue_select(hd, target, our_addr)
- volatile struct scsidevice *hd;
- u_char target, our_addr;
-{
- if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY))
- return (1);
-
- if (hd->scsi_ints & INTS_DISCON)
- hd->scsi_ints = INTS_DISCON;
-
- hd->scsi_pctl = 0;
- hd->scsi_temp = (1 << target) | our_addr;
- /* select timeout is hardcoded to 2ms */
- hd->scsi_tch = 15;
- hd->scsi_tcm = 32;
- hd->scsi_tcl = 4;
-
- hd->scsi_scmd = SCMD_SELECT;
- return (0);
-}
-
-static int
-wait_for_select(hd)
- volatile struct scsidevice *hd;
-{
- u_char ints;
-
- while ((ints = hd->scsi_ints) == 0)
- DELAY(1);
- hd->scsi_ints = ints;
- return (!(hd->scsi_ssts & SSTS_INITIATOR));
-}
-
-static int
-ixfer_start(hd, len, phase, wait)
- volatile struct scsidevice *hd;
- int len;
- u_char phase;
- int wait;
-{
-
- hd->scsi_tch = len >> 16;
- hd->scsi_tcm = len >> 8;
- hd->scsi_tcl = len;
- hd->scsi_pctl = phase;
- hd->scsi_tmod = 0; /*XXX*/
- hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
-
- /* wait for xfer to start or svc_req interrupt */
- while ((hd->scsi_ssts & SSTS_BUSY) == 0) {
- if (hd->scsi_ints || --wait < 0) {
-#ifdef DEBUG
- if (scsi_debug)
- printf("ixfer_start fail: i%x, w%d\n",
- hd->scsi_ints, wait);
-#endif
- HIST(ixstart_wait, wait)
- return (0);
- }
- DELAY(1);
- }
- HIST(ixstart_wait, wait)
- return (1);
-}
-
-static int
-ixfer_out(hd, len, buf)
- volatile struct scsidevice *hd;
- int len;
- u_char *buf;
-{
- int wait = scsi_data_wait;
-
- for (; len > 0; --len) {
- while (hd->scsi_ssts & SSTS_DREG_FULL) {
- if (hd->scsi_ints || --wait < 0) {
-#ifdef DEBUG
- if (scsi_debug)
- printf("ixfer_out fail: l%d i%x w%d\n",
- len, hd->scsi_ints, wait);
-#endif
- HIST(ixout_wait, wait)
- return (len);
- }
- DELAY(1);
- }
- hd->scsi_dreg = *buf++;
- }
- HIST(ixout_wait, wait)
- return (0);
-}
-
-static void
-ixfer_in(hd, len, buf)
- volatile struct scsidevice *hd;
- int len;
- u_char *buf;
-{
- int wait = scsi_data_wait;
-
- for (; len > 0; --len) {
- while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
- if (hd->scsi_ints || --wait < 0) {
- while (! (hd->scsi_ssts & SSTS_DREG_EMPTY)) {
- *buf++ = hd->scsi_dreg;
- --len;
- }
-#ifdef DEBUG
- if (scsi_debug)
- printf("ixfer_in fail: l%d i%x w%d\n",
- len, hd->scsi_ints, wait);
-#endif
- HIST(ixin_wait, wait)
- return;
- }
- DELAY(1);
- }
- *buf++ = hd->scsi_dreg;
- }
- HIST(ixin_wait, wait)
-}
-
-static int
-mxfer_in(hd, len, buf, phase)
- volatile struct scsidevice *hd;
- int len;
- u_char *buf;
- u_char phase;
-{
- int wait = scsi_cmd_wait;
- int i;
-
- hd->scsi_tmod = 0;
- for (i = 0; i < len; ++i) {
- /*
- * manual says: reset ATN before ACK is sent.
- */
- if (hd->scsi_psns & PSNS_ATN)
- hd->scsi_scmd = SCMD_RST_ATN;
- /*
- * wait for the request line (which says the target
- * wants to give us data). If the phase changes while
- * we're waiting, we're done.
- */
- while ((hd->scsi_psns & PSNS_REQ) == 0) {
- if (--wait < 0) {
- HIST(mxin_wait, wait)
- return (-1);
- }
- if ((hd->scsi_psns & PHASE) != phase ||
- (hd->scsi_ssts & SSTS_INITIATOR) == 0)
- goto out;
-
- DELAY(1);
- }
- /*
- * set ack (which says we're ready for the data, wait for
- * req to go away (target says data is available), grab the
- * data, then reset ack (say we've got the data).
- */
- hd->scsi_pctl = phase;
- hd->scsi_scmd = SCMD_SET_ACK;
- while (hd->scsi_psns & PSNS_REQ) {
- if (--wait < 0) {
- HIST(mxin_wait, wait)
- return (-2);
- }
- DELAY(1);
- }
- *buf++ = hd->scsi_temp;
- hd->scsi_scmd = SCMD_RST_ACK;
- }
-out:
- HIST(mxin_wait, wait)
- /*
- * Wait for manual transfer to finish.
- * Avoids occasional "unexpected phase" errors in finishxfer
- * formerly addressed by per-slave delays.
- */
- wait = scsi_cmd_wait;
- while ((hd->scsi_ssts & SSTS_ACTIVE) == SSTS_INITIATOR) {
- if (--wait < 0)
- break;
- DELAY(1);
- }
- HIST(mxin2_wait, wait)
- return (i);
-}
-
-/*
- * SCSI 'immediate' command: issue a command to some SCSI device
- * and get back an 'immediate' response (i.e., do programmed xfer
- * to get the response data). 'cbuf' is a buffer containing a scsi
- * command of length clen bytes. 'buf' is a buffer of length 'len'
- * bytes for data. The transfer direction is determined by the device
- * (i.e., by the scsi bus data xfer phase). If 'len' is zero, the
- * command must supply no data. 'xferphase' is the bus phase the
- * caller expects to happen after the command is issued. It should
- * be one of DATA_IN_PHASE, DATA_OUT_PHASE or STATUS_PHASE.
- */
-static int
-scsiicmd(hs, target, cbuf, clen, buf, len, xferphase)
- struct scsi_softc *hs;
- int target;
- u_char *cbuf;
- int clen;
- u_char *buf;
- int len;
- u_char xferphase;
-{
- volatile struct scsidevice *hd = hs->sc_regs;
- u_char phase, ints;
- int wait;
-
- /* select the SCSI bus (it's an error if bus isn't free) */
- if (issue_select(hd, target, hs->sc_scsi_addr))
- return (-1);
- if (wait_for_select(hd))
- return (-1);
- /*
- * Wait for a phase change (or error) then let the device
- * sequence us through the various SCSI phases.
- */
- hs->sc_stat[0] = 0xff;
- hs->sc_msg[0] = 0xff;
- phase = CMD_PHASE;
- while (1) {
- wait = scsi_cmd_wait;
- switch (phase) {
-
- case CMD_PHASE:
- if (ixfer_start(hd, clen, phase, wait))
- if (ixfer_out(hd, clen, cbuf))
- goto abort;
- phase = xferphase;
- break;
-
- case DATA_IN_PHASE:
- if (len <= 0)
- goto abort;
- wait = scsi_data_wait;
- if (ixfer_start(hd, len, phase, wait) ||
- !(hd->scsi_ssts & SSTS_DREG_EMPTY))
- ixfer_in(hd, len, buf);
- phase = STATUS_PHASE;
- break;
-
- case DATA_OUT_PHASE:
- if (len <= 0)
- goto abort;
- wait = scsi_data_wait;
- if (ixfer_start(hd, len, phase, wait)) {
- if (ixfer_out(hd, len, buf))
- goto abort;
- }
- phase = STATUS_PHASE;
- break;
-
- case STATUS_PHASE:
- wait = scsi_data_wait;
- if (ixfer_start(hd, sizeof(hs->sc_stat), phase, wait) ||
- !(hd->scsi_ssts & SSTS_DREG_EMPTY))
- ixfer_in(hd, sizeof(hs->sc_stat), hs->sc_stat);
- phase = MESG_IN_PHASE;
- break;
-
- case MESG_IN_PHASE:
- if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait) ||
- !(hd->scsi_ssts & SSTS_DREG_EMPTY)) {
- ixfer_in(hd, sizeof(hs->sc_msg), hs->sc_msg);
- hd->scsi_scmd = SCMD_RST_ACK;
- }
- phase = BUS_FREE_PHASE;
- break;
-
- case BUS_FREE_PHASE:
- goto out;
-
- default:
- printf("%s: unexpected phase %d in icmd from %d\n",
- hs->sc_dev.dv_xname, phase, target);
- goto abort;
- }
- /* wait for last command to complete */
- while ((ints = hd->scsi_ints) == 0) {
- if (--wait < 0) {
- HIST(cxin_wait, wait)
- goto abort;
- }
- DELAY(1);
- }
- HIST(cxin_wait, wait)
- hd->scsi_ints = ints;
- if (ints & INTS_SRV_REQ)
- phase = hd->scsi_psns & PHASE;
- else if (ints & INTS_DISCON)
- goto out;
- else if ((ints & INTS_CMD_DONE) == 0) {
- scsierror(hs, hd, ints);
- goto abort;
- }
- }
-abort:
- scsiabort(target, hs, hd, "icmd");
-out:
- return (hs->sc_stat[0]);
-}
-
-/*
- * Finish SCSI xfer command: After the completion interrupt from
- * a read/write operation, sequence through the final phases in
- * programmed i/o. This routine is a lot like scsiicmd except we
- * skip (and don't allow) the select, cmd out and data in/out phases.
- */
-static void
-finishxfer(hs, hd, target)
- struct scsi_softc *hs;
- volatile struct scsidevice *hd;
- int target;
-{
- u_char phase, ints;
-
- /*
- * We specified padding xfer so we ended with either a phase
- * change interrupt (normal case) or an error interrupt (handled
- * elsewhere). Reset the board dma logic then try to get the
- * completion status & command done msg. The reset confuses
- * the SPC REQ/ACK logic so we have to do any status/msg input
- * operations via 'manual xfer'.
- */
- if (hd->scsi_ssts & SSTS_BUSY) {
- int wait = scsi_cmd_wait;
-
- /* wait for dma operation to finish */
- while (hd->scsi_ssts & SSTS_BUSY) {
- if (--wait < 0) {
-#ifdef DEBUG
- if (scsi_debug)
- printf("finishxfer fail: ssts %x\n",
- hd->scsi_ssts);
-#endif
- HIST(fxfr_wait, wait)
- goto abort;
- }
- }
- HIST(fxfr_wait, wait)
- }
- hd->scsi_scmd |= SCMD_PROG_XFR;
- hd->scsi_sctl |= SCTL_CTRLRST;
- DELAY(2);
- hd->scsi_sctl &=~ SCTL_CTRLRST;
- hd->scsi_hconf = 0;
- /*
- * The following delay is definitely needed when trying to
- * write on a write protected disk (in the optical jukebox anyways),
- * but we shall see if other unexplained machine freezeups
- * also stop occurring... A value of 5 seems to work but
- * 10 seems safer considering the potential consequences.
- */
- DELAY(10);
- hs->sc_stat[0] = 0xff;
- hs->sc_msg[0] = 0xff;
- hd->scsi_csr = 0;
- hd->scsi_ints = ints = hd->scsi_ints;
- while (1) {
- phase = hd->scsi_psns & PHASE;
- switch (phase) {
-
- case STATUS_PHASE:
- if (mxfer_in(hd, sizeof(hs->sc_stat),
- (u_char *)hs->sc_stat, phase) <= 0)
- goto abort;
- break;
-
- case MESG_IN_PHASE:
- if (mxfer_in(hd, sizeof(hs->sc_msg),
- (u_char *)hs->sc_msg, phase) < 0)
- goto abort;
- break;
-
- case BUS_FREE_PHASE:
- return;
-
- default:
- printf("%s: unexpected phase %d in finishxfer from %d\n",
- hs->sc_dev.dv_xname, phase, target);
- goto abort;
- }
- if ((ints = hd->scsi_ints)) {
- hd->scsi_ints = ints;
- if (ints & INTS_DISCON)
- return;
- else if (ints & ~(INTS_SRV_REQ|INTS_CMD_DONE)) {
- scsierror(hs, hd, ints);
- break;
- }
- }
- if ((hd->scsi_ssts & SSTS_INITIATOR) == 0)
- return;
- }
-abort:
- scsiabort(target, hs, hd, "finishxfer");
- hs->sc_stat[0] = 0xfe;
-}
-
-int
-scsi_test_unit_rdy(ctlr, slave, unit)
- int ctlr, slave, unit;
-{
- struct scsi_softc *hs = oscsi_cd.cd_devs[ctlr];
- static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
-
- cdb.lun = unit;
- return (scsiicmd(hs, slave, (u_char *)&cdb, sizeof(cdb),
- (u_char *)0, 0, STATUS_PHASE));
-}
-
-int
-scsi_request_sense(ctlr, slave, unit, buf, len)
- int ctlr, slave, unit;
- u_char *buf;
- u_int len;
-{
- struct scsi_softc *hs = oscsi_cd.cd_devs[ctlr];
- static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE };
-
- cdb.lun = unit;
- cdb.len = len;
- return (scsiicmd(hs, slave, (u_char *)&cdb, sizeof(cdb),
- buf, len, DATA_IN_PHASE));
-}
-
-int
-scsi_immed_command(ctlr, slave, unit, cdb, buf, len, rd)
- int ctlr, slave, unit, rd;
- struct scsi_fmt_cdb *cdb;
- u_char *buf;
- u_int len;
-{
- struct scsi_softc *hs = oscsi_cd.cd_devs[ctlr];
-
- cdb->cdb[1] |= unit << 5;
- return (scsiicmd(hs, slave, cdb->cdb, cdb->len, buf, len,
- rd != 0? DATA_IN_PHASE : DATA_OUT_PHASE));
-}
-
-/*
- * The following routines are test-and-transfer i/o versions of read/write
- * for things like reading disk labels and writing core dumps. The
- * routine scsigo should be used for normal data transfers, NOT these
- * routines.
- */
-int
-scsi_tt_read(ctlr, slave, unit, buf, len, blk, bshift)
- int ctlr, slave, unit;
- u_char *buf;
- u_int len;
- daddr_t blk;
- int bshift;
-{
- struct scsi_softc *hs = oscsi_cd.cd_devs[ctlr];
- struct scsi_cdb10 cdb;
- int stat;
- int old_wait = scsi_data_wait;
-
- scsi_data_wait = 300000;
- bzero(&cdb, sizeof(cdb));
- cdb.cmd = CMD_READ_EXT;
- cdb.lun = unit;
- blk >>= bshift;
- cdb.lbah = blk >> 24;
- cdb.lbahm = blk >> 16;
- cdb.lbalm = blk >> 8;
- cdb.lbal = blk;
- cdb.lenh = len >> (8 + DEV_BSHIFT + bshift);
- cdb.lenl = len >> (DEV_BSHIFT + bshift);
- stat = scsiicmd(hs, slave, (u_char *)&cdb, sizeof(cdb),
- buf, len, DATA_IN_PHASE);
- scsi_data_wait = old_wait;
- return (stat);
-}
-
-int
-scsi_tt_write(ctlr, slave, unit, buf, len, blk, bshift)
- int ctlr, slave, unit;
- u_char *buf;
- u_int len;
- daddr_t blk;
- int bshift;
-{
- struct scsi_softc *hs = oscsi_cd.cd_devs[ctlr];
- struct scsi_cdb10 cdb;
- int stat;
- int old_wait = scsi_data_wait;
-
- scsi_data_wait = 300000;
-
- bzero(&cdb, sizeof(cdb));
- cdb.cmd = CMD_WRITE_EXT;
- cdb.lun = unit;
- blk >>= bshift;
- cdb.lbah = blk >> 24;
- cdb.lbahm = blk >> 16;
- cdb.lbalm = blk >> 8;
- cdb.lbal = blk;
- cdb.lenh = len >> (8 + DEV_BSHIFT + bshift);
- cdb.lenl = len >> (DEV_BSHIFT + bshift);
- stat = scsiicmd(hs, slave, (u_char *)&cdb, sizeof(cdb),
- buf, len, DATA_OUT_PHASE);
- scsi_data_wait = old_wait;
- return (stat);
-}
-
-int
-scsireq(pdev, sq)
- struct device *pdev;
- struct scsiqueue *sq;
-{
- struct scsi_softc *hs = (struct scsi_softc *)pdev;
- int s;
-
- s = splhigh(); /* XXXthorpej */
- TAILQ_INSERT_TAIL(&hs->sc_queue, sq, sq_list);
- splx(s);
-
- if (hs->sc_queue.tqh_first == sq)
- return (1);
-
- return (0);
-}
-
-int
-scsiustart(unit)
- int unit;
-{
- struct scsi_softc *hs = oscsi_cd.cd_devs[unit];
-
- hs->sc_dq.dq_chan = DMA0 | DMA1;
- hs->sc_flags |= SCSI_HAVEDMA;
- if (dmareq(&hs->sc_dq))
- return(1);
- return(0);
-}
-
-void
-scsistart(arg)
- void *arg;
-{
- struct scsi_softc *hs = arg;
- struct scsiqueue *sq;
-
- sq = hs->sc_queue.tqh_first;
- (sq->sq_go)(sq->sq_softc);
-}
-
-int
-scsigo(ctlr, slave, unit, bp, cdb, pad)
- int ctlr, slave, unit;
- struct buf *bp;
- struct scsi_fmt_cdb *cdb;
- int pad;
-{
- struct scsi_softc *hs = oscsi_cd.cd_devs[ctlr];
- volatile struct scsidevice *hd = hs->sc_regs;
- int i, dmaflags;
- u_char phase, ints, cmd;
-
- cdb->cdb[1] |= unit << 5;
-
- /* select the SCSI bus (it's an error if bus isn't free) */
- if (issue_select(hd, slave, hs->sc_scsi_addr) || wait_for_select(hd)) {
- if (hs->sc_flags & SCSI_HAVEDMA) {
- hs->sc_flags &=~ SCSI_HAVEDMA;
- dmafree(&hs->sc_dq);
- }
- return (1);
- }
- /*
- * Wait for a phase change (or error) then let the device
- * sequence us through command phase (we may have to take
- * a msg in/out before doing the command). If the disk has
- * to do a seek, it may be a long time until we get a change
- * to data phase so, in the absense of an explicit phase
- * change, we assume data phase will be coming up and tell
- * the SPC to start a transfer whenever it does. We'll get
- * a service required interrupt later if this assumption is
- * wrong. Otherwise we'll get a service required int when
- * the transfer changes to status phase.
- */
- phase = CMD_PHASE;
- while (1) {
- int wait = scsi_cmd_wait;
-
- switch (phase) {
-
- case CMD_PHASE:
- if (ixfer_start(hd, cdb->len, phase, wait))
- if (ixfer_out(hd, cdb->len, cdb->cdb))
- goto abort;
- break;
-
- case MESG_IN_PHASE:
- if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait)||
- !(hd->scsi_ssts & SSTS_DREG_EMPTY)) {
- ixfer_in(hd, sizeof(hs->sc_msg), hs->sc_msg);
- hd->scsi_scmd = SCMD_RST_ACK;
- }
- phase = BUS_FREE_PHASE;
- break;
-
- case DATA_IN_PHASE:
- case DATA_OUT_PHASE:
- goto out;
-
- default:
- printf("%s: unexpected phase %d in go from %d\n",
- hs->sc_dev.dv_xname, phase, slave);
- goto abort;
- }
- while ((ints = hd->scsi_ints) == 0) {
- if (--wait < 0) {
- HIST(sgo_wait, wait)
- goto abort;
- }
- DELAY(1);
- }
- HIST(sgo_wait, wait)
- hd->scsi_ints = ints;
- if (ints & INTS_SRV_REQ)
- phase = hd->scsi_psns & PHASE;
- else if (ints & INTS_CMD_DONE)
- goto out;
- else {
- scsierror(hs, hd, ints);
- goto abort;
- }
- }
-out:
- /*
- * Reset the card dma logic, setup the dma channel then
- * get the dio part of the card set for a dma xfer.
- */
- hd->scsi_hconf = 0;
- cmd = CSR_IE;
- dmaflags = DMAGO_NOINT;
- if (scsi_pridma)
- dmaflags |= DMAGO_PRI;
- if (bp->b_flags & B_READ)
- dmaflags |= DMAGO_READ;
- if ((hs->sc_flags & SCSI_DMA32) &&
- ((int)bp->b_un.b_addr & 3) == 0 && (bp->b_bcount & 3) == 0) {
- cmd |= CSR_DMA32;
- dmaflags |= DMAGO_LWORD;
- } else
- dmaflags |= DMAGO_WORD;
- dmago(hs->sc_dq.dq_chan, bp->b_un.b_addr, bp->b_bcount, dmaflags);
-
- if (bp->b_flags & B_READ) {
- cmd |= CSR_DMAIN;
- phase = DATA_IN_PHASE;
- } else
- phase = DATA_OUT_PHASE;
- /*
- * DMA enable bits must be set after size and direction bits.
- */
- hd->scsi_csr = cmd;
- hd->scsi_csr |= (CSR_DE0 << hs->sc_dq.dq_chan);
- /*
- * Setup the SPC for the transfer. We don't want to take
- * first a command complete then a service required interrupt
- * at the end of the transfer so we try to disable the cmd
- * complete by setting the transfer counter to more bytes
- * than we expect. (XXX - This strategy may have to be
- * modified to deal with devices that return variable length
- * blocks, e.g., some tape drives.)
- */
- cmd = SCMD_XFR;
- i = (unsigned)bp->b_bcount;
- if (pad) {
- cmd |= SCMD_PAD;
- /*
- * XXX - If we don't do this, the last 2 or 4 bytes
- * (depending on word/lword DMA) of a read get trashed.
- * It looks like it is necessary for the DMA to complete
- * before the SPC goes into "pad mode"??? Note: if we
- * also do this on a write, the request never completes.
- */
- if (bp->b_flags & B_READ)
- i += 2;
-#ifdef DEBUG
- hs->sc_flags |= SCSI_PAD;
- if (i & 1)
- printf("%s: odd byte count: %d bytes @ %ld\n",
- hs->sc_dev.dv_xname, i, bp->b_cylin);
-#endif
- } else
- i += 4;
- hd->scsi_tch = i >> 16;
- hd->scsi_tcm = i >> 8;
- hd->scsi_tcl = i;
- hd->scsi_pctl = phase;
- hd->scsi_tmod = 0;
- hd->scsi_scmd = cmd;
- hs->sc_flags |= SCSI_IO;
- return (0);
-abort:
- scsiabort(slave, hs, hd, "go");
- hs->sc_flags &=~ SCSI_HAVEDMA;
- dmafree(&hs->sc_dq);
- return (1);
-}
-
-void
-scsidone(arg)
- void *arg;
-{
- struct scsi_softc *hs = arg;
- volatile struct scsidevice *hd = hs->sc_regs;
-
-#ifdef DEBUG
- if (scsi_debug)
- printf("%s: done called!\n", hs->sc_dev.dv_xname);
-#endif
- /* dma operation is done -- turn off card dma */
- hd->scsi_csr &=~ (CSR_DE1|CSR_DE0);
-}
-
-int
-scsiintr(arg)
- void *arg;
-{
- struct scsi_softc *hs = arg;
- volatile struct scsidevice *hd = hs->sc_regs;
- u_char ints;
- struct scsiqueue *sq;
-
- if ((hd->scsi_csr & (CSR_IE|CSR_IR)) != (CSR_IE|CSR_IR))
- return (0);
-
- sq = hs->sc_queue.tqh_first;
-
- ints = hd->scsi_ints;
- if ((ints & INTS_SRV_REQ) && (hs->sc_flags & SCSI_IO)) {
- /*
- * this should be the normal i/o completion case.
- * get the status & cmd complete msg then let the
- * device driver look at what happened.
- */
-#ifdef DEBUG
- int len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) |
- hd->scsi_tcl;
- if (!(hs->sc_flags & SCSI_PAD))
- len -= 4;
- hs->sc_flags &=~ SCSI_PAD;
-#endif
- finishxfer(hs, hd, sq->sq_target);
- hs->sc_flags &=~ (SCSI_IO|SCSI_HAVEDMA);
- dmafree(&hs->sc_dq);
- (sq->sq_intr)(sq->sq_softc, hs->sc_stat[0]);
- } else {
- /* Something unexpected happened -- deal with it. */
- hd->scsi_ints = ints;
- hd->scsi_csr = 0;
- scsierror(hs, hd, ints);
- scsiabort(sq->sq_target, hs, hd, "intr");
- if (hs->sc_flags & SCSI_IO) {
- hs->sc_flags &=~ (SCSI_IO|SCSI_HAVEDMA);
- dmafree(&hs->sc_dq);
- (sq->sq_intr)(sq->sq_softc, -1);
- }
- }
- return(1);
-}
-
-void
-scsifree(pdev, sq)
- struct device *pdev;
- struct scsiqueue *sq;
-{
- struct scsi_softc *hs = (struct scsi_softc *)pdev;
- int s;
-
- s = splhigh(); /* XXXthorpej */
- TAILQ_REMOVE(&hs->sc_queue, sq, sq_list);
- splx(s);
-
- if ((sq = hs->sc_queue.tqh_first) != NULL)
- (*sq->sq_start)(sq->sq_softc);
-}
-
-/*
- * (XXX) The following routine is needed for the SCSI tape driver
- * to read odd-size records.
- */
-
-#include "st.h"
-#if NST > 0
-int
-scsi_tt_oddio(ctlr, slave, unit, buf, len, b_flags, freedma)
- int ctlr, slave, unit, b_flags, freedma;
- u_char *buf;
- u_int len;
-{
- struct scsi_softc *hs = oscsi_cd.cd_devs[ctlr];
- struct scsi_cdb6 cdb;
- u_char iphase;
- int stat;
-
-#ifdef DEBUG
- if ((freedma && (hs->sc_flags & SCSI_HAVEDMA) == 0) ||
- (!freedma && (hs->sc_flags & SCSI_HAVEDMA)))
- printf("oddio: freedma (%d) inconsistency (flags=%x)\n",
- freedma, hs->sc_flags);
-#endif
- /*
- * First free any DMA channel that was allocated.
- * We can't use DMA to do this transfer.
- */
- if (freedma) {
- hs->sc_flags &=~ SCSI_HAVEDMA;
- dmafree(&hs->sc_dq);
- }
- /*
- * Initialize command block
- */
- bzero(&cdb, sizeof(cdb));
- cdb.lun = unit;
- cdb.lbam = (len >> 16) & 0xff;
- cdb.lbal = (len >> 8) & 0xff;
- cdb.len = len & 0xff;
- if (buf == 0) {
- cdb.cmd = CMD_SPACE;
- cdb.lun |= 0x00;
- len = 0;
- iphase = MESG_IN_PHASE;
- } else if (b_flags & B_READ) {
- cdb.cmd = CMD_READ;
- iphase = DATA_IN_PHASE;
- } else {
- cdb.cmd = CMD_WRITE;
- iphase = DATA_OUT_PHASE;
- }
- /*
- * Perform command (with very long delays)
- */
- scsi_delay(30000000);
- stat = scsiicmd(hs, slave, (u_char *)&cdb, sizeof(cdb),
- buf, len, iphase);
- scsi_delay(0);
- return (stat);
-}
-#endif
-
-/*
- * Copy a counted string, trimming the trailing space, and turn
- * the result into a C-style string.
- */
-void
-scsi_str(src, dst, len)
- char *src, *dst;
- size_t len;
-{
-
- while (src[len - 1] == ' ') {
- if (--len == 0) {
- *dst = '\0';
- return;
- }
- }
- bcopy(src, dst, len);
- dst[len] = '\0';
-}
-
-/*
- * Probe for a device at the given ctlr/target/lun, and fill in the inqbuf.
- */
-int
-scsi_probe_device(ctlr, targ, lun, inqbuf, inqlen)
- int ctlr, targ, lun;
- struct scsi_inquiry *inqbuf;
- int inqlen;
-{
- static struct scsi_fmt_cdb inq = {
- 6, { CMD_INQUIRY, 0, 0, 0, 0, 0 }
- };
- int i, tries = 10, isrm = 0;
-
- inq.cdb[4] = inqlen & 0xff;
-
- scsi_delay(-1);
-
- /*
- * See if the unit exists.
- */
- while ((i = scsi_test_unit_rdy(ctlr, targ, lun)) != 0) {
- if (i == -1 || --tries < 0) {
- if (isrm)
- break;
- /* doesn't exist or not a CCS device */
- goto failed;
- }
- if (i == STS_CHECKCOND) {
- u_char sensebuf[128];
- struct scsi_xsense *sp =
- (struct scsi_xsense *)sensebuf;
-
- scsi_request_sense(ctlr, targ, lun, (u_char *)sensebuf,
- sizeof(sensebuf));
- if (sp->class == 7) {
- switch (sp->key) {
- /*
- * Not ready -- might be removable media
- * device with no media. Assume as much,
- * if it really isn't, the inquiry command
- * below will fail.
- */
- case 2:
- isrm = 1;
- break;
- /* drive doing an RTZ -- give it a while */
- case 6:
- delay(1000000);
- break;
- default:
- break;
- }
- }
- }
- delay(1000);
- }
-
- /*
- * Find out about the device.
- */
- if (scsi_immed_command(ctlr, targ, lun, &inq, (u_char *)inqbuf,
- inqlen, B_READ))
- goto failed;
-
- scsi_delay(0);
- return (0);
-
- failed:
- scsi_delay(0);
- return (-1);
-}
diff --git a/sys/arch/hp300/dev/scsireg.h b/sys/arch/hp300/dev/scsireg.h
deleted file mode 100644
index 03a246c4660..00000000000
--- a/sys/arch/hp300/dev/scsireg.h
+++ /dev/null
@@ -1,477 +0,0 @@
-/* $OpenBSD: scsireg.h,v 1.3 2003/06/02 23:27:45 millert Exp $ */
-/* $NetBSD: scsireg.h,v 1.4 1994/10/26 07:24:59 cgd Exp $ */
-
-/*
- * Copyright (c) 1990, 1993
- * 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.
- *
- * @(#)scsireg.h 8.1 (Berkeley) 6/10/93
- */
-
-/*
- * HP 98265A SCSI Interface Hardware Description.
- */
-
-struct scsidevice {
- u_char p0, scsi_id;
-#define ID_MASK 0x1f
-#define SCSI_ID 0x07
-#define ID_WORD_DMA 0x20
- u_char p2, scsi_csr;
-#define CSR_IE 0x80
-#define CSR_IR 0x40
-#define SCSI_IPL(csr) ((((csr)>>4)&3)+3)
-#define CSR_DMA32 0x08
-#define CSR_DMAIN 0x04
-#define CSR_DE1 0x02
-#define CSR_DE0 0x01
- u_char p4, scsi_wrap;
-#define WRAP_REQ 0x80
-#define WRAP_ACK 0x40
-#define WRAP_BSY 0x08
-#define WRAP_MSG 0x04
-#define WRAP_CD 0x02
-#define WRAP_IO 0x01
- u_char p6, scsi_hconf;
-#define HCONF_TP 0x80
-#define SCSI_SYNC_XFER(hconf) (((hconf)>>5)&3)
-#define HCONF_SD 0x10
-#define HCONF_PARITY 0x08
- u_char p8[24];
- u_char p32, scsi_bdid;
- u_char p34, scsi_sctl;
-#define SCTL_DISABLE 0x80
-#define SCTL_CTRLRST 0x40
-#define SCTL_DIAG 0x20
-#define SCTL_ABRT_ENAB 0x10
-#define SCTL_PARITY_ENAB 0x08
-#define SCTL_SEL_ENAB 0x04
-#define SCTL_RESEL_ENAB 0x02
-#define SCTL_INTR_ENAB 0x01
- u_char p36, scsi_scmd;
-#define SCMD_RST 0x10
-#define SCMD_ICPT_XFR 0x08
-#define SCMD_PROG_XFR 0x04
-#define SCMD_PAD 0x01 /* if initiator */
-#define SCMD_PERR_STOP 0x01 /* if target */
- /* command codes */
-#define SCMD_BUS_REL 0x00
-#define SCMD_SELECT 0x20
-#define SCMD_RST_ATN 0x40
-#define SCMD_SET_ATN 0x60
-#define SCMD_XFR 0x80
-#define SCMD_XFR_PAUSE 0xa0
-#define SCMD_RST_ACK 0xc0
-#define SCMD_SET_ACK 0xe0
- u_char p38, scsi_tmod;
-#define TMOD_SYNC 0x80
- u_char p40, scsi_ints;
-#define INTS_SEL 0x80
-#define INTS_RESEL 0x40
-#define INTS_DISCON 0x20
-#define INTS_CMD_DONE 0x10
-#define INTS_SRV_REQ 0x08
-#define INTS_TIMEOUT 0x04
-#define INTS_HARD_ERR 0x02
-#define INTS_RST 0x01
- u_char p42, scsi_psns;
-#define PSNS_REQ 0x80
-#define PSNS_ACK 0x40
-#define PSNS_ATN 0x20
-#define PSNS_SEL 0x10
-#define PSNS_BSY 0x08
- u_char p44, scsi_ssts;
-#define SSTS_INITIATOR 0x80
-#define SSTS_TARGET 0x40
-#define SSTS_BUSY 0x20
-#define SSTS_XFR 0x10
-#define SSTS_ACTIVE (SSTS_INITIATOR|SSTS_XFR)
-#define SSTS_RST 0x08
-#define SSTS_TCZERO 0x04
-#define SSTS_DREG_FULL 0x02
-#define SSTS_DREG_EMPTY 0x01
- u_char p46, scsi_serr;
-#define SERR_SCSI_PAR 0x80
-#define SERR_SPC_PAR 0x40
-#define SERR_TC_PAR 0x08
-#define SERR_PHASE_ERR 0x04
-#define SERR_SHORT_XFR 0x02
-#define SERR_OFFSET 0x01
- u_char p48, scsi_pctl;
-#define PCTL_BFINT_ENAB 0x80
- u_char p50, scsi_mbc;
- u_char p52, scsi_dreg;
- u_char p54, scsi_temp;
- u_char p56, scsi_tch;
- u_char p58, scsi_tcm;
- u_char p60, scsi_tcl;
- u_char p62, scsi_exbf;
-};
-
-/* psns/pctl phase lines as bits */
-#define PHASE_MSG 0x04
-#define PHASE_CD 0x02 /* =1 if 'command' */
-#define PHASE_IO 0x01 /* =1 if data inbound */
-/* Phase lines as values */
-#define PHASE 0x07 /* mask for psns/pctl phase */
-#define DATA_OUT_PHASE 0x00
-#define DATA_IN_PHASE 0x01
-#define CMD_PHASE 0x02
-#define STATUS_PHASE 0x03
-#define BUS_FREE_PHASE 0x04
-#define ARB_SEL_PHASE 0x05 /* Fuji chip combines arbitration with sel. */
-#define MESG_OUT_PHASE 0x06
-#define MESG_IN_PHASE 0x07
-
-/* SCSI Messages */
-
-#define MSG_CMD_COMPLETE 0x00
-#define MSG_EXT_MESSAGE 0x01
-#define MSG_SAVE_DATA_PTR 0x02
-#define MSG_RESTORE_PTR 0x03
-#define MSG_DISCONNECT 0x04
-#define MSG_INIT_DETECT_ERROR 0x05
-#define MSG_ABORT 0x06
-#define MSG_REJECT 0x07
-#define MSG_NOOP 0x08
-#define MSG_PARITY_ERROR 0x09
-#define MSG_BUS_DEVICE_RESET 0x0C
-#define MSG_IDENTIFY 0x80
-#define MSG_IDENTIFY_DR 0xc0 /* (disconnect/reconnect allowed) */
-#define MSG_SYNC_REQ 0x01
-
-/* SCSI Commands */
-
-#define CMD_TEST_UNIT_READY 0x00
-#define CMD_REQUEST_SENSE 0x03
-#define CMD_INQUIRY 0x12
-#define CMD_SEND_DIAGNOSTIC 0x1D
-
-#define CMD_REWIND 0x01
-#define CMD_REZERO 0x01
-#define CMD_FORMAT_UNIT 0x04
-#define CMD_READ_BLOCK_LIMITS 0x05
-#define CMD_REASSIGN_BLOCKS 0x07
-#define CMD_READ 0x08
-#define CMD_WRITE 0x0A
-#define CMD_WRITE_FILEMARK 0x10
-#define CMD_SPACE 0x11
-#define CMD_MODE_SELECT 0x15
-#define CMD_RELEASE_UNIT 0x17
-#define CMD_ERASE 0x19
-#define CMD_MODE_SENSE 0x1A
-#define CMD_LOADUNLOAD 0x1B
-#define CMD_RECEIVE_DIAG 0x1C
-#define CMD_SEND_DIAG 0x1D
-#define CMD_P_A_MEDIA_REMOVAL 0x1E
-#define CMD_READ_CAPACITY 0x25
-#define CMD_READ_EXT 0x28
-#define CMD_WRITE_EXT 0x2A
-#define CMD_READ_DEFECT_DATA 0x37
-#define SD_MANUFAC_DEFECTS 0x14000000
-#define SD_GROWN_DEFECTS 0x0c000000
-#define CMD_READ_BUFFER 0x3B
-#define CMD_WRITE_BUFFER 0x3C
-#define CMD_READ_FULL 0xF0
-#define CMD_MEDIA_TEST 0xF1
-#define CMD_ACCESS_LOG 0xF2
-#define CMD_WRITE_FULL 0xFC
-#define CMD_MANAGE_PRIMARY 0xFD
-#define CMD_EXECUTE_DATA 0xFE
-
-/* SCSI status bits */
-
-#define STS_CHECKCOND 0x02 /* Check Condition (ie., read sense) */
-#define STS_CONDMET 0x04 /* Condition Met (ie., search worked) */
-#define STS_BUSY 0x08
-#define STS_INTERMED 0x10 /* Intermediate status sent */
-#define STS_EXT 0x80 /* Extended status valid */
-
-/* command descriptor blocks */
-
-struct scsi_cdb6 {
- u_char cmd; /* command code */
- u_char lun: 3, /* logical unit on ctlr */
- lbah: 5; /* msb of read/write logical block addr */
- u_char lbam; /* middle byte of l.b.a. */
- u_char lbal; /* lsb of l.b.a. */
- u_char len; /* transfer length */
- u_char xtra;
-};
-
-struct scsi_cdb10 {
- u_char cmd; /* command code */
- u_char lun: 3, /* logical unit on ctlr */
- : 4,
- rel: 1; /* l.b.a. is relative addr if =1 */
- u_char lbah; /* msb of read/write logical block addr */
- u_char lbahm; /* high middle byte of l.b.a. */
- u_char lbalm; /* low middle byte of l.b.a. */
- u_char lbal; /* lsb of l.b.a. */
- u_char reserved;
- u_char lenh; /* msb transfer length */
- u_char lenl; /* lsb transfer length */
- u_char xtra;
-};
-
-/* basic sense data */
-
-struct scsi_sense {
- u_char valid: 1, /* l.b.a. is valid */
- class: 3,
- code: 4;
- u_char vu: 4, /* vendor unique */
- lbah: 4;
- u_char lbam;
- u_char lbal;
-};
-
-struct scsi_xsense {
- u_char valid: 1, /* l.b.a. is valid */
- class: 3,
- code: 4;
- u_char segment;
- u_char filemark: 1,
- eom: 1,
- ili: 1, /* illegal length indicator */
- rsvd: 1,
- key: 4;
- u_char info1;
- u_char info2;
- u_char info3;
- u_char info4;
- u_char len; /* additional sense length */
-};
-
-/* inquiry data */
-struct scsi_inquiry {
- u_char type;
- u_char qual;
- u_char version;
- u_char rsvd;
- u_char len;
- char class[3];
- char vendor_id[8];
- char product_id[16];
- char rev[4];
-};
-
-struct scsi_format_parms { /* physical BFI format */
- u_short reserved;
- u_short list_len;
- struct defect {
- unsigned cyl : 24;
- unsigned head : 8;
- long bytes_from_index;
- } defect[127];
-} format_parms;
-
-struct scsi_reassign_parms {
- u_short reserved;
- u_short list_len; /* length in bytes of defects only */
- struct new_defect {
- unsigned lba; /* logical block address */
- } new_defect[2];
-} reassign_parms;
-
-struct scsi_modesel_hdr {
- u_char rsvd1;
- u_char media_type;
- u_char rsvd2;
- u_char block_desc_len;
- u_int density : 8;
- u_int number_blocks :24;
- u_int rsvd3 : 8;
- u_int block_length :24;
-};
-
-struct scsi_modesense_hdr {
- u_char len;
- u_char media_type;
- u_char wp : 1;
- u_char rsvd1 : 7;
- u_char block_desc_len;
- u_int density : 8;
- u_int number_blocks :24;
- u_int rsvd2 : 8;
- u_int block_length :24;
-};
-
-/*
- * Mode Select / Mode sense "pages"
- */
-
-/*
- * Page One - Error Recovery Parameters
- */
-struct scsi_err_recovery {
- u_char page_savable : 1; /* save parameters */
- u_char reserved : 1;
- u_char page_code : 6; /* = 0x01 */
- u_char page_length; /* = 6 */
- u_char awre : 1; /* auto write realloc enabled */
- u_char arre : 1; /* auto read realloc enabled */
- u_char tb : 1; /* transfer block */
- u_char rc : 1; /* read continuous */
- u_char eec : 1; /* enable early correction */
- u_char per : 1; /* post error */
- u_char dte : 1; /* disable transfer on error */
- u_char dcr : 1; /* disable correction */
- u_char retry_count;
- u_char correction_span;
- u_char head_offset_count;
- u_char strobe_offset_count;
- u_char recovery_time_limit;
-};
-
-/*
- * Page Two - Disconnect / Reconnect Control Parameters
- */
-struct scsi_disco_reco {
- u_char page_savable : 1; /* save parameters */
- u_char rsvd : 1;
- u_char page_code : 6; /* = 0x02 */
- u_char page_length; /* = 10 */
- u_char buffer_full_ratio; /* write, how full before reconnect? */
- u_char buffer_empty_ratio; /* read, how full before reconnect? */
-
- u_short bus_inactivity_limit; /* how much bus time for busy */
- u_short disconnect_time_limit; /* min to remain disconnected */
- u_short connect_time_limit; /* min to remain connected */
- u_short reserved_1;
-};
-
-/*
- * Page Three - Direct Access Device Format Parameters
- */
-struct scsi_format {
- u_char page_savable : 1; /* save parameters */
- u_char rsvd : 1;
- u_char page_code : 6; /* = 0x03 */
- u_char page_length; /* = 22 */
- u_short tracks_per_zone; /* Handling of Defects Fields */
- u_short alt_sect_zone;
- u_short alt_tracks_zone;
- u_short alt_tracks_vol;
- u_short sect_track; /* Track Format Field */
- u_short data_sect; /* Sector Format Fields */
- u_short interleave;
- u_short track_skew_factor;
- u_short cyl_skew_factor;
- u_char ssec : 1; /* Drive Type Field */
- u_char hsec : 1;
- u_char rmb : 1;
- u_char surf : 1;
- u_char ins : 1;
- u_char reserved_1 : 3;
- u_char reserved_2;
- u_char reserved_3;
- u_char reserved_4;
-};
-
-/*
- * Page Four - Rigid Disk Drive Geometry Parameters
- */
-struct scsi_geometry {
- u_char page_savable : 1; /* save parameters */
- u_char rsvd : 1;
- u_char page_code : 6; /* = 0x04 */
- u_char page_length; /* = 18 */
- u_char cyl_ub; /* number of cylinders */
- u_char cyl_mb;
- u_char cyl_lb;
- u_char heads; /* number of heads */
- u_char precomp_cyl_ub; /* cylinder to start precomp */
- u_char precomp_cyl_mb;
- u_char precomp_cyl_lb;
- u_char current_cyl_ub; /* cyl to start reduced current */
- u_char current_cyl_mb;
- u_char current_cyl_lb;
- u_short step_rate; /* drive step rate */
- u_char landing_cyl_ub; /* landing zone cylinder */
- u_char landing_cyl_mb;
- u_char landing_cyl_lb;
- u_char reserved_1;
- u_char reserved_2;
- u_char reserved_3;
-};
-
-/*
- * Page 0x38 - Cache Control Parameters
- */
-struct scsi_cache {
- u_char page_savable : 1; /* save parameters */
- u_char rsvd : 1;
- u_char page_code : 6; /* = 0x38 */
- u_char page_length; /* = 14 */
- u_char rsvd_1 : 1;
- u_char wie : 1; /* write index enable */
- u_char rsvd_2 : 1;
- u_char ce : 1; /* cache enable */
- u_char table_size : 4;
- u_char prefetch_threshold;
- u_char maximum_threshold;
- u_char maximumprefetch_multiplier;
- u_char minimum_threshold;
- u_char minimum_prefetch_multiplier;
- u_char reserved[8];
-};
-
-/*
- * Control for SCSI "format" mode.
- *
- * "Format" mode allows a privileged process to issue direct SCSI
- * commands to a drive (it is intended primarily to allow on-line
- * formatting). SDIOCSFORMAT with a non-zero arg will put the drive
- * into format mode; a zero arg will take it out. When in format
- * mode, only the process that issued the SDIOCFORMAT can read or
- * write the drive.
- *
- * In format mode, process is expected to
- * - do SDIOCSCSICOMMAND to supply cdb for next SCSI op
- * - do read or write as appropriate for cdb
- * - if i/o error, optionally do SDIOCSENSE to get completion
- * status and sense data from last scsi operation.
- */
-
-struct scsi_fmt_cdb {
- int len; /* cdb length (in bytes) */
- u_char cdb[28]; /* cdb to use on next read/write */
-};
-
-struct scsi_fmt_sense {
- u_int status; /* completion status of last op */
- u_char sense[28]; /* sense data (if any) from last op */
-};
-
-#define SDIOCSFORMAT _IOW('S', 0x1, int)
-#define SDIOCGFORMAT _IOR('S', 0x2, int)
-#define SDIOCSCSICOMMAND _IOW('S', 0x3, struct scsi_fmt_cdb)
-#define SDIOCSENSE _IOR('S', 0x4, struct scsi_fmt_sense)
diff --git a/sys/arch/hp300/dev/scsivar.h b/sys/arch/hp300/dev/scsivar.h
deleted file mode 100644
index 6beeeae655f..00000000000
--- a/sys/arch/hp300/dev/scsivar.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* $OpenBSD: scsivar.h,v 1.7 2003/06/02 23:27:45 millert Exp $ */
-/* $NetBSD: scsivar.h,v 1.7 1997/03/31 07:40:05 scottr Exp $ */
-
-/*
- * Copyright (c) 1997 Jason R. Thorpe. All rights reserved.
- * Copyright (c) 1990, 1993
- * 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.
- *
- * @(#)scsivar.h 8.1 (Berkeley) 6/10/93
- */
-
-#include <sys/queue.h>
-
-/*
- * A SCSI job queue entry. Target drivers each have of of these,
- * used to queue requests with the initiator.
- */
-struct scsiqueue {
- TAILQ_ENTRY(scsiqueue) sq_list; /* entry on queue */
- void *sq_softc; /* target's softc */
- int sq_target; /* target on bus */
- int sq_lun; /* lun on target */
-
- /*
- * Callbacks used to start and stop the target driver.
- */
- void (*sq_start)(void *);
- void (*sq_go)(void *);
- void (*sq_intr)(void *, int);
-};
-
-struct scsi_inquiry;
-struct scsi_fmt_cdb;
-
-struct oscsi_attach_args {
- int osa_target; /* target */
- int osa_lun; /* logical unit */
- /* inquiry data */
- struct scsi_inquiry *osa_inqbuf;
-};
-
-#ifdef _KERNEL
-int scsi_print(void *, const char *);
-
-void scsi_delay(int);
-void scsistart(void *);
-void scsireset(int);
-int scsi_test_unit_rdy(int, int, int);
-int scsi_request_sense(int, int, int, u_char *, u_int);
-int scsi_immed_command(int, int, int, struct scsi_fmt_cdb *,
- u_char *, u_int, int);
-int scsi_tt_read(int, int, int, u_char *, u_int, daddr_t, int);
-int scsi_tt_write(int, int, int, u_char *, u_int, daddr_t, int);
-int scsireq(struct device *, struct scsiqueue *);
-int scsiustart(int);
-void scsistart(void *);
-int scsigo(int, int, int, struct buf *, struct scsi_fmt_cdb *, int);
-void scsidone(void *);
-int scsiintr(void *);
-void scsifree(struct device *, struct scsiqueue *);
-int scsi_tt_oddio(int, int, int, u_char *, u_int, int, int);
-void scsi_str(char *, char *, size_t);
-int scsi_probe_device(int, int, int, struct scsi_inquiry *, int);
-#endif
diff --git a/sys/arch/hp300/dev/sd.c b/sys/arch/hp300/dev/sd.c
deleted file mode 100644
index ceeb8aa0e02..00000000000
--- a/sys/arch/hp300/dev/sd.c
+++ /dev/null
@@ -1,1271 +0,0 @@
-/* $OpenBSD: sd.c,v 1.33 2004/02/15 02:56:13 tedu Exp $ */
-/* $NetBSD: sd.c,v 1.34 1997/07/10 18:14:10 kleink Exp $ */
-
-/*
- * Copyright (c) 1996, 1997 Jason R. Thorpe. All rights reserved.
- * Copyright (c) 1990, 1993
- * 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.
- *
- * @(#)sd.c 8.5 (Berkeley) 5/19/94
- */
-
-/*
- * SCSI CCS (Command Command Set) disk driver.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/device.h>
-#include <sys/disk.h>
-#include <sys/disklabel.h>
-#include <sys/fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/malloc.h>
-#include <sys/proc.h>
-#include <sys/stat.h>
-
-#include <ufs/ffs/fs.h> /* for BBSIZE and SBSIZE */
-
-#include <sys/conf.h>
-
-#include <hp300/dev/scsireg.h>
-#include <hp300/dev/scsivar.h>
-#include <hp300/dev/sdvar.h>
-
-#ifdef USELEDS
-#include <hp300/hp300/leds.h>
-#endif
-
-int sdmatch(struct device *, void *, void *);
-void sdattach(struct device *, struct device *, void *);
-
-struct cfattach sd_ca = {
- sizeof(struct sd_softc), sdmatch, sdattach
-};
-
-struct cfdriver sd_cd = {
- NULL, "sd", DV_DISK
-};
-
-#ifdef DEBUG
-int sddebug = 1;
-#define SDB_ERROR 0x01
-#define SDB_PARTIAL 0x02
-#define SDB_CAPACITY 0x04
-#endif
-
-static struct scsi_fmt_cdb sd_read_cmd = { 10, { CMD_READ_EXT } };
-static struct scsi_fmt_cdb sd_write_cmd = { 10, { CMD_WRITE_EXT } };
-
-/*
- * Table of scsi commands users are allowed to access via "format"
- * mode. 0 means not legal. 1 means "immediate" (doesn't need dma).
- * -1 means needs dma and/or wait for intr.
- */
-static char legal_cmds[256] = {
-/***** 0 1 2 3 4 5 6 7 8 9 A B C D E F */
-/*00*/ 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/*10*/ 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
-/*20*/ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/*30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/*a0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-bdev_decl(sd);
-cdev_decl(sd);
-
-void sdreset(struct sd_softc *);
-
-static void sdgetgeom(struct sd_softc *);
-static void sdlblkstrat(struct buf *, int);
-static int sderror(struct sd_softc *, int);
-static void sdfinish(struct sd_softc *, struct buf *);
-
-/*
- * Perform a mode-sense on page 0x04 (rigid geometry).
- */
-static void
-sdgetgeom(sc)
- struct sd_softc *sc;
-{
- struct scsi_mode_sense_geom {
- struct scsi_modesense_hdr header;
- struct scsi_geometry geom;
- } sensebuf;
- struct scsi_fmt_cdb modesense_geom;
- int ctlr, slave, unit;
-
- /* XXX - if we try to do this in the declaration gcc uses memset() */
- bzero(&modesense_geom, sizeof(modesense_geom));
- modesense_geom.len = 6;
- modesense_geom.cdb[0] = CMD_MODE_SENSE;
- modesense_geom.cdb[2] = 0x04;
- modesense_geom.cdb[4] = sizeof(sensebuf);
-
- ctlr = sc->sc_dev.dv_parent->dv_unit;
- slave = sc->sc_target;
- unit = sc->sc_lun;
-
- scsi_delay(-1); /* XXX */
- (void)scsi_immed_command(ctlr, slave, unit, &modesense_geom,
- (u_char *)&sensebuf, sizeof(sensebuf), B_READ);
- scsi_delay(0); /* XXX */
-
- sc->sc_heads = sensebuf.geom.heads;
- sc->sc_cyls = (sensebuf.geom.cyl_ub << 16) |
- (sensebuf.geom.cyl_mb << 8) | sensebuf.geom.cyl_lb;
-}
-
-int
-sdmatch(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- struct oscsi_attach_args *osa = aux;
-
- switch (osa->osa_inqbuf->type) {
- case 0: /* disk */
- case 4: /* WORM */
- case 5: /* CD-ROM */
- case 7: /* Magneto-optical */
- break;
- default: /* not a disk */
- return 0;
- }
-
- return (1);
-}
-
-void
-sdattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
-{
- struct sd_softc *sc = (struct sd_softc *)self;
- struct oscsi_attach_args *osa = aux;
-
- /*
- * XXX formerly 0 meant unused but now pid 0 can legitimately
- * use this interface (sdgetcapacity).
- */
- sc->sc_format_pid = -1;
- sc->sc_flags = 0;
-
- sc->sc_target = osa->osa_target;
- sc->sc_lun = osa->osa_lun;
- sc->sc_type = osa->osa_inqbuf->type;
-
- if (osa->osa_inqbuf->qual & 0x80)
- sc->sc_flags |= SDF_RMEDIA;
-
- printf("\n");
-
- /* Initialize the SCSI queue entry. */
- sc->sc_sq.sq_softc = sc;
- sc->sc_sq.sq_target = sc->sc_target;
- sc->sc_sq.sq_lun = sc->sc_lun;
- sc->sc_sq.sq_start = sdstart;
- sc->sc_sq.sq_go = sdgo;
- sc->sc_sq.sq_intr = sdintr;
-
- if (sdgetcapacity(sc, NODEV) < 0) {
- printf("%s: getcapacity failed!\n", sc->sc_dev.dv_xname);
- return;
- }
-
- /*
- * Print out some additional information.
- */
- printf("%s: ", sc->sc_dev.dv_xname);
- switch (sc->sc_type) {
- case 4:
- printf("WORM, ");
- break;
-
- case 5:
- printf("CD-ROM, ");
- break;
-
- case 7:
- printf("Magneto-optical, ");
- break;
-
- default:
- printf("%d cylinders, %d heads, ",
- sc->sc_cyls, sc->sc_heads);
- }
- if (sc->sc_blks)
- printf("%d blocks, %d bytes/block\n",
- sc->sc_blks >> sc->sc_bshift, sc->sc_blksize);
- else
- printf("drive empty\n");
-
- /* Initialize the disk structure. */
- sc->sc_dkdev.dk_name = sc->sc_dev.dv_xname;
-
- /* Attach the disk. */
- disk_attach(&sc->sc_dkdev);
-
- dk_establish(&sc->sc_dkdev, &sc->sc_dev); /* XXX */
-
- sc->sc_flags |= SDF_ALIVE;
-}
-
-void
-sdreset(sc)
- struct sd_softc *sc;
-{
- sc->sc_stats.sdresets++;
-}
-
-/*
- * Determine capacity of a drive.
- * Returns -1 on a failure, 0 on success, 1 on a failure that is probably
- * due to missing media.
- */
-int
-sdgetcapacity(sc, dev)
- struct sd_softc *sc;
- dev_t dev;
-{
- static struct scsi_fmt_cdb cap = {
- 10,
- { CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
- };
- u_char *capbuf;
- int i, capbufsize;
-
- /*
- * Cannot use stack space for this buffer since stack KVA may not
- * be valid (i.e. in context of this process) when the operation
- * actually starts.
- */
- capbufsize = 8;
- capbuf = malloc(capbufsize, M_DEVBUF, M_WAITOK);
-
- if (dev == NODEV) {
- scsi_delay(-1); /* XXX */
- i = scsi_immed_command(sc->sc_dev.dv_parent->dv_unit,
- sc->sc_target, sc->sc_lun, &cap, capbuf,
- capbufsize, B_READ);
- scsi_delay(0); /* XXX */
- } else {
- struct buf *bp;
-
- /*
- * XXX this is horrible
- */
- if (sc->sc_format_pid >= 0)
- panic("sdgetcapacity");
- bp = malloc(sizeof *bp, M_DEVBUF, M_WAITOK);
- sc->sc_format_pid = curproc->p_pid;
- bcopy(&cap, &sc->sc_cmdstore, sizeof cap);
- bp->b_dev = dev;
- bp->b_flags = B_READ | B_BUSY;
- bp->b_un.b_addr = (caddr_t)capbuf;
- bp->b_bcount = capbufsize;
- LIST_INIT(&bp->b_dep);
- sdstrategy(bp);
- i = biowait(bp) ? sc->sc_sensestore.status : 0;
- free(bp, M_DEVBUF);
- sc->sc_format_pid = -1;
- }
- if (i) {
- if (i != STS_CHECKCOND || (sc->sc_flags & SDF_RMEDIA) == 0) {
-#ifdef DEBUG
- if (sddebug & SDB_CAPACITY)
- printf("%s: read_capacity returns %d\n",
- sc->sc_dev.dv_xname, i);
-#endif
- free(capbuf, M_DEVBUF);
- return (-1);
- }
- /*
- * XXX assume unformatted or non-existent media
- */
- sc->sc_blks = 0;
- sc->sc_blksize = DEV_BSIZE;
- sc->sc_bshift = 0;
-#ifdef DEBUG
- if (sddebug & SDB_CAPACITY)
- printf("%s: removable media not present\n",
- sc->sc_dev.dv_xname);
-#endif
- free(capbuf, M_DEVBUF);
- return (1);
- }
- sc->sc_blks = *(u_int *)&capbuf[0];
- sc->sc_blksize = *(int *)&capbuf[4];
- free(capbuf, M_DEVBUF);
- sc->sc_bshift = 0;
-
- /* return value of read capacity is last valid block number */
- sc->sc_blks++;
-
- if (sc->sc_blksize != DEV_BSIZE) {
- if (sc->sc_blksize < DEV_BSIZE) {
- printf("%s: need at least %d byte blocks - %s\n",
- sc->sc_dev.dv_xname, DEV_BSIZE, "drive ignored");
- return (-1);
- }
- for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1)
- ++sc->sc_bshift;
- sc->sc_blks <<= sc->sc_bshift;
- }
-#ifdef DEBUG
- if (sddebug & SDB_CAPACITY)
- printf("%s: blks=%d, blksize=%d, bshift=%d\n",
- sc->sc_dev.dv_xname, sc->sc_blks, sc->sc_blksize,
- sc->sc_bshift);
-#endif
- sc->sc_heads = sc->sc_cyls = 0;
- sdgetgeom(sc);
- return (0);
-}
-
-/*
- * Read or constuct a disklabel
- */
-int
-sdgetinfo(dev, sc, lp, spoofonly)
- dev_t dev;
- struct sd_softc *sc;
- struct disklabel *lp;
- int spoofonly;
-{
- char *errstring;
-
- bzero((caddr_t)lp, sizeof *lp);
- errstring = NULL;
-
- /*
- * If removable media or the size unavailable at boot time
- * (i.e. unformatted hard disk), attempt to set the capacity
- * now.
- */
- if ((sc->sc_flags & SDF_RMEDIA) || sc->sc_blks == 0) {
- switch (sdgetcapacity(sc, dev)) {
- case 0:
- break;
- case -1:
- /*
- * Hard error, just return (open will fail).
- */
- return (EIO);
- case 1:
- /*
- * XXX return 0 so open can continue just in case
- * the media is unformatted and we want to format it.
- * We set the error flag so they cannot do much else.
- */
- sc->sc_flags |= SDF_ERROR;
- /* XXX set magic here or it will never be set */
- lp->d_magic = DISKMAGIC;
- lp->d_magic2 = DISKMAGIC;
- errstring = "unformatted/missing media";
- break;
- }
- }
-
- /*
- * Create a default disk label based on scsi info.
- * This will get overridden if there is a real label on the disk.
- */
- if (errstring == NULL) {
- /* XXX we can open a device even without SDF_ALIVE */
- if (sc->sc_blksize == 0)
- sc->sc_blksize = DEV_BSIZE;
-
- /* Fill in info from disk geometry if it exists. */
- lp->d_secperunit = sc->sc_blks >> sc->sc_bshift;
- if (lp->d_secperunit > 0 && sc->sc_heads > 0 && sc->sc_cyls > 0) {
- lp->d_ntracks = sc->sc_heads;
- lp->d_ncylinders = sc->sc_cyls;
- lp->d_nsectors = lp->d_secperunit /
- (lp->d_ntracks * lp->d_ncylinders);
- /*
- * We must make sure d_nsectors is a sane value.
- * Adjust d_ncylinders to be reasonable if we
- * monkey with d_nsectors.
- */
- if (lp->d_nsectors < 1) {
- lp->d_nsectors = 32;
- lp->d_ncylinders = lp->d_secperunit /
- ( lp->d_ntracks * lp->d_nsectors);
- if (lp->d_ncylinders == 0)
- lp->d_ncylinders = sc->sc_cyls;
- }
- } else {
- lp->d_ntracks = 20;
- lp->d_ncylinders = 1;
- lp->d_nsectors = 32;
- }
-
- switch (sc->sc_type) {
- case 4:
- strncpy(lp->d_typename, "SCSI WORM", sizeof lp->d_typename);
- break;
- case 5:
- strncpy(lp->d_typename, "SCSI CD-ROM", sizeof lp->d_typename);
- break;
- case 7:
- strncpy(lp->d_typename, "SCSI optical", sizeof lp->d_typename);
- break;
- default:
- strncpy(lp->d_typename, "SCSI disk", sizeof lp->d_typename);
- break;
- }
- lp->d_type = DTYPE_SCSI;
- strncpy(lp->d_packname, "fictitious", sizeof lp->d_packname);
- lp->d_secsize = sc->sc_blksize;
- lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
- lp->d_rpm = 3600;
- lp->d_interleave = 1;
-
- /* XXX - these values for BBSIZE and SBSIZE assume ffs */
- lp->d_bbsize = BBSIZE;
- lp->d_sbsize = SBSIZE;
-
- lp->d_partitions[RAW_PART].p_offset = 0;
- if (lp->d_secperunit > 0)
- lp->d_partitions[RAW_PART].p_size =
- lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
- else
- lp->d_partitions[RAW_PART].p_size =
- roundup(LABELSECTOR+1, btodb(sc->sc_blksize));
- lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
- lp->d_npartitions = RAW_PART + 1;
-
- lp->d_magic = DISKMAGIC;
- lp->d_magic2 = DISKMAGIC;
- lp->d_checksum = dkcksum(lp);
-
- errstring = readdisklabel(SDLABELDEV(dev), sdstrategy, lp, NULL,
- spoofonly);
- }
-
- if (errstring) {
- printf("%s: WARNING: %s, defining `c' partition as entire disk\n",
- sc->sc_dev.dv_xname, errstring);
- /* XXX reset partition info as readdisklabel screws with it */
- lp->d_partitions[0].p_size = 0;
- lp->d_partitions[RAW_PART].p_offset = 0;
- lp->d_partitions[RAW_PART].p_size =
- lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
- lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
- lp->d_npartitions = RAW_PART + 1;
- lp->d_checksum = dkcksum(lp);
- }
-
- return(0);
-}
-
-int
-sdopen(dev, flags, mode, p)
- dev_t dev;
- int flags, mode;
- struct proc *p;
-{
- int unit = SDUNIT(dev);
- struct sd_softc *sc;
- int error, mask, part;
-
- if (unit >= sd_cd.cd_ndevs ||
- (sc = sd_cd.cd_devs[unit]) == NULL ||
- (sc->sc_flags & SDF_ALIVE) == 0)
- return (ENXIO);
-
- /*
- * Wait for any pending opens/closes to complete
- */
- while (sc->sc_flags & (SDF_OPENING|SDF_CLOSING))
- tsleep((caddr_t)sc, PRIBIO, "sdopen", 0);
-
- /*
- * On first open, get label and partition info.
- * We may block reading the label, so be careful
- * to stop any other opens.
- */
- if (sc->sc_dkdev.dk_openmask == 0) {
- sc->sc_flags |= SDF_OPENING;
- error = sdgetinfo(dev, sc, sc->sc_dkdev.dk_label, 0);
- sc->sc_flags &= ~SDF_OPENING;
- wakeup((caddr_t)sc);
- if (error)
- return(error);
- }
-
- part = SDPART(dev);
- mask = 1 << part;
-
- /* Check that the partition exists. */
- if (part != RAW_PART &&
- (part >= sc->sc_dkdev.dk_label->d_npartitions ||
- sc->sc_dkdev.dk_label->d_partitions[part].p_fstype == FS_UNUSED))
- return (ENXIO);
-
- /* Ensure only one open at a time. */
- switch (mode) {
- case S_IFCHR:
- sc->sc_dkdev.dk_copenmask |= mask;
- break;
- case S_IFBLK:
- sc->sc_dkdev.dk_bopenmask |= mask;
- break;
- }
- sc->sc_dkdev.dk_openmask =
- sc->sc_dkdev.dk_copenmask | sc->sc_dkdev.dk_bopenmask;
-
- return(0);
-}
-
-int
-sdclose(dev, flag, mode, p)
- dev_t dev;
- int flag, mode;
- struct proc *p;
-{
- int unit = SDUNIT(dev);
- struct sd_softc *sc = sd_cd.cd_devs[unit];
- struct disk *dk = &sc->sc_dkdev;
- int mask, s;
-
- mask = 1 << SDPART(dev);
- if (mode == S_IFCHR)
- dk->dk_copenmask &= ~mask;
- else
- dk->dk_bopenmask &= ~mask;
- dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask;
- /*
- * On last close, we wait for all activity to cease since
- * the label/parition info will become invalid. Since we
- * might sleep, we must block any opens while we are here.
- * Note we don't have to about other closes since we know
- * we are the last one.
- */
- if (dk->dk_openmask == 0) {
- sc->sc_flags |= SDF_CLOSING;
- s = splbio();
- while (sc->sc_tab.b_active) {
- sc->sc_flags |= SDF_WANTED;
- tsleep((caddr_t)&sc->sc_tab, PRIBIO, "sdclose", 0);
- }
- splx(s);
- sc->sc_flags &= ~(SDF_CLOSING|SDF_ERROR);
- wakeup((caddr_t)sc);
- }
- sc->sc_format_pid = -1;
- return(0);
-}
-
-/*
- * This routine is called for partial block transfers and non-aligned
- * transfers (the latter only being possible on devices with a block size
- * larger than DEV_BSIZE). The operation is performed in three steps
- * using a locally allocated buffer:
- * 1. transfer any initial partial block
- * 2. transfer full blocks
- * 3. transfer any final partial block
- */
-static void
-sdlblkstrat(bp, bsize)
- struct buf *bp;
- int bsize;
-{
- struct sd_softc *sc = sd_cd.cd_devs[SDUNIT(bp->b_dev)];
- struct buf *cbp = (struct buf *)malloc(sizeof(struct buf),
- M_DEVBUF, M_WAITOK);
- caddr_t cbuf = (caddr_t)malloc(bsize, M_DEVBUF, M_WAITOK);
- int bn, resid;
- caddr_t addr;
-
- bzero((caddr_t)cbp, sizeof(*cbp));
- cbp->b_proc = curproc; /* XXX */
- cbp->b_dev = bp->b_dev;
- LIST_INIT(&cbp->b_dep);
- bn = bp->b_blkno;
- resid = bp->b_bcount;
- addr = bp->b_un.b_addr;
-#ifdef DEBUG
- if (sddebug & SDB_PARTIAL)
- printf("sdlblkstrat: bp %p flags %lx bn %x resid %x addr %p\n",
- bp, bp->b_flags, bn, resid, addr);
-#endif
-
- while (resid > 0) {
- int boff = dbtob(bn) & (bsize - 1);
- int count;
-
- if (boff || resid < bsize) {
- sc->sc_stats.sdpartials++;
- count = min(resid, bsize - boff);
- cbp->b_flags = B_BUSY | B_PHYS | B_READ;
- cbp->b_blkno = bn - btodb(boff);
- cbp->b_un.b_addr = cbuf;
- cbp->b_bcount = bsize;
-#ifdef DEBUG
- if (sddebug & SDB_PARTIAL)
- printf(" readahead: bn %x cnt %x off %x addr %p\n",
- cbp->b_blkno, count, boff, addr);
-#endif
- sdstrategy(cbp);
- biowait(cbp);
- if (cbp->b_flags & B_ERROR) {
- bp->b_flags |= B_ERROR;
- bp->b_error = cbp->b_error;
- break;
- }
- if (bp->b_flags & B_READ) {
- bcopy(&cbuf[boff], addr, count);
- goto done;
- }
- bcopy(addr, &cbuf[boff], count);
-#ifdef DEBUG
- if (sddebug & SDB_PARTIAL)
- printf(" writeback: bn %x cnt %x off %x addr %p\n",
- cbp->b_blkno, count, boff, addr);
-#endif
- } else {
- count = resid & ~(bsize - 1);
- cbp->b_blkno = bn;
- cbp->b_un.b_addr = addr;
- cbp->b_bcount = count;
-#ifdef DEBUG
- if (sddebug & SDB_PARTIAL)
- printf(" fulltrans: bn %x cnt %x addr %p\n",
- cbp->b_blkno, count, addr);
-#endif
- }
- cbp->b_flags = B_BUSY | B_PHYS | (bp->b_flags & B_READ);
- sdstrategy(cbp);
- biowait(cbp);
- if (cbp->b_flags & B_ERROR) {
- bp->b_flags |= B_ERROR;
- bp->b_error = cbp->b_error;
- break;
- }
-done:
- bn += btodb(count);
- resid -= count;
- addr += count;
-#ifdef DEBUG
- if (sddebug & SDB_PARTIAL)
- printf(" done: bn %x resid %x addr %p\n",
- bn, resid, addr);
-#endif
- }
- free(cbuf, M_DEVBUF);
- free(cbp, M_DEVBUF);
-}
-
-void
-sdstrategy(bp)
- struct buf *bp;
-{
- int unit = SDUNIT(bp->b_dev);
- struct sd_softc *sc = sd_cd.cd_devs[unit];
- struct buf *dp = &sc->sc_tab;
- struct partition *pinfo;
- daddr_t bn;
- int sz, s;
- int offset;
-
- if (sc->sc_format_pid >= 0) {
- if (sc->sc_format_pid != curproc->p_pid) { /* XXX */
- bp->b_error = EPERM;
- goto bad;
- }
- bp->b_cylin = 0;
- } else {
- if (sc->sc_flags & SDF_ERROR) {
- bp->b_error = EIO;
- goto bad;
- }
- bn = bp->b_blkno;
- sz = howmany(bp->b_bcount, DEV_BSIZE);
- pinfo = &sc->sc_dkdev.dk_label->d_partitions[SDPART(bp->b_dev)];
-
- /* Don't perform partition translation on RAW_PART. */
- offset = (SDPART(bp->b_dev) == RAW_PART) ? 0 : pinfo->p_offset;
-
- if (SDPART(bp->b_dev) != RAW_PART) {
- /*
- * XXX This block of code belongs in
- * XXX bounds_check_with_label()
- */
-
- if (bn < 0 || bn + sz > pinfo->p_size) {
- sz = pinfo->p_size - bn;
- if (sz == 0) {
- bp->b_resid = bp->b_bcount;
- goto done;
- }
- if (sz < 0) {
- bp->b_error = EINVAL;
- goto bad;
- }
- bp->b_bcount = dbtob(sz);
- }
- /*
- * Check for write to write protected label
- */
- if (bn + offset <= LABELSECTOR &&
-#if LABELSECTOR != 0
- bn + offset + sz > LABELSECTOR &&
-#endif
- !(bp->b_flags & B_READ) &&
- !(sc->sc_flags & SDF_WLABEL)) {
- bp->b_error = EROFS;
- goto bad;
- }
- }
- /*
- * Non-aligned or partial-block transfers handled specially.
- */
- s = sc->sc_blksize - 1;
- if ((dbtob(bn) & s) || (bp->b_bcount & s)) {
- sdlblkstrat(bp, sc->sc_blksize);
- goto done;
- }
- bp->b_cylin = (bn + offset) >> sc->sc_bshift;
- }
- s = splbio();
- disksort(dp, bp);
- if (dp->b_active == 0) {
- dp->b_active = 1;
- sdustart(unit);
- }
- splx(s);
- return;
-bad:
- bp->b_flags |= B_ERROR;
-done:
- s = splbio();
- biodone(bp);
- splx(s);
-}
-
-void
-sdustart(unit)
- int unit;
-{
- struct sd_softc *sc = sd_cd.cd_devs[unit];
-
- if (scsireq(sc->sc_dev.dv_parent, &sc->sc_sq))
- sdstart(sc);
-}
-
-/*
- * Return:
- * 0 if not really an error
- * <0 if we should do a retry
- * >0 if a fatal error
- */
-static int
-sderror(sc, stat)
- struct sd_softc *sc;
- int stat;
-{
- int cond = 1;
-
- sc->sc_sensestore.status = stat;
- if (stat & STS_CHECKCOND) {
- struct scsi_xsense *sp;
-
- scsi_request_sense(sc->sc_dev.dv_parent->dv_unit,
- sc->sc_target, sc->sc_lun, sc->sc_sensestore.sense,
- sizeof(sc->sc_sensestore.sense));
- sp = (struct scsi_xsense *)(sc->sc_sensestore.sense);
- printf("%s: scsi sense class %d, code %d", sc->sc_dev.dv_xname,
- sp->class, sp->code);
- if (sp->class == 7) {
- printf(", key %d", sp->key);
- if (sp->valid)
- printf(", blk %d", *(int *)&sp->info1);
- switch (sp->key) {
- /* no sense, try again */
- case 0:
- cond = -1;
- break;
- /* recovered error, not a problem */
- case 1:
- cond = 0;
- break;
- /* possible media change */
- case 6:
- /*
- * For removable media, if we are doing the
- * first open (i.e. reading the label) go
- * ahead and retry, otherwise someone has
- * changed the media out from under us and
- * we should abort any further operations
- * until a close is done.
- */
- if (sc->sc_flags & SDF_RMEDIA) {
- if (sc->sc_flags & SDF_OPENING)
- cond = -1;
- else
- sc->sc_flags |= SDF_ERROR;
- }
- break;
- }
- }
- printf("\n");
- }
- return(cond);
-}
-
-static void
-sdfinish(sc, bp)
- struct sd_softc *sc;
- struct buf *bp;
-{
- struct buf *dp = &sc->sc_tab;
-
- dp->b_errcnt = 0;
- dp->b_actf = bp->b_actf;
- bp->b_resid = 0;
- biodone(bp);
- scsifree(sc->sc_dev.dv_parent, &sc->sc_sq);
- if (dp->b_actf)
- sdustart(sc->sc_dev.dv_unit);
- else {
- dp->b_active = 0;
- if (sc->sc_flags & SDF_WANTED) {
- sc->sc_flags &= ~SDF_WANTED;
- wakeup((caddr_t)dp);
- }
- }
-}
-
-void
-sdstart(arg)
- void *arg;
-{
- struct sd_softc *sc = arg;
-
- /*
- * we have the SCSI bus -- in format mode, we may or may not need dma
- * so check now.
- */
- if (sc->sc_format_pid >= 0 && legal_cmds[sc->sc_cmdstore.cdb[0]] > 0) {
- struct buf *bp = sc->sc_tab.b_actf;
- int sts;
-
- sc->sc_tab.b_errcnt = 0;
- while (1) {
- sts = scsi_immed_command(sc->sc_dev.dv_parent->dv_unit,
- sc->sc_target, sc->sc_lun, &sc->sc_cmdstore,
- bp->b_un.b_addr, bp->b_bcount,
- bp->b_flags & B_READ);
- sc->sc_sensestore.status = sts;
- if ((sts & 0xfe) == 0 ||
- (sts = sderror(sc, sts)) == 0)
- break;
- if (sts > 0 || sc->sc_tab.b_errcnt++ >= SDRETRY) {
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- break;
- }
- }
- sdfinish(sc, bp);
-
- } else if (scsiustart(sc->sc_dev.dv_parent->dv_unit))
- sdgo(sc);
-}
-
-void
-sdgo(arg)
- void *arg;
-{
- struct sd_softc *sc = arg;
- struct buf *bp = sc->sc_tab.b_actf;
- int pad;
- struct scsi_fmt_cdb *cmd;
-
- if (sc->sc_format_pid >= 0) {
- cmd = &sc->sc_cmdstore;
- pad = 0;
- } else {
- /*
- * Drive is in an error state, abort all operations
- */
- if (sc->sc_flags & SDF_ERROR) {
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- sdfinish(sc, bp);
- return;
- }
- cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd;
- *(int *)(&cmd->cdb[2]) = bp->b_cylin;
- pad = howmany(bp->b_bcount, sc->sc_blksize);
- *(u_short *)(&cmd->cdb[7]) = pad;
- pad = (bp->b_bcount & (sc->sc_blksize - 1)) != 0;
-#ifdef DEBUG
- if (pad)
- printf("%s: partial block xfer -- %lx bytes\n",
- sc->sc_dev.dv_xname, bp->b_bcount);
-#endif
- sc->sc_stats.sdtransfers++;
- }
-#ifdef USELEDS
- ledcontrol(0, 0, LED_DISK);
-#endif
- if (scsigo(sc->sc_dev.dv_parent->dv_unit, sc->sc_target, sc->sc_lun,
- bp, cmd, pad) == 0) {
- /* Instrumentation. */
- disk_busy(&sc->sc_dkdev);
- sc->sc_dkdev.dk_seek++; /* XXX */
- return;
- }
-#ifdef DEBUG
- if (sddebug & SDB_ERROR)
- printf("%s: sdstart: %s adr %p blk %ld len %ld ecnt %ld\n",
- sc->sc_dev.dv_xname,
- bp->b_flags & B_READ? "read" : "write",
- bp->b_un.b_addr, bp->b_cylin, bp->b_bcount,
- sc->sc_tab.b_errcnt);
-#endif
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- sdfinish(sc, bp);
-}
-
-void
-sdintr(arg, stat)
- void *arg;
- int stat;
-{
- struct sd_softc *sc = arg;
- struct buf *bp = sc->sc_tab.b_actf;
- int cond;
-
- if (bp == NULL) {
- printf("%s: bp == NULL\n", sc->sc_dev.dv_xname);
- return;
- }
-
- disk_unbusy(&sc->sc_dkdev, (bp->b_bcount - bp->b_resid),
- (bp->b_flags & B_READ));
-
- if (stat) {
-#ifdef DEBUG
- if (sddebug & SDB_ERROR)
- printf("%s: sdintr: bad scsi status 0x%x\n",
- sc->sc_dev.dv_xname, stat);
-#endif
- cond = sderror(sc, stat);
- if (cond) {
- if (cond < 0 && sc->sc_tab.b_errcnt++ < SDRETRY) {
-#ifdef DEBUG
- if (sddebug & SDB_ERROR)
- printf("%s: retry #%ld\n",
- sc->sc_dev.dv_xname,
- sc->sc_tab.b_errcnt);
-#endif
- sdstart(sc);
- return;
- }
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- }
- }
- sdfinish(sc, bp);
-}
-
-int
-sdread(dev, uio, flags)
- dev_t dev;
- struct uio *uio;
- int flags;
-{
- int unit = SDUNIT(dev);
- struct sd_softc *sc = sd_cd.cd_devs[unit];
- int pid;
-
- if ((pid = sc->sc_format_pid) >= 0 &&
- pid != uio->uio_procp->p_pid)
- return (EPERM);
-
- return (physio(sdstrategy, NULL, dev, B_READ, minphys, uio));
-}
-
-int
-sdwrite(dev, uio, flags)
- dev_t dev;
- struct uio *uio;
- int flags;
-{
- int unit = SDUNIT(dev);
- struct sd_softc *sc = sd_cd.cd_devs[unit];
- int pid;
-
- if ((pid = sc->sc_format_pid) >= 0 &&
- pid != uio->uio_procp->p_pid)
- return (EPERM);
-
- return (physio(sdstrategy, NULL, dev, B_WRITE, minphys, uio));
-}
-
-int
-sdioctl(dev, cmd, data, flag, p)
- dev_t dev;
- u_long cmd;
- caddr_t data;
- int flag;
- struct proc *p;
-{
- int unit = SDUNIT(dev);
- struct sd_softc *sc = sd_cd.cd_devs[unit];
- struct disklabel *lp = sc->sc_dkdev.dk_label;
- int error, flags;
-
- switch (cmd) {
- case DIOCGPDINFO:
- error = sdgetinfo(dev, sc, (struct disklabel *)data, 1);
- return (error);
-
- case DIOCGDINFO:
- *(struct disklabel *)data = *lp;
- return (0);
-
- case DIOCGPART:
- ((struct partinfo *)data)->disklab = lp;
- ((struct partinfo *)data)->part =
- &lp->d_partitions[SDPART(dev)];
- return (0);
-
- case DIOCWLABEL:
- if ((flag & FWRITE) == 0)
- return (EBADF);
- if (*(int *)data)
- sc->sc_flags |= SDF_WLABEL;
- else
- sc->sc_flags &= ~SDF_WLABEL;
- return (0);
-
- case DIOCSDINFO:
- if ((flag & FWRITE) == 0)
- return (EBADF);
- error = setdisklabel(lp, (struct disklabel *)data,
- (sc->sc_flags & SDF_WLABEL) ? 0
- : sc->sc_dkdev.dk_openmask,
- (struct cpu_disklabel *)0);
- return (error);
-
- case DIOCWDINFO:
- if ((flag & FWRITE) == 0)
- return (EBADF);
- error = setdisklabel(lp, (struct disklabel *)data,
- (sc->sc_flags & SDF_WLABEL) ? 0
- : sc->sc_dkdev.dk_openmask,
- (struct cpu_disklabel *)0);
- if (error)
- return (error);
- flags = sc->sc_flags;
- sc->sc_flags = SDF_ALIVE | SDF_WLABEL;
- error = writedisklabel(SDLABELDEV(dev), sdstrategy, lp,
- (struct cpu_disklabel *)0);
- sc->sc_flags = flags;
- return (error);
-
- case SDIOCSFORMAT:
- /* take this device into or out of "format" mode */
- if (suser(p, 0))
- return(EPERM);
-
- if (*(int *)data) {
- if (sc->sc_format_pid >= 0)
- return (EPERM);
- sc->sc_format_pid = p->p_pid;
- } else
- sc->sc_format_pid = -1;
- return (0);
-
- case SDIOCGFORMAT:
- /* find out who has the device in format mode */
- *(int *)data = sc->sc_format_pid;
- return (0);
-
- case SDIOCSCSICOMMAND:
- /*
- * Save what user gave us as SCSI cdb to use with next
- * read or write to the char device.
- */
- if (sc->sc_format_pid != p->p_pid)
- return (EPERM);
- if (legal_cmds[((struct scsi_fmt_cdb *)data)->cdb[0]] == 0)
- return (EINVAL);
- bcopy(data, &sc->sc_cmdstore, sizeof(struct scsi_fmt_cdb));
- return (0);
-
- case SDIOCSENSE:
- /*
- * return the SCSI sense data saved after the last
- * operation that completed with "check condition" status.
- */
- bcopy(&sc->sc_sensestore, data, sizeof(sc->sc_sensestore));
- return (0);
-
- default:
- return (EINVAL);
-
- }
- /*NOTREACHED*/
-}
-
-int
-sdsize(dev)
- dev_t dev;
-{
- int unit = SDUNIT(dev);
- struct sd_softc *sc = sd_cd.cd_devs[unit];
- int psize, didopen = 0;
-
- if (unit >= sd_cd.cd_ndevs ||
- (sc = sd_cd.cd_devs[unit]) == NULL ||
- (sc->sc_flags & SDF_ALIVE) == 0)
- return (-1);
-
- /*
- * We get called very early on (via swapconf)
- * without the device being open so we may need
- * to handle it here.
- */
- if (sc->sc_dkdev.dk_openmask == 0) {
- if (sdopen(dev, FREAD|FWRITE, S_IFBLK, NULL))
- return(-1);
- didopen = 1;
- }
- psize = sc->sc_dkdev.dk_label->d_partitions[SDPART(dev)].p_size *
- (sc->sc_dkdev.dk_label->d_secsize / DEV_BSIZE);
- if (didopen)
- (void) sdclose(dev, FREAD|FWRITE, S_IFBLK, NULL);
- return (psize);
-}
-
-static int sddoingadump; /* simple mutex */
-
-/*
- * Non-interrupt driven, non-dma dump routine.
- */
-int
-sddump(dev, blkno, va, size)
- dev_t dev;
- daddr_t blkno;
- caddr_t va;
- size_t size;
-{
- int sectorsize; /* size of a disk sector */
- int nsects; /* number of sectors in partition */
- int sectoff; /* sector offset of partition */
- int totwrt; /* total number of sectors left to write */
- int nwrt; /* current number of sectors to write */
- int unit, part;
- struct sd_softc *sc;
- struct disklabel *lp;
- char stat;
-
- /* Check for recursive dump; if so, punt. */
- if (sddoingadump)
- return (EFAULT);
- sddoingadump = 1;
-
- /* Decompose unit and partition. */
- unit = SDUNIT(dev);
- part = SDPART(dev);
-
- /* Make sure device is ok. */
- if (unit >= sd_cd.cd_ndevs ||
- (sc = sd_cd.cd_devs[unit]) == NULL ||
- (sc->sc_flags & SDF_ALIVE) == 0)
- return (ENXIO);
-
- /*
- * Convert to disk sectors. Request must be a multiple of size.
- */
- lp = sc->sc_dkdev.dk_label;
- sectorsize = lp->d_secsize;
- if ((size % sectorsize) != 0)
- return (EFAULT);
- totwrt = size / sectorsize;
- blkno = dbtob(blkno) / sectorsize; /* blkno in DEV_BSIZE units */
-
- nsects = lp->d_partitions[part].p_size;
- sectoff = lp->d_partitions[part].p_offset;
-
- /* Check transfer bounds against partition size. */
- if ((blkno < 0) || (blkno + totwrt) > nsects)
- return (EINVAL);
-
- /* Offset block number to start of partition. */
- blkno += sectoff;
-
- while (totwrt > 0) {
- nwrt = totwrt; /* XXX */
-#ifndef SD_DUMP_NOT_TRUSTED
- /*
- * Send the data. Note the `0' argument for bshift;
- * we've done the necessary conversion above.
- */
- stat = scsi_tt_write(sc->sc_dev.dv_parent->dv_unit,
- sc->sc_target, sc->sc_lun, va, nwrt * sectorsize,
- blkno, 0);
- if (stat) {
- printf("\nsddump: scsi write error 0x%x\n", stat);
- return (EIO);
- }
-#else /* SD_DUMP_NOT_TRUSTED */
- /* Lets just talk about it first. */
- printf("%s: dump addr %p, blk %d\n", sc->sc_dev.dv_xname,
- va, blkno);
- delay(500 * 1000); /* half a second */
-#endif /* SD_DUMP_NOT_TRUSTED */
-
- /* update block count */
- totwrt -= nwrt;
- blkno += nwrt;
- va += sectorsize * nwrt;
- }
- sddoingadump = 0;
- return (0);
-}
diff --git a/sys/arch/hp300/dev/spc.c b/sys/arch/hp300/dev/spc.c
new file mode 100644
index 00000000000..08e95a11182
--- /dev/null
+++ b/sys/arch/hp300/dev/spc.c
@@ -0,0 +1,276 @@
+/* $OpenBSD: spc.c,v 1.1 2004/08/03 21:46:56 miod Exp $ */
+/* $NetBSD: spc.c,v 1.2 2003/11/17 14:37:59 tsutsui Exp $ */
+
+/*
+ * Copyright (c) 2003 Izumi Tsutsui.
+ * 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, 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 ``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 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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+
+#include <machine/autoconf.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <hp300/dev/dioreg.h>
+#include <hp300/dev/diovar.h>
+#include <hp300/dev/diodevs.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsi_message.h>
+#include <scsi/scsiconf.h>
+
+#include <hp300/dev/mb89352reg.h>
+#include <hp300/dev/mb89352var.h>
+
+#include <hp300/dev/hp98265reg.h>
+#include <hp300/dev/dmareg.h>
+#include <hp300/dev/dmavar.h>
+
+int spc_dio_match(struct device *, void *, void *);
+void spc_dio_attach(struct device *, struct device *, void *);
+void spc_dio_dmastart(struct spc_softc *, void *, size_t, int);
+void spc_dio_dmadone(struct spc_softc *);
+void spc_dio_dmago(void *);
+void spc_dio_dmastop(void *);
+int spc_dio_intr(void *);
+
+#define HPSPC_ADDRESS(o) (dsc->sc_dregs + ((o) << 1) + 1)
+#define hpspc_read(o) *(volatile u_int8_t *)(HPSPC_ADDRESS(o))
+#define hpspc_write(o, v) *(volatile u_int8_t *)(HPSPC_ADDRESS(o)) = (v)
+
+struct spc_dio_softc {
+ struct spc_softc sc_spc; /* MI spc softc */
+ volatile u_int8_t *sc_dregs; /* Complete registers */
+
+ struct dmaqueue sc_dq; /* DMA job queue */
+ u_int sc_dflags; /* DMA flags */
+#define SCSI_DMA32 0x01 /* 32-bit DMA should be used */
+#define SCSI_HAVEDMA 0x02 /* controller has DMA channel */
+#define SCSI_DATAIN 0x04 /* DMA direction */
+};
+
+struct cfattach spc_ca = {
+ sizeof(struct spc_dio_softc), spc_dio_match, spc_dio_attach
+};
+
+struct cfdriver spc_cd = {
+ NULL, "spc", DV_DULL
+};
+
+int
+spc_dio_match(struct device *parent, void *vcf, void *aux)
+{
+ struct dio_attach_args *da = aux;
+
+ switch (da->da_id) {
+ case DIO_DEVICE_ID_SCSI0:
+ case DIO_DEVICE_ID_SCSI1:
+ case DIO_DEVICE_ID_SCSI2:
+ case DIO_DEVICE_ID_SCSI3:
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+spc_dio_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct spc_dio_softc *dsc = (struct spc_dio_softc *)self;
+ struct spc_softc *sc = &dsc->sc_spc;
+ struct dio_attach_args *da = aux;
+ int ipl;
+ u_int8_t id;
+
+ dsc->sc_dregs = (u_int8_t *)iomap(dio_scodetopa(da->da_scode),
+ da->da_size);
+ if (dsc->sc_dregs == NULL) {
+ printf(": can't map SCSI registers\n");
+ return;
+ }
+ sc->sc_regs = dsc->sc_dregs + SPC_OFFSET;
+
+ ipl = DIO_IPL(sc->sc_regs);
+ printf(" ipl %d: 98265A SCSI", ipl);
+
+ hpspc_write(HPSCSI_ID, 0xff);
+ DELAY(100);
+ id = hpspc_read(HPSCSI_ID);
+ if ((id & ID_WORD_DMA) == 0) {
+ printf(", 32-bit DMA");
+ dsc->sc_dflags |= SCSI_DMA32;
+ }
+ id &= ID_MASK;
+ printf(", SCSI ID %d\n", id);
+
+ sc->sc_initiator = id;
+
+ sc->sc_dma_start = spc_dio_dmastart;
+ sc->sc_dma_done = spc_dio_dmadone;
+
+ dsc->sc_dq.dq_softc = dsc;
+ dsc->sc_dq.dq_start = spc_dio_dmago;
+ dsc->sc_dq.dq_done = spc_dio_dmastop;
+
+ hpspc_write(HPSCSI_CSR, 0x00);
+ hpspc_write(HPSCSI_HCONF, 0x00);
+
+ dio_intr_establish(spc_dio_intr, (void *)dsc, ipl, IPL_BIO);
+
+ spc_attach(sc);
+
+ /* Enable SPC interrupts. */
+ hpspc_write(HPSCSI_CSR, CSR_IE);
+}
+
+void
+spc_dio_dmastart(struct spc_softc *sc, void *addr, size_t size, int datain)
+{
+ struct spc_dio_softc *dsc = (struct spc_dio_softc *)sc;
+
+ dsc->sc_dq.dq_chan = DMA0 | DMA1;
+ dsc->sc_dflags |= SCSI_HAVEDMA;
+ if (datain)
+ dsc->sc_dflags |= SCSI_DATAIN;
+ else
+ dsc->sc_dflags &= ~SCSI_DATAIN;
+
+ if (dmareq(&dsc->sc_dq) != 0)
+ /* DMA channel is available, so start DMA immediately */
+ spc_dio_dmago((void *)dsc);
+ /* else dma start function will be called later from dmafree(). */
+}
+
+void
+spc_dio_dmago(void *arg)
+{
+ struct spc_dio_softc *dsc = (struct spc_dio_softc *)arg;
+ struct spc_softc *sc = &dsc->sc_spc;
+ int len, chan;
+ u_int32_t dmaflags;
+ u_int8_t cmd;
+
+ hpspc_write(HPSCSI_HCONF, 0);
+
+ cmd = CSR_IE;
+ dmaflags = DMAGO_NOINT;
+ chan = dsc->sc_dq.dq_chan;
+ if ((dsc->sc_dflags & SCSI_DATAIN) != 0) {
+ cmd |= CSR_DMAIN;
+ dmaflags |= DMAGO_READ;
+ }
+ if ((dsc->sc_dflags & SCSI_DMA32) != 0 &&
+ ((u_int)sc->sc_dp & 3) == 0 &&
+ (sc->sc_dleft & 3) == 0) {
+ cmd |= CSR_DMA32;
+ dmaflags |= DMAGO_LWORD;
+ } else
+ dmaflags |= DMAGO_WORD;
+
+ dmago(chan, sc->sc_dp, sc->sc_dleft, dmaflags);
+
+ hpspc_write(HPSCSI_CSR, cmd);
+ cmd |= (chan == 0) ? CSR_DE0 : CSR_DE1;
+ hpspc_write(HPSCSI_CSR, cmd);
+
+ cmd = SCMD_XFR;
+ len = sc->sc_dleft;
+
+ spc_write(TCH, len >> 16);
+ spc_write(TCM, len >> 8);
+ spc_write(TCL, len);
+ spc_write(PCTL, sc->sc_phase | PCTL_BFINT_ENAB);
+ spc_write(SCMD, cmd);
+
+ sc->sc_flags |= SPC_DOINGDMA;
+}
+
+void
+spc_dio_dmadone(struct spc_softc *sc)
+{
+ struct spc_dio_softc *dsc = (struct spc_dio_softc *)sc;
+ int resid, trans;
+ u_int8_t cmd;
+
+ /* wait DMA complete */
+ if ((spc_read(SSTS) & SSTS_BUSY) != 0) {
+ int timeout = 1000; /* XXX how long? */
+ while ((spc_read(SSTS) & SSTS_BUSY) != 0) {
+ if (--timeout < 0)
+ printf("%s: DMA complete timeout\n",
+ sc->sc_dev.dv_xname);
+ DELAY(1);
+ }
+ }
+
+ if ((dsc->sc_dflags & SCSI_HAVEDMA) != 0) {
+ dmafree(&dsc->sc_dq);
+ dsc->sc_dflags &= ~SCSI_HAVEDMA;
+ }
+
+ cmd = hpspc_read(HPSCSI_CSR);
+ cmd &= ~(CSR_DE1 | CSR_DE0);
+ hpspc_write(HPSCSI_CSR, cmd);
+
+ resid = spc_read(TCH) << 16 |
+ spc_read(TCM) << 8 |
+ spc_read(TCL);
+ trans = sc->sc_dleft - resid;
+ sc->sc_dp += trans;
+ sc->sc_dleft -= trans;
+
+ sc->sc_flags &= ~SPC_DOINGDMA;
+}
+
+void
+spc_dio_dmastop(void *arg)
+{
+ struct spc_dio_softc *dsc = (struct spc_dio_softc *)arg;
+ struct spc_softc *sc = &dsc->sc_spc;
+ u_int8_t cmd;
+
+ cmd = hpspc_read(HPSCSI_CSR);
+ cmd &= ~(CSR_DE1 | CSR_DE0);
+ hpspc_write(HPSCSI_CSR, cmd);
+
+ dsc->sc_dflags &= ~SCSI_HAVEDMA;
+ sc->sc_flags &= ~SPC_DOINGDMA;
+}
+
+int
+spc_dio_intr(void *arg)
+{
+ struct spc_dio_softc *dsc = (struct spc_dio_softc *)arg;
+
+ /* if we are sharing the ipl level, this interrupt may not be for us. */
+ if ((hpspc_read(HPSCSI_CSR) & (CSR_IE | CSR_IR)) != (CSR_IE | CSR_IR))
+ return 0;
+
+ return spc_intr(arg);
+}
diff --git a/sys/arch/hp300/dev/st.c b/sys/arch/hp300/dev/st.c
deleted file mode 100644
index 937349e0ef2..00000000000
--- a/sys/arch/hp300/dev/st.c
+++ /dev/null
@@ -1,1413 +0,0 @@
-/* $OpenBSD: st.c,v 1.18 2003/12/22 20:38:07 jmc Exp $ */
-/* $NetBSD: st.c,v 1.22 1997/04/02 22:37:38 scottr Exp $ */
-
-/*
- * Copyright (c) 1996, 1997 Jason R. Thorpe. All rights reserved.
- * Copyright (c) 1990 University of Utah.
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * the Systems Programming Group of the University of Utah Computer
- * Science Department.
- *
- * 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.
- *
- * from: Utah $Hdr: st.c 1.11 92/01/21$
- *
- * @(#)st.c 8.3 (Berkeley) 1/12/94
- */
-
-/*
- * SCSI CCS (Command Command Set) tape driver.
- *
- * Specific to Exabyte:
- * mt status: residual="Mbytes to LEOM"
- * minor bit 4 [b1bbbb] (aka /dev/rst16) selects short filemarks
- * minor bit 5 [1bbbbb] (aka /dev/rst32) selects fix block mode, 1k blocks.
- *
- * Archive drive:
- * can read both QIC-24 and QIC-II. But only writes
- * QIC-24.
- *
- * Supports Archive Viper QIC-150 tape drive, but scsi.c reports selection
- * errors.
- *
- * Supports Archive Python DAT drive, but will sometimes hang machine.
- *
- * Supports HP 35450A DAT drive, but will sometimes hang machine.
- * Partitioning of tape not supported.
- * Vendor unique support has not been added.
- *
- *
- * Supports Archive VIPER (QIC-150).
- * Mostly Supports Archive PYTHON (DAT).
- * Hangs if write after spin down.
- * Need scsi.c that does connect/disconnect.
- */
-
-/*
- * support for the block device not implemented
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/file.h>
-#include <sys/proc.h>
-#include <sys/ioctl.h>
-#include <sys/tty.h>
-#include <sys/mtio.h>
-#include <sys/kernel.h>
-#include <sys/tprintf.h>
-#include <sys/device.h>
-
-#include <sys/conf.h>
-
-#include <hp300/dev/scsireg.h>
-#include <hp300/dev/scsivar.h>
-#include <hp300/dev/stvar.h>
-
-static struct scsi_fmt_cdb st_read_cmd = { 6, { CMD_READ } };
-static struct scsi_fmt_cdb st_write_cmd = { 6, { CMD_WRITE } };
-
-#define UNIT(x) (minor(x) & 3)
-#define stpunit(x) ((x) & 7)
-
-#define STDEV_NOREWIND 0x04
-#define STDEV_HIDENSITY 0x08
-#define STDEV_EXSFMK 0x10
-#define STDEV_FIXEDBLK 0x20
-
-#ifdef DEBUG
-int st_debug = 0x0000;
-#define ST_OPEN 0x0001
-#define ST_GO 0x0002
-#define ST_FMKS 0x0004
-#define ST_OPENSTAT 0x0008
-#define ST_BRESID 0x0010
-#define ST_ODDIO 0x0020
-#endif
-
-/*
- * Patchable variable. If an even length read is requested a dma transfer is
- * used. Only after the read will we find out if the read had an odd number
- * of bytes. The HP98658 hardware cannot do odd length transfers, the last
- * byte of the data will always be 0x00. Normally, the driver will complain
- * about such transfers and return EIO. However, if st_dmaoddretry is non-
- * zero, the driver will try and issue a BSR and then re-read the data using
- * 'programmed transfer mode'. In most cases this works, however for unknown
- * reasons it will hang the machine in certain cases.
- *
- * Note:
- * Odd length read requests are always done using programmed transfer mode.
- */
-int st_dmaoddretry = 0;
-
-/*
- * Exabyte only:
- * From adb can have access to fixed vs. variable length modes.
- * Use 0x400 for 1k (best capacity) fixed length records.
- * In st_open, if minor bit 4 set then 1k records are used.
- * If st_exblken is set to anything other then 0 we are in fixed length mode.
- * Minor bit 5 requests 1K fixed-length, overriding any setting of st_exblklen.
- */
-int st_exblklen = 0;
-
-/* exabyte here for adb access, set at open time */
-#define EX_CT 0x80 /* international cart - more space W/P6 */
-#define EX_ND 0x20 /* no disconnect */
-#define EX_NBE 0x08 /* no busy enable */
-#define EX_EBD 0x04 /* even byte disconnect */
-#define EX_PE 0x02 /* parity enable */
-#define EX_NAL 0x01 /* no auto load */
-int st_exvup = (EX_CT|EX_ND|EX_NBE); /* vendor unique parameters */
-
-/*
- * motion and reconnect thresholds guidelines:
- * write operation; lower motion threshold for faster transfer
- * raise reconnect threshold for slower transfer
- * read operation; lower motion threshold for slower transfer
- * raise reconnect threshold for faster transfer
- */
-int st_exmotthr = 0x80; /* motion threshold, 0x80 default */
-int st_exreconthr = 0xa0; /* reconnect threshold, 0xa0 default */
-int st_exgapthr = 7; /* gap threshold, 7 default */
-#ifdef TTI
-int st_extti = 0x01; /* bitmask of unit numbers, do extra */
- /* sensing so TTi display gets updated */
-#endif
-
-bdev_decl(st);
-cdev_decl(st);
-
-#ifdef DEBUG
-void dumpxsense(struct st_xsense *);
-void prtmodsel(struct mode_select_data *, int);
-void prtmodstat(struct mode_sense *);
-#endif /* DEBUG */
-
-static void stfinish(struct st_softc *, struct buf *);
-static void sterror(struct st_softc *, int);
-static int stmatch(struct device *, void *, void *);
-static void stattach(struct device *, struct device *, void *);
-
-struct cfattach st_ca = {
- sizeof(struct st_softc), stmatch, stattach
-};
-
-struct cfdriver st_cd = {
- NULL, "st", DV_TAPE
-};
-
-static int
-stmatch(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- struct oscsi_attach_args *osa = aux;
-
- if ((osa->osa_inqbuf->type != 0x01 || /* sequential access device */
- osa->osa_inqbuf->qual != 0x80 || /* removable media */
- (osa->osa_inqbuf->version != 0x01 &&
- osa->osa_inqbuf->version != 0x02)) &&
- (osa->osa_inqbuf->type != 0x01 || /* M4 ??! */
- /*
- * the M4 is a little too smart (ass?) for its own good:
- * qual codes:
- * 0x80: you can take the tape out (unit not online)
- * 0xf8: online and at 6250bpi
- * 0xf9: online and at 1600bpi
- */
- osa->osa_inqbuf->version != 0x09)) /* M4 tape */
- return (0);
-
- return (1);
-}
-
-static void
-stattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
-{
- struct st_softc *sc = (struct st_softc *)self;
- struct oscsi_attach_args *osa = aux;
- char vendor[9], product[17], revision[5];
- int stat;
- static int havest = 0;
-
- printf("\n");
-
- sc->sc_tab.b_actb = &sc->sc_tab.b_actf;
-
- bzero(vendor, sizeof(vendor));
- bzero(product, sizeof(product));
- bzero(revision, sizeof(revision));
-
- scsi_str(osa->osa_inqbuf->vendor_id, vendor,
- sizeof(osa->osa_inqbuf->vendor_id));
- scsi_str(osa->osa_inqbuf->product_id, product,
- sizeof(osa->osa_inqbuf->product_id));
- scsi_str(osa->osa_inqbuf->rev, revision,
- sizeof(osa->osa_inqbuf->rev));
-
- sc->sc_target = osa->osa_target;
- sc->sc_lun = osa->osa_lun;
-
- /* Initialize SCSI queue entry. */
- sc->sc_sq.sq_softc = sc;
- sc->sc_sq.sq_target = sc->sc_target;
- sc->sc_sq.sq_lun = sc->sc_lun;
- sc->sc_sq.sq_start = ststart;
- sc->sc_sq.sq_go = stgo;
- sc->sc_sq.sq_intr = stintr;
-
- if (bcmp("EXB-8200", product, 8) == 0) {
- sc->sc_tapeid = MT_ISEXABYTE;
- sc->sc_datalen[CMD_REQUEST_SENSE] = 26;
- sc->sc_datalen[CMD_INQUIRY] = 52;
- sc->sc_datalen[CMD_MODE_SELECT] = 17;
- sc->sc_datalen[CMD_MODE_SENSE] = 17;
- } else if (bcmp("VIPER 150", product, 9) == 0 ||
- bcmp("VIPER 60", product, 8) == 0) {
- sc->sc_tapeid = MT_ISVIPER1;
- sc->sc_datalen[CMD_REQUEST_SENSE] = 14;
- sc->sc_datalen[CMD_INQUIRY] = 36;
- sc->sc_datalen[CMD_MODE_SELECT] = 12;
- sc->sc_datalen[CMD_MODE_SENSE] = 12;
- } else if (bcmp("Python 25501", product, 12) == 0 ||
- bcmp("Python 28849", product, 12) == 0) {
- sc->sc_tapeid = MT_ISPYTHON;
- sc->sc_datalen[CMD_REQUEST_SENSE] = 14;
- sc->sc_datalen[CMD_INQUIRY] = 36;
- sc->sc_datalen[CMD_MODE_SELECT] = 12;
- sc->sc_datalen[CMD_MODE_SENSE] = 12;
- } else if (bcmp("HP35450A", product, 8) == 0) {
- /* XXX "extra" stat makes the HP drive happy at boot time */
- stat = scsi_test_unit_rdy(sc->sc_dev.dv_parent->dv_unit,
- sc->sc_target, sc->sc_lun);
- sc->sc_tapeid = MT_ISHPDAT;
- sc->sc_datalen[CMD_REQUEST_SENSE] = 14;
- sc->sc_datalen[CMD_INQUIRY] = 36;
- sc->sc_datalen[CMD_MODE_SELECT] = 12;
- sc->sc_datalen[CMD_MODE_SENSE] = 12;
- } else if (bcmp("123107 SCSI", product, 11) == 0 ||
- bcmp("OPEN REEL TAPE", product, 14) == 0) {
- sc->sc_tapeid = MT_ISMFOUR;
- sc->sc_datalen[CMD_REQUEST_SENSE] = 8;
- sc->sc_datalen[CMD_INQUIRY] = 5;
- sc->sc_datalen[CMD_MODE_SELECT] = 12;
- sc->sc_datalen[CMD_MODE_SENSE] = 12;
- } else {
- printf("%s: Unsupported tape device, faking it\n",
- sc->sc_dev.dv_xname);
- sc->sc_tapeid = MT_ISAR;
- sc->sc_datalen[CMD_REQUEST_SENSE] = 8;
- sc->sc_datalen[CMD_INQUIRY] = 5;
- sc->sc_datalen[CMD_MODE_SELECT] = 12;
- sc->sc_datalen[CMD_MODE_SENSE] = 12;
- }
-
- sc->sc_filepos = 0;
-
- /* load xsense */
- scsi_delay(-1);
- stxsense(sc->sc_dev.dv_parent->dv_unit, sc->sc_target, sc->sc_lun, sc);
- scsi_delay(0);
-
- /* XXX if we have a tape, we must up the delays in the HA driver */
- if (!havest) {
- havest = 1;
- scsi_delay(20000);
- }
-
- sc->sc_blkno = 0;
- sc->sc_flags = STF_ALIVE;
-}
-
-int
-stopen(dev, flag, type, p)
- dev_t dev;
- int flag, type;
- struct proc *p;
-{
- struct st_softc *sc;
- struct st_xsense *xsense;
- int count;
- int stat;
- int ctlr, slave, unit;
- struct mode_select_data msd;
- struct mode_sense mode;
- int modlen;
- int error;
- static struct scsi_fmt_cdb modsel = {
- 6,
- { CMD_MODE_SELECT, 0, 0, 0, sizeof(msd), 0 }
- };
- static struct scsi_fmt_cdb modsense = {
- 6,
- { CMD_MODE_SENSE, 0, 0, 0, sizeof(mode), 0 }
- };
-
- if (UNIT(dev) >= st_cd.cd_ndevs ||
- (sc = st_cd.cd_devs[UNIT(dev)]) == NULL ||
- (sc->sc_flags & STF_ALIVE) == 0)
- return (ENXIO);
-
- if (sc->sc_flags & STF_OPEN)
- return (EBUSY);
-
- ctlr = sc->sc_dev.dv_parent->dv_unit;
- slave = sc->sc_target;
- unit = sc->sc_lun;
- xsense = &sc->sc_sense;
-
- /*
- * Be prepared to print error messages
- */
- sc->sc_ctty = tprintf_open(p);
-
- /* do a mode sense to get current */
- modlen = sc->sc_datalen[CMD_MODE_SENSE];
- modsense.cdb[4] = modlen;
- stat = scsi_immed_command(ctlr, slave, unit, &modsense,
- (u_char *)&mode, modlen, B_READ);
-
- /* do a mode sense to get current */
- modlen = sc->sc_datalen[CMD_MODE_SENSE];
- modsense.cdb[4] = modlen;
- stat = scsi_immed_command(ctlr, slave, unit, &modsense,
- (u_char *)&mode, modlen, B_READ);
-
- /* set record length */
- switch (sc->sc_tapeid) {
- case MT_ISAR:
- sc->sc_blklen = 512;
- break;
- case MT_ISEXABYTE:
- if (minor(dev) & STDEV_FIXEDBLK)
- sc->sc_blklen = 0x400;
- else
- sc->sc_blklen = st_exblklen;
- break;
- case MT_ISHPDAT:
- sc->sc_blklen = 512;
- break;
- case MT_ISVIPER1:
- sc->sc_blklen = 512;
- break;
- case MT_ISPYTHON:
- sc->sc_blklen = 512;
- break;
- case MT_ISMFOUR:
- sc->sc_blklen = 0;
- break;
- default:
- if ((mode.md.blklen2 << 16 |
- mode.md.blklen1 << 8 |
- mode.md.blklen0) != 0)
- sc->sc_blklen = mode.md.blklen2 << 16 |
- mode.md.blklen1 << 8 |
- mode.md.blklen0;
- else
- sc->sc_blklen = 512;
- }
-
- /* setup for mode select */
- msd.rsvd1 = 0;
- msd.rsvd2 = 0;
- msd.rsvd3 = 0;
- msd.buff = 1;
- msd.speed = 0;
- msd.blkdeslen = 0x08;
- msd.density = 0;
- msd.blks2 = 0;
- msd.blks1 = 0;
- msd.blks0 = 0;
- msd.rsvd4 = 0;
- msd.blklen2 = (sc->sc_blklen >> 16) & 0xff;
- msd.blklen1 = (sc->sc_blklen >> 8) & 0xff;
- msd.blklen0 = sc->sc_blklen & 0xff;
-
- /*
- * Do we have any density problems?
- */
-
- switch (sc->sc_tapeid) {
- case MT_ISAR:
- if (minor(dev) & STDEV_HIDENSITY)
- msd.density = 0x5;
- else {
- if (flag & FWRITE) {
- uprintf("Can only write QIC-24\n");
- return(EIO);
- }
- msd.density = 0x4;
- }
- break;
- case MT_ISEXABYTE:
- if (minor(dev) & STDEV_HIDENSITY)
- uprintf("EXB-8200 density support only\n");
- msd.vupb = (u_char)st_exvup;
- msd.rsvd5 = 0;
- msd.p5 = 0;
- msd.motionthres = (u_char)st_exmotthr;
- msd.reconthres = (u_char)st_exreconthr;
- msd.gapthres = (u_char)st_exgapthr;
- break;
- case MT_ISHPDAT:
- case MT_ISVIPER1:
- case MT_ISPYTHON:
- if (minor(dev) & STDEV_HIDENSITY)
- uprintf("Only one density supported\n");
- break;
- case MT_ISMFOUR:
- break; /* XXX could do density select? */
- default:
- uprintf("Unsupported drive\n");
- return(EIO);
- }
-
- modlen = sc->sc_datalen[CMD_MODE_SELECT];
- modsel.cdb[4] = modlen;
-
- /* mode select */
- count = 0;
-retryselect:
- stat = scsi_immed_command(ctlr, slave, unit, &modsel,
- (u_char *)&msd, modlen, B_WRITE);
- /*
- * First command after power cycle, bus reset or tape change
- * will error. Try command again
- */
- if (stat == STS_CHECKCOND) {
- sc->sc_filepos = 0;
- stxsense(ctlr, slave, unit, sc);
- stat = scsi_immed_command(ctlr, slave, unit, &modsel,
- (u_char *)&msd, modlen, B_WRITE);
-#ifdef DEBUG
- if (stat && (st_debug & ST_OPEN))
- printf("stopen: stat on mode select 0x%x second try\n", stat);
-#endif
- if (stat == STS_CHECKCOND) {
- stxsense(ctlr, slave, unit, sc);
- prtkey(sc);
- }
- if (stat)
- return(EIO);
- }
- if (stat == -1 || stat == STS_BUSY) {
- /*
- * XXX it might just be that the bus is busy because
- * another tape is doing a command. This would change
- * with connect/disconnect, ie. the other drive would
- * not hold onto the bus.
- *
- * Sleep on lbolt for up to 20 minutes (max time to FSF
- * an exabyte to EOT: 16:xx minutes)
- */
- if (++count > 60*20) {
- uprintf("SCSI bus timeout\n");
- return(EBUSY);
- }
- if ((error = tsleep((caddr_t)&lbolt, PZERO | PCATCH,
- "st_scsiwait", 0)))
- return (error);
- goto retryselect;
- }
-
- /* drive ready ? */
- stat = scsi_test_unit_rdy(ctlr, slave, unit);
-
- if (stat == STS_CHECKCOND) {
- stxsense(ctlr, slave, unit, sc);
- switch (sc->sc_tapeid) {
- case MT_ISEXABYTE:
- if ((xsense->sc_xsense.key & XSK_NOTRDY) &&
- xsense->exb_xsense.tnp)
- uprintf("no cartridge\n");
- else if (xsense->sc_xsense.key & XSK_NOTRDY)
- uprintf("cartridge not loaded\n");
- else if (xsense->sc_xsense.key & XSK_UNTATTEN) {
- uprintf("new cart/power interrupt\n");
- stat = 0;
- } else if ((xsense->sc_xsense.key & XSK_UNTATTEN) &&
- xsense->exb_xsense.tnp)
- uprintf("cartridge unloading\n");
- else
- prtkey(sc);
- break;
- case MT_ISMFOUR:
- case MT_ISAR:
- if (xsense->sc_xsense.key & XSK_UNTATTEN)
- stat = scsi_test_unit_rdy(ctlr, slave, unit);
- if (stat == STS_CHECKCOND) {
- stxsense(ctlr, slave, unit, sc);
- if (xsense->sc_xsense.key)
- prtkey(sc);
- } else {
- sc->sc_filepos = 0; /* new tape */
- stat = 0;
- }
- break;
- case MT_ISHPDAT:
- case MT_ISVIPER1:
- case MT_ISPYTHON:
- if (xsense->sc_xsense.key & XSK_UNTATTEN)
- stat = scsi_test_unit_rdy(ctlr, slave, unit);
- if (stat == STS_CHECKCOND) {
- stxsense(ctlr, slave, unit, sc);
- if (xsense->sc_xsense.key)
- prtkey(sc);
- }
- break;
- default:
- uprintf("%s: not ready\n", sc->sc_dev.dv_xname);
- prtkey(sc);
- break;
- }
- }
- if (stat)
- return(EIO);
-
- /* mode sense */
- modlen = sc->sc_datalen[CMD_MODE_SENSE];
- modsense.cdb[4] = modlen;
- stat = scsi_immed_command(ctlr, slave, unit, &modsense,
- (u_char *)&mode, modlen, B_READ);
-#ifdef DEBUG
- if (st_debug & ST_OPENSTAT)
- prtmodstat(&mode);
-#endif
-
- if (stat == STS_CHECKCOND) {
- stxsense(ctlr, slave, unit, sc);
-#ifdef DEBUG
- if (st_debug & ST_OPEN)
- dumpxsense(xsense);
-#endif
- }
- if (stat)
- return(EIO);
-
- if ((flag & FWRITE) && mode.md.wp) {
- uprintf("st:%d write protected\n", UNIT(dev));
- return(EACCES);
- }
-
- /* save total number of blocks on tape */
- sc->sc_numblks = mode.md.numblk2 << 16 |
- mode.md.numblk1 << 8 |
- mode.md.numblk0;
-
- if (xsense->sc_xsense.eom && !(sc->sc_flags & STF_LEOT))
- sc->sc_filepos = 0;
-#ifdef DEBUG
- if (st_debug & ST_FMKS)
- printf("%s: open filepos = %d\n", sc->sc_dev.dv_xname,
- sc->sc_filepos);
-#endif
-
- sc->sc_flags |= (STF_OPEN);
- if (flag & FWRITE)
- sc->sc_flags |= STF_WMODE;
- sc->sc_flags &= ~STF_MOVED;
-
-#ifdef TTI
- /* make stats available, also lit up TTi display */
- sc->sc_tticntdwn = 100;
-#endif
- stxsense(ctlr, slave, unit, sc);
-
- return(0);
-}
-
-/*ARGSUSED*/
-int
-stclose(dev, flag, mode, p)
- dev_t dev;
- int flag, mode;
- struct proc *p;
-{
- struct st_softc *sc = st_cd.cd_devs[UNIT(dev)];
- int hit = 0;
-
- if ((sc->sc_flags & (STF_WMODE|STF_WRTTN)) == (STF_WMODE|STF_WRTTN)) {
- /*
- * Cartridge tapes don't do double EOFs on EOT.
- * We assume that variable-block devices use double EOF.
- */
- stcommand(dev, MTWEOF, 1);
- if (sc->sc_blklen == 0) {
- stcommand(dev, MTWEOF, 1);
- stcommand(dev, MTBSR, 1);
- }
- hit++;
- }
- if ((minor(dev) & STDEV_NOREWIND) == 0) {
- stcommand(dev, MTREW, 1);
- hit++;
- }
-#ifdef NOTDEF
- /* wait until more stable before trying [XXX Needed ?] */
- if (!hit && (sc->sc_flags & SFT_WMODE))
- /* force out any buffered write data */
- stcommand(dev, MTFSR, 0);
-#endif
- /* make stats available */
- stxsense(sc->sc_dev.dv_parent->dv_unit, sc->sc_target, sc->sc_lun, sc);
-
- sc->sc_flags &= ~(STF_OPEN|STF_WMODE|STF_WRTTN);
- tprintf_close(sc->sc_ctty);
- return(0); /* XXX */
-}
-
-void
-ststrategy(bp)
- struct buf *bp;
-{
- struct st_softc *sc;
- struct buf *dp;
- int unit, s;
-
- unit = UNIT(bp->b_dev);
- sc = st_cd.cd_devs[unit];
-
- dp = &sc->sc_tab;
- bp->b_actf = NULL;
- s = splbio();
- bp->b_actb = dp->b_actb;
- *dp->b_actb = bp;
- dp->b_actb = &bp->b_actf;
- if (dp->b_active == 0) {
- dp->b_active = 1;
- stustart(unit);
- }
- splx(s);
-}
-
-void
-stustart(unit)
- int unit;
-{
- struct st_softc *sc = st_cd.cd_devs[unit];
-
- if (scsireq(sc->sc_dev.dv_parent, &sc->sc_sq))
- ststart(sc);
-}
-
-void
-ststart(arg)
- void *arg;
-{
- struct st_softc *sc = arg;
-
- if (scsiustart(sc->sc_dev.dv_parent->dv_unit))
- stgo(arg);
-}
-
-void
-stgo(arg)
- void *arg;
-{
- struct st_softc *sc = arg;
- struct scsi_fmt_cdb *cmd;
- struct buf *bp = sc->sc_tab.b_actf;
- int pad, stat;
- long nblks;
-
- if (sc->sc_flags & STF_CMD) {
- cmd = &sc->sc_cmdstore;
- pad = 0;
- } else {
- cmd = bp->b_flags & B_READ ? &st_read_cmd : &st_write_cmd;
- if (sc->sc_blklen)
- cmd->cdb[1] |= 0x01; /* fixed mode */
- else
- cmd->cdb[1] &= 0xfe;
- if (bp->b_flags & B_READ)
- sc->sc_flags &= ~STF_WRTTN;
- else
- sc->sc_flags |= STF_WRTTN;
-
- if (sc->sc_blklen) { /* fixed mode */
- nblks = bp->b_bcount / sc->sc_blklen;
- if (bp->b_bcount % sc->sc_blklen) {
- tprintf(sc->sc_ctty,
- "%s: I/O not block aligned %d/%ld\n",
- sc->sc_dev.dv_xname, sc->sc_blklen,
- bp->b_bcount);
- cmd->cdb[1] &= 0xfe; /* force error */
- }
- } else /* variable len */
- nblks = bp->b_bcount;
-
- *(u_char *)(&cmd->cdb[2]) = (u_char) (nblks >> 16);
- *(u_char *)(&cmd->cdb[3]) = (u_char) (nblks >> 8);
- *(u_char *)(&cmd->cdb[4]) = (u_char) nblks;
- /*
- * Always Zero. We are either writing in variable
- * length mode we are writing in fixed block mode,
- * or we are going to do odd length IO and are not
- * going to use DMA.
- */
- pad = 0;
- }
-
-#ifdef DEBUG
- if (st_debug & ST_GO)
- printf("stgo: cmd len %d [0]0x%x [1]0x%x [2]0x%x [3]0x%x [4]0x%x [5]0x%x\n",
- cmd->len, cmd->cdb[0], cmd->cdb[1], cmd->cdb[2],
- cmd->cdb[3], cmd->cdb[4], cmd->cdb[5]);
-#endif
-
- sc->sc_flags |= STF_MOVED;
- if (bp->b_bcount & 1) {
-#ifdef DEBUG
- if (st_debug & ST_ODDIO)
- printf("%s: stgo: odd count %ld using manual transfer\n",
- sc->sc_dev.dv_xname, bp->b_bcount);
-#endif
- stat = scsi_tt_oddio(sc->sc_dev.dv_parent->dv_unit,
- sc->sc_target, sc->sc_lun, bp->b_un.b_addr, bp->b_bcount,
- bp->b_flags, 1);
- if (stat == 0) {
- bp->b_resid = 0;
- stfinish(sc, bp);
- }
- } else
- stat = scsigo(sc->sc_dev.dv_parent->dv_unit,
- sc->sc_target, sc->sc_lun, bp, cmd, pad);
- if (stat) {
- bp->b_error = EIO;
- bp->b_flags |= B_ERROR;
- stxsense(sc->sc_dev.dv_parent->dv_unit, sc->sc_target,
- sc->sc_lun, sc);
- sterror(sc, stat);
- stfinish(sc, bp);
- }
-}
-
-static void
-stfinish(sc, bp)
- struct st_softc *sc;
- struct buf *bp;
-{
- struct buf *dp;
-
- sc->sc_tab.b_errcnt = 0;
- if ((dp = bp->b_actf))
- dp->b_actb = bp->b_actb;
- else
- sc->sc_tab.b_actb = bp->b_actb;
- *bp->b_actb = dp;
- biodone(bp);
- scsifree(sc->sc_dev.dv_parent, &sc->sc_sq);
- if (sc->sc_tab.b_actf)
- stustart(sc->sc_dev.dv_unit);
- else
- sc->sc_tab.b_active = 0;
-}
-
-int
-stread(dev, uio, flags)
- dev_t dev;
- struct uio *uio;
- int flags;
-{
-
- return (physio(ststrategy, NULL, dev, B_READ, minphys, uio));
-}
-
-int
-stwrite(dev, uio, flags)
- dev_t dev;
- struct uio *uio;
- int flags;
-{
-
- /* XXX: check for hardware write-protect? */
- return (physio(ststrategy, NULL, dev, B_WRITE, minphys, uio));
-}
-
-/*ARGSUSED*/
-int
-stdump(dev_t dev, daddr_t blkno, caddr_t va, size_t size)
-{
- return(ENXIO);
-}
-
-/*ARGSUSED*/
-int
-stioctl(dev, cmd, data, flag, p)
- dev_t dev;
- u_long cmd;
- caddr_t data;
- int flag;
- struct proc *p;
-{
- struct st_softc *sc = st_cd.cd_devs[UNIT(dev)];
- int cnt;
- struct mtget *mtget;
- struct st_xsense *xp = &sc->sc_sense;
- struct mtop *op;
- long resid = 0; /* XXX compiler complains needlessly :-( */
-
- switch (cmd) {
-
- /* tape operation */
- case MTIOCTOP:
- op = (struct mtop *)data;
- switch (op->mt_op) {
-
- case MTBSR:
- case MTFSR:
- if (sc->sc_tapeid == MT_ISAR)
- return(ENXIO);
- case MTWEOF:
- case MTFSF:
- case MTBSF:
- cnt = (int)op->mt_count;
- break;
-
- case MTREW:
- case MTOFFL:
- cnt = 1;
- break;
-
- case MTNOP:
- return(0);
- default:
- return(EINVAL);
- }
- if (cnt <= 0)
- return(EINVAL);
- stcommand(dev, (u_int)op->mt_op, cnt);
- break;
-
- /* drive status */
- case MTIOCGET:
- mtget = (struct mtget *)data;
- stxsense(sc->sc_dev.dv_parent->dv_unit, sc->sc_target,
- sc->sc_lun, sc);
- mtget->mt_type = sc->sc_tapeid;
- mtget->mt_dsreg = 0;
- mtget->mt_erreg = ((xp->sc_xsense.valid << 15) |
- (xp->sc_xsense.filemark << 14) |
- (xp->sc_xsense.eom << 13) |
- (xp->sc_xsense.ili << 12) |
- (xp->sc_xsense.key << 8));
-
- if (sc->sc_tapeid == MT_ISEXABYTE) {
- mtget->mt_dsreg = sc->sc_flags;
- resid = (xp->exb_xsense.tplft2 << 16 |
- xp->exb_xsense.tplft1 << 8 |
- xp->exb_xsense.tplft0);
- mtget->mt_resid = resid / 1000;
- mtget->mt_erreg |= (((xp->exb_xsense.rwerrcnt2 << 16 |
- xp->exb_xsense.rwerrcnt1 << 8 |
- xp->exb_xsense.rwerrcnt0) * 100) /
- (sc->sc_numblks - resid)) & 0xff;
- } else if (xp->sc_xsense.valid) {
- resid = ((xp->sc_xsense.info1 << 24) |
- (xp->sc_xsense.info2 << 16) |
- (xp->sc_xsense.info3 << 8) |
- (xp->sc_xsense.info4));
- if (sc->sc_blklen) /* if fixed mode */
- resid *= sc->sc_blklen;
- mtget->mt_resid = resid;
- } else
- mtget->mt_resid = 0;
- break;
-
- default:
- return(ENXIO);
- }
- return(0);
-}
-
-void
-stintr(arg, stat)
- void *arg;
- int stat;
-{
- struct st_softc *sc = arg;
- struct st_xsense *xp = &sc->sc_sense;
- struct buf *bp = sc->sc_tab.b_actf;
-
-#ifdef DEBUG
- if (bp == NULL) {
- printf("%s: bp == NULL\n", sc->sc_dev.dv_xname);
- return;
- }
-#endif
- switch (stat) {
- /* scsi command completed ok */
- case 0:
- bp->b_resid = 0;
- break;
-
- /* more status */
- case STS_CHECKCOND:
- stxsense(sc->sc_dev.dv_parent->dv_unit, sc->sc_target,
- sc->sc_lun, sc);
- if (xp->sc_xsense.valid) {
- bp->b_resid = (u_long)((xp->sc_xsense.info1 << 24) |
- (xp->sc_xsense.info2 << 16) |
- (xp->sc_xsense.info3 << 8) |
- (xp->sc_xsense.info4));
- if (sc->sc_blklen) /* fixed mode */
- bp->b_resid *= sc->sc_blklen;
- }
- if (xp->sc_xsense.filemark) {
- sc->sc_filepos++;
- break;
- }
- if (xp->sc_xsense.key != XSK_NOSENCE
- && xp->sc_xsense.key != XSK_NOTUSED1
- && xp->sc_xsense.key != XSK_NOTUSEDC
- && xp->sc_xsense.key != XSK_NOTUSEDE) {
- sterror(sc, stat);
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- break;
- }
- if (xp->sc_xsense.ili) {
- /*
- * Fixed length blocks, an error.
- */
- if (sc->sc_blklen) {
- tprintf(sc->sc_ctty,
- "%s: Incorrect Length Indicator, blkcnt diff %d\n",
- sc->sc_dev.dv_xname,
- sc->sc_blklen - bp->b_resid);
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- break;
- }
- /*
- * Variable length but read more than requested,
- * an error. (XXX ??? wrong for 9 track?)
- */
- if (bp->b_resid < 0) {
- bp->b_resid = 0;
- bp->b_flags |= B_ERROR;
- bp->b_error = ENOMEM;
- break;
- }
- /*
- * Variable length and odd, may require special
- * handling.
- */
- if (bp->b_resid & 1 && (sc->sc_tapeid != MT_ISAR)) {
- /*
- * Normal behavior, treat as an error.
- */
- if (!st_dmaoddretry) {
- tprintf(sc->sc_ctty,
- "%s: Odd length read %ld\n",
- sc->sc_dev.dv_xname,
- bp->b_bcount - bp->b_resid);
- bp->b_error = EIO;
- bp->b_flags |= B_ERROR;
- break;
- }
- /*
- * Attempt to back up and re-read using oddio.
- */
-#ifdef DEBUG
- if (st_debug & ST_ODDIO)
- printf("%s: stintr odd count %ld, do BSR then oddio\n",
- sc->sc_dev.dv_xname,
- bp->b_bcount - bp->b_resid);
-#endif
- stat =
- scsi_tt_oddio(sc->sc_dev.dv_parent->dv_unit,
- sc->sc_target, sc->sc_lun, 0, -1, 0, 0);
- if (stat == 0)
- stat = scsi_tt_oddio(
- sc->sc_dev.dv_parent->dv_unit,
- sc->sc_target, sc->sc_lun,
- bp->b_un.b_addr,
- bp->b_bcount - bp->b_resid,
- bp->b_flags, 0);
- if (stat) {
- bp->b_error = EIO;
- bp->b_flags |= B_ERROR;
- stxsense(sc->sc_dev.dv_parent->dv_unit,
- sc->sc_target, sc->sc_lun, sc);
- sterror(sc, stat);
- }
- }
- break;
- }
- if (xp->sc_xsense.eom) {
- bp->b_flags |= B_ERROR;
- bp->b_error = ENOSPC;
- break;
- }
- tprintf(sc->sc_ctty, "%s: unknown scsi error\n",
- sc->sc_dev.dv_xname);
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- break;
-
- default:
- printf("%s: stintr unknown stat 0x%x\n", sc->sc_dev.dv_xname,
- stat);
- break;
- }
-#ifdef DEBUG
- if ((st_debug & ST_BRESID) && bp->b_resid != 0)
- printf("b_resid %u b_flags 0x%lx b_error 0x%x\n",
- bp->b_resid, bp->b_flags, bp->b_error);
-#endif
- /* asked for more filemarks then on tape */
- if (bp->b_resid != 0 &&
- (sc->sc_flags & STF_CMD) && sc->sc_cmd == CMD_SPACE) {
- sc->sc_filepos -= bp->b_resid;
- if (sc->sc_filepos < 0)
- sc->sc_filepos = 0;
- }
-
-#ifdef TTI
- if (st_extti & (1 << sc->sc_dev.dv_unit) &&
- sc->sc_type == MT_ISEXABYTE) /* to make display lit up */
- /*
- * XXX severe performance penality for this.
- * Try and throttle by not calling stxsense on every intr.
- * Mostly for TTi we, get a stxsense call in open and close.
- */
- if (sc->sc_tticntdwn-- == 0) {
- stxsense(sc->sc_dev.dv_parent->dv_unit,
- sc->sc_target, sc->sc_lun, sc);
- sc->sc_tticntdwn = 100;
- }
-#endif
-
- stfinish(sc, bp);
-}
-
-void
-stcommand(dev, command, cnt)
- dev_t dev;
- u_int command;
- int cnt;
-{
- struct st_softc *sc = st_cd.cd_devs[UNIT(dev)];
- struct buf *bp = &sc->sc_bufstore;
- struct scsi_fmt_cdb *cmd = &sc->sc_cmdstore;
- int cmdcnt, s;
-
- cmd->len = 6; /* all tape commands are cdb6 */
- cmd->cdb[1] = sc->sc_lun;
- cmd->cdb[2] = cmd->cdb[3] = cmd->cdb[4] = cmd->cdb[5] = 0;
- cmdcnt = 0;
-
- /*
- * XXX Assumption is that everything except Archive can take
- * repeat count in cdb block.
- */
- switch (command) {
- case MTWEOF:
- cmd->cdb[0] = CMD_WRITE_FILEMARK;
- if (sc->sc_tapeid != MT_ISAR) {
- cmdcnt = cnt;
- cnt = 1;
- } else
- cmdcnt = 1;
- *(u_char *)(&cmd->cdb[2]) = (u_char) (cmdcnt >> 16);
- *(u_char *)(&cmd->cdb[3]) = (u_char) (cmdcnt >> 8);
- *(u_char *)(&cmd->cdb[4]) = (u_char) cmdcnt;
-
- if (sc->sc_tapeid == MT_ISEXABYTE &&
- (minor(dev) & STDEV_EXSFMK)) /* short filemarks */
- cmd->cdb[5] |= 0x80;
- else
- cmd->cdb[5] &= 0x7f;
- break;
- case MTBSF:
- /* Archive can't back up, will not get to BSR case */
- if (sc->sc_tapeid == MT_ISAR) {
- if ((sc->sc_filepos - cnt) < 0) {
- stcommand(dev, MTREW, 1);
- return;
- }
- cmdcnt = sc->sc_filepos - cnt + 1;
- stcommand(dev, MTREW, 1);
- stcommand(dev, MTFSF, cmdcnt);
- return;
- }
- case MTBSR:
- case MTFSR:
- case MTFSF:
- if (command == MTBSF || command == MTBSR)
- cnt = cnt * (-1); /* backward move */
- if (command == MTFSF || command == MTBSF)
- cmd->cdb[1] |= 0x01; /* filemarks */
- else
- cmd->cdb[1] |= 0x00; /* logical blocks */
- if (sc->sc_tapeid != MT_ISAR) {
- cmdcnt = cnt;
- cnt = 1;
- } else
- cmdcnt = 1;
- *(u_char *)(&cmd->cdb[2]) = (u_char) (cmdcnt >> 16);
- *(u_char *)(&cmd->cdb[3]) = (u_char) (cmdcnt >> 8);
- *(u_char *)(&cmd->cdb[4]) = (u_char) cmdcnt;
- cmd->cdb[0] = CMD_SPACE;
- break;
- case MTREW:
- cmd->cdb[0] = CMD_REWIND;
- sc->sc_filepos = 0;
- break;
- case MTOFFL:
- cmd->cdb[0] = CMD_LOADUNLOAD;
- sc->sc_filepos = 0;
- break;
- default:
- printf("%s: stcommand bad command 0x%x\n",
- sc->sc_dev.dv_xname, command);
- }
-
- sc->sc_flags |= STF_CMD;
- sc->sc_cmd = cmd->cdb[0];
-
- sc->sc_bp = bp;
-again:
-#ifdef DEBUG
- if (st_debug & ST_FMKS)
- printf("%s: stcommand filepos %d cmdcnt %d cnt %d\n",
- sc->sc_dev.dv_xname, sc->sc_filepos, cmdcnt, cnt);
-#endif
- s = splbio();
- while (bp->b_flags & B_BUSY) {
- if (bp->b_flags & B_DONE)
- break;
- bp->b_flags |= B_WANTED;
- tsleep((caddr_t)bp, PRIBIO, "stcommand", 0);
- }
- bp->b_flags = B_BUSY|B_READ;
- splx(s);
- bp->b_dev = dev;
- bp->b_bcount = 0;
- bp->b_resid = 0;
- bp->b_blkno = 0;
- bp->b_error = 0;
- ststrategy(bp);
- biowait(bp);
- if (bp->b_flags & B_WANTED)
- wakeup((caddr_t)bp);
- bp->b_flags &= B_ERROR;
-
- if (command == MTWEOF || command == MTFSF || command == MTBSF)
- sc->sc_filepos += cmdcnt;
-
- if (--cnt > 0)
- goto again;
-
- sc->sc_flags |= STF_MOVED;
- sc->sc_flags &= ~(STF_CMD|STF_WRTTN);
-}
-
-static void
-sterror(sc, stat)
- struct st_softc *sc;
- int stat;
-{
- /* stxsense must have been called before sterror() */
- if (stat & STS_CHECKCOND)
- prtkey(sc);
- else if (stat)
- tprintf(sc->sc_ctty,
- "%s: bad scsi status 0x%x\n", sc->sc_dev.dv_xname,
- stat);
-
- if ((sc->sc_flags & STF_CMD) && sc->sc_cmd == CMD_SPACE) /* fsf */
- sc->sc_filepos--;
-}
-
-void
-stxsense(ctlr, slave, unit, sc)
- int ctlr, slave, unit;
- struct st_softc *sc;
-{
- unsigned len;
-
- len = sc->sc_datalen[CMD_REQUEST_SENSE];
- scsi_request_sense(ctlr, slave, unit, (u_char *)&sc->sc_sense, len);
-}
-
-void
-prtkey(sc)
- struct st_softc *sc;
-{
- struct st_xsense *xp = &sc->sc_sense;
-
- switch (xp->sc_xsense.key) {
- case XSK_NOSENCE:
- break;
- case XSK_NOTUSED1:
- case XSK_NOTUSEDC:
- case XSK_NOTUSEDE:
- break;
- case XSK_REVERVED:
- tprintf(sc->sc_ctty, "%s: Reserved sense key 0x%x\n",
- sc->sc_dev.dv_xname, xp->sc_xsense.key);
- break;
- case XSK_NOTRDY:
- tprintf(sc->sc_ctty, "%s: NOT READY\n", sc->sc_dev.dv_xname);
- break;
- case XSK_MEDERR:
- tprintf(sc->sc_ctty, "%s: MEDIUM ERROR\n", sc->sc_dev.dv_xname);
- break;
- case XSK_HRDWERR:
- tprintf(sc->sc_ctty, "%s: HARDWARE ERROR\n",
- sc->sc_dev.dv_xname);
- break;
- case XSK_ILLREQ:
- tprintf(sc->sc_ctty, "%s: ILLEGAL REQUEST\n",
- sc->sc_dev.dv_xname);
- break;
- case XSK_UNTATTEN:
- tprintf(sc->sc_ctty, "%s: UNIT ATTENTION\n",
- sc->sc_dev.dv_xname);
- break;
- case XSK_DATAPROT:
- tprintf(sc->sc_ctty, "%s: DATA PROTECT\n", sc->sc_dev.dv_xname);
- break;
- case XSK_BLNKCHK:
- tprintf(sc->sc_ctty, "%s: BLANK CHECK\n", sc->sc_dev.dv_xname);
- break;
- case XSK_VENDOR:
- tprintf(sc->sc_ctty, "%s: VENDER UNIQUE SENSE KEY ",
- sc->sc_dev.dv_xname);
- switch (sc->sc_tapeid) {
- case MT_ISEXABYTE:
- tprintf(sc->sc_ctty, "Exabyte: ");
- if (xp->exb_xsense.xfr)
- tprintf(sc->sc_ctty,
- "Transfer Abort Error\n");
- if (xp->exb_xsense.tmd)
- tprintf(sc->sc_ctty,
- "Tape Mark Detect Error\n");
- break;
- default:
- tprintf(sc->sc_ctty, "\n");
- }
- break;
- case XSK_CPYABORT:
- tprintf(sc->sc_ctty, "%s: COPY ABORTED\n", sc->sc_dev.dv_xname);
- break;
- case XSK_ABORTCMD:
- tprintf(sc->sc_ctty, "%s: ABORTED COMMAND\n",
- sc->sc_dev.dv_xname);
- break;
- case XSK_VOLOVER:
- tprintf(sc->sc_ctty, "%s: VOLUME OVERFLOW\n",
- sc->sc_dev.dv_xname);
- break;
- default:
- tprintf(sc->sc_ctty, "%s: unknown sense key 0x%x\n",
- sc->sc_dev.dv_xname, xp->sc_xsense.key);
- }
- if (sc->sc_tapeid == MT_ISEXABYTE) {
- if (xp->exb_xsense.bpe)
- tprintf(sc->sc_ctty, "%s: Bus Parity Error",
- sc->sc_dev.dv_xname);
- if (xp->exb_xsense.fpe)
- tprintf(sc->sc_ctty,
- "%s: Formatted Buffer Parity Error",
- sc->sc_dev.dv_xname);
- if (xp->exb_xsense.eco)
- tprintf(sc->sc_ctty, "%s: Error Counter Overflow",
- sc->sc_dev.dv_xname);
- if (xp->exb_xsense.tme)
- tprintf(sc->sc_ctty, "%s: Tape Motion Error",
- sc->sc_dev.dv_xname);
- if (xp->exb_xsense.xfr)
- tprintf(sc->sc_ctty, "%s: Transfer About Error",
- sc->sc_dev.dv_xname);
- if (xp->exb_xsense.tmd)
- tprintf(sc->sc_ctty, "%s: Tape Mark Detect Error",
- sc->sc_dev.dv_xname);
- if (xp->exb_xsense.fmke)
- tprintf(sc->sc_ctty, "%s: Filemark Error",
- sc->sc_dev.dv_xname);
- if (xp->exb_xsense.ure)
- tprintf(sc->sc_ctty, "%s: Under Run Error",
- sc->sc_dev.dv_xname);
- if (xp->exb_xsense.sse)
- tprintf(sc->sc_ctty, "%s: Servo System Error",
- sc->sc_dev.dv_xname);
- if (xp->exb_xsense.fe)
- tprintf(sc->sc_ctty, "%s: Formatter Error",
- sc->sc_dev.dv_xname);
- if (xp->exb_xsense.wseb)
- tprintf(sc->sc_ctty, "%s: WSEB Error",
- sc->sc_dev.dv_xname);
- if (xp->exb_xsense.wseo)
- tprintf(sc->sc_ctty, "%s: WSEO Error",
- sc->sc_dev.dv_xname);
- }
-}
-
-#ifdef DEBUG
-void
-dumpxsense(sensebuf)
- struct st_xsense *sensebuf;
-{
- struct st_xsense *xp = sensebuf;
-
- printf("valid 0x%x errorclass 0x%x errorcode 0x%x\n",
- xp->sc_xsense.valid,
- xp->sc_xsense.class, xp->sc_xsense.code);
- printf("seg number 0x%x\n", xp->sc_xsense.segment);
- printf("FMK 0x%x EOM 0x%x ILI 0x%x RSVD 0x%x sensekey 0x%x\n",
- xp->sc_xsense.filemark, xp->sc_xsense.eom, xp->sc_xsense.ili,
- xp->sc_xsense.rsvd, xp->sc_xsense.key);
- printf("info 0x%lx\n",
- (u_long)((xp->sc_xsense.info1<<24)|(xp->sc_xsense.info2<<16)|
- (xp->sc_xsense.info3<<8)|(xp->sc_xsense.info4)) );
- printf("ASenseL 0x%x\n", xp->sc_xsense.len);
-
- if (xp->sc_xsense.len != 0x12) /* MT_ISEXB Exabyte only ?? */
- return; /* What about others */
-
- printf("ASenseC 0x%x\n", xp->exb_xsense.addsens);
- printf("AsenseQ 0x%x\n", xp->exb_xsense.addsensq);
- printf("R/W Errors 0x%lx\n",
- (u_long)((xp->exb_xsense.rwerrcnt2<<16)|
- (xp->exb_xsense.rwerrcnt1<<8)|
- (xp->exb_xsense.rwerrcnt1)) );
- printf("PF 0x%x BPE 0x%x FPE 0x%x ME 0x%x ECO 0x%x TME 0x%x TNP 0x%x BOT 0x%x\n",
- xp->exb_xsense.pf, xp->exb_xsense.bpe, xp->exb_xsense.fpe,
- xp->exb_xsense.me, xp->exb_xsense.eco, xp->exb_xsense.tme,
- xp->exb_xsense.tnp, xp->exb_xsense.bot);
- printf("XFR 0x%x TMD 0x%x WP 0x%x FMKE 0x%x URE 0x%x WE1 0x%x SSE 0x%x FE 0x%x\n",
- xp->exb_xsense.xfr, xp->exb_xsense.tmd, xp->exb_xsense.wp,
- xp->exb_xsense.fmke, xp->exb_xsense.ure, xp->exb_xsense.we1,
- xp->exb_xsense.sse, xp->exb_xsense.fe);
- printf("WSEB 0x%x WSEO 0x%x\n",
- xp->exb_xsense.wseb, xp->exb_xsense.wseo);
- printf("Remaining Tape 0x%lx\n",
- (u_long)((xp->exb_xsense.tplft2<<16)|
- (xp->exb_xsense.tplft1<<8)|
- (xp->exb_xsense.tplft0)) );
-}
-
-void
-prtmodsel(msd, modlen)
- struct mode_select_data *msd;
- int modlen;
-{
- printf("Modsel command. len is 0x%x.\n", modlen);
- printf("rsvd1 0x%x rsvd2 0x%x rsvd3 0x%x buffered 0x%x speed 0x%x bckdeslen 0x%x\n",
- msd->rsvd1,msd->rsvd2,msd->rsvd3,msd->buff,msd->speed,msd->blkdeslen);
- printf("density 0x%x blks2 0x%x blks1 0x%x blks0 0x%x rsvd 0x%x blklen2 0x%x blklen1 0x%x blklen0 0x%x\n",
- msd->density,msd->blks2,msd->blks1,msd->blks0,msd->rsvd4,msd->blklen2,msd->blklen1,msd->blklen0);
- printf("vupb 0x%x rsvd 0x%x p5 0x%x motionthres 0x%x reconthres 0x%x gapthres 0x%x \n",
- msd->vupb,msd->rsvd5,msd->p5,msd->motionthres,msd->reconthres,msd->gapthres);
-}
-
-void
-prtmodstat(mode)
- struct mode_sense *mode;
-{
- printf("Mode Status\n");
- printf("sdl 0x%x medtype 0x%x wp 0x%x bfmd 0x%x speed 0x%x bdl 0x%x\n",
- mode->md.sdl, mode->md.medtype, mode->md.wp, mode->md.bfmd,
- mode->md.speed, mode->md.bdl);
- printf("dencod 0x%x numblk 0x%x blklen 0x%x\n",
- mode->md.dencod,
- (mode->md.numblk2<<16)|(mode->md.numblk1<<8)|(mode->md.numblk0),
- (mode->md.blklen2<<16)|(mode->md.blklen1<<8)|(mode->md.blklen0) );
- printf("ct 0x%x nd 0x%x nbe 0x%x edb 0x%x pe 0x%x nal 0x%x p5 0x%x\n",
- mode->ex.ct, mode->ex.nd, mode->ex.nbe,
- mode->ex.ebd, mode->ex.pe, mode->ex.nal, mode->ex.p5);
- printf("motionthres 0x%x reconthres 0x%x gapthres 0x%x\n",
- mode->ex.motionthres, mode->ex.reconthres, mode->ex.gapthres);
-}
-#endif /* DEBUG */
diff --git a/sys/arch/hp300/dev/stvar.h b/sys/arch/hp300/dev/stvar.h
deleted file mode 100644
index d2e3eb38f37..00000000000
--- a/sys/arch/hp300/dev/stvar.h
+++ /dev/null
@@ -1,220 +0,0 @@
-/* $OpenBSD: stvar.h,v 1.5 2003/06/02 23:27:45 millert Exp $ */
-/* $NetBSD: stvar.h,v 1.6 1997/04/02 22:37:40 scottr Exp $ */
-
-/*
- * Copyright (c) 1990 University of Utah.
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * the Systems Programming Group of the University of Utah Computer
- * Science Department.
- *
- * 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.
- *
- * @(#)stvar.h 8.1 (Berkeley) 6/10/93
- */
-
-/*
- * stvar.h scsi tape driver
- */
-struct exb_xsense {
- u_char reserved8;
- u_char reserved9;
- u_char reserved10;
- u_char reserved11;
- u_char addsens;
- u_char addsensq;
- u_char reserved14;
- u_char reserved15;
- u_char rwerrcnt2;
- u_char rwerrcnt1;
- u_char rwerrcnt0;
- u_char pf: 1,
- bpe: 1,
- fpe: 1,
- me: 1,
- eco: 1,
- tme: 1,
- tnp: 1,
- bot: 1;
- u_char xfr: 1,
- tmd: 1,
- wp: 1,
- fmke: 1,
- ure: 1,
- we1: 1,
- sse: 1,
- fe: 1;
- u_char rsvd: 6,
- wseb: 1,
- wseo: 1;
- u_char reserved22;
- u_char tplft2;
- u_char tplft1;
- u_char tplft0;
-};
-
-/* xsense sense key */
-#define XSK_NOSENCE 0x0
-#define XSK_NOTUSED1 0x1
-#define XSK_NOTRDY 0x2
-#define XSK_MEDERR 0x3
-#define XSK_HRDWERR 0x4
-#define XSK_ILLREQ 0x5
-#define XSK_UNTATTEN 0x6
-#define XSK_DATAPROT 0x7
-#define XSK_BLNKCHK 0x8
-#define XSK_VENDOR 0x9
-#define XSK_CPYABORT 0xa
-#define XSK_ABORTCMD 0xb
-#define XSK_NOTUSEDC 0xc
-#define XSK_VOLOVER 0xd
-#define XSK_NOTUSEDE 0xe
-#define XSK_REVERVED 0xf
-
-struct exb_inquiry {
- char venderunique[16];
-};
-
-struct st_mode {
- u_char sdl;
- u_char medtype;
- u_char wp: 1, /* write protect */
- bfmd: 3, /* buffered write mode */
- speed: 4;
- u_char bdl;
- u_char dencod;
- u_char numblk2; /* number of blocks */
- u_char numblk1;
- u_char numblk0;
- u_char rsvd1;
- u_char blklen2; /* block length */
- u_char blklen1;
- u_char blklen0;
-};
-
-struct st_mode_exvup {
- /* vender unique */
- u_char ct: 1, /* international cartridge */
- rs1: 1,
- nd: 1, /* no disconnect, date transfer */
- rs2: 1,
- nbe: 1, /* no busy enable */
- ebd: 1, /* even byte disconnect */
- pe: 1, /* parity enable */
- nal: 1; /* no auto load */
- u_char rsvd: 7,
- p5: 1;
- u_char motionthres;
- u_char reconthres;
- u_char gapthres;
-};
-
-struct mode_select_data {
- u_char rsvd1;
- u_char rsvd2;
- u_char rsvd3: 1,
- buff: 3,
- speed: 4;
- u_char blkdeslen;
- u_char density;
- u_char blks2;
- u_char blks1;
- u_char blks0;
- u_char rsvd4;
- u_char blklen2;
- u_char blklen1;
- u_char blklen0;
- u_char vupb;
- u_char rsvd5: 7,
- p5: 1;
- u_char motionthres;
- u_char reconthres;
- u_char gapthres;
-};
-
-struct mode_sense {
- struct st_mode md;
- struct st_mode_exvup ex;
-};
-
-#define EXDS_BITS \
-"\20\20\
-\7MOVED\6LEOT\5CMD\4WRTTN\3WMODE\2OPEN\1ALIV"
-
-#define EXER_BITS \
-"\20\20VAL\17FMK\16EOM\15ILI\14KEY3\13KEY2\12KEY1\11KEY0\
-\10RETRY7\7RETRY6\6RETRY5\5RETRY4\4RETRY3\3RETRY2\2RETRY1\1RETRY0"
-
-struct st_xsense {
- struct scsi_xsense sc_xsense; /* data from sense */
- struct exb_xsense exb_xsense; /* additional info from exabyte */
-};
-
-struct st_softc {
- struct device sc_dev;
- struct scsiqueue sc_sq;
- long sc_blkno; /* (possible block device support?) */
- long sc_resid; /* (possible block device support?) */
- int sc_flags;
- int sc_blklen; /* 0 = variable len records */
- int sc_filepos; /* file position on tape */
- long sc_numblks; /* number of blocks on tape */
- short sc_type; /* ansi scsi type */
- int sc_target;
- int sc_lun;
- short sc_tapeid; /* tape drive id */
- char sc_datalen[32]; /* additional data length on some commands */
- short sc_tticntdwn; /* interrupts between TTi display updates */
- tpr_t sc_ctty;
- struct buf *sc_bp;
- u_char sc_cmd;
- struct st_xsense sc_sense;
- struct scsi_fmt_cdb sc_cmdstore;
- struct buf sc_tab; /* buffer queue */
- struct buf sc_bufstore; /* XXX buffer storage */
-};
-
-/* softc flags */
-#define STF_ALIVE 0x0001
-#define STF_OPEN 0x0002
-#define STF_WMODE 0x0004
-#define STF_WRTTN 0x0008
-#define STF_CMD 0x0010
-#define STF_LEOT 0x0020
-#define STF_MOVED 0x0040
-
-#ifdef _KERNEL
-void stcommand(dev_t, u_int, int);
-void stustart(int);
-
-void ststart(void *);
-void stgo(void *);
-void stintr(void *, int);
-
-void stxsense(int, int, int, struct st_softc *);
-void prtkey(struct st_softc *);
-#endif /* _KERNEL */
diff --git a/sys/arch/hp300/hp300/autoconf.c b/sys/arch/hp300/hp300/autoconf.c
index 4f429cec6c8..20140db6314 100644
--- a/sys/arch/hp300/hp300/autoconf.c
+++ b/sys/arch/hp300/hp300/autoconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: autoconf.c,v 1.25 2003/06/02 23:27:45 millert Exp $ */
+/* $OpenBSD: autoconf.c,v 1.26 2004/08/03 21:46:58 miod Exp $ */
/* $NetBSD: autoconf.c,v 1.45 1999/04/10 17:31:02 kleink Exp $ */
/*
@@ -93,14 +93,14 @@
#include <hp300/dev/hilvar.h>
#include <hp300/dev/hpibvar.h>
-#include <hp300/dev/scsivar.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
/*
* The following several variables are related to
* the configuration process, and are used in initializing
* the machine.
*/
-int cold; /* if 1, still working on cold-start */
struct extent *extio;
@@ -340,16 +340,16 @@ device_register(dev, aux)
goto linkup;
}
- if (bcmp(dev->dv_xname, "fhpib", 5) == 0 ||
- bcmp(dev->dv_xname, "nhpib", 5) == 0 ||
- bcmp(dev->dv_xname, "oscsi", 5) == 0) {
+ if (strncmp(dev->dv_xname, "fhpib", 5) == 0 ||
+ strncmp(dev->dv_xname, "nhpib", 5) == 0 ||
+ strncmp(dev->dv_xname, "spc", 3) == 0) {
struct dio_attach_args *da = aux;
dd->dd_scode = da->da_scode;
goto linkup;
}
- if (bcmp(dev->dv_xname, "hd", 2) == 0) {
+ if (strncmp(dev->dv_xname, "hd", 2) == 0) {
struct hpibbus_attach_args *ha = aux;
dd->dd_slave = ha->ha_slave;
@@ -357,11 +357,13 @@ device_register(dev, aux)
goto linkup;
}
- if (bcmp(dev->dv_xname, "sd", 2) == 0) {
- struct oscsi_attach_args *osa = aux;
+ if (strncmp(dev->dv_xname, "cd", 2) == 0 ||
+ strncmp(dev->dv_xname, "sd", 2) == 0 ||
+ strncmp(dev->dv_xname, "st", 2) == 0) {
+ struct scsibus_attach_args *sa = aux;
- dd->dd_slave = osa->osa_target;
- dd->dd_punit = osa->osa_lun;
+ dd->dd_slave = sa->sa_sc_link->target;
+ dd->dd_punit = sa->sa_sc_link->lun;
goto linkup;
}
@@ -374,13 +376,13 @@ device_register(dev, aux)
linkup:
LIST_INSERT_HEAD(&dev_data_list, dd, dd_list);
- if (bcmp(dev->dv_xname, "fhpib", 5) == 0 ||
- bcmp(dev->dv_xname, "nhpib", 5) == 0) {
+ if (strncmp(dev->dv_xname, "fhpib", 5) == 0 ||
+ strncmp(dev->dv_xname, "nhpib", 5) == 0) {
dev_data_insert(dd, &dev_data_list_hpib);
return;
}
- if (bcmp(dev->dv_xname, "oscsi", 5) == 0) {
+ if (strncmp(dev->dv_xname, "spc", 3) == 0) {
dev_data_insert(dd, &dev_data_list_scsi);
return;
}
@@ -417,7 +419,9 @@ struct nam2blk {
{ "ct", 0 },
{ "hd", 2 },
{ "sd", 4 },
+ { "st", 7 },
{ "rd", 8 },
+ { "cd", 9 },
};
static int
@@ -860,16 +864,18 @@ findbootdev()
if (booted_device == NULL)
return;
+#ifdef DIAGNOSTIC
/*
* Sanity check.
*/
- if ((type == 0 && bcmp(booted_device->dv_xname, "ct", 2)) ||
- (type == 2 && bcmp(booted_device->dv_xname, "hd", 2))) {
+ if ((type == 0 && strncmp(booted_device->dv_xname, "ct", 2)) ||
+ (type == 2 && strncmp(booted_device->dv_xname, "hd", 2))) {
printf("WARNING: boot device/type mismatch!\n");
printf("device = %s, type = %d\n",
booted_device->dv_xname, type);
booted_device = NULL;
}
+#endif
return;
}
@@ -882,15 +888,19 @@ findbootdev()
if (booted_device == NULL)
return;
+#ifdef DIAGNOSTIC
/*
* Sanity check.
*/
- if ((type == 4 && bcmp(booted_device->dv_xname, "sd", 2))) {
+ if (strncmp(booted_device->dv_xname, "cd", 2) != 0 &&
+ strncmp(booted_device->dv_xname, "sd", 2) != 0 &&
+ strncmp(booted_device->dv_xname, "st", 2) != 0) {
printf("WARNING: boot device/type mismatch!\n");
printf("device = %s, type = %d\n",
booted_device->dv_xname, type);
booted_device = NULL;
}
+#endif
return;
}
@@ -925,23 +935,11 @@ findbootdev_slave(ddlist, ctlr, slave, punit)
for (dd = dev_data_list.lh_first; dd != NULL;
dd = dd->dd_list.le_next) {
/*
- * XXX We don't yet have the extra bus indirection
- * XXX for SCSI, so we have to do a little bit of
- * XXX extra work.
+ * "sd" / "st" / "cd" -> "scsibus" -> "spc"
+ * "hd" -> "hpibbus" -> "fhpib"
*/
- if (bcmp(dd->dd_dev->dv_xname, "sd", 2) == 0) {
- /*
- * "sd" -> "oscsi"
- */
- if (dd->dd_dev->dv_parent != cdd->dd_dev)
- continue;
- } else {
- /*
- * "hd" -> "hpibbus" -> "fhpib"
- */
- if (dd->dd_dev->dv_parent->dv_parent != cdd->dd_dev)
- continue;
- }
+ if (dd->dd_dev->dv_parent->dv_parent != cdd->dd_dev)
+ continue;
if (dd->dd_slave == slave &&
dd->dd_punit == punit) {
@@ -965,13 +963,13 @@ setbootdev()
*
* 0 == ct
* 2 == hd
- * 4 == sd
+ * 4 == scsi
* 6 == le
*
- * Allare bdevsw major numbers, except for le, which
- * is just special.
- *
- * We can't mount root on a tape, so we ignore those.
+ * All are bdevsw major numbers, except for le, which
+ * is just special. SCSI needs specific care since the
+ * ROM wants to see 4, but depending upon the real device
+ * we booted from, we might have a different major value.
*/
/*
@@ -999,9 +997,12 @@ setbootdev()
/*
* Determine device type.
*/
- if (bcmp(root_device->dv_xname, "hd", 2) == 0)
+ if (strncmp(root_device->dv_xname, "hd", 2) == 0)
type = 2;
- else if (bcmp(root_device->dv_xname, "sd", 2) == 0)
+ else if (strncmp(root_device->dv_xname, "cd", 2) == 0 ||
+ strncmp(root_device->dv_xname, "sd", 2) == 0 ||
+ strncmp(root_device->dv_xname, "st", 2) == 0)
+ /* force scsi disk regardless of the actual device */
type = 4;
else {
printf("WARNING: strange root device!\n");
@@ -1010,43 +1011,20 @@ setbootdev()
/*
* Get parent's info.
+ *
+ * "hd" -> "hpibbus" -> "fhpib"
+ * "sd" / "cd" / "st" -> "scsibus" -> "spc"
*/
- switch (type) {
- case 2:
- /*
- * "hd" -> "hpibbus" -> "fhpib"
- */
- for (cdd = dev_data_list_hpib.lh_first, ctlr = 0;
- cdd != NULL; cdd = cdd->dd_clist.le_next, ctlr++) {
- if (cdd->dd_dev == root_device->dv_parent->dv_parent) {
- /*
- * Found it!
- */
- bootdev = MAKEBOOTDEV(type,
- ctlr, dd->dd_slave, dd->dd_punit,
- DISKPART(rootdev));
- break;
- }
- }
- break;
-
- case 4:
- /*
- * "sd" -> "oscsi"
- */
- for (cdd = dev_data_list_scsi.lh_first, ctlr = 0;
- cdd != NULL; cdd = cdd->dd_clist.le_next, ctlr++) {
- if (cdd->dd_dev == root_device->dv_parent) {
- /*
- * Found it!
- */
- bootdev = MAKEBOOTDEV(type,
- ctlr, dd->dd_slave, dd->dd_punit,
- DISKPART(rootdev));
- break;
- }
+ for (cdd = dev_data_list_hpib.lh_first, ctlr = 0;
+ cdd != NULL; cdd = cdd->dd_clist.le_next, ctlr++) {
+ if (cdd->dd_dev == root_device->dv_parent->dv_parent) {
+ /*
+ * Found it!
+ */
+ bootdev = MAKEBOOTDEV(type, ctlr, dd->dd_slave,
+ dd->dd_punit, DISKPART(rootdev));
+ break;
}
- break;
}
out:
@@ -1086,8 +1064,7 @@ dev_data_insert(dd, ddlist)
#ifdef DIAGNOSTIC
if (dd->dd_scode < 0 || dd->dd_scode > 255) {
- printf("bogus select code for %s\n", dd->dd_dev->dv_xname);
- panic("dev_data_insert");
+ panic("bogus select code for %s", dd->dd_dev->dv_xname);
}
#endif
diff --git a/sys/arch/hp300/hp300/conf.c b/sys/arch/hp300/hp300/conf.c
index 46fb9b97a81..a95ae75b598 100644
--- a/sys/arch/hp300/hp300/conf.c
+++ b/sys/arch/hp300/hp300/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.35 2004/02/10 01:31:21 millert Exp $ */
+/* $OpenBSD: conf.c,v 1.36 2004/08/03 21:46:58 miod Exp $ */
/* $NetBSD: conf.c,v 1.39 1997/05/12 08:17:53 thorpej Exp $ */
/*-
@@ -40,17 +40,21 @@
#include <sys/conf.h>
#include <sys/vnode.h>
+#include "ccd.h"
+#include "cd.h"
+#include "ch.h"
#include "ct.h"
bdev_decl(ct);
#include "mt.h"
bdev_decl(mt);
#include "hd.h"
bdev_decl(hd);
+#include "rd.h"
#include "sd.h"
-#include "ccd.h"
-#include "vnd.h"
+#include "ss.h"
#include "st.h"
-#include "rd.h"
+#include "uk.h"
+#include "vnd.h"
struct bdevsw bdevsw[] =
{
@@ -63,12 +67,13 @@ struct bdevsw bdevsw[] =
bdev_disk_init(NVND,vnd), /* 6: vnode disk driver */
bdev_tape_init(NST,st), /* 7: SCSI tape */
bdev_disk_init(NRD,rd), /* 8: RAM disk */
- bdev_lkm_dummy(), /* 9 */
+ bdev_disk_init(NCD,cd), /* 9: SCSI CD-ROM */
bdev_lkm_dummy(), /* 10 */
bdev_lkm_dummy(), /* 11 */
bdev_lkm_dummy(), /* 12 */
bdev_lkm_dummy(), /* 13 */
bdev_lkm_dummy(), /* 14 */
+ bdev_lkm_dummy(), /* 15 */
};
int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]);
@@ -146,7 +151,7 @@ struct cdevsw cdevsw[] =
cdev_tty_init(NDCM,dcm), /* 15: 4-port serial */
cdev_tape_init(NMT,mt), /* 16: magnetic reel tape */
cdev_disk_init(NCCD,ccd), /* 17: concatenated disk */
- cdev_notdef(), /* 18 */
+ cdev_disk_init(NCD,cd), /* 18: SCSI CD-ROM */
cdev_disk_init(NVND,vnd), /* 19: vnode disk driver */
cdev_tape_init(NST,st), /* 20: SCSI tape */
cdev_fd_init(1,filedesc), /* 21: file descriptor pseudo-device */
@@ -165,9 +170,9 @@ struct cdevsw cdevsw[] =
cdev_disk_init(NRD,rd), /* 34: RAM disk */
cdev_tty_init(NAPCI,apci), /* 35: Apollo APCI UARTs */
cdev_ksyms_init(NKSYMS,ksyms), /* 36: Kernel symbols device */
- cdev_notdef(), /* 37 */
- cdev_notdef(), /* 38 */
- cdev_notdef(), /* 39 */
+ cdev_uk_init(NUK,uk), /* 37 */
+ cdev_ss_init(NSS,ss), /* 38 */
+ cdev_ch_init(NCH,ch), /* 39 */
cdev_notdef(), /* 40 */
cdev_notdef(), /* 41 */
cdev_notdef(), /* 42 */
@@ -252,7 +257,7 @@ int chrtoblktbl[] = {
/* 15 */ NODEV,
/* 16 */ NODEV,
/* 17 */ 5,
- /* 18 */ NODEV,
+ /* 18 */ 9,
/* 19 */ 6,
/* 20 */ 7,
/* 21 */ NODEV,