[comp.sys.nsc.32k] SCSI floppy message..

news@bungi.com.ogi.edu (05/17/91)

I thought the attached message from 'comp.periphs.scsi' might be
of interest given the recent discussion of Teac SCSI floppy 
drives.  I found of particular interest the note at the end of the 
article mentioning the Sun Common SCSI Architecture mailing list 
and the availability of a Teac device driver.

Best regards,
johnc

  --------------------- attached message ----------------------

From: Harvey_Taylor@mindlink.bc.ca (Harvey Taylor)
Newsgroups: comp.periphs.scsi
Subject: Teac 235-JS info needed
Message-ID: <5821@mindlink.bc.ca>
Date: 11 May 91 16:24:15 GMT
Organization: MIND LINK! - British Columbia, Canada
Lines: 42
To: johnc
Status: RO


    Well at long & dear last, my Teac Scsi Floppy arrived.

    It seems that I have a different version of the TEAC FDH-235JS SCSI
 floppy than the hardware spec (both JS & HS) . What I want to do is
 put it in auto density sense as mentioned in the SCSA driver Readme
 (see below).
    The problem is that there is a new row of shorting blocks which are
 undocumented. These are at the back beside the power connector & are
 labelled from front to back:

            AC AE IR RY D2 D1 D0

                            : The factory config was AE & D0 shorted.

    So, does anybody know the blocks to set for auto density sense mode
 on the 235JS?
    Does anybody know what all the blocks configure? There are the User
 settable blocks, as well:

        EJC J H G F LEV HDS STL

                          : PAR, MON are the only two documented in the
 hardware specification.
    And finally, has anybody got a copy of the "FC-1-01 Software
 Specification" out of Teac?
    -het

    PS.
    Jonathan Hue maintains the SCSA mailing list. Here is a clip:
|Re:The Sun Common SCSI Architecture mailing list. Send your subscription
|request to scsa-request@island.com, submissions to scsa@island.com.  There
|are people there who can answer your questions. There's even a complete
|SCSA driver in the archives to control a TEAC SCSI floppy.


  "DOS ... is still a real mode only non-reentrant
  interrupt handler, and always will be." - Russell William

 Harvey Taylor      Meta Media Productions
 uunet!van-bc!rsoft!mindlink!Harvey_Taylor
            a186@mindlink.bc.ca


-- 
John Connin: manatee Orlando, Florida
         UUCP: {uunet,ge-dab,ucf-cs}!tarpit!tous!manatee!johnc

swansonc@acc.stolaf.edu (Chris Swanson) (05/20/91)

 >>>>> On 17 May 91 01:54:20 GMT,
>>>>> in message <9105162154.AA00422@manatee.UUCP>,
>>>>> news@bungi.com.mu.edu wrote:


news> I thought the attached message from 'comp.periphs.scsi' might be
news> of interest given the recent discussion of Teac SCSI floppy
news> drives.  I found of particular interest the note at the end of
news> the article mentioning the Sun Common SCSI Architecture mailing
news> list and the availability of a Teac device driver.

news> Best regards, johnc

news>   --------------------- attached message ----------------------

news> From: Harvey_Taylor@mindlink.bc.ca (Harvey Taylor) Newsgroups:
news> comp.periphs.scsi Subject: Teac 235-JS info needed Message-ID:
news> <5821@mindlink.bc.ca> Date: 11 May 91 16:24:15 GMT Organization:
news> MIND LINK! - British Columbia, Canada Lines: 42 To: johnc
news> Status: RO


news>     Well at long & dear last, my Teac Scsi Floppy arrived.


Greetings,

	Does anybody have a list of suppliers and prices for SCSI
floppy drives?

	Thank's in advance,
	-=Chris

P.S.  Please reply via e-mail.   I will post a follow-up if there is
interest.

--
Chris Swanson, Chem/CS/Pre-med Undergrad, St. Olaf College, Northfield,MN 55057
 DDN: [CDS6]   INTERNET:  swansonc@acc.stolaf.edu  UUCP: uunet!stolaf!swansonc
  AT&T:		Work: (507)-645-4528			Home: (507)-663-6424
	I would deny this reality, but that wouldn't pay the bills...

sverre@lars.Seri.GOV (Sverre Froyen) (05/20/91)

>    It seems that I have a different version of the TEAC FDH-235JS SCSI
> floppy than the hardware spec (both JS & HS) . What I want to do is
> put it in auto density sense as mentioned in the SCSA driver Readme
> (see below).

Just so that nobody gets confused:

TEAC FD-235HS-302
1.44MB / 720kB
does NOT support auto density sense

TEAC FD-235JS-501-U
2.88MB / 1.44MB / 720kB
does support auto density sense (provided you get the 501-U)

I have gotten the 235HS to work on the pc532 with minimal changes
to scsi_hi.c.  I have also compiled (calling it ported would be an
overstatement) the mtools package which allows me to read and write
MSDOS format diskettes.

Sverre

news@bungi.com.mu.edu (05/21/91)

Attached is a copy of the Sun SCSA TEAC floppy driver mentioned in 
a previous posting.  

Best regards,
johnc

	================== Attachment ==================

Subject: SCSA TEAC floppy driver

This driver is a first version SCSA top-level floppy driver,
but maybe elements are usable in other applications (I am working on
porting VME bus and IEEE488 devices (via SCSI) from older SUN SCSI
implementations to SCSA)

Please report bugs, flames and suggestions to me (and/or the SCSA mailing
list, many thanks to Jonathan Hue (hue@island.com) for creating this list !)
and let me know if you are interested to receive updates.

Fons Ullings
fons@nat.vu.nl

: This is a shar archive.  Extract with sh, not csh.
: This archive ends with exit, so do not worry about trailing junk.
: --------------------------- cut here --------------------------
PATH=/bin:/usr/bin:/usr/ucb
echo Extracting 'README'
sed 's/^X//' > 'README' << '+ END-OF-FILE ''README'
XDear SCSA developer,
X
X
XThis is a >>first<< version of a SCSA floppy driver that makes it possible
Xto use a TEAC embedded floppy drive (TEAC FD-235HS-300) to SUN 4/20's
X(other SUN4 models do have embedded Intel floppy controllers)
X
XYou do need some experience adding device drivers to BSD/SunOS,
Xotherwise DO read SUN related documents first  ('writing a device driver', etc)
Xand PLEASE save original copies of files anyway....
X
Xinstall steps (in short):
X
X1. move 'szdef.h' and 'sz.c' to the './sys/scsi/targets' directory
X2. apply the diffs to the './sys/sun/conf.c' file with potentially
X   different block/character device numbers depending on the SunOS release !
X   this one is ok for SunOS4.1.1
X3. add the line:
X	scsi/targets/sz.c	optional sz scsibus
X   to the file './sys/sun4c/conf/files'
X4. add the line:
X	disk sz0 at scsibus0 target 5 lun 0	# TEAC SCSI floppy
X   to your config file './sys/sun4c/conf/your_SUN4C_config_file'
X5. config your kernel again  (see SunOS documentation)
X6. make your kernel (it should compile 'sz.c'...)
X7. make sure that there is NO other SCSI device on the bus with address '5'.
X8. make sure that there is only ONE SCSI device (at the end of the cable(s))
X   with terminators installed
X9. strap the TEAC floppy drive (see TEAC manual for auto density sense):
X
X
X   50           SCSI               1
X   :::::::::::::::::::::::::::::::::   :              < NO strap
X                                       X              < strap
X                                       :              < NO strap   gives ID=5
X
X                                           VCC GND
X				             | | | |  < power
X                         strap >      XX.    | | | |
X                         strap >      .XX
X
Xand on the SCSI controller board:
X
X                          ::X:XXXX::
X
Xin words:
XEJC, J, G, PAR, MON     are OUT
XH, F, LEV, HDS, STL     are IN
X
X10. boot the new kernel, and with the floppy powered on, it should
X    give the message:
X
X	sz0: TEAC    FC-1     HF   00RV L
X	sz0 at esp0 target 5 lun 0
X
X11. make both the block and character device, with the right R/W permissions
X    for your site, and with matching (major) numbers from './sys/sun/conf.c' !!
X
X    mknod /dev/fz0c b 50 0
X    mknod /dev/rfz0c c 104 0
X
X12. try to read an already formatted floppy (720K or 1.44Mbyte)
X
X    dd if=/dev/rfz0c of=/dev/null count=1
X
X13. use the 'mtools' package from Emmet P. Gray (great stuff !) to handle
X    MSDOS flops (with all references to '/dev/rfd0c' changed to '/dev/rfz0c')
X
X14. use 'newfs' and 'mount' to use the drive as an UNIX file system
X
X
XPlease report bugs, flames and suggestions to me and let me know if you are
Xinterested to receive updates, because I have still marked a (large) number
Xof issues 'TODO' (see the 'sz.c' source).
XNote that I do not have ANY relationship with TEAC, just used their SCSI floppy.
X
XI really would like to thank the SUN SCSA and SBus engineering groups in the
XUSA that did send me an early draft for free of the SCSA documents and do
Xhave supported me very nicely in many ways already..... ! (thanks again)
X
X(Sun Microsystems >> the Netherlands << quoted $8 per page ! for the final
X SCSA draft, uhmm, not so nice, but ok, their choice)
X
XGood Luck
X
X
XFons Ullings, VU, Amsterdam, The Netherlands
Xemail: fons@nat.vu.nl
+ END-OF-FILE README
chmod 'u=rw,g=r,o=r' 'README'
set `wc -c 'README'`
count=$1
case $count in
3278)	:;;
*)	echo 'Bad character count in ''README' >&2
		echo 'Count should be 3278' >&2
esac
echo Extracting 'conf.c.diff'
sed 's/^X//' > 'conf.c.diff' << '+ END-OF-FILE ''conf.c.diff'
X2c2
X< static	char sccsid[] = "@(#)conf.c 5.91 90/06/26 SMI";
X---
X> static	char sccsid[] = "@(#)conf.c 5.91 90/06/26 SMI   AHU 910114";
X194a195,208
X> #include "sz.h"
X> #if NSZ > 0
X> extern int szopen(), szclose(), szstrategy(), szread(), szwrite();
X> extern int szioctl(), szsize();
X> #else
X> #define	szopen		nodev
X> #define	szclose		nodev
X> #define	szstrategy	nodev
X> #define	szread		nodev
X> #define	szwrite		nodev
X> #define	szioctl		nodev
X> #define	szsize		0
X> #endif
X> 
X379a394,395
X>  	{ szopen,	szclose,	szstrategy,	nodev,		/*50*/
X>  	  szsize,	0 },
X1322a1339,1343
X>     },
X>     {
X>  	szopen,		szclose,	szread,		szwrite,	/*104*/
X>  	szioctl,	nulldev,	nulldev,	0,
X> 	0,		0,
+ END-OF-FILE conf.c.diff
chmod 'u=rw,g=r,o=r' 'conf.c.diff'
set `wc -c 'conf.c.diff'`
count=$1
case $count in
677)	:;;
*)	echo 'Bad character count in ''conf.c.diff' >&2
		echo 'Count should be 677' >&2
esac
echo Extracting 'sz.c'
sed 's/^X//' > 'sz.c' << '+ END-OF-FILE ''sz.c'
X/*
X *  SCSA compatible SCSI floppy driver for TEAC FD-235HS-300
X *
X *	Copyright (c) 1990/1991  A.Ullings, Vrije Universiteit, Amsterdam.
X *	Limited rights to use and modify are hereby granted for non-commercial
X *	purposes, provided that all copyright notices remain intact.
X *
X *	email:  fons@nat.vu.nl
X *
X *  @(#)sz.c	1.14 1/14/91
X *
X *  
X *  this driver has been tested with:
X *  SUN4/20		SunOS4.0.3
X *  SUN4/60 + WREN-IV	SunOS4.1
X *  SUN4/20 + WREN-V	SunOS4.1.1
X *
X *  and works OK with the 'mtools' package from Emmet P. Gray,
X *  and as character and block device with both 720K and 1.44M 3.5inch floppy's
X *
X *  TODO
X *	- test multiple units support.
X *	- add 'format' ioctl (easy)
X *	- add 'dk' statistics for 'iostat/vmstat' (how ?, the old way ??).
X *	- should add partition support ???! and the capacity should
X *	  always get updated after a media change is sensed.
X *	- the code assumes that DEV_BSIZE is 512 ()
X *	- SCSA allocs should be restartable iff no resources (??!!)
X *	- there MUST be a method to avoid copying data by mapping
X *	  kernel addresses via 'buf' structures....
X *	- should add non OPENPROM code version (but for which machines ??
X *	  the other SUN kernels I know of are using the old SCSI layers
X *	  described in STB jun/jul 1989
X *	- is the 'szsize()' implementation correct ??
X *	- cleanup INQUIRY messages printout at startup time
X *	- add dynamic loading support when this becomes available for
X *	  SCSA drivers (see SBulletin December 1990) 
X */
X
X#include <scsi/scsi.h>
X#include <scsi/targets/szdef.h>
X
Xstatic struct scsi_device	*szunits[SZ_MAXUNIT];
Xstatic int	szpri = 0;	/* device priority */
Xstatic int	szflag = 0;	/* SCSA 'flag' used in SCSI operations */
X
X#define SZAUTOSENSE		/* TEAC auto density sense option enable */
X#define SZ_DEBUG		/* DEBUG code enable */
X#ifdef SZ_DEBUG
Xint	szdebug = 0;
X#define TRACE(fmt, p0, p1, p2)	if(szdebug)printf(fmt, p0, p1, p2)
X#else
X#define TRACE(fmt, p0, p1, p2)	;
X#endif
X
Xint	szslave(), szattach(), szopen(), szclose(), szread(), szwrite();
Xint	szstrategy(), szioctl(), szsize();
Xvoid	szintr();
Xextern int	nodev();
X
X#ifdef OPENPROMS
Xstruct dev_ops	sz_ops = {
X	1,
X	szslave,
X	szattach,
X	szopen,
X	szclose,
X	szread,
X	szwrite,
X	szstrategy,
X	nodev,
X	0,
X	szioctl
X};
X
X#else
XNO OPENPROMS;
X#endif
X
X/*
X *  message functions and tables
X */
Xstatic char	*szmesg();	/* message lookup function */
Xchar	*sz_keys[];		/* SCSI key table */
Xchar	*sz_codes[];		/* SCSI/TEAC extended sense code table */
Xchar	*sz_reasons[];		/* SCSA pkt_reason table */
X
X/*
X */
Xint
Xszslave(devp)
Xstruct scsi_device	*devp;
X{
X	struct scsi_address	*scsi_addr = &devp->sd_address;
X	struct scsi_pkt		*pkt;
X	struct sz_device	*un;
X	char	id[32];
X
X	TRACE("szslave: target=%d lun=%d\n",
X		scsi_addr->a_target, scsi_addr->a_lun, 0);
X	switch(scsi_slave(devp, 0)) {
X	case SCSIPROBE_NOMEM:
X	case SCSIPROBE_FAILURE:
X	case SCSIPROBE_NORESP:
X	case SCSIPROBE_NONCCS:
X		printf("sz%d: offline\n", devp->sd_dev->devi_unit);
X		return(0);
X	case SCSIPROBE_EXISTS:
X		bzero(id, sizeof(id));
X		bcopy(devp->sd_inq->inq_vid, id, 8+16+4);
X/* should be cleaner here.... */
X		printf("sz%d: %s\n", devp->sd_dev->devi_unit, id);
X	}
X
X	un = (struct sz_device *)kmem_zalloc(sizeof(struct sz_device));
X	if(!un) {		/* should be a panic() */
X		printf("sz: kmem_zalloc failed\n");
X		return(0);
X	}
X	(struct sz_device *)devp->sd_private = un;
X	szunits[devp->sd_dev->devi_unit] = devp;
X
X	pkt = get_pktiopb(&devp->sd_address, (caddr_t *)&un->un_sense,
X		CDB_GROUP0, 1, SZ_SENSE_LENGTH, B_READ, NULL_FUNC);
X	if(!pkt) {		/* should be a panic() */
X		printf("sz: get_pktiopb failed\n");
X		return(0);
X	}
X	un->un_sense_pkt = pkt;
X	pkt->pkt_pmon = -1;		/* no performance monitor */
X	pkt->pkt_comp = szintr;
X	pkt->pkt_time = 0;
X
X	szpri = MAX(szpri, ipltospl(devp->sd_dev->devi_intr->int_pri));
X	devp->sd_dev->devi_driver = &sz_ops;
X	devp->sd_present = 1;
X	return(1);
X}
X
X/*
X *  szsetmode(mod, medium)
X *	setup a SCSI/TEAC mode structure to some defaults
X */
Xstatic
Xszsetmode(mode, medium)
Xstruct scsi_mode	*mode;
Xint	medium;
X{
X	bzero(mode, sizeof(struct scsi_mode));	/* all zeros */
X	mode->mod_medium_type = medium;		/* fill in medium */
X	mode->mod_block_length = 8;		/* block descriptor only */
X	mode->mod_density_code = SZ_DENSITY_MFM;	/* high density */
X	mode->mod_block_length_0 = 0x00;		/* 512 bytes/block */
X	mode->mod_block_length_1 = 0x02;
X	mode->mod_block_length_2 = 0x00;
X}
X
X/*
X */
Xint
Xszattach(devp)
Xstruct scsi_device	*devp;
X{
X	struct scsi_pkt		*pkt;
X	caddr_t		arg;
X
X	pkt = get_pktiopb(&devp->sd_address, &arg,
X		CDB_GROUP0, 1, sizeof(struct scsi_mode), B_WRITE, NULL_FUNC);
X	if(!pkt) {
X		TRACE("szattach: get_pktiopb failed\n", 0, 0, 0);
X		return;
X	}
X	szsetmode(arg, SZ_MEDIUM_AUTO);
X	makecom_g0(pkt, devp, FLAG_NOINTR|FLAG_NODISCON,
X		SCMD_MODE_SELECT, 0, sizeof(struct scsi_mode));
X	(void) scsi_poll(pkt);
X	free_pktiopb(pkt, arg, sizeof(struct scsi_mode));
X}
X
X/*
X */
Xint
Xszstrategy(bp)
Xstruct buf	*bp;
X{
X	struct scsi_device	*devp;
X	struct sz_device	*un;
X	struct diskhd	*dp;
X	daddr_t		bn;
X	register	s;
X
X	devp = szunits[SZ_UNIT(bp->b_dev)];
X	un = (struct sz_device *)devp->sd_private;
X	dp = &un->un_utab;
X
X	bp->b_flags &= ~(B_DONE|B_ERROR);
X
X	if(bp != &un->un_sbuf) {
X		bn = dkblock(bp);
X		if(bn >= un->un_capacity) {
X			if(bn > un->un_capacity)
X				bp->b_flags |= B_ERROR;
X			bp->b_resid = bp->b_bcount;
X			TRACE("szstrategy: bn=%d > %d\n",
X				bn, un->un_capacity, 0); 
X			iodone(bp);
X			return;
X		}
X	}
X
X	s = splr(szpri);
X	if(dp->b_actf == (struct buf *)NULL)
X		dp->b_actf = bp;
X	else
X		dp->b_actl->av_forw = bp;
X	dp->b_actl = bp;
X	bp->av_forw = (struct buf *)NULL;
X	if(dp->b_forw == (struct buf *)NULL) {
X		szstart(devp);
X	}
X	(void) splx(s);
X}
X
X/*
X */
Xszstart(devp)
Xstruct scsi_device	*devp;
X{
X	struct sz_device	*un = (struct sz_device *)devp->sd_private;
X	struct diskhd	*dp = &un->un_utab;
X	struct buf	*bp;
X	struct scsi_pkt		*pkt;
X	daddr_t		bn;
X	daddr_t		overflow;
X	int	count;
X	int	cmd;
X
X	if(dp->b_forw || ((bp = dp->b_actf) == (struct buf *)NULL)) {
X		TRACE("szstart: dp->b_forw BUSY\n", 0, 0, 0);
X		return;
X	}
X	dp->b_forw = bp;		/* this is the active one */
X	dp->b_actf = bp->av_forw;	/* next in queue */
X	bp->av_forw = (struct buf *)NULL;	/* */
X	bp->av_back = (struct buf *)NULL;	/* no resource yet */
X
X	if(bp != &un->un_sbuf) {
X		pkt = scsi_resalloc(&devp->sd_address, CDB_GROUP0,
X			0, (opaque_t)bp, NULL_FUNC);
X		if(!pkt) {
X			TRACE("szstart: scsi_resalloc failed\n", 0, 0, 0);
X			bp->b_flags |= B_ERROR;
X			szdone(devp);
X			return;
X		}
X		bn = dkblock(bp);
X		count = bp->b_bcount / SZ_DEV_BSIZE;
X		bp->b_resid = 0;
X		overflow = bn + count - un->un_capacity;
X		if(overflow > 0) {
X			TRACE("szstart: overflow %d\n", overflow, 0, 0);
X			count -= overflow;
X			bp->b_resid = overflow * SZ_DEV_BSIZE;
X		}
X		cmd = bp->b_flags & B_READ ? SCMD_READ : SCMD_WRITE;
X	} else {
X		pkt = un->un_sbuf_pkt;
X		bn = bp->b_blkno;
X		count = bp->b_resid;
X		bp->b_resid = 0;
X		cmd = un->un_scmd;
X	}
X
X	TRACE("szstart: cmd=0x%x bn=%d count=%d\n", cmd, bn, count);
X/* assume SCSI GROUP1 if not GROUP0..... */
X	if(CDB_GROUPID(cmd) == 0) 
X		makecom_g0(pkt, devp, szflag, cmd, (int)bn, count);
X	else
X		makecom_g1(pkt, devp, szflag, cmd, (int)bn, count);
X
X	pkt->pkt_pmon = -1;
X	pkt->pkt_comp = szintr;
X	pkt->pkt_time = SZ_TIMEOUT + count;		/* 1 sec / block ?? */
X	pkt->pkt_private = (opaque_t)bp;
X
X	(struct scsi_pkt *)bp->av_back = pkt;
X
X	if(pkt_transport(pkt) <= 0) {
X		TRACE("szstart: pkt_transport failed\n", 0, 0, 0);
X		bp->b_flags |= B_ERROR;
X		szdone(devp);
X		return;
X	}
X}
X
X/*
X *  szdone(devp)
X *	finish up the current active transfer, and startup a
X * 	new one	if any.
X */
Xszdone(devp)
Xstruct scsi_device	*devp;
X{
X	struct sz_device	*un = (struct sz_device *)devp->sd_private;
X	struct scsi_pkt		*pkt;
X	struct diskhd	*dp = &un->un_utab;
X	struct buf	*bp;
X
X	bp = dp->b_forw;	/* save the current active */
X	dp->b_forw = NULL;	/* and mark done */
X	if(dp->b_actf) {	/* is there a next one */
X		szstart(devp);
X	}
X	if(pkt = (struct scsi_pkt *)bp->av_back) {	/* resource anyway ?? */
X		if(bp != &un->un_sbuf) {
X			scsi_resfree(pkt);
X		}
X	}
X	if(bp->b_flags & B_ERROR)
X		if(bp->b_error == 0)
X			bp->b_error = 0xff;	/* ?? */
X	iodone(bp);
X}
X
X/*
X *  szcommand(dev, cmd, flag, addr, n, cdb123, cdb4)
X *	run a SCSI (special) command in queued interrupt mode
X */
Xstatic
Xszcommand(dev, cmd, flag, addr, n, cdb123, cdb4)
Xdev_t	dev;			/* device */
Xint	cmd;			/* SCSI GROUP0/GROUP1 command */
Xint	flag;			/* B_READ/B_WRITE */
Xcaddr_t	addr;			/* DMA data address, if any */
Xint	n;			/* DMA data bytecount, if any */
Xdaddr_t	cdb123;			/* SCSI CDB address/blocknumber field */
Xint	cdb4;			/* SCSI CDB transfer field */
X{
X	struct scsi_device	*devp = szunits[SZ_UNIT(dev)];
X	struct sz_device	*un = (struct sz_device *)devp->sd_private;
X	struct scsi_pkt		*pkt;
X	register struct buf	*bp;
X	register int	r;
X	register int	s;
X	caddr_t		arg;
X
X	bp = &un->un_sbuf;
X
X	s = splr(szpri);
X	while(bp->b_flags & B_BUSY) {
X		bp->b_flags |= B_WANTED;
X		(void) sleep((caddr_t)bp, PRIBIO);
X	}
X	bp->b_flags = B_BUSY | flag;
X	(void) splx(s);
X
X	bp->b_error = 0;	/* !! */
X	bp->b_dev = dev;
X	bp->b_bcount = n;	/* number of data xfer bytes */
X	bp->b_blkno = cdb123;	/* SCSI blocknumber field */
X	bp->b_resid = cdb4;	/* SCSI transfer length field */
X/* get_pktiopb doesn't accept n == 0..... */
X	if(n) {
X		pkt = get_pktiopb(&devp->sd_address, &arg,
X			CDB_GROUPID(cmd) == 0 ? CDB_GROUP0 : CDB_GROUP1,
X			1, n, flag, SLEEP_FUNC);
X	} else {
X		pkt = scsi_pktalloc(&devp->sd_address,
X			CDB_GROUPID(cmd) == 0 ? CDB_GROUP0 : CDB_GROUP1,
X			1, SLEEP_FUNC);
X	}
X	bp->b_un.b_addr = arg;
X	if(!pkt) {
X		TRACE("szcommand: get_pktiopb failed\n", 0, 0, 0);
X		bp->b_flags &= ~B_BUSY;
X		if(bp->b_flags & B_WANTED)
X			wakeup((caddr_t)bp);
X		return(-1);
X	}
X	if(n && ((bp->b_flags & B_READ) == 0))
X		bcopy(addr, bp->b_un.b_addr, n);
X
X	un->un_sbuf_pkt = pkt;		/* save the allocated packet */
X	un->un_scmd = cmd;		/* copy special command */
X	TRACE("szcommand: cmd=0x%x b_bcount=%d b_un.b_addr=0x%x\n",
X				cmd, bp->b_bcount, bp->b_un.b_addr);
X	szstrategy(bp);
X	iowait(bp);
X
X	if(n && (bp->b_flags & B_READ))
X		bcopy(bp->b_un.b_addr, addr, n);
X
X	if(n) {
X		free_pktiopb(pkt, bp->b_un.b_addr, n);
X	} else {
X		scsi_resfree(pkt);
X	}
X
X	r = bp->b_flags & B_ERROR ? bp->b_error : bp->b_resid;
X	TRACE("szcommand: b_resid=%d r=0x%x\n", bp->b_resid, r, 0);
X	bp->b_flags &= ~B_BUSY;
X	if(bp->b_flags & B_WANTED)
X		wakeup((caddr_t)bp);
X	return(r);
X}
X
X/*
X */
Xvoid
Xszintr(pkt)
Xstruct scsi_pkt	*pkt;
X{
X	struct buf	*bp;
X	struct scsi_device	*devp;
X	struct sz_device	*un;
X	struct scsi_status	*ss;
X
X	bp = (struct buf *)pkt->pkt_private;
X	devp = szunits[SZ_UNIT(bp->b_dev)];
X	un = (struct sz_device *)devp->sd_private;
X	TRACE("szintr: pkt_reason=0x%x state=0x%x\n",
X		pkt->pkt_reason, pkt->pkt_state, 0);
X	if((pkt->pkt_reason != CMD_CMPLT) ||
X			((pkt->pkt_state & STATE_GOT_STATUS) == 0)) {
X		printf("sz%d: hard SCSI error 0x%x %s\n", SZ_UNIT(bp->b_dev),
X			pkt->pkt_reason,
X			szmesg(sz_reasons, (int)pkt->pkt_reason));
X		bp->b_flags |= B_ERROR;
X		szdone(devp);
X		return;
X	}
X	if(pkt == un->un_sense_pkt) {	/* REQUEST sense */
X		struct scsi_extended_sense	*es = un->un_sense;
X 
X		if(es->es_key != KEY_UNIT_ATTENTION) {
X			printf("sz%d: %s %s\n", SZ_UNIT(bp->b_dev),
X				szmesg(sz_keys, (int)es->es_key),
X				szmesg(sz_codes, (int)es->es_add_info[4]));
X			bp->b_error = es->es_key;
X			bp->b_flags |= B_ERROR;
X			szdone(devp);
X			return;
X		}
X		TRACE("szintr: sense_pkt restart\n", 0, 0, 0);
X/* restart the original request.... */
X		pkt = (struct scsi_pkt *)bp->av_back;
X		if(pkt_transport(pkt) <= 0) {
X			TRACE("szintr: pkt_transport failed\n", 0, 0, 0);
X			bp->b_flags |= B_ERROR;
X			szdone(devp);
X			return;
X		}
X		return;
X
X	}
X	ss = (struct scsi_status *)pkt->pkt_scbp;
X	if(ss->sts_chk) {	/* status check condition */
X		pkt = un->un_sense_pkt;
X		makecom_g0(pkt, devp, FLAG_NODISCON,
X			SCMD_REQUEST_SENSE, 0, SZ_SENSE_LENGTH);
X		bzero((caddr_t)un->un_sense, SZ_SENSE_LENGTH);
X		pkt->pkt_private = (opaque_t)bp;
X		if(pkt_transport(pkt) <= 0) {
X			TRACE("szintr: pkt_transport failed\n", 0, 0, 0);
X			bp->b_flags |= B_ERROR;
X			szdone(devp);
X			return;
X		}
X		return;
X	}
X	bp->b_resid += pkt->pkt_resid;	/* */
X	TRACE("szintr: OK resid=%d count=%d 0x%x\n",
X		bp->b_resid, bp->b_bcount, bp->b_flags);
X	szdone(devp);
X}
X
X/*
X *  sztrack(dev)
X *	try to (auto) sense the current floppy density
X *
X */
Xsztrack(dev)
Xdev_t	dev;
X{
X	int	r;
X	int	medium;
X	struct scsi_device	*devp;
X	struct sz_device	*un;
X
X	devp = szunits[SZ_UNIT(dev)];
X	un = (struct sz_device *)devp->sd_private;
X
X#ifdef SZAUTOSENSE
X/* just select the TEAC autosense option HDS with the correct FDD options... */
X	szsetmode(&un->un_mode, SZ_MEDIUM_AUTO);
X	if(szcommand(dev, SCMD_MODE_SELECT, B_WRITE,
X			(caddr_t)&un->un_mode, sizeof(struct scsi_mode),
X			(daddr_t)0, sizeof(struct scsi_mode)) < 0)
X		return(EIO);
X	return(0);
X#else
X/* get current density/mode, but maybe we have had power-down... */
X	if(szcommand(dev, SCMD_MODE_SENSE, B_READ,
X			(caddr_t)&un->un_mode, sizeof(struct scsi_mode),
X			(daddr_t)0, sizeof(struct scsi_mode)) < 0)
X		return(EIO);
X/* so make it 'sane' anyway */
X	medium = un->un_mode.mod_medium_type == SZ_MEDIUM_2MB ?
X					SZ_MEDIUM_2MB : SZ_MEDIUM_1MB;
X	TRACE("szopen: 0x%x\n", medium, 0, 0);
X/* force density code, block_length, etc... */
X	szsetmode(&un->un_mode, medium);
X	if(szcommand(dev, SCMD_MODE_SELECT, B_WRITE,
X			(caddr_t)&un->un_mode, sizeof(struct scsi_mode),
X			(daddr_t)0, sizeof(struct scsi_mode)) < 0)
X		return(EIO);
X/* will current setting work ?? */
X	if((r = szcommand(dev, SCMD_VERIFY, B_READ,
X			(caddr_t)0, 0, (daddr_t)0, 1)) == 0)
X		return(0);
X	if(r != KEY_MEDIUM_ERROR && r != KEY_MISCOMPARE)
X		return(EIO);
X/* no, flip the medium... */
X	un->un_mode.mod_medium_type = medium == SZ_MEDIUM_2MB ?
X					SZ_MEDIUM_1MB : SZ_MEDIUM_2MB;
X	if(szcommand(dev, SCMD_MODE_SELECT, B_WRITE,
X			(caddr_t)&un->un_mode, sizeof(struct scsi_mode),
X			(daddr_t)0, sizeof(struct scsi_mode)) < 0)
X		return(EIO);
X/* and retry */
X	if((r = szcommand(dev, SCMD_VERIFY, B_READ,
X			(caddr_t)0, 0, (daddr_t)0, 1)) == 0)
X		return(0);
X	return(EIO);
X#endif SZAUTOSENSE
X}
X
X/*
X */
Xszopen(dev)
Xdev_t	dev;
X{
X	int	unit = SZ_UNIT(dev);
X	struct scsi_device	*devp;
X	struct sz_device	*un;
X
X	TRACE("szopen: unit=%d\n", unit, 0, 0);
X	if(unit >= SZ_MAXUNIT)
X		return(ENXIO);
X	if((devp = szunits[SZ_UNIT(dev)]) == (struct scsi_device *)0)
X		return(ENXIO);
X	un = (struct sz_device *)devp->sd_private;
X	if(un->un_openf)
X		return(0);
X	if(sztrack(dev))
X		return(EIO);
X	if(szcommand(dev, SCMD_MODE_SENSE, B_READ,
X			(caddr_t)&un->un_mode, sizeof(struct scsi_mode),
X			(daddr_t)0, sizeof(struct scsi_mode)) < 0)
X		return(EIO);
X	un->un_capacity = ((daddr_t)un->un_mode.mod_num_block_2 << 16) |
X				(un->un_mode.mod_num_block_1 << 8) |
X				(un->un_mode.mod_num_block_0);
X	TRACE("szopen: capacity=%d\n", un->un_capacity, 0, 0);
X	un->un_openf = 1;
X	return(0);
X}
X
X/*
X */
Xszclose(dev)
Xdev_t	dev;
X{
X	int	unit = SZ_UNIT(dev);
X	struct scsi_device	*devp;
X	struct sz_device	*un;
X
X	devp = szunits[unit];
X	un = (struct sz_device *)devp->sd_private;
X	un->un_openf = 0;
X	return(0);
X}
X
X/*
X *  szminphys(bp)
X *	allow only 'SZ_DMA_SIZE' transfers (SCSI)
X */
Xszminphys(bp)
Xstruct buf	*bp;
X{
X#define SZ_DMA_SIZE	(255*SZ_DEV_BSIZE)
X	if(bp->b_bcount > SZ_DMA_SIZE)
X		bp->b_bcount = SZ_DMA_SIZE;
X}
X
X/*
X */
Xszread(dev, uio)
Xdev_t	dev;
Xstruct uio	*uio;
X{
X	struct sz_device	*un;
X	struct scsi_device	*devp;
X	int	unit = SZ_UNIT(dev);
X
X	if(unit >= SZ_MAXUNIT)
X		return(ENXIO);
X	if(uio->uio_offset & (SZ_DEV_BSIZE - 1))
X		return(EINVAL);
X        if(uio->uio_iov->iov_len & (SZ_DEV_BSIZE - 1))
X                return(EINVAL);
X	devp = szunits[unit];
X	un = (struct sz_device *)devp->sd_private;
X	return(physio(szstrategy, &un->un_rbuf, dev, B_READ, szminphys, uio));

X/*
X */
Xszwrite(dev, uio)
Xdev_t	dev;
Xstruct uio	*uio;
X{
X	struct sz_device	*un;
X	struct scsi_device	*devp;
X	int	unit = SZ_UNIT(dev);
X
X	if(unit >= SZ_MAXUNIT)
X		return(ENXIO);
X	if(uio->uio_offset & (SZ_DEV_BSIZE - 1))
X		return(EINVAL);
X        if(uio->uio_iov->iov_len & (SZ_DEV_BSIZE - 1))
X                return(EINVAL);
X	devp = szunits[unit];
X	un = (struct sz_device *)devp->sd_private;
X	return(physio(szstrategy, &un->un_rbuf, dev, B_WRITE, szminphys, uio));
X}
X
X/*
X *
X *  SUN's disk 'ioctl' structure for floppy's is a problem...
X *  So for now there is just enough support to let 'newfs', 'mkfs'
X *  and 'dkinfo' work
X */
Xszioctl(dev, cmd, data, flag)
Xdev_t	dev;
Xregister int	cmd;
Xcaddr_t	data;
X{
X	struct scsi_device	*devp = szunits[SZ_UNIT(dev)];
X	struct sz_device	*un = (struct sz_device *)devp->sd_private;
X
X	TRACE("szioctl: dev=0x%x cmd=0x%x\n", dev, cmd, 0);
X	switch(cmd) {
X	case DKIOCGGEOM:
X		((struct dk_geom *)data)->dkg_ncyl = 80;
X		((struct dk_geom *)data)->dkg_acyl = 0;
X		((struct dk_geom *)data)->dkg_bcyl = 0;
X		((struct dk_geom *)data)->dkg_nhead = 2;
X		((struct dk_geom *)data)->dkg_bhead = 0;
X		((struct dk_geom *)data)->dkg_nsect = un->un_capacity / 160;
X		((struct dk_geom *)data)->dkg_intrlv = 0;
X		((struct dk_geom *)data)->dkg_gap1 = 0;
X		((struct dk_geom *)data)->dkg_gap2 = 0;
X		((struct dk_geom *)data)->dkg_apc = 0;
X		return(0);
X
X	case DKIOCGPART:
X		((struct dk_map *)data)->dkl_cylno = 0;
X		((struct dk_map *)data)->dkl_nblk = un->un_capacity;
X		return(0);
X
X	case DKIOCINFO:	
X		((struct dk_info *)data)->dki_ctlr = 0x0;
X		((struct dk_info *)data)->dki_unit = SZ_UNIT(dev);	/* ?? */
X		((struct dk_info *)data)->dki_ctype = DKC_SCSI_CCS;
X		((struct dk_info *)data)->dki_flags = 0;
X		return(0);
X
X	case DKIOCSCMD:
X		break;
X	}
X	return(ENXIO);
X}
X
X/*
X *  szsize(dev)
X *	return the maximum number of blocks for the block device.
X *	seems to be consulted only at startup time ??!, so give the
X *	maximum then.... and this routine is even called when the unit
X *	is marked NOT present, uhmm
X */
Xszsize(dev)
Xdev_t	dev;
X{
X	struct scsi_device	*devp;
X	struct sz_device	*un;
X
X	if((devp = szunits[SZ_UNIT(dev)]) == (struct scsi_device *)0)
X		return(-1);
X	un = (struct sz_device *)devp->sd_private;
X	TRACE("szsize: %d\n", un->un_capacity, 0, 0);
X	return(un->un_capacity ? un->un_capacity : SZ_SIZE);
X}
X
X/*
X *  szmesg(cp, no)
X *	return a string that matches the number from a message table
X */
Xstatic char *
Xszmesg(cp, no)
Xchar	**cp;
X{
X	while(*cp[1]) {
X		if(*cp[0] == no)
X			return(*cp + 1);
X		cp++;
X	}
X	return("");
X	
X}
X
X/*
X *  SCSI sense key messages
X */
Xchar	*sz_keys[] = {
X	"\000KEY_NO_SENSE",
X	"\001KEY_RECOVERABLE_ERROR",
X	"\002KEY_NOT_READY",
X	"\003KEY_MEDIUM_ERROR",
X	"\004KEY_HARDWARE_ERROR",
X	"\005KEY_ILLEGAL_REQUEST",
X	"\006KEY_UNIT_ATTENTION",
X	"\007KEY_WRITE_PROTECT",
X	"\010KEY_BLANK_CHECK",
X	"\011KEY_VENDOR_UNIQUE",
X	"\012KEY_COPY_ABORTED",
X	"\013KEY_ABORTED_COMMAND",
X	"\014KEY_EQUAL",
X	"\015KEY_VOLUME_OVERFLOW",
X	"\016KEY_MISCOMPARE",
X	"\017KEY_RESERVED",
X	"\000",
X};
X
X/*
X *  TEAC extended code messages
X */
Xchar	*sz_codes[] = {
X	"\001No Index Signal",
X	"\004Drive Not Ready",
X	"\006Track Zero Found",
X	"\020ID CRC Error",
X	"\021Data CRC Error",
X	"\022No Address Mark in ID Field",
X	"\023No Address Mark in Data Field",
X	"\024No Record Found",
X	"\025Seek Error",
X	"\027Read Retries",
X	"\040Invalid Command",
X	"\041Illegal Logical Block",
X	"\044Illegal CDB Field",
X	"\045Invalid LUN",
X	"\046Invalid Field in Parameters",
X	"\047Write Protected",
X	"\050Medium Changed",
X	"\051Power/Device Reset",
X	"\052Parameters Changed",
X	"\053FDC Error",
X	"\060Incompatible Cartridge",
X	"\061Medium Format Corrupted",
X	"\084Internal Controller Error",
X	"\087SCSI Parity Error",
X	"\090Write Command Aborted",
X	"\214Deleted Data Address Mark",
X	"\240Selftest Error",
X	"\241Terminator Power Off",
X	"\242Strap SW set Error",
X	"\000",
X};
X
X/*
X *  SCSA packet fail reason messages
X */
Xchar	*sz_reasons[] = {
X	"\000no transport errors",
X	"\001stopped with not normal state",
X	"\002dma direction error occurred",
X	"\003unspecified transport error",
X	"\004SCSI bus reset destroyed command",
X	"\005Command transport aborted",
X	"\006Command timed out",
X	"\007Data Overrun",
X	"\010Command Overrun",
X	"\011Status Overrun",
X	"\012Message not Command Complete",
X	"\013Target refused Message Out phase",
X	"\014Extended Identify message rejected",
X	"\015Detected Error message rejected",
X	"\016Abort message rejected",
X	"\017Reject message rejected",
X	"\020No Operation message rejected",
X	"\021Parity Error message rejected",
X	"\022Bus Device Reset message rejected",
X	"\023Identify message rejected",
X	"\000",
X};
+ END-OF-FILE sz.c
chmod 'u=rw,g=r,o=r' 'sz.c'
set `wc -c 'sz.c'`
count=$1
case $count in
20289)	:;;
*)	echo 'Bad character count in ''sz.c' >&2
		echo 'Count should be 20289' >&2
esac
echo Extracting 'szdef.h'
sed 's/^X//' > 'szdef.h' << '+ END-OF-FILE ''szdef.h'
X/*
X *  SCSA compatible SCSI floppy driver includes for TEAC FD-235HS-300
X *
X *	Copyright (c) 1990/1991  A.Ullings, Vrije Universiteit, Amsterdam.
X *	Limited rights to use and modify are hereby granted for non-commercial
X *	purposes, provided that all copyright notices remain intact.
X *
X *	email:  fons@nat.vu.nl
X *
X *  @(#)szdef.h	1.5 1/14/91
X *
X */
X
X/*
X *  SCSA doesn't bother about modes... ??
X *  from the TEAC FC-1-00 Software Specification
X */
Xstruct scsi_mode {
X	u_char	mod_00;
X	u_char	mod_medium_type;
X#define SZ_MEDIUM_AUTO		0x02
X#define SZ_MEDIUM_1MB		0x80
X#define SZ_MEDIUM_2MB		0x88
X	u_char	mod_02;
X	u_char	mod_block_length;
X	u_char	mod_density_code;
X#define SZ_DENSITY_FM		0x01
X#define SZ_DENSITY_MFM		0x02
X	u_char	mod_num_block_2;
X	u_char	mod_num_block_1;
X	u_char	mod_num_block_0;
X	u_char	mod_08;
X	u_char	mod_block_length_2;
X	u_char	mod_block_length_1;
X	u_char	mod_block_length_0;
X};
X
X/*
X */
Xstruct sz_device {
X	struct scsi_pkt		*un_sense_pkt;	/* request sense packet */
X	struct scsi_pkt		*un_sbuf_pkt;	/* special function packet */
X	struct scsi_extended_sense	*un_sense;
X	short		un_openf;		/* opened flag */
X	short		un_scmd;		/* special command */
X	struct buf	un_sbuf;		/* specials buffer header */
X	struct buf	un_rbuf;		/* raw I/O header */
X	struct diskhd	un_utab;		/* queue header */
X	struct scsi_mode	un_mode;	/* per drive mode */
X	daddr_t		un_capacity;		/* number of blocks */
X};
X
X#define SZ_MAXUNIT		1
X#define SZ_UNIT(dev)		((minor(dev)>>3)&0x07)
X#define SZ_DEV_BSIZE		DEV_BSIZE
X#define SZ_SENSE_LENGTH		16
X#define SZ_MODE_LENGTH		sizeof(struct scsi_mode)
X#define SZ_TIMEOUT		12		/* 16 retries... */
X#define SZ_SIZE			(80*2*18)	/* default medium size */
+ END-OF-FILE szdef.h
chmod 'u=rw,g=r,o=r' 'szdef.h'
set `wc -c 'szdef.h'`
count=$1
case $count in
1674)	:;;
*)	echo 'Bad character count in ''szdef.h' >&2
		echo 'Count should be 1674' >&2
esac
exit 0


-- 
John Connin: manatee Orlando, Florida
         UUCP: {uunet,ge-dab,ucf-cs}!tarpit!tous!manatee!johnc