*BSD News Article 5217


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