diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2004-08-03 21:46:59 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2004-08-03 21:46:59 +0000 |
commit | e710973823a9bbc5e904b1e829a0707e61ff21c5 (patch) | |
tree | b089733d9e628b19e64a9e7909e96308a3f8877f | |
parent | 64d5018aaa427d0e10165c038e59678b058e4f55 (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@
31 files changed, 3041 insertions, 6382 deletions
diff --git a/etc/etc.hp300/MAKEDEV b/etc/etc.hp300/MAKEDEV index a6c540c41ef..acb6c86ea07 100644 --- a/etc/etc.hp300/MAKEDEV +++ b/etc/etc.hp300/MAKEDEV @@ -31,14 +31,16 @@ # local Configuration specific devices # Disks: # ccd* Concatenated disk devices +# cd* ATAPI and SCSI CD-ROM drives # hd* HP300 HP-IB disks # rd* "rd" pseudo-disks # sd* SCSI disks, including flopticals # vnd* "file" pseudo-disk devices # Tapes: +# ch* SCSI media changers # ct* HP300 HP-IB cartridge tape drives # mt* (Magnetic) 9-track reel tape drives -# st* Exabyte tape +# st* SCSI tape drives # Terminal ports: # apci* HP400 4 port serial mux interface # dca* HP200/300 single port serial interface @@ -59,8 +61,10 @@ # lkm Loadable kernel modules interface # pf* Packet Filter # *random In-kernel random data source -# tun* Network tunnel driver +# ss* SCSI scanners # systrace* System call tracing device +# tun* Network tunnel driver +# uk* SCSI unknown devices # xfs* XFS filesystem node PATH=/sbin:/usr/sbin:/bin:/usr/bin T=$0 @@ -195,7 +199,7 @@ U=`unt $i` case $i in ramdisk) R std ct0 ct1 st0 st1 hd0 hd1 hd2 hd3 hd4 - R sd0 sd1 sd2 sd3 sd4 rd0 pty0 + R sd0 sd1 sd2 sd3 sd4 cd0 cd1 rd0 pty0 R hil grf0 apci0 ite0 dca0 dcm0 dcm1 R bpf0 bpf1 tun0 tun1 lkm random ;; @@ -311,14 +315,26 @@ xfs*) M xfs$U c 51 $U 600 ;; -systrace) - M systrace c 50 0 644 +uk*) + M uk$U c 37 $U 640 operator ;; tun*) M tun$U c 23 $U 600 ;; +systrace) + M systrace c 50 0 644 + ;; + +ss*) + M ss$U c 38 $(($U*16)) 640 operator + M nss$U c 38 $(($(($U*16))+1)) 640 operator + M enss$U c 38 $(($(($U*16))+3)) 640 operator + RMlist="$RMlist scan$U" + MKlist="$MKlist;umask 77;ln -s ss$U scan$U" + ;; + *random) n=0 for pre in " " s u p a @@ -372,11 +388,20 @@ ptm) M ptm c 52 0 666 ;; -ct*|mt*|st*) +st*) + n=$(($U*16)) + for pre in " " n e en + do + M ${pre}st$U b 7 $n 660 operator + M ${pre}rst$U c 20 $n 660 operator + n=$(($n+1)) + done + ;; + +ct*|mt*) case $i in ct*) name=ct blk=0 chr=7;; mt*) name=mt blk=1 chr=16;; - st*) name=st blk=7 chr=20;; esac case $U in [0-7]) @@ -396,6 +421,10 @@ ct*|mt*|st*) esac ;; +ch*) + M ch$U c 39 $U 660 operator + ;; + vnd*) dodisk vnd $U 6 19 $U 0 dodisk svnd $U 6 19 $U 2048 @@ -405,16 +434,20 @@ rd*) dodisk2 rd $U 8 34 $U 0 ;; +cd*) + dodisk2 cd $U 9 18 $U 0 + ;; + local) test -s $T.local && sh $T.local ;; all) - R ite0 ct0 ct1 hd0 hd1 hd2 dcm0 dcm1 dcm2 dcm3 dca0 dca1 st0 - R st1 hil grf0 ccd0 ccd1 ccd2 ccd3 vnd0 vnd1 vnd2 vnd3 sd0 sd1 - R sd2 sd3 sd4 rd0 tun0 tun1 tun2 tun3 bpf0 bpf1 bpf2 bpf3 bpf4 - R bpf5 bpf6 bpf7 bpf8 bpf9 pty0 xfs0 ptm local ppi0 apci0 - R random lkm pf systrace std fd + R ite0 ct0 ct1 hd0 hd1 hd2 dcm0 dcm1 dcm2 dcm3 dca0 dca1 hil + R grf0 ccd0 ccd1 ccd2 ccd3 vnd0 vnd1 vnd2 vnd3 sd0 sd1 sd2 sd3 + R sd4 cd0 cd1 rd0 tun0 tun1 tun2 tun3 bpf0 bpf1 bpf2 bpf3 bpf4 + R bpf5 bpf6 bpf7 bpf8 bpf9 pty0 xfs0 ss0 ch0 ptm local ppi0 + R apci0 uk0 random lkm pf systrace std st0 st1 fd ;; sd*|hd*|ccd*) diff --git a/etc/etc.hp300/MAKEDEV.md b/etc/etc.hp300/MAKEDEV.md index 871f5a32c41..cab4c45e608 100644 --- a/etc/etc.hp300/MAKEDEV.md +++ b/etc/etc.hp300/MAKEDEV.md @@ -1,5 +1,5 @@ vers(__file__, - {-$OpenBSD: MAKEDEV.md,v 1.21 2004/04/11 18:05:23 millert Exp $-}, + {-$OpenBSD: MAKEDEV.md,v 1.22 2004/08/03 21:46:46 miod Exp $-}, etc.MACHINE)dnl dnl dnl Copyright (c) 2001-2004 Todd T. Fries <todd@OpenBSD.org> @@ -20,11 +20,10 @@ dnl *** hp300 specific device scripts/descriptions dnl __devitem(ct, ct*, HP300 HP-IB cartridge tape drives,{-\&ct-})dnl __devitem(hd, {-hd*-}, HP300 HP-IB disks)dnl -_mkdev(st_hp300, ct*|mt*|st*, +_mkdev(ct, ct*|mt*, {-case $i in ct*) name=ct blk=major_ct_b chr=major_ct_c;; mt*) name=mt blk=major_mt_b chr=major_mt_c;; - st*) name=st blk=major_st_hp300_b chr=major_st_hp300_c;; esac case $U in [0-7]) @@ -42,7 +41,6 @@ _mkdev(st_hp300, ct*|mt*|st*, echo bad unit for tape in: $1 ;; esac-})dnl -__devitem(st_hp300, st*, Exabyte tape,st)dnl __devitem(grf, grf*, Raw interface to HP300 graphics devices)dnl dnl dnl @@ -53,14 +51,16 @@ _DEV(std) _DEV(local) _TITLE(dis) _DEV(ccd, 17, 5) +_DEV(cd, 18, 9) _DEV(hd, 9, 2) _DEV(rd, 34, 8) _DEV(sd, 8, 4) _DEV(vnd, 19, 6) _TITLE(tap) +_DEV(ch, 39) _DEV(ct, 7, 0) _DEV(mt, 16, 1) -_DEV(st_hp300, 20, 7) +_DEV(st, 20, 7) _TITLE(term) _DEV(apci) _DEV(dca, 12) @@ -82,15 +82,17 @@ _DEV(hil, 14) _DEV(lkm, 24) _DEV(pf, 33) _DEV(rnd, 32) -_DEV(tun, 23) +_DEV(ss, 38) _DEV(systrace, 50) +_DEV(tun, 23) +_DEV(uk, 37) _DEV(xfs, 51) dnl divert(__mddivert)dnl dnl ramdisk) _recurse std ct0 ct1 st0 st1 hd0 hd1 hd2 hd3 hd4 - _recurse sd0 sd1 sd2 sd3 sd4 rd0 pty0 + _recurse sd0 sd1 sd2 sd3 sd4 cd0 cd1 rd0 pty0 _recurse hil grf0 apci0 ite0 dca0 dcm0 dcm1 _recurse bpf0 bpf1 tun0 tun1 lkm random ;; @@ -192,7 +194,7 @@ hil) dnl target(all, ses, 0)dnl target(all, ch, 0)dnl -target(all, ss, 0, 1)dnl +target(all, ss, 0)dnl target(all, xfs, 0)dnl twrget(all, flo, fd, 0, 0B, 0C, 0D, 0E, 0F, 0G, 0H)dnl twrget(all, flo, fd, 1, 1B, 1C, 1D, 1E, 1F, 1G, 1H)dnl @@ -203,21 +205,24 @@ target(all, xy, 0, 1, 2, 3)dnl target(all, rd, 0)dnl target(all, cd, 0, 1)dnl target(all, sd, 0, 1, 2, 3, 4)dnl +target(all, st, 0, 1)dnl +target(all, uk, 0)dnl target(all, vnd, 0, 1, 2, 3)dnl target(all, ccd, 0, 1, 2, 3)dnl target( all, grf, 0)dnl dnl XXX target( all, hil, 0, 1, 2, 3, 4, 5, 6, 7)dnl target( all, hil, )dnl -twrget( all, st_hp300, st, 0, 1)dnl target( all, dca, 0, 1)dnl target( all, dcm, 0, 1, 2, 3)dnl target( all, hd, 0, 1, 2)dnl target( all, ct, 0, 1)dnl target( all, ite, 0)dnl target( all, ttye, 0, 1, 2, 3, 4, 5, 6)dnl +target(ramd, cd, 0, 1)dnl target(ramd, ct, 0, 1)dnl target(ramd, hd, 0, 1, 2)dnl target(ramd, sd, 0, 1, 2)dnl +target(ramd, st, 0, 1)dnl target(ramd, rd, 0, 1)dnl target(ramd, pty, 0)dnl target(ramd, hil, )dnl diff --git a/share/man/man4/man4.hp300/Makefile b/share/man/man4/man4.hp300/Makefile index 9a1385826d6..ed6fa56d45c 100644 --- a/share/man/man4/man4.hp300/Makefile +++ b/share/man/man4/man4.hp300/Makefile @@ -1,9 +1,9 @@ -# $OpenBSD: Makefile,v 1.8 2003/03/16 20:12:50 miod Exp $ +# $OpenBSD: Makefile,v 1.9 2004/08/03 21:46:49 miod Exp $ # from: @(#)Makefile 5.1 (Berkeley) 6/29/90 MAN= apci.4 autoconf.4 cons.4 ct.4 dca.4 dcm.4 dio.4 dvbox.4 frodo.4 gbox.4 \ - grf.4 hd.4 hil.4 hyper.4 intro.4 ite.4 le.4 mem.4 nhpib.4 oscsi.4 \ - ppi.4 rbox.4 sd.4 topcat.4 + grf.4 hd.4 hil.4 hyper.4 intro.4 ite.4 le.4 mem.4 nhpib.4 \ + ppi.4 rbox.4 spc.4 topcat.4 MLINKS= mem.4 kmem.4 MLINKS+=nhpib.4 fhpib.4 nhpib.4 hpibbus.4 MANSUBDIR=hp300 diff --git a/share/man/man4/man4.hp300/ct.4 b/share/man/man4/man4.hp300/ct.4 index 24b9e691830..b186367cbea 100644 --- a/share/man/man4/man4.hp300/ct.4 +++ b/share/man/man4/man4.hp300/ct.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ct.4,v 1.9 2003/06/02 23:30:13 millert Exp $ +.\" $OpenBSD: ct.4,v 1.10 2004/08/03 21:46:49 miod Exp $ .\ .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -96,12 +96,16 @@ through refer to streaming no-rewind interfaces. .Sh SEE ALSO .Xr mt 1 , +.Xr cd 4 , +.Xr ch 4 , .Xr hd 4 , .Xr hpibbus 4 , .Xr intro 4 , .Xr mtio 4 , .Xr sd 4 , -.Xr st 4 +.Xr ss 4 , +.Xr st 4 , +.Xr uk 4 .Sh BUGS Read and writes of less than 1024 bytes will not behave as expected. The 9145 device is currently treated as a 9144. diff --git a/share/man/man4/man4.hp300/dio.4 b/share/man/man4/man4.hp300/dio.4 index 797a379c29b..045120005c4 100644 --- a/share/man/man4/man4.hp300/dio.4 +++ b/share/man/man4/man4.hp300/dio.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: dio.4,v 1.3 2004/03/22 22:07:20 miod Exp $ +.\" $OpenBSD: dio.4,v 1.4 2004/08/03 21:46:49 miod Exp $ .\" $NetBSD: dio.4,v 1.2 2002/01/15 01:31:30 wiz Exp $ .\" .\" Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd September 10, 2001 +.Dd July 27, 2004 .Dt DIO 4 hp300 .Os .Sh NAME @@ -105,8 +105,8 @@ HP-IB interface .El .Ss SCSI interfaces .Bl -tag -width XXXXXX_4_ -offset indent -compact -.It Xr oscsi 4 -Old HP300 SCSI driver +.It Xr spc 4 +HP 98658 SCSI host adaptor .El .Sh SEE ALSO .Xr dca 4 , @@ -117,6 +117,6 @@ Old HP300 SCSI driver .Xr hyper 4 , .Xr intro 4 , .Xr le 4 , -.Xr oscsi 4 , .Xr rbox 4 , +.Xr spc 4 , .Xr topcat 4 diff --git a/share/man/man4/man4.hp300/hd.4 b/share/man/man4/man4.hp300/hd.4 index bfd7796050c..29b38741bfc 100644 --- a/share/man/man4/man4.hp300/hd.4 +++ b/share/man/man4/man4.hp300/hd.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: hd.4,v 1.11 2003/07/21 09:24:33 jmc Exp $ +.\" $OpenBSD: hd.4,v 1.12 2004/08/03 21:46:49 miod Exp $ .\" .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -315,11 +315,15 @@ An unrecoverable data error occurred during transfer of the specified block on the specified disk. .El .Sh SEE ALSO +.Xr cd 4 , +.Xr ch 4 , .Xr \&ct 4 , .Xr hpibbus 4 , .Xr intro 4 , .Xr sd 4 , -.Xr st 4 +.Xr ss 4 , +.Xr st 4 , +.Xr uk 4 .Sh BUGS The current disk partitioning is totally bogus. .Tn CS/80 diff --git a/share/man/man4/man4.hp300/intro.4 b/share/man/man4/man4.hp300/intro.4 index 163bbedb448..dde08fe2ffd 100644 --- a/share/man/man4/man4.hp300/intro.4 +++ b/share/man/man4/man4.hp300/intro.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: intro.4,v 1.19 2004/03/31 08:33:56 jmc Exp $ +.\" $OpenBSD: intro.4,v 1.20 2004/08/03 21:46:49 miod Exp $ .\" .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -29,7 +29,7 @@ .\" .\" from: @(#)intro.4 8.1 (Berkeley) 6/5/93 .\" -.Dd June 5, 1993 +.Dd July 27, 2004 .Dt INTRO 4 hp300 .Os .Sh NAME @@ -140,18 +140,14 @@ frame buffer. HP Internal Terminal Emulator. .It Xr le 4 98643 LANCE-based Ethernet interface. -.It Xr oscsi -Old HP300 SCSI interface. .It Xr ppi 4 HP-IB printer/plotter interface. .It Xr rbox 4 .Tn HP98720 .Dq Renaissance frame buffer. -.It Xr sd 4 -SCSI disk drives. -.It Xr st 4 -CCS SCSI tape drives. +.It Xr spc 4 +HP 98658 SCSI host adaptor. .It Xr topcat 4 .Tn HP98544 .Dq Topcat , diff --git a/share/man/man4/man4.hp300/oscsi.4 b/share/man/man4/man4.hp300/oscsi.4 deleted file mode 100644 index 540aeebbcf3..00000000000 --- a/share/man/man4/man4.hp300/oscsi.4 +++ /dev/null @@ -1,63 +0,0 @@ -.\" $OpenBSD: oscsi.4,v 1.1 2003/03/16 20:12:51 miod Exp $ -.\" $NetBSD: oscsi.4,v 1.2 2002/01/15 01:36:36 wiz Exp $ -.\" -.\" Copyright (c) 2001 The NetBSD Foundation, Inc. -.\" All rights reserved. -.\" -.\" This code is derived from software contributed to The NetBSD Foundation -.\" by Gregory McGarry. -.\" -.\" 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 NetBSD -.\" Foundation, Inc. and its contributors. -.\" 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. -.\" -.Dd September 11, 2001 -.Dt OSCSI 4 hp300 -.Os -.Sh NAME -.Nm oscsi -.Nd -.Tn old HP300 CCS SCSI interface -.Sh SYNOPSIS -.Cd "oscsi* at dio? scode ?" -.Cd "sd* at oscsi? target ? lun ?" -.Cd "st* at oscsi? target ? lun ?" -.Cd "ac* at oscsi? target ? lun ?" -.Sh DESCRIPTION -The -.Nm -driver supports the SCSI interface on HP 9000/3xx and 9000/4xx series -workstations. -.Sh SEE ALSO -.\".Xr ac 4 , -.Xr dio 4 , -.Xr intro 4 , -.Xr sd 4 , -.Xr st 4 -.Sh BUGS -The current interface should be replaced with the -machine-independent SCSI subsystem. diff --git a/share/man/man4/man4.hp300/sd.4 b/share/man/man4/man4.hp300/sd.4 deleted file mode 100644 index 7404ce5671f..00000000000 --- a/share/man/man4/man4.hp300/sd.4 +++ /dev/null @@ -1,154 +0,0 @@ -.\" $OpenBSD: sd.4,v 1.7 2003/11/09 16:06:07 jmc Exp $ -.\" -.\" Copyright (c) 1996 -.\" Julian Elischer <julian@freebsd.org>. 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. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.Dd January 18, 1996 -.Dt SD 4 hp300 -.Os -.Sh NAME -.Nm sd -.Nd SCSI disk driver -.Sh SYNOPSIS -.Cd "sd* at oscsi? target ? lun ?" -.Sh DESCRIPTION -The -.Nm -driver provides support for a -.Tn SCSI -disk. -It allows the disk to be divided up into a set of pseudo devices called -.Em partitions . -.Pp -When the -.Tn SCSI -adapter is probed during boot, the -.Tn SCSI -bus is scanned for devices. -Any devices found which answer as -.Sq Em Direct -type devices will be attached to the -.Nm -driver. -The devices will be attached as -.Li sdN -devices, matching their -.Tn SCSI -identifiers. -For example, a disk with -.Tn SCSI -id set to 6 will attach as -.Li sd6 . -.Sh PARTITIONING -.Xr disklabel 8 -is used to partition the drive into filesystems. -.Sh IOCTLS -The following -.Xr ioctl 2 -calls apply to -.Tn SCSI -disks as well as to other disks. -They are defined in the header file -.Aq Pa sys/disklabel.h . -.Bl -tag -width DIOCSDINFO -.\".It Dv DIOCSBAD -.\"Usually used to set up a bad-block mapping system on the disk. -.\".Tn SCSI -.\"drive incorporate their own bad-block mapping so this command is not -.\"implemented. -.It Dv DIOCGDINFO -Read, from the kernel, the in-core copy of the disklabel for the -drive. -This may be a fictitious disklabel if the drive has never -been initialized, in which case it will contain information read -from the -.Tn SCSI -inquiry commands. -.It Dv DIOCSDINFO -Give the driver a new disklabel to use. -The driver -.Em will not -write the new -disklabel to the disk. -.It Dv DIOCWLABEL -Enable or disable the driver's software -write protect of the disklabel on the disk. -.It Dv DIOCWDINFO -Give the driver a new disklabel to use. -The driver -.Em will -write the new disklabel to the disk. -.It Dv DIOCLOCK -Lock the media cartridge into the device, or unlock a cartridge previously -locked. -Used to prevent user and software eject while the media is in use. -.It Dv DIOCEJECT -Eject the media cartridge from a removable device. -.El -.Pp -In addition, the -.Tn SCSI -general -.Fn ioctl -commands may be used with the -.Nm -driver, but only against the -.Sq Li c -(whole disk) partition. -.Sh NOTES -If a removable device is attached to the -.Nm -driver, then the act of changing the media will invalidate the -disklabel and information held within the kernel. -To avoid corruption, all access to the device will be discarded until there -are no more open file descriptors referencing the device. -During this period, all new open attempts will be rejected. -When no more open file descriptors reference the device, the next -open will load a new set of parameters (including disklabel) for the drive. -.Sh FILES -.Bl -tag -width /dev/rsdXXXXX -compact -.It Pa /dev/sd Ns Ar u Ns Ar p -block mode -.Tn SCSI -disk unit -.Ar u , -partition -.Ar p -.It Pa /dev/rsd Ns Ar u Ns Ar p -raw mode -.Tn SCSI -disk unit -.Ar u , -partition -.Ar p -.El -.Sh SEE ALSO -.Xr \&ct 4 , -.Xr hd 4 , -.Xr intro 4 , -.Xr oscsi 4 , -.Xr st 4 , -.Xr disklabel 5 , -.Xr disklabel 8 diff --git a/share/man/man4/man4.hp300/spc.4 b/share/man/man4/man4.hp300/spc.4 new file mode 100644 index 00000000000..472c22fc9c0 --- /dev/null +++ b/share/man/man4/man4.hp300/spc.4 @@ -0,0 +1,59 @@ +.\" $OpenBSD: spc.4,v 1.1 2004/08/03 21:46:49 miod Exp $ +.\" $NetBSD: spc.4,v 1.1 2003/08/01 02:36:04 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. +.\" +.Dd July 27, 2004 +.Dt SPC 4 hp300 +.Os +.Sh NAME +.Nm spc +.Nd HP 98658 SCSI host adaptor driver +.Sh SYNOPSIS +.Cd "spc* at dio? scode ?" +.Pp +.Cd "scsibus* at spc?" +.Sh DESCRIPTION +The +.Nm +driver provides support for the +.Tn Fujitsu +MB87030/MB89352 +.Tn SCSI +Protocol Controller (SPC) chips, used as part of the +.Tn HP +98658 SCSI interface. +.Sh SEE ALSO +.Xr cd 4 , +.Xr ch 4 , +.Xr dio 4 , +.Xr intro 4 , +.Xr scsi 4 , +.Xr sd 4 , +.Xr ss 4 , +.Xr st 4 , +.Xr uk 4 +.Sh BUGS +Synchronous data transfers are not currently supported. diff --git a/share/man/man4/man4.hp300/st.4 b/share/man/man4/man4.hp300/st.4 deleted file mode 100644 index 16c841980c6..00000000000 --- a/share/man/man4/man4.hp300/st.4 +++ /dev/null @@ -1,241 +0,0 @@ -.\" $OpenBSD: st.4,v 1.15 2003/06/06 10:29:42 jmc Exp $ -.\" -.\" Copyright (c) 1990, 1991, 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: @(#)st.4 8.2 (Berkeley) 11/30/93 -.\" -.Dd November 30, 1993 -.Dt ST 4 hp300 -.Os -.Sh NAME -.Nm st -.Nd -.Tn CCS SCSI -tape driver -.Sh SYNOPSIS -.Cd "st* at oscsi? target ? lun ?" -.Sh DESCRIPTION -The -.Nm -driver was written especially to support the Exabyte -.Tn EXB-8200 8MM -Cartridge -Tape Subsystem. -It has several extensions specific to the Exabyte, but should support other -tape drives as long as they follow the -.Tn ANSI SCSI-I -specification. -Besides extensive use with an Exabyte, the driver has been tested with an -Archive -.Tn QIC-24 -tape drive. -The -.Nm -tape interface provides a standard tape drive interface -as described in -.Xr mtio 4 -with the following exceptions: -.Bl -enum -.It -Density is dependent on device type. -Current Exabyte hardware has only one density. -The -.Tn EXB-8500 -drive, when released, will have a high -density format of -.Tn 5.6GB . -On an Archive -.Tn QIC-24 -drive the driver reads both -.Tn QIC-11 -and -.Tn QIC-24 -formats -but writes only -.Tn QIC-24 . -.It -Only the ``raw'' interface is supported. -.El -.Pp -Special Exabyte Support: -.Pp -The -.Dv MTIOCGET -.Xr ioctl 2 -call on an Exabyte returns this structure: -.Bd -literal -struct mtget { - short mt_type; /* type of magtape device */ - short mt_dsreg; /* sc_flags */ - short mt_erreg; /* high 8 bytes error status */ - /* low 8 bytes percentage of Rewrites - if writing, ECC errors if reading */ - short mt_resid; /* Mbyte until end of tape */ -}; -.Ed -.Pp -Bit 4 in the minor device number is used -to select long filemarks or short filemarks. -A long filemark occupies 2.12 MBytes of space on the tape, while a short -filemark occupies 488 KBytes. -A long filemark includes an erase gap while the short filemark does not. -The tape can be positioned on the -.Tn BOT -side of a long filemark allowing -data to be appended with a write operation. -Since the short filemark does not contain an erase gap which would allow -writing it is considered to be non-erasable. -If either type of filemark is followed by blank tape, data may be appended -on its -.Tn EOT -side. -.Pp -Bit 5 in the minor device number selects fixed block mode with a block -size of 1K. -Variable length records are the default if bit 5 is not set. -.Pp -For unit 0 here are the effects of minor device bits 2,3,4,5. -For other units add the -.Em unit# -to each of the device names. -.Bl -column norewind density filemarks -offset indent -.Em norewind high short fixed -.Em density filemarks block mode -rst0 -nrst0 X -rst8 X -nrst8 X X -rst16 X -nrst16 X X -rst24 X X -nrst24 X X X -rst32 X -nrst32 X X -rst40 X X -nrst40 X X X -rst48 X X -nrst48 X X X -rst56 X X X -nrst56 X X X X -.El -.Sh SEE ALSO -.Xr mt 1 , -.Xr \&ct 4 , -.Xr hd 4 , -.Xr intro 4 , -.Xr mtio 4 , -.Xr oscsi 4 , -.Xr sd 4 -.Rs -.%T EXB-8200 8MM Cartridge Tape Subsystem Interface User Manual -.Re -.Sh BUGS -The -.Tn HP -98268 -.Tn SCSI -controller hardware can not do odd length -.Tn DMA -transfers. -If odd length -.Tn DMA I/O -is requested the driver will use the -"Program Transfer Mode" of the Fujitsu -.Tn MB87030 -chip. -Read requests are normally even length for which a -.Tn DMA -transfer is used. -If, however, the driver detects that an odd length read has happened -(when an even length was requested) it will issue the -.Dv EIO -error and the last byte of the read -data will be 0x00. -Odd length read requests must match the size of the requested data block -on tape. -.Pp -The following only applies when using long filemarks. -Short filemarks can not be overwritten. -.Bd -filled -offset 4n -Due to the helical scan and the erase mechanism, there is a writing -limitation on Exabyte drives. -.Dq Li tar r -or -.Dq Li tar u -will not work -.Pf ( Dq Li tar c -is ok). -One can only start writing at 1) beginning of tape, 2) on the -end of what was last written, 3) "front" side of a regular (long) filemark. -For example, you have a tape with 3 tar files. -If you want to save the first file, but overwrite the second two files with -new data, on a normal -1/4" or 1/2" drive you would do: -.Pp -.Li "mt fsf 1; tar cf /dev/nrst0 ..." -.Pp -but for an Exabyte you need to do: -.Pp -.Li "mt fsf 1; mt bsf 1; mt weof 1; tar cf /dev/nrst0 ..." -.Pp -The regular long filemark consists of an erased zone 3.8" long -(needed to begin a write). -In this case, the first filemark is rewritten in place, which creates an -erased zone -.Em after -it, clearing the -way to write more on the tape. -The erase head is not helical. -.Pp -One can position a tape to the end of what was last written by reading -until a -.Tn \*qBLANK CHECK\*q -error is returned. -Writing can be started at this point. -(This applies to both long and short filemarks.) -The tape does not become positioned somewhere down the "erased" area as -does a conventional magtape. -One can issue multiple reads at the -.Tn \*qBLANK CHECK\*q -error, but the Exabyte stays positioned at the beginning of the -blank area, ready to accept write commands. -File skip operations do not stop at blank tape and will run into old data -or run to the end of the tape, so you have to be careful not to -.Dq Li mt fsf too_many . -.Ed -.Pp -Archive support gets confused if asked to move more filemarks than there are -on the tape. -.Pp -This man page needs some work. -Some of these are not really bugs, just unavoidable consequences of the -hardware. diff --git a/share/man/man8/man8.hp300/MAKEDEV.8 b/share/man/man8/man8.hp300/MAKEDEV.8 index a398a1d204a..6f614328295 100644 --- a/share/man/man8/man8.hp300/MAKEDEV.8 +++ b/share/man/man8/man8.hp300/MAKEDEV.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: MAKEDEV.8,v 1.24 2004/06/03 18:40:17 grange Exp $ +.\" $OpenBSD: MAKEDEV.8,v 1.25 2004/08/03 21:46:51 miod Exp $ .\" .\" THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT. .\" generated from: @@ -23,7 +23,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd June 3, 2004 +.Dd July 27, 2004 .Dt MAKEDEV 8 hp300 .Os .Sh NAME @@ -78,6 +78,9 @@ Creates configuration-specific devices, by invoking the shell file .It Ar ccd* Concatenated disk devices, see .Xr ccd 4 . +.It Ar cd* +ATAPI and SCSI CD-ROM drives, see +.Xr cd 4 . .It Ar hd* HP300 HP-IB disks, see .Xr hd 4 . @@ -96,6 +99,9 @@ pseudo-disk devices, see .Pp .Sy Tapes .Bl -tag -width tenletters -compact +.It Ar ch* +SCSI media changers, see +.Xr ch 4 . .It Ar ct* HP300 HP-IB cartridge tape drives, see .Xr \&ct 4 . @@ -103,7 +109,7 @@ HP300 HP-IB cartridge tape drives, see (Magnetic) 9-track reel tape drives, see .Xr mt 4 . .It Ar st* -Exabyte tape, see +SCSI tape drives, see .Xr st 4 . .El .Pp @@ -170,12 +176,18 @@ Packet Filter, see .It Ar *random In-kernel random data source, see .Xr random 4 . -.It Ar tun* -Network tunnel driver, see -.Xr tun 4 . +.It Ar ss* +SCSI scanners, see +.Xr ss 4 . .It Ar systrace* System call tracing device, see .Xr systrace 4 . +.It Ar tun* +Network tunnel driver, see +.Xr tun 4 . +.It Ar uk* +SCSI unknown devices, see +.Xr uk 4 . .It Ar xfs* XFS filesystem node, see .Xr mount_xfs 8 . 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, |