Return to BSD News archive
Newsgroups: comp.unix.bsd Path: sserve!manuel!munnari.oz.au!uunet!spool.mu.edu!agate!tfs.com!tfs.com!julian From: julian@tfs.com (Julian Elischer) Subject: NEW SCSI SYSTEM ( Beta ) part 1 of 4 (repost) Message-ID: <1992Sep18.050542.2953@tfs.com> Organization: TRW Financial Systems Date: Fri, 18 Sep 1992 05:05:42 GMT Lines: 1955 This is the net-beta version of the scsi subsystem I've been promissing for so long. Sorry no cd-rom driver until late next week. The inclusion of this driver into a kernel does not exclude the kernel's capability to produce kernels using the old 'as' scsi drivers (but you can't have a kernel with both) I will attempt to help anybody htat has problems with this each evening or as time allows. For a good start, read scsi/README # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # ddb/db_command.c.patch # kern/kern_subr.c.patch # i386/isa/isa.h.patch # i386/isa/clock.c.patch # i386/i386/conf.c.patch # i386/conf/SCSITEST # i386/conf/devices.i386.patch # i386/conf/files.i386.patch # i386/conf/Makefile.i386.patch # scsi # scsi/README # scsi/scsiconf.h # scsi/scsiconf.c # scsi/scsi.h # echo x - ddb/db_command.c.patch sed 's/^X//' >ddb/db_command.c.patch << 'END-of-ddb/db_command.c.patch' X*** /usr/src/syschanges/sys.originals/ddb/db_command.c Thu Apr 16 00:00:20 1992 X--- /usr/src/sys.386bsd/ddb/db_command.c Sun Aug 23 16:10:49 1992 X*************** X*** 515,531 **** X args[5], args[6], args[7], args[8], args[9] ); X db_printf("%#n\n", retval); X } X- X- int X- strcmp(s1, s2) X- register const char *s1, *s2; X- { X- while (*s1 == *s2++) X- if (*s1++ == 0) X- return (0); X- return (*(unsigned char *)s1 - *(unsigned char *)--s2); X- } X- X- X- X- X--- 515,517 ---- END-of-ddb/db_command.c.patch echo x - kern/kern_subr.c.patch sed 's/^X//' >kern/kern_subr.c.patch << 'END-of-kern/kern_subr.c.patch' X*** /usr/src/syschanges/sys.originals/kern/kern_subr.c Mon Jul 13 07:24:35 1992 X--- /usr/src/sys.386bsd/kern/kern_subr.c Sun Aug 23 16:11:29 1992 X*************** X*** 199,204 **** X--- 199,220 ---- X *to = '\0'; X } X X+ X+ int X+ strcmp(s1, s2) X+ register const char *s1, *s2; X+ { X+ while (*s1 == *s2++) X+ if (*s1++ == 0) X+ return (0); X+ return (*(unsigned char *)s1 - *(unsigned char *)--s2); X+ } X+ X+ X+ X+ X+ X+ X #ifndef lint /* unused except by ct.c, other oddities XXX */ X /* X * Get next character written in by user from uio. END-of-kern/kern_subr.c.patch echo x - i386/isa/isa.h.patch sed 's/^X//' >i386/isa/isa.h.patch << 'END-of-i386/isa/isa.h.patch' X*** /usr/src/syschanges/sys.originals/i386/isa/isa.h Tue May 12 21:51:02 1992 X--- /usr/src/sys.386bsd/i386/isa/isa.h Sat Aug 22 00:23:26 1992 X*************** X*** 86,93 **** X /* 0x280 - 0x2F7 Open */ X X #define IO_COM2 0x2f8 /* COM2 i/o address */ X X! /* 0x300 - 0x36F Open */ X X #define IO_FD2 0x370 /* secondary base i/o address */ X #define IO_LPT1 0x378 /* Parallel Port #1 */ X--- 86,96 ---- X /* 0x280 - 0x2F7 Open */ X X #define IO_COM2 0x2f8 /* COM2 i/o address */ X+ /* 0x300 - 0x32F Open */ X X! #define IO_AHA0 0x330 /* adaptec 1542 default addr. */ X! #define IO_AHA1 0x334 /* adaptec 1542 default addr. */ X! /* 0x338 - 0x36F Open */ X X #define IO_FD2 0x370 /* secondary base i/o address */ X #define IO_LPT1 0x378 /* Parallel Port #1 */ END-of-i386/isa/isa.h.patch echo x - i386/isa/clock.c.patch sed 's/^X//' >i386/isa/clock.c.patch << 'END-of-i386/isa/clock.c.patch' X*** /usr/src/syschanges/sys.originals/i386/isa/clock.c Tue Dec 24 14:23:38 1991 X--- /usr/src/sys.386bsd/i386/isa/clock.c Sun Aug 23 20:27:24 1992 X*************** X*** 49,62 **** X X #define DAYST 119 X #define DAYEN 303 X X startrtclock() { X int s; X X /* initialize 8253 clock */ X outb (IO_TIMER1+3, 0x36); X! outb (IO_TIMER1, 1193182/hz); X! outb (IO_TIMER1, (1193182/hz)/256); X X /* initialize brain-dead battery powered clock */ X outb (IO_RTC, RTC_STATUSA); X--- 49,65 ---- X X #define DAYST 119 X #define DAYEN 303 X+ #define XTALSPEED 1193182 X X startrtclock() { X int s; X X+ findcpuspeed(); /* use the clock (while it's free) X+ to find the cpu speed */ X /* initialize 8253 clock */ X outb (IO_TIMER1+3, 0x36); X! outb (IO_TIMER1, XTALSPEED/hz); X! outb (IO_TIMER1, (XTALSPEED/hz)/256); X X /* initialize brain-dead battery powered clock */ X outb (IO_RTC, RTC_STATUSA); X*************** X*** 71,76 **** X--- 74,105 ---- X outb (IO_RTC+1, 0); X } X X+ unsigned int delaycount; /* calibrated loop variable (1 millisecond) */ X+ X+ #define FIRST_GUESS 0x2000 X+ findcpuspeed() X+ { X+ unsigned char low; X+ unsigned int remainder; X+ X+ /* Put counter in count down mode */ X+ outb(IO_TIMER1+3, 0x34); X+ outb(IO_TIMER1, 0xff); X+ outb(IO_TIMER1, 0xff); X+ delaycount = FIRST_GUESS; X+ spinwait(1); X+ /* Read the value left in the counter */ X+ low = inb(IO_TIMER1); /* least siginifcant */ X+ remainder = inb(IO_TIMER1); /* most significant */ X+ remainder = (remainder<<8) + low ; X+ /* Formula for delaycount is : X+ * (loopcount * timer clock speed)/ (counter ticks * 1000) X+ */ X+ delaycount = (FIRST_GUESS * (XTALSPEED/1000)) / (0xffff-remainder); X+ } X+ X+ X+ X /* convert 2 digit BCD number */ X bcd(i) X int i; X*************** X*** 204,206 **** X--- 233,249 ---- X setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL); X splnone(); X } X+ X+ X+ X+ X+ spinwait(millisecs) X+ int millisecs; /* number of milliseconds to delay */ X+ { X+ int i, j; X+ X+ for (i=0;i<millisecs;i++) X+ for (j=0;j<delaycount;j++) X+ ; X+ } X+ END-of-i386/isa/clock.c.patch echo x - i386/i386/conf.c.patch sed 's/^X//' >i386/i386/conf.c.patch << 'END-of-i386/i386/conf.c.patch' X*** /usr/src/syschanges/sys.originals/i386/i386/conf.c Sat May 30 16:48:08 1992 X--- /usr/src/sys.386bsd/i386/i386/conf.c Sat Aug 29 15:39:43 1992 X*************** X*** 74,79 **** X--- 74,107 ---- X #define assize NULL X #endif X X+ #include "sd.h" X+ #if NSD > 0 X+ int sdopen(),sdclose(),sdstrategy(),sdioctl(); X+ int /*sddump(),*/sdsize(); X+ #define sddump enxio X+ #else X+ #define sdopen enxio X+ #define sdclose enxio X+ #define sdstrategy enxio X+ #define sdioctl enxio X+ #define sddump enxio X+ #define sdsize NULL X+ #endif X+ X+ #include "st.h" X+ #if NST > 0 X+ int stopen(),stclose(),ststrategy(),stioctl(); X+ int /*stdump(),*/stsize(); X+ #define stdump enxio X+ #else X+ #define stopen enxio X+ #define stclose enxio X+ #define ststrategy enxio X+ #define stioctl enxio X+ #define stdump enxio X+ #define stsize NULL X+ #endif X+ X #include "wt.h" X #if NWT > 0 X int wtopen(),wtclose(),wtstrategy(),wtioctl(); X*************** X*** 114,121 **** X--- 142,154 ---- X fddump, fdsize, NULL }, X { wtopen, wtclose, wtstrategy, wtioctl, /*3*/ X wtdump, wtsize, B_TAPE }, X+ #if NSD > 0 X+ { sdopen, sdclose, sdstrategy, sdioctl, /*4*/ X+ sddump, sdsize, NULL }, X+ #else NSD > 0 X { asopen, asclose, asstrategy, asioctl, /*4*/ X asdump, assize, NULL }, X+ #endif NSD > 0 X }; X int nblkdev = sizeof (bdevsw) / sizeof (bdevsw[0]); X X*************** X*** 211,219 **** X--- 244,261 ---- X { pcopen, pcclose, pcread, pcwrite, /*C*/ X pcioctl, nullop, nullop, &pccons, X ttselect, pcmmap, NULL }, X+ #if NSD > 0 X+ { sdopen, sdclose, rawread, rawwrite, /*D*/ X+ sdioctl, enodev, nullop, NULL, X+ seltrue, enodev, sdstrategy }, X+ #else NSD > 0 X { asopen, asclose, rawread, rawwrite, /*D*/ X asioctl, enodev, nullop, NULL, X seltrue, enodev, asstrategy }, X+ #endif NSD > 0 X+ { stopen, stclose, rawread, rawwrite, /*E*/ X+ stioctl, enodev, nullop, NULL, X+ seltrue, enodev, ststrategy }, X }; X int nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]); X END-of-i386/i386/conf.c.patch echo x - i386/conf/SCSITEST sed 's/^X//' >i386/conf/SCSITEST << 'END-of-i386/conf/SCSITEST' X# X# SCSITEST -- Generic ISA machine -- scsi test kernel X# Xmachine "i386" Xcpu "i386" Xident SCSITEST Xtimezone 8 dst Xmaxusers 10 Xoptions INET,ISOFS,NFS Xoptions "COMPAT_43" Xoptions "TCP_COMPAT_42" X Xconfig "386bsd" root on wd0 swap on wd0 and sd0 X Xcontroller isa0 Xcontroller wd0 at isa? port "IO_WD1" bio irq 14 vector wdintr Xdisk wd0 at wd0 drive 0 Xdisk wd0 at wd0 drive 1 X Xcontroller fd0 at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr Xdisk fd0 at fd0 drive 0 Xdisk fd1 at fd0 drive 1 X Xdevice pc0 at isa? port "IO_KBD" tty irq 1 vector pcrint Xdevice npx0 at isa? port "IO_NPX" irq 13 vector npxintr Xdevice com1 at isa? port "IO_COM1" tty irq 4 vector comintr Xdevice com2 at isa? port "IO_COM2" tty irq 3 vector comintr X Xcontroller aha0 at isa? port "IO_AHA0" bio irq 11 drq 5 vector ahaintr Xcontroller aha1 at isa? port "IO_AHA1" bio irq 12 drq 7 vector ahaintr X#controller bt0 at isa? port "IO_BT0" bio irq 12 vector btintr Xcontroller scbus0 X Xdevice sd0 Xdevice sd1 Xdevice sd2 Xdevice sd3 X Xdevice st0 Xdevice st1 Xdevice st2 Xdevice st3 X Xdevice we0 at isa? port 0x280 net irq 2 iomem 0xd0000 iosiz 8192 vector weintr X X Xpseudo-device loop Xpseudo-device ether Xpseudo-device sl 2 Xpseudo-device log Xpseudo-device ddb Xpseudo-device pty 4 X Xpseudo-device swappager Xpseudo-device vnodepager Xpseudo-device devpager END-of-i386/conf/SCSITEST echo x - i386/conf/devices.i386.patch sed 's/^X//' >i386/conf/devices.i386.patch << 'END-of-i386/conf/devices.i386.patch' X*** /usr/src/syschanges/sys.originals/i386/conf/devices.i386 Thu Jun 11 14:09:16 1992 X--- /usr/src/sys.386bsd/i386/conf/devices.i386 Wed Sep 16 21:59:36 1992 X*************** X*** 2,5 **** X--- 2,6 ---- X dk 1 X fd 2 X wt 3 X+ sd 4 X as 4 END-of-i386/conf/devices.i386.patch echo x - i386/conf/files.i386.patch sed 's/^X//' >i386/conf/files.i386.patch << 'END-of-i386/conf/files.i386.patch' X*** /usr/src/syschanges/sys.originals/i386/conf/files.i386 Mon May 25 12:25:04 1992 X--- /usr/src/sys.386bsd/i386/conf/files.i386 Thu Sep 10 22:30:12 1992 X*************** X*** 25,27 **** X--- 25,33 ---- X i386/i386/db_disasm.c optional ddb X i386/i386/db_interface.c optional ddb X i386/i386/db_trace.c optional ddb X+ i386/isa/aha1542.c optional aha X+ i386/eisa/bt742a.c optional bt X+ scsi/st.c optional st X+ scsi/sd.c optional sd X+ scsi/ch.c optional ch X+ scsi/scsiconf.c optional scbus END-of-i386/conf/files.i386.patch echo x - i386/conf/Makefile.i386.patch sed 's/^X//' >i386/conf/Makefile.i386.patch << 'END-of-i386/conf/Makefile.i386.patch' X*** /usr/src/syschanges/sys.originals/i386/conf/Makefile.i386 Mon Feb 24 14:52:46 1992 X--- /usr/src/sys.386bsd/i386/conf/Makefile.i386 Mon Aug 24 13:02:30 1992 X*************** X*** 38,44 **** X SYSTEM_OBJS=locore.o ${OBJS} param.o ioconf.o conf.o X SYSTEM_DEP=Makefile symbols.sort ${SYSTEM_OBJS} X SYSTEM_LD_HEAD= @echo loading $@; rm -f $@ X! SYSTEM_LD= @${LD} -z -T FE000000 -o $@ -X ${SYSTEM_OBJS} X SYSTEM_LD_TAIL= @echo rearranging symbols; symorder symbols.sort $@; size $@; chmod 755 $@ X X %OBJS X--- 38,44 ---- X SYSTEM_OBJS=locore.o ${OBJS} param.o ioconf.o conf.o X SYSTEM_DEP=Makefile symbols.sort ${SYSTEM_OBJS} X SYSTEM_LD_HEAD= @echo loading $@; rm -f $@ X! SYSTEM_LD= @${LD} -z -T FE000000 -o $@ -X vers.o ${SYSTEM_OBJS} X SYSTEM_LD_TAIL= @echo rearranging symbols; symorder symbols.sort $@; size $@; chmod 755 $@ X X %OBJS X*************** X*** 63,71 **** X X locore.o: assym.s ${I386}/i386/locore.s machine/trap.h machine/psl.h \ X machine/pte.h vector.s ${I386}/isa/icu.s ${I386}/isa/isa.h \ X! ${I386}/isa/icu.h X ${CPP} -I. -DLOCORE ${COPTS} ${I386}/i386/locore.s | \ X ${AS} ${ASFLAGS} -o locore.o X X # the following is necessary because autoconf.o depends on #if GENERIC X autoconf.o: Makefile X--- 63,74 ---- X X locore.o: assym.s ${I386}/i386/locore.s machine/trap.h machine/psl.h \ X machine/pte.h vector.s ${I386}/isa/icu.s ${I386}/isa/isa.h \ X! ${I386}/isa/icu.h vers.o X ${CPP} -I. -DLOCORE ${COPTS} ${I386}/i386/locore.s | \ X ${AS} ${ASFLAGS} -o locore.o X+ X+ vers.c: Makefile X+ sh ../../conf/newvers.sh X X # the following is necessary because autoconf.o depends on #if GENERIC X autoconf.o: Makefile END-of-i386/conf/Makefile.i386.patch echo c - scsi mkdir scsi > /dev/null 2>&1 echo x - scsi/README sed 's/^X//' >scsi/README << 'END-of-scsi/README' XThis release consists of the following files X(relative to the base of the kernel tree) X Xddb/db_command.c.patch Xkern/kern_subr.c.patch Xi386/isa/isa.h.patch Xi386/isa/clock.c.patch Xi386/i386/conf.c.patch Xi386/conf/SCSITEST Xi386/conf/devices.i386.patch Xi386/conf/files.i386.patch Xi386/conf/Makefile.i386.patch Xscsi Xscsi/README Xscsi/scsiconf.h Xscsi/scsiconf.c Xscsi/scsi.h Xscsi/st.c Xscsi/sd.c Xi386/isa/aha1542.c X/dev/MAKEDEV X XThe patch files do the following things: X X ddb/db_command.c.patch X kern/kern_subr.c.patch XThese move the strcmp function out of ddb to a more generic place Xso I can use it even if ddb is not configured in. X X i386/isa/isa.h.patch Xdefine ports needed for the adaptec board. X X i386/isa/clock.c.patch Xadd a calibrated spinwait that can be used before the clock interrupts Xcan be used. (i.e. in boot up) X X i386/i386/conf.c.patch Xadd cdevsw and bdevsw table entries for the scsi disk and tape devices. X X i386/conf/devices.i386.patch Xdefine an sd device so I can config it for swap X X i386/conf/files.i386.patch Xdefine the files we need to compile in for this scsi system. X X i386/conf/Makefile.i386.patch XThis Makefile knows how to make the vers.c program. This should Xbecome un-needed when the patch kit fixes this bug. X X /dev/MAKEDEV XA replacement MAKEDEV that knows about these devices. X X X---------------------------------------------------------------- XThis scsi system is designed to allow the re-use of top end drivers Xsuch as disk and tape drivers, with different scsi adapters. X XAs of writing this document, There are top end drivers working for: X---------------------------------------------------------------- Xgeneric scsi disk Xgeneric scsi tape XAEG Character recognition devices * XCalera Character recognition devices * XKodak IL900 scanner * XExabyte tape changer device.** X---------------------------------------------------------------- X X XThere are also working bottom end drivers for: X---------------------------------------------------------------- Xadaptec 1542 (and 1742 in 1542 mode) Xbustec 742a ** X---------------------------------------------------------------- X X XWork is proceeding on the following bottom end drivers: X---------------------------------------------------------------- XFuture Domain (8 and 16 bit)**** hosler@tfs.com & rpr@oce.nl XWD7000**** terry@icarus.weber.edu Xseagate st01/st02**** overby@aspen.cray.com ? Xadaptec 174x *** me XUltrastore *** overby@aspen.cray.com & friend? X---------------------------------------------------------------- X* drivers not made public (proprietary.. proof that the concept works though) X** driver not yet released but working. X*** just a dream so far. X**** some amount more than just a dream so far. X X X################## Using the scsi system ################## X------------minor numbers--------------- XThis scsi system does not allocate minor numbers to devices depending Xon their SCSI IDs is any way. A devices minor number is dependant Xon the order in which it was found. Xe.g. the first tape found will become st0 (minor number 0) X the second found will become st1 (minor number 16) X the third will become st2 (minor 32) X etc. X XThese devices could be on the same scsi bus or different scsi busses. XThat would not change their minor numbers. X XIt is possible to run two different TYPES of scsi adapters at the Xsame time and have st0 on one and st1 on another. (for example) X XThere is a scheme supported in which scsi devices can be 'wired in' even Xif they are not present or powered on at probe time. (see scsiconf.c) X X--------------getting started------------ XIt should be possible to use the /dev entries for as0 as if they were X/dev entries for sd0 and the old as bootblocks should Xcontinue to work if youe are using an adaptec 1542b. X X--------------making devices------------ XA changed version of /dev/MAKEDEV is supplied that Xcan be used to make devices sd[01234] and st[01234] X Xe.g. Xcd /dev Xsh MAKEDEV sd0 sd1 sd2 st0 st1 X X XThe tape devices are as follows: Xrst0 basic raw device, will rewind on close Xnrst0 will not rewind on close Xerst0 will rewind and EJECTon close Xnerst0 will not rewind and WILL eject (some devices may rewind anyhow) X X------------future enhancements-------------- XSome people have indicated that they would like to have the SCSI ID Xencoded into the minor number in some way, and Xthis may be supported at some timein the future, using Xminor numbers greater than 128. (or maybe a different major number) X XI will also be writing (probably) a generic scsi-error Xhandling routine that will be table driven, so that the routine can Xbe removed from each individual driver. With enough care, Xtwo similar devices with different error codes (quite common) could run Xthe same driver but use different error tables. X X END-of-scsi/README echo x - scsi/scsiconf.h sed 's/^X//' >scsi/scsiconf.h << 'END-of-scsi/scsiconf.h' X/* X * Written by Julian Elischer (julian@tfs.com) X * for TRW Financial Systems for use under the MACH(2.5) operating system. X * X * TRW Financial Systems, in accordance with their agreement with Carnegie X * Mellon University, makes this software available to CMU to distribute X * or use in any manner that they see fit as long as this message is kept with X * the software. For this reason TFS also grants any other persons or X * organisations permission to use or modify this software. X * X * TFS supplies this software to be publicly redistributed X * on the understanding that TFS is not responsible for the correct X * functioning of this software in any circumstances. X * X */ X X/* X * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 X */ X Xstruct scsi_switch X{ X int (*scsi_cmd)(); X void (*scsi_minphys)(); X int (*open_target_lu)(); X int (*close_target_lu)(); X int (*adapter_info)(); X X}; X X/***********************************************\ X* The scsi debug control bits * X\***********************************************/ Xextern int scsi_debug; X#define PRINTROUTINES 0x01 X#define TRACEOPENS 0x02 X#define TRACEINTERRUPTS 0x04 X#define SHOWREQUESTS 0x08 X#define SHOWSCATGATH 0x10 X#define SHOWINQUIRY 0x20 X#define SHOWCOMMANDS 0x40 X X X/********************************/ X/* return values for scsi_cmd() */ X/********************************/ X#define SUCCESSFULLY_QUEUED 0 X#define TRY_AGAIN_LATER 1 X#define COMPLETE 2 X#define HAD_ERROR 3 X Xstruct scsi_xfer X{ X struct scsi_xfer *next; /* when free */ X int flags; X u_char adapter; X u_char targ; X u_char lu; X u_char retries; /* the number of times to retry */ X long int timeout; /* in miliseconds */ X union scsi_cmd *cmd; X int cmdlen; X u_char *data; /* either the dma address OR a uio address */ X int datalen; /* data len (blank if uio) */ X int resid; X int (*when_done)(); X int done_arg; X int done_arg2; X int error; X struct buf *bp; X struct scsi_sense_data sense; X}; X/********************************/ X/* Flag values */ X/********************************/ X#define SCSI_NOSLEEP 0x01 /* Not a user... don't sleep */ X#define SCSI_NOMASK 0x02 /* dont allow interrupts.. booting */ X#define SCSI_NOSTART 0x04 /* left over from ancient history */ X#define ITSDONE 0x10 /* the transfer is as done as it gets */ X#define INUSE 0x20 /* The scsi_xfer block is in use */ X#define SCSI_SILENT 0x40 /* Don't report errors to console */ X#define SCSI_ERR_OK 0x80 /* An error on this operation is OK. */ X#define SCSI_RESET 0x100 /* Reset the device in question */ X#define SCSI_DATA_UIO 0x200 /* The data address refers to a UIO */ X#define SCSI_DATA_IN 0x400 /* expect data to come INTO memory */ X#define SCSI_DATA_OUT 0x800 /* expect data to flow OUT of memory */ X/********************************/ X/* Error values */ X/********************************/ X#define XS_NOERROR 0x0 /* there is no error, (sense is invalid) */ X#define XS_SENSE 0x1 /* Check the returned sense for the error */ X#define XS_DRIVER_STUFFUP 0x2 /* Driver failed to perform operation */ X#define XS_TIMEOUT 0x03 /* The device timed out.. turned off? */ X#define XS_SWTIMEOUT 0x04 /* The Timeout reported was caught by SW */ X#define XS_BUSY 0x08 /* The device busy, try again later? */ X END-of-scsi/scsiconf.h echo x - scsi/scsiconf.c sed 's/^X//' >scsi/scsiconf.c << 'END-of-scsi/scsiconf.c' X/* X * Written by Julian Elischer (julian@tfs.com) X * for TRW Financial Systems for use under the MACH(2.5) operating system. X * X * TRW Financial Systems, in accordance with their agreement with Carnegie X * Mellon University, makes this software available to CMU to distribute X * or use in any manner that they see fit as long as this message is kept with X * the software. For this reason TFS also grants any other persons or X * organisations permission to use or modify this software. X * X * TFS supplies this software to be publicly redistributed X * on the understanding that TFS is not responsible for the correct X * functioning of this software in any circumstances. X * X */ X X/* X * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 X */ X X/* X$Log: X* X*/ X#include <sys/types.h> X#include "st.h" X#include "sd.h" X#include "ch.h" X X#ifdef MACH X#include <i386/machparam.h> X#include <i386at/scsi.h> X#include <i386at/scsiconf.h> X#else MACH X#ifdef __386BSD__ X#include <scsi/scsi.h> X#include <scsi/scsiconf.h> X#endif __386BSD__ X#endif MACH X X#if !defined(OSF) && !defined(__386BSD__) X#include "bll.h" X#include "cals.h" X#endif /* !defined(OSF) && !defined(__386BSD__) */ X X#if NSD > 0 Xextern sdattach(); X#endif NSD X#if NST > 0 Xextern stattach(); X#endif NST X#if NCH > 0 Xextern chattach(); X#endif NCH X#if NBLL > 0 Xextern bllattach(); X#endif NBLL X#if NCALS > 0 Xextern calsattach(); X#endif NCALS X X/***************************************************************\ X* The structure of pre-configured devices that might be turned * X* off and therefore may not show up * X\***************************************************************/ Xstruct predefined X{ X u_char scsibus; X u_char dev; X u_char lu; X int (*attach_rtn)(); X char *devname; X} Xpd[] = X{ X#ifdef EXAMPLE_PREDEFINE X#if NSD > 0 X {0,0,0,sdattach,"sd"}, /* define a disk at scsibus=0 dev=0 lu=0 */ X#endif NSD X#endif EXAMPLE_PREDEFINE X {0,9,9} /*illegal dummy end entry */ X}; X X X/***************************************************************\ X* The structure of known drivers for autoconfiguration * X\***************************************************************/ Xstatic struct scsidevs X{ X int type; X int removable; X char *manufacturer; X char *model; X char *version; X int (*attach_rtn)(); X char *devname; X char showme; /* 1 show my comparisons during boot(debug) */ X} Xknowndevs[] = { X#if NSD > 0 X { T_DIRECT,T_FIXED,"standard","any","any",sdattach,"sd" }, X { T_DIRECT,T_FIXED,"MAXTOR ","XT-4170S ","B5A ",sdattach,"mx1",0 }, X#endif NSD X#if NST > 0 X { T_SEQUENTIAL,T_REMOV,"standard","any","any",stattach,"st" }, X#endif NST X#if NCALS > 0 X { T_PROCESSOR,T_FIXED,"standard","any","any",calsattach,"cals" }, X#endif NCALS X#if NCH > 0 X { T_CHANGER,T_REMOV,"standard","any","any",chattach,"ch" }, X#endif NCH X#if NBLL > 0 X { T_PROCESSOR,T_FIXED,"AEG ","READER ","V1.0",bllattach,"bll" }, X#endif NBLL X{0} X}; X/***************************************************************\ X* Declarations * X\***************************************************************/ Xstruct predefined *scsi_get_predef(); Xstruct scsidevs *scsi_probedev(); Xstruct scsidevs *selectdev(); X X/* controls debug level within the scsi subsystem */ X/* see scsiconf.h for values */ Xint scsi_debug = 0x0; Xint scsibus = 0x0; /* This is the Nth scsibus */ X X/***************************************************************\ X* The routine called by the adapter boards to get all their * X* devices configured in. * X\***************************************************************/ Xscsi_attachdevs( unit, scsi_addr, scsi_switch) Xint unit,scsi_addr; Xstruct scsi_switch *scsi_switch; X{ X int targ,lun; X struct scsidevs *bestmatch = (struct scsidevs *)0; X struct predefined *predef; X X#ifdef KODAK_SCANNER X printf("waiting for scsi devices to settle\n"); X spinwait(1000 * 30); X#endif KODAK_SCANNER X targ = 0; X while(targ < 8) X { X if (targ == scsi_addr) X { X targ++; X continue; X } X lun = 0; X while(lun < 8) X { X predef = scsi_get_predef(scsibus,targ,lun); X bestmatch = scsi_probedev(unit,targ,lun,scsi_switch); X if((bestmatch) && (predef)) /* both exist */ X { X if(bestmatch->attach_rtn X != predef->attach_rtn) X { X printf("Clash in found/expected devices\n"); X printf("will link in FOUND\n"); X } X (*(bestmatch->attach_rtn))(unit, X targ, X lun, X scsi_switch); X } X if((bestmatch) && (!predef)) /* just FOUND */ X { X (*(bestmatch->attach_rtn))(unit, X targ, X lun, X scsi_switch); X } X if((!bestmatch) && (predef)) /* just predef */ X { X (*(predef->attach_rtn))(unit, X targ, X lun, X scsi_switch); X } X lun++; X } X targ++; X } X scsibus++; /* next time we are on the NEXT scsi bus */ X} X X/***********************************************\ X* given a target and lu, check if there is a * X* predefined device for that address * X\***********************************************/ Xstruct predefined *scsi_get_predef(unit,target,lu) Xint unit,target,lu; X{ X int upto,numents; X X numents = (sizeof(pd)/sizeof(struct predefined)) - 1; X X for(upto = 0;upto < numents;upto++) X { X if(pd[upto].scsibus != unit) X continue; X if(pd[upto].dev != target) X continue; X if(pd[upto].lu != lu) X continue; X X printf(" dev%d,lu%d: %s - PRECONFIGURED -\n" X ,target X ,lu X ,pd[upto].devname); X return(&(pd[upto])); X } X return((struct predefined *)0); X} X X/***********************************************\ X* given a target and lu, ask the device what * X* it is, and find the correct driver table * X* entry. * X\***********************************************/ Xstruct scsidevs *scsi_probedev(unit,target,lu,scsi_switch) X Xstruct scsi_switch *scsi_switch; Xint unit,target,lu; X{ X char *dtype,*desc; X struct scsi_device_inquiry inqbuf; X int len,type,remov; X char manu[32]; X char model[32]; X char version[32]; X X bzero(&inqbuf,sizeof(inqbuf)); X /***********************************************\ X * Ask the device what it is * X \***********************************************/ X#ifdef DEBUG X if((target == 0) && (lu == 0)) X scsi_debug = 0xfff; X else X scsi_debug = 0; X#endif DEBUG X if(scsi_ready( unit, X target, X lu, X scsi_switch, X SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE) X { X return(struct scsidevs *)0; X } X if(scsi_inquire(unit, X target, X lu, X scsi_switch, X &inqbuf, X SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE) X { X return(struct scsidevs *)0; X } X X /***********************************************\ X * note what BASIC type of device it is * X \***********************************************/ X if(scsi_debug & SHOWINQUIRY) X { X desc=(char *)&inqbuf; X printf("inq: %x %x %x %x %x %x %x %x %x %x %x %x %x\n", X desc[0], desc[1], desc[2], desc[3], X desc[4], desc[5], desc[6], desc[7], X desc[8], desc[9], desc[10], desc[11], X desc[12]); X } X type = inqbuf.device_type; X remov = inqbuf.removable; X switch(type) X { X case T_DIRECT: X dtype="direct"; X break; X case T_SEQUENTIAL: X dtype="sequential"; X break; X case T_PRINTER: X dtype="printer"; X break; X case T_PROCESSOR: X dtype="processor"; X break; X case T_READONLY: X dtype="readonly direct"; X break; X case T_WORM: X dtype="worm"; X break; X case T_SCANNER: X dtype="scanner"; X break; X case T_OPTICAL: X dtype="optical"; X break; X case T_CHANGER: X dtype="changer"; X break; X case T_COMM: X dtype="communication"; X break; X default: X dtype="unknown"; X break; X } X /***********************************************\ X * Then if it's advanced enough, more detailed * X * information * X \***********************************************/ X if(inqbuf.ansii_version > 0) X { X if ((len = inqbuf.additional_length X + ( (char *)inqbuf.unused X - (char *)&inqbuf)) X > (sizeof(struct scsi_device_inquiry) - 1)) X len = sizeof(struct scsi_device_inquiry) - 1; X desc=inqbuf.vendor; X desc[len-(desc - (char *)&inqbuf)] = 0; X strncpy(manu,inqbuf.vendor,8);manu[8]=0; X strncpy(model,inqbuf.product,16);model[16]=0; X strncpy(version,inqbuf.revision,4);version[4]=0; X } X else X /***********************************************\ X * If not advanced enough, use default values * X \***********************************************/ X { X desc="early protocol device"; X strncpy(manu,"unknown",8); X strncpy(model,"unknown",16); X strncpy(version,"????",4); X } X printf(" dev%d,lu%d: type %d(%s),%s '%s%s%s' scsi%d\n" X ,target X ,lu X ,type X ,dtype X ,remov?"removable":"fixed" X ,manu X ,model X ,version X ,inqbuf.ansii_version X ); X /***********************************************\ X * Try make as good a match as possible with * X * available sub drivers * X \***********************************************/ X return(selectdev(unit,target,lu,&scsi_switch, X type,remov,manu,model,version)); X} X X/***********************************************\ X* Try make as good a match as possible with * X* available sub drivers * X\***********************************************/ Xstruct scsidevs X*selectdev(unit,target,lu,dvr_switch,type,remov,manu,model,rev) Xint unit,target,lu; Xstruct scsi_switch *dvr_switch; Xint type,remov; Xchar *manu,*model,*rev; X{ X int numents = (sizeof(knowndevs)/sizeof(struct scsidevs)) - 1; X int count = 0; X int bestmatches; X struct scsidevs *bestmatch = (struct scsidevs *)0; X struct scsidevs *thisentry = knowndevs; X X thisentry--; X while( count++ < numents) X { X thisentry++; X if(type != thisentry->type) X { X continue; X } X if(bestmatches < 1) X { X bestmatches = 1; X bestmatch = thisentry; X } X if(remov != thisentry->removable) X { X continue; X } X if(bestmatches < 2) X { X bestmatches = 2; X bestmatch = thisentry; X } X if(thisentry->showme) X printf("\n%s-\n%s-",thisentry->manufacturer, manu); X if(strcmp(thisentry->manufacturer, manu)) X { X continue; X } X if(bestmatches < 3) X { X bestmatches = 3; X bestmatch = thisentry; X } X if(thisentry->showme) X printf("\n%s-\n%s-",thisentry->model, model); X if(strcmp(thisentry->model, model)) X { X continue; X } X if(bestmatches < 4) X { X bestmatches = 4; X bestmatch = thisentry; X } X if(thisentry->showme) X printf("\n%s-\n%s-",thisentry->version, rev); X if(strcmp(thisentry->version, rev)) X { X continue; X } X if(bestmatches < 5) X { X bestmatches = 5; X bestmatch = thisentry; X break; X } X } X return(bestmatch); X} X Xstatic int recurse = 0; X/***********************************************\ X* Do a scsi operation asking a device if it is * X* ready. Use the scsi_cmd routine in the switch * X* table. * X\***********************************************/ Xscsi_ready(unit,target,lu,scsi_switch, flags) Xstruct scsi_switch *scsi_switch; X{ X union scsi_cmd scsi_cmd; X struct scsi_xfer scsi_xfer; X volatile int rval; X int key; X X bzero(&scsi_cmd, sizeof(scsi_cmd)); X bzero(&scsi_xfer, sizeof(scsi_xfer)); X scsi_cmd.generic.opcode = TEST_UNIT_READY; X X scsi_xfer.flags=flags | INUSE; X scsi_xfer.adapter=unit; X scsi_xfer.targ=target; X scsi_xfer.lu=lu; X scsi_xfer.cmd=&scsi_cmd; X scsi_xfer.retries=8; X scsi_xfer.timeout=10000; X scsi_xfer.cmdlen=sizeof(struct scsi_inquiry); X scsi_xfer.data=0; X scsi_xfer.datalen=0; X scsi_xfer.resid=0; X scsi_xfer.when_done=0; X scsi_xfer.done_arg=0; Xretry: scsi_xfer.error=0; X /*******************************************************\ X * do not use interrupts * X \*******************************************************/ X rval = (*(scsi_switch->scsi_cmd))(&scsi_xfer); X if (rval != COMPLETE) X { X if(scsi_debug) X { X printf("scsi error, rval = 0x%x\n",rval); X printf("code from driver: 0x%x\n",scsi_xfer.error); X } X switch(scsi_xfer.error) X { X case XS_SENSE: X /*******************************************************\ X * Any sense value is illegal except UNIT ATTENTION * X * In which case we need to check again to get the * X * correct response. * X *( especially exabytes) * X \*******************************************************/ X if(scsi_xfer.sense.error_class == 7 ) X { X key = scsi_xfer.sense.ext.extended.sense_key ; X switch(key) X { X case 2: /* not ready BUT PRESENT! */ X return(COMPLETE); X case 6: X for(rval = 0 ;rval < 1000000 ;rval++); X if(scsi_xfer.retries--) X { X scsi_xfer.flags &= ~ITSDONE; X goto retry; X } X return(COMPLETE); X default: X if(scsi_debug) X printf("%d:%d,key=%x.", X target,lu,key); X } X } X return(HAD_ERROR); X case XS_BUSY: X for(rval = 0 ;rval < 1000000 ;rval++); X if(scsi_xfer.retries--) X { X scsi_xfer.flags &= ~ITSDONE; X goto retry; X } X return(COMPLETE); /* it's busy so it's there */ X case XS_TIMEOUT: X default: X return(HAD_ERROR); X } X } X return(COMPLETE); X} X/***********************************************\ X* Do a scsi operation asking a device what it is* X* Use the scsi_cmd routine in the switch table. * X\***********************************************/ Xscsi_inquire(unit,target,lu,scsi_switch,inqbuf, flags) Xstruct scsi_switch *scsi_switch; Xu_char *inqbuf; X{ X union scsi_cmd scsi_cmd; X struct scsi_xfer scsi_xfer; X volatile int rval; X X bzero(&scsi_cmd, sizeof(scsi_cmd)); X bzero(&scsi_xfer, sizeof(scsi_xfer)); X scsi_cmd.generic.opcode = INQUIRY; X scsi_cmd.inquiry.length = sizeof(struct scsi_device_inquiry); X X scsi_xfer.flags=flags | SCSI_DATA_IN | INUSE; X scsi_xfer.adapter=unit; X scsi_xfer.targ=target; X scsi_xfer.lu=lu; X scsi_xfer.retries=8; X scsi_xfer.timeout=10000; X scsi_xfer.cmd=&scsi_cmd; X scsi_xfer.cmdlen= sizeof(struct scsi_inquiry); X scsi_xfer.data=inqbuf; X scsi_xfer.datalen=sizeof(struct scsi_device_inquiry); X scsi_xfer.resid=sizeof(struct scsi_device_inquiry); X scsi_xfer.when_done=0; X scsi_xfer.done_arg=0; Xretry: scsi_xfer.error=0; X /*******************************************************\ X * do not use interrupts * X \*******************************************************/ X if ((*(scsi_switch->scsi_cmd))(&scsi_xfer) != COMPLETE) X { X switch(scsi_xfer.error) X { X case XS_SENSE: X /*******************************************************\ X * Any sense value is illegal except UNIT ATTENTION * X * In which case we need to check again to get the * X * correct response. * X *( especially exabytes) * X \*******************************************************/ X if((scsi_xfer.sense.error_class == 7 ) X && (scsi_xfer.sense.ext.extended.sense_key == 6)) X { /* it's changed so it's there */ X for(rval = 0 ;rval < 1000000 ;rval++); X { X scsi_xfer.flags &= ~ITSDONE; X goto retry; X } X return( COMPLETE); X } X return(HAD_ERROR); X case XS_BUSY: X for(rval = 0 ;rval < 1000000 ;rval++); X if(scsi_xfer.retries--) X { X scsi_xfer.flags &= ~ITSDONE; X goto retry; X } X return(COMPLETE); /* it's busy so it's there */ X case XS_TIMEOUT: X default: X return(HAD_ERROR); X } X } X return(COMPLETE); X} X X X X X/***********************************************\ X* Utility routines often used in SCSI stuff * X\***********************************************/ X X/***********************************************\ X* convert a physical address to 3 bytes, * X* MSB at the lowest address, * X* LSB at the highest. * X\***********************************************/ X Xlto3b(val, bytes) Xu_char *bytes; X{ X *bytes++ = (val&0xff0000)>>16; X *bytes++ = (val&0xff00)>>8; X *bytes = val&0xff; X} X X/***********************************************\ X* The reverse of lto3b * X\***********************************************/ X_3btol(bytes) Xu_char *bytes; X{ X int rc; X rc = (*bytes++ << 16); X rc += (*bytes++ << 8); X rc += *bytes; X return(rc); X} X END-of-scsi/scsiconf.c echo x - scsi/scsi.h sed 's/^X//' >scsi/scsi.h << 'END-of-scsi/scsi.h' X/* X * HISTORY X * $Log: scsi.h,v $ X * X */ X X/* X * SCSI interface description X */ X X/* X * Some lines of this file comes from a file of the same name X * distributed by OSF, so the following disclaimer has been kept. X * X * Copyright 1990 by Open Software Foundation, X * Grenoble, FRANCE X * X * All Rights Reserved X * X * Permission to use, copy, modify, and distribute this software and X * its documentation for any purpose and without fee is hereby granted, X * provided that the above copyright notice appears in all copies and X * that both the copyright notice and this permission notice appear in X * supporting documentation, and that the name of OSF or Open Software X * Foundation not be used in advertising or publicity pertaining to X * distribution of the software without specific, written prior X * permission. X * X * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE X * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, X * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR X * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM X * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, X * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION X * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * Largely written by Julian Elischer (julian@tfs.com) X * for TRW Financial Systems. X * X * TRW Financial Systems, in accordance with their agreement with Carnegie X * Mellon University, makes this software available to CMU to distribute X * or use in any manner that they see fit as long as this message is kept with X * the software. For this reason TFS also grants any other persons or X * organisations permission to use or modify this software. X * X * TFS supplies this software to be publicly redistributed X * on the understanding that TFS is not responsible for the correct X * functioning of this software in any circumstances. X * X */ X X/* X * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 X */ X X/* X * SCSI command format X */ X Xunion scsi_cmd X{ X X struct scsi_generic X { X u_char opcode; X u_char bytes[11]; X } generic; X X struct scsi_test_unit_ready X { X u_char op_code; X u_char :5; X u_char lun:3; X u_char unused[3]; X u_char link:1; X u_char flag:4; X u_char :3; X } test_unit_ready; X X struct scsi_send_diag X { X u_char op_code; X u_char uol:1; X u_char dol:1; X u_char selftest:1; X u_char :1; X u_char pf:1; X u_char lun:3; X u_char unused[1]; X u_char paramlen[2]; X u_char link:1; X u_char flag:4; X u_char :3; X } send_diag; X X struct scsi_sense X { X u_char op_code; X u_char :5; X u_char lun:3; X u_char unused[2]; X u_char length; X u_char link:1; X u_char flag:1; X u_char :6; X } sense; X X struct scsi_inquiry X { X u_char op_code; X u_char :5; X u_char lun:3; X u_char unused[2]; X u_char length; X u_char link:1; X u_char flag:1; X u_char :6; X } inquiry; X X struct scsi_mode_sense X { X u_char op_code; X u_char :3; X u_char dbd:1; X u_char rsvd:1; X u_char lun:3; X u_char page_code:6; X u_char page_ctrl:2; X u_char unused; X u_char length; X u_char link:1; X u_char flag:1; X u_char :6; X } mode_sense; X X struct scsi_mode_select X { X u_char op_code; X u_char :5; X u_char lun:3; X u_char unused[2]; X u_char length; X u_char link:1; X u_char flag:1; X u_char :6; X } mode_select; X X struct scsi_reassign_blocks X { X u_char op_code; X u_char :5; X u_char lun:3; X u_char unused[3]; X u_char link:1; X u_char flag:1; X u_char :6; X } reassign_blocks; X X struct scsi_rw X { X u_char op_code; X u_char addr_2:5; /* Most significant */ X u_char lun:3; X u_char addr_1; X u_char addr_0; /* least significant */ X u_char length; X u_char link:1; X u_char flag:1; X u_char :6; X } rw; X X struct scsi_rw_big X { X u_char op_code; X u_char rel_addr:1; X u_char :4; /* Most significant */ X u_char lun:3; X u_char addr_3; X u_char addr_2; X u_char addr_1; X u_char addr_0; /* least significant */ X u_char reserved;; X u_char length2; X u_char length1; X u_char link:1; X u_char flag:1; X u_char :4; X u_char vendor:2; X } rw_big; X X struct scsi_rw_tape X { X u_char op_code; X u_char fixed:1; X u_char :4; X u_char lun:3; X u_char len[3]; X u_char link:1; X u_char flag:1; X u_char :6; X } rw_tape; X X struct scsi_read_capacity X { X u_char op_code; X u_char :5; X u_char lun:3; X u_char addr_3; /* Most Significant */ X u_char addr_2; X u_char addr_1; X u_char addr_0; /* Least Significant */ X u_char unused[3]; X u_char link:1; X u_char flag:1; X u_char :6; X } read_capacity; X X struct scsi_start_stop X { X u_char op_code; X u_char :5; X u_char lun:3; X u_char unused[2]; X u_char start:1; X u_char :7; X u_char link:1; X u_char flag:1; X u_char :6; X } start_stop; X X struct scsi_space X { X u_char op_code; X u_char code:2; X u_char :3; X u_char lun:3; X u_char number[3]; X u_char link:1; X u_char flag:1; X u_char :6; X } space; X#define SP_BLKS 0 X#define SP_FILEMARKS 1 X#define SP_SEQ_FILEMARKS 2 X#define SP_EOM 3 X X struct scsi_write_filemarks X { X u_char op_code; X u_char :5; X u_char lun:3; X u_char number[3]; X u_char link:1; X u_char flag:1; X u_char :6; X } write_filemarks; X X struct scsi_rewind X { X u_char op_code; X u_char immed:1; X u_char :4; X u_char lun:3; X u_char unused[3]; X u_char link:1; X u_char flag:1; X u_char :6; X } rewind; X X struct scsi_load X { X u_char op_code; X u_char immed:1; X u_char :4; X u_char lun:3; X u_char unused[2]; X u_char load:1; X u_char reten:1; X u_char :6; X u_char link:1; X u_char flag:1; X u_char :6; X } load; X#define LD_UNLOAD 0 X#define LD_LOAD 1 X X struct scsi_reserve X { X u_char op_code; X u_char :5; X u_char lun:3; X u_char unused[2]; X u_char length; X u_char link:1; X u_char flag:1; X u_char :6; X } reserve; X X struct scsi_release X { X u_char op_code; X u_char :5; X u_char lun:3; X u_char unused[2]; X u_char length; X u_char link:1; X u_char flag:1; X u_char :6; X } release; X X struct scsi_prevent X { X u_char op_code; X u_char :5; X u_char lun:3; X u_char unused[2]; X u_char prevent:1; X u_char :7; X u_char link:1; X u_char flag:1; X u_char :6; X } prevent; X#define PR_PREVENT 1 X#define PR_ALLOW 0 X X struct scsi_blk_limits X { X u_char op_code; X u_char :5; X u_char lun:3; X u_char unused[3]; X u_char link:1; X u_char flag:1; X u_char :6; X } blk_limits; X}; X Xunion mode_sel_data X{ X struct X { X u_char unused[2]; X u_char speed:4; X u_char buf_mode:3; X u_char :1; X u_char length; X struct X { X u_char density; X u_char seg_len[3]; X u_char unused; X u_char blklen[3]; X }segs[1]; X }tape; X}; X/* X * Opcodes X */ X X#define TEST_UNIT_READY 0x00 X#define REWIND 0x01 X#define REQUEST_SENSE 0x03 X#define READ_BLK_LIMITS 0x05 X#define REASSIGN_BLOCKS 0x07 X#define READ_COMMAND 0x08 X#define WRITE_COMMAND 0x0a X#define WRITE_FILEMARKS 0x10 X#define SPACE 0x11 X#define INQUIRY 0x12 X#define MODE_SELECT 0x15 X#define MODE_SENSE 0x1a X#define START_STOP 0x1b X#define LOAD_UNLOAD 0x1b /* same as above */ X#define RESERVE 0x16 X#define RELEASE 0x17 X#define PREVENT_ALLOW 0x1e X#define READ_CAPACITY 0x25 X#define READ_BIG 0x28 X#define WRITE_BIG 0x2a X#define MOVE_MEDIUM 0xa5 X#define POSITION_TO_ELEMENT 0x2b X#define READ_ELEMENT_STATUS 0xb8 X X X/* X * sense data format X */ X#define T_DIRECT 0 X#define T_SEQUENTIAL 1 X#define T_PRINTER 2 X#define T_PROCESSOR 3 X#define T_WORM 4 X#define T_READONLY 5 X#define T_SCANNER 6 X#define T_OPTICAL 7 X#define T_CHANGER 8 X#define T_COMM 9 X X#define T_REMOV 1 X#define T_FIXED 0 X Xstruct scsi_device_inquiry X{ X u_char device_type:5; X u_char device_qualifier:3; X u_char dev_qual2:7; X u_char removable:1; X u_char ansii_version:3; X u_char :5; X u_char response_format; X u_char additional_length; X u_char unused[2]; X u_char :3; X u_char can_link:1; X u_char can_sync:1; X u_char :3; X char vendor[8]; X char product[16]; X char revision[4]; X u_char extra[8]; X}; X X Xstruct scsi_sense_data X{ X u_char error_code:4; X u_char error_class:3; X u_char valid:1; X union X { X struct X { X u_char blockhi:5; X u_char vendor:3; X u_char blockmed; X u_char blocklow; X } unextended; X struct X { X u_char segment; X u_char sense_key:4; X u_char :1; X u_char ili:1; X u_char eom:1; X u_char filemark:1; X u_char info[4]; X u_char extra_len; X /* allocate enough room to hold new stuff X u_char cmd_spec_info[4]; X u_char add_sense_code; X u_char add_sense_code_qual; X u_char fru; X u_char sense_key_spec_1:7; X u_char sksv:1; X u_char sense_key_spec_2; X u_char sense_key_spec_3; X ( by increasing 16 to 26 below) */ X u_char extra_bytes[26]; X } extended; X }ext; X}; Xstruct scsi_sense_data_new X{ X u_char error_code:7; X u_char valid:1; X union X { X struct X { X u_char blockhi:5; X u_char vendor:3; X u_char blockmed; X u_char blocklow; X } unextended; X struct X { X u_char segment; X u_char sense_key:4; X u_char :1; X u_char ili:1; X u_char eom:1; X u_char filemark:1; X u_char info[4]; X u_char extra_len; X u_char cmd_spec_info[4]; X u_char add_sense_code; X u_char add_sense_code_qual; X u_char fru; X u_char sense_key_spec_1:7; X u_char sksv:1; X u_char sense_key_spec_2; X u_char sense_key_spec_3; X u_char extra_bytes[16]; X } extended; X }ext; X}; X X Xstruct scsi_blk_limits_data X{ X u_char reserved; X u_char max_length_2; /* Most significant */ X u_char max_length_1; X u_char max_length_0; /* Least significant */ X u_char min_length_1; /* Most significant */ X u_char min_length_0; /* Least significant */ X}; X Xstruct scsi_read_cap_data X{ X u_char addr_3; /* Most significant */ X u_char addr_2; X u_char addr_1; X u_char addr_0; /* Least significant */ X u_char length_3; /* Most significant */ X u_char length_2; X u_char length_1; X u_char length_0; /* Least significant */ X}; X Xstruct scsi_reassign_blocks_data X{ X u_char reserved[2]; X u_char length_msb; X u_char length_lsb; X struct X { X u_char dlbaddr_3; /* defect logical block address (MSB) */ X u_char dlbaddr_2; X u_char dlbaddr_1; X u_char dlbaddr_0; /* defect logical block address (LSB) */ X } defect_descriptor[1]; X}; X Xstruct scsi_mode_sense_data X{ X X u_char data_length; /* Sense data length */ X u_char unused1[3]; X X u_char density; X u_char nblocks_2; X u_char nblocks_1; X u_char nblocks_0; X u_char unused2; X u_char blksz_2; X u_char blksz_1; X u_char blksz_0; X X union X{ X struct pgcode_3 { X u_char pg_code:6; /* page code (should be 3) */ X u_char :2; X u_char pg_length; /* page length (should be 0x16) */ X u_char trk_z_1; /* tracks per zone (MSB) */ X u_char trk_z_0; /* tracks per zone (LSB) */ X u_char alt_sec_1; /* alternate sectors per zone (MSB) */ X u_char alt_sec_0; /* alternate sectors per zone (LSB) */ X u_char alt_trk_z_1; /* alternate tracks per zone (MSB) */ X u_char alt_trk_z_0; /* alternate tracks per zone (LSB) */ X u_char alt_trk_v_1; /* alternate tracks per volume (MSB) */ X u_char alt_trk_v_0; /* alternate tracks per volume (LSB) */ X u_char ph_sec_t_1; /* physical sectors per track (MSB) */ X u_char ph_sec_t_0; /* physical sectors per track (LSB) */ X u_char bytes_s_1; /* bytes per sector (MSB) */ X u_char bytes_s_0; /* bytes per sector (LSB) */ X u_char interleave_1;/* interleave (MSB) */ X u_char interleave_0;/* interleave (LSB) */ X u_char trk_skew_1; /* track skew factor (MSB) */ X u_char trk_skew_0; /* track skew factor (LSB) */ X u_char cyl_skew_1; /* cylinder skew (MSB) */ X u_char cyl_skew_0; /* cylinder skew (LSB) */ X u_char reserved1:4; X u_char surf:1; X u_char rmb:1; X u_char hsec:1; X u_char ssec:1; X u_char reserved2; X u_char reserved3; X } pgcode_3; X struct pgcode_4 { X u_char pg_code:7; /* page code (should be 4) */ X u_char mbone:1; /* must be one */ X u_char pg_length; /* page length (should be 0x16) */ X u_char ncyl_2; /* number of cylinders (MSB) */ X u_char ncyl_1; /* number of cylinders */ X u_char ncyl_0; /* number of cylinders (LSB) */ X u_char nheads; /* number of heads */ X u_char st_cyl_wp_2; /* starting cyl., write precomp (MSB) */ X u_char st_cyl_wp_1; /* starting cyl., write precomp */ X u_char st_cyl_wp_0; /* starting cyl., write precomp (LSB) */ X u_char st_cyl_rwc_2;/* starting cyl., red. write cur (MSB)*/ X u_char st_cyl_rwc_1;/* starting cyl., red. write cur */ X u_char st_cyl_rwc_0;/* starting cyl., red. write cur (LSB)*/ X u_char driv_step_1; /* drive step rate (MSB) */ X u_char driv_step_0; /* drive step rate (LSB) */ X u_char land_zone_2; /* landing zone cylinder (MSB) */ X u_char land_zone_1; /* landing zone cylinder */ X u_char land_zone_0; /* landing zone cylinder (LSB) */ X u_char reserved1; X u_char reserved2; X u_char reserved3; X } pgcode_4; X } params; X} ; X X/**********************************************/ X/* define the standard scsi window definition */ X/**********************************************/ Xstruct scsi_scan_win_def X{ Xu_char win_id, X reserved_2, X x_res[2], X y_res[2], X upper_left_x[4], X upper_left_y[4], X width[4], X len[4], X brightness, X thresh, X cont, X im_compo, X pixel_bits, X halftone_pat[2], X rif :1, X reserved_3 :4, X pad_type :3, X byte_order[2], X cmp_type, X cmp_arg, X reserved_4[6]; X} ; X X/* X * Status Byte X */ X#define SCSI_OK 0x00 X#define SCSI_CHECK 0x02 X#define SCSI_BUSY 0x08 X#define SCSI_INTERM 0x10 END-of-scsi/scsi.h exit