xref: /csrg-svn/sys/vax/uba/uu.c (revision 13834)
1*13834Ssam /*	uu.c	4.8	83/07/07	*/
211876Shelge 
312332Shelge #include "uu.h"
412857Shelge #if NUU > 0
511876Shelge /*
611896Shelge  * TU58 DECtape II/DL11 device driver
711876Shelge  *
813156Shelge  * The TU58 is treated as a block device (only).  Error detection and
913156Shelge  * recovery is not very extensive, but sufficient to handle the most
1013156Shelge  * common errors. It is assumed that the
1111876Shelge  * TU58 will follow the RSP protocol exactly, very few protocol
1211896Shelge  * errors are checked for.
1311876Shelge  */
1411896Shelge 
1512332Shelge #include "../machine/pte.h"
1611896Shelge 
1711876Shelge #include "../h/param.h"
1811876Shelge #include "../h/systm.h"
1911876Shelge #include "../h/buf.h"
2011876Shelge #include "../h/conf.h"
2112332Shelge #include "../h/time.h"
2211896Shelge #include "../h/kernel.h"
2311896Shelge #include "../h/errno.h"
2411896Shelge #include "../h/file.h"
2511876Shelge 
2611876Shelge #include "../vax/cpu.h"
2712332Shelge #include "../vax/nexus.h"
2812937Shelge #include "../vax/rsp.h"
2912332Shelge 
3011896Shelge #include "../vaxuba/ubavar.h"
3111896Shelge #include "../vaxuba/ubareg.h"
3211896Shelge #include "../vaxuba/uureg.h"
3311876Shelge 
3411876Shelge #define	NTUBLK	512		/* number of blocks on a TU58 cassette */
3512857Shelge #define	WRV     01              /* bit in minor dev => write w. read verify */
3612332Shelge #define	NDPC	02		/* drives per controller */
3712857Shelge #define	NUX	NDPC * NUU	/* number of drives */
3812332Shelge #define	NTUQ	02		/* # of block which can be queued up */
3912857Shelge #define	UMASK	01		/* unit number mask */
4012937Shelge #define UUIPL	0x14		/* ipl level to use */
4111876Shelge 
4212857Shelge struct packet uucmd[NUU];	/* a command sent to the TU58 */
4312857Shelge struct packet uudata[NUU];	/* a command or data returned from TU58 */
4412857Shelge struct buf uitab[NUU];		/* buffer queue headers */
4511876Shelge 
4611876Shelge /*
4712937Shelge  * Driver soft carrier structure
4811876Shelge  */
4912937Shelge struct uu_softc {
5012937Shelge 	u_char	*tu_rbptr;	/* pointer to buffer for read */
5112937Shelge 	int	tu_rcnt;	/* how much to read */
5212937Shelge 	u_char	*tu_wbptr;	/* pointer to buffer for write */
5312937Shelge 	int	tu_wcnt;	/* how much to write */
5412937Shelge 	int	tu_state;	/* current state of tansfer operation */
5512937Shelge 	int	tu_flag;	/* read in progress flag */
5612937Shelge 	char	*tu_addr;	/* real buffer data address */
5712937Shelge 	int	tu_count;	/* real requested count */
5812937Shelge 	int	tu_serrs;	/* count of soft errors */
5912937Shelge 	int	tu_cerrs;	/* count of checksum errors */
6012937Shelge 	int	tu_herrs;	/* count of hard errors */
6112937Shelge 	char    tu_dopen[2];	/* drive is open */
6213014Shelge } uu_softc[NUU];
6311876Shelge 
6412937Shelge #if defined(VAX750) || defined(VAX730)
6512937Shelge extern char *tustates[];
6612937Shelge #else
6712937Shelge char *tustates[TUS_NSTATES] = {
6811876Shelge 	"INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR",
6913014Shelge 	"SENDW", "GETH", "GETD", "GETC", "GET", "WAIT", "RCVERR", "CHKERR"
7011876Shelge };
7112937Shelge #endif
7212332Shelge 
7312857Shelge #define	UNIT(dev)	(minor(dev)>>1)
7411876Shelge 
7513156Shelge u_char	uunull[4] = { 0, 0, 0, 0 };	/* nulls to send for initialization */
7611896Shelge u_char	uuinit[2] = { TUF_INITF, TUF_INITF };	/* inits to send */
7711876Shelge 
7811896Shelge struct	uba_device	*uudinfo[NUU];
7911896Shelge 
8012857Shelge int uuprobe(), uuattach(), uurintr(), uuxintr(), uuwatch();
8112857Shelge u_short uustd[] = { 0176500 };
8212857Shelge struct uba_driver uudriver =
8312857Shelge     { uuprobe, 0, uuattach, 0, uustd, "uu", uudinfo };
8411896Shelge 
8511896Shelge int	uuwstart;
8612937Shelge static char pcnt[NUX];			/* pee/vee counters, one per drive */
8711896Shelge 
8811876Shelge /*ARGSUSED*/
8911896Shelge uuprobe(reg)
9011896Shelge 	caddr_t reg;
9111876Shelge {
9211896Shelge 	register int br, cvec;			/* value result */
9311896Shelge 	struct uudevice *uuaddr = (struct uudevice *)reg;
9411876Shelge 
9511876Shelge #ifdef lint
9611896Shelge 	br = 0; cvec = br; br = cvec;
9711896Shelge 	uurintr(0); uuxintr(0);
9811876Shelge #endif
9912857Shelge 	uuaddr->tcs = UUCS_INTR;
10012857Shelge 	DELAY(1000);
10112857Shelge 	uuaddr->tcs = 0;
10212857Shelge 	cvec -= 4;		/* since we are using the xmitter intrpt */
10311896Shelge 	return(sizeof (*uuaddr));
10411896Shelge }
10511896Shelge 
10611896Shelge uuattach(ui)
10712857Shelge 	register struct uba_device *ui;
10811896Shelge {
10911896Shelge }
11011896Shelge 
11111896Shelge /*ARGSUSED1*/
11211896Shelge uuopen(dev, flag)
11311896Shelge 	dev_t dev;
11411896Shelge 	int flag;
11511896Shelge {
11611896Shelge 	register struct uba_device *ui;
11713014Shelge 	register struct uu_softc *uuc;
11811896Shelge 	register struct uudevice *uuaddr;
11912332Shelge 	int ctlr, unit = UNIT(dev), s;
12011896Shelge 
12112857Shelge 	ctlr = unit / NDPC;
12212857Shelge 	if (unit >= NUX || (ui = uudinfo[ctlr]) == 0 || ui->ui_alive == 0)
12311876Shelge 		return (ENXIO);
12412937Shelge 	uuc = &uu_softc[ctlr];
12512937Shelge 	if (uuc->tu_dopen[unit&UMASK])
12611896Shelge 		return (EBUSY);
12711896Shelge 	if (uuwstart++ == 0)
12811896Shelge 		timeout(uuwatch, (caddr_t)0, hz);
12911896Shelge 
13012937Shelge 	uuc->tu_dopen[unit&UMASK]++;
13112857Shelge 	uuaddr = (struct uudevice *)ui->ui_addr;
13212857Shelge 	s = splx(UUIPL);
13311876Shelge 	/*
13413014Shelge 	 * If the other device on this controller
13513014Shelge 	 * is already active, just return
13613014Shelge 	 */
13713014Shelge 	if (uuc->tu_dopen[0] && uuc->tu_dopen[1])
13813156Shelge 		goto ok;
13913014Shelge 
14013014Shelge 	/*
14111896Shelge 	 * If the unit already initialized,
14211876Shelge 	 * just enable interrupts and return.
14311876Shelge 	 */
14412937Shelge 	if (uuc->tu_state == TUS_IDLE) {
14511896Shelge 		uuaddr->rcs = UUCS_INTR;
14612937Shelge 		goto ok;
14711876Shelge 	}
14811876Shelge 
14911876Shelge 	/*
15011876Shelge 	 * Must initialize, reset the cassette
15111876Shelge 	 * and wait for things to settle down.
15211876Shelge 	 */
15311896Shelge 	uureset(ctlr);
15411896Shelge 	sleep((caddr_t)uuc, PZERO+1);
15512857Shelge 	uitab[ctlr].b_active = NULL;
15612937Shelge 	if (uuc->tu_state != TUS_IDLE) {
15712937Shelge 		uuc->tu_state = TUS_INIT1;
15812937Shelge 		uuc->tu_dopen[unit&UMASK] = 0;
15912937Shelge 		uuc->tu_rcnt = uuc->tu_wcnt = 0;
16011896Shelge 		uuaddr->rcs = 0;
16111896Shelge 		uuaddr->tcs = 0;
16211896Shelge 		splx(s);
16312937Shelge 		return (EIO);
16411876Shelge 	}
16512937Shelge ok:
16611876Shelge 	splx(s);
16711876Shelge 	return (0);
16811876Shelge }
16911876Shelge 
17011896Shelge uuclose(dev, flag)
17111896Shelge 	dev_t dev;
17211896Shelge 	int flag;
17311876Shelge {
17413014Shelge 	register struct uu_softc *uuc;
17511876Shelge 
17613156Shelge 	uuc = &uu_softc[UNIT(dev)/NDPC];
17713156Shelge 	uuc->tu_dopen[UNIT(dev)&UMASK] = 0;
17811876Shelge }
17911876Shelge 
18011896Shelge uureset(ctlr)
18111896Shelge 	int ctlr;
18211876Shelge {
18313014Shelge 	register struct uu_softc *uuc = &uu_softc[ctlr];
18412332Shelge 	register struct packet *cmd = &uucmd[ctlr];
18512857Shelge 	struct uba_device *ui = uudinfo[ctlr];
18612857Shelge 	register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr;
18711876Shelge 
18812857Shelge 	uitab[ctlr].b_active++;
18912937Shelge 	uuc->tu_state = TUS_INIT1;
19012937Shelge 	uuc->tu_wbptr = uunull;
19112937Shelge 	uuc->tu_wcnt = sizeof (uunull);
19211896Shelge 	cmd->pk_flag = TUF_CMD;
19312332Shelge 	cmd->pk_mcount = sizeof (*cmd) - 4;
19411896Shelge 	cmd->pk_mod = 0;
19511896Shelge 	cmd->pk_seq = 0;
19612332Shelge 	cmd->pk_sw = 0;
19711896Shelge 	uuaddr->rcs = 0;
19811896Shelge 	uuaddr->tcs = UUCS_INTR | UUCS_BREAK;
19911896Shelge 	uuxintr(ctlr);				/* start output */
20011876Shelge }
20111876Shelge 
20211876Shelge /*
20311876Shelge  * Strategy routine for block I/O
20411876Shelge  */
20511896Shelge uustrategy(bp)
20611876Shelge 	register struct buf *bp;
20711876Shelge {
20812332Shelge 	register struct buf *uutab;
20911896Shelge 	struct uba_device *ui;
21012857Shelge 	int s, unit = UNIT(minor(bp->b_dev));
21111876Shelge 
21212857Shelge 	if (unit > NUX)
21311896Shelge 		goto bad;
21411896Shelge 	if (bp->b_blkno >= NTUBLK)
21511896Shelge 		goto bad;
21612857Shelge 	ui = uudinfo[unit/NDPC];
21711896Shelge 	if (ui == 0 || ui->ui_alive == 0)
21811896Shelge 		goto bad;
21912857Shelge 	uutab = &uitab[unit/NDPC];	/* one request queue per controller */
22013156Shelge 	s = splx(UUIPL);
22112332Shelge 	if ((bp->b_flags&B_READ) == 0)
22212937Shelge 		tu_pee(&pcnt[unit]);
22312937Shelge 	bp->av_forw = NULL;
22412332Shelge 	if (uutab->b_actf == NULL)
22512332Shelge 		uutab->b_actf = bp;
22612332Shelge 	else
22712937Shelge 		uutab->b_actl->av_forw = bp;
22812332Shelge 	uutab->b_actl = bp;
22912332Shelge 	if (uutab->b_active == 0)
23012857Shelge 		uustart(ui);
23111876Shelge 	splx(s);
23211896Shelge 	return;
23311896Shelge 
23411896Shelge bad:
23511896Shelge 	bp->b_flags |= B_ERROR;
23612332Shelge 	bp->b_error = ENXIO;
23711896Shelge 	iodone(bp);
23811896Shelge 	return;
23911876Shelge }
24011876Shelge 
24111876Shelge /*
24211876Shelge  * Start the transfer
24311876Shelge  */
24412857Shelge uustart(ui)
24512857Shelge 	register struct uba_device *ui;
24611876Shelge {
24711876Shelge 	register struct buf *bp;
24813014Shelge 	register struct uu_softc *uuc;
24911896Shelge 	struct packet *cmd;
25012857Shelge 	int ctlr = ui->ui_unit;
25111876Shelge 
25212857Shelge 	if ((bp = uitab[ctlr].b_actf) == NULL)
25311876Shelge 		return;
25412937Shelge 	uuc = &uu_softc[ctlr];
25512332Shelge 	cmd = &uucmd[ctlr];
25612937Shelge 	if (uuc->tu_state != TUS_IDLE) {
25712332Shelge 		uureset(ctlr);
25811876Shelge 		return;
25911876Shelge 	}
26012857Shelge 	uitab[ctlr].b_active++;
26112937Shelge 	uitab[ctlr].b_errcnt = 0;
26212937Shelge 	uuc->tu_addr = bp->b_un.b_addr;
26312937Shelge 	uuc->tu_count = cmd->pk_count = bp->b_bcount;
26412937Shelge 	cmd->pk_block = bp->b_blkno;
26512937Shelge 	if (bp->b_flags&B_READ) {
26612937Shelge 		cmd->pk_op = TUOP_READ;
26712937Shelge 		cmd->pk_mod = 0;
26812937Shelge 		uuc->tu_state = TUS_SENDR;
26912937Shelge 	} else {
27012937Shelge 		cmd->pk_op = TUOP_WRITE;
27112937Shelge 		cmd->pk_mod = minor(bp->b_dev)&WRV ? TUMD_WRV : 0;
27212937Shelge 		uuc->tu_state = TUS_SENDW;
27312937Shelge 	}
27412857Shelge 	cmd->pk_unit = UNIT(minor(bp->b_dev));
27512332Shelge 	cmd->pk_sw = 0;
27611896Shelge 	cmd->pk_chksum =
27712937Shelge 	    tuchk(*((short *)cmd), (u_short *)&cmd->pk_op, (int)cmd->pk_mcount);
27812937Shelge 	uuc->tu_wbptr = (u_char *)cmd;
27912937Shelge 	uuc->tu_wcnt = sizeof (*cmd);
28012332Shelge 	uuxintr(ctlr);
28111876Shelge }
28211876Shelge 
28311876Shelge /*
28413014Shelge  * TU58 receiver interrupt,
28513014Shelge  * handles whatever condition the
28613014Shelge  * pseudo DMA routine in locore is
28713014Shelge  * unable to handle, or, if UUDMA is
28813014Shelge  * undefined, handle all receiver interrupt
28913014Shelge  * processing
29011876Shelge  */
29112332Shelge uurintr(ctlr)
29212332Shelge 	int ctlr;
29311876Shelge {
29412857Shelge 	struct uba_device *ui = uudinfo[ctlr];
29513014Shelge 	register struct uu_softc *uuc = &uu_softc[ctlr];
29612857Shelge 	register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr;
29712857Shelge 	register struct buf *uutab = &uitab[ctlr];
29812332Shelge 	struct packet *data, *cmd;
29912937Shelge 	struct buf *bp;
30012937Shelge 	int c, unit;
30111876Shelge 
30212857Shelge 	c = uuaddr->rdb;
30312937Shelge 	data = &uudata[ctlr];
30413014Shelge 	cmd = &uucmd[ctlr];
30513014Shelge #if !defined(UUDMA)
30613014Shelge 	if (c & UURDB_ERROR)
30713014Shelge 		uuc->tu_state = TUS_RCVERR;
30813014Shelge 	else {
30913014Shelge 		if (uuc->tu_rcnt) {
31013014Shelge 			*uuc->tu_rbptr++ = c;
31113014Shelge 			if (--uuc->tu_rcnt)
31213014Shelge 				return;
31313014Shelge 		}
31413014Shelge 	}
31513014Shelge #endif
31613014Shelge 
31713014Shelge 	/*
31813014Shelge 	 * Switch on the tu_state of the transfer.
31913014Shelge 	 */
32013014Shelge 	switch(uuc->tu_state) {
32113014Shelge 
32213014Shelge 	/*
32313014Shelge 	 * A data error occured in uudma
32413014Shelge 	 * (either overrun or break)
32513014Shelge 	 */
32613014Shelge 	case TUS_RCVERR:
32713156Shelge 		if ((c & UURDB_ORUN) == 0)
32813156Shelge 			printf("uu%d: break received, transfer restarted\n",
329*13834Ssam 			    data->pk_unit);
33013156Shelge 		uuc->tu_serrs++;
33113014Shelge 		uu_restart(ctlr, ui);
33213014Shelge 		break;
33311876Shelge 
33411876Shelge 	/*
33511876Shelge 	 * If we get an unexpected "continue",
33611876Shelge 	 * start all over again...
33711876Shelge 	 */
33812937Shelge 	case TUS_INIT2:
33912937Shelge 		uuc->tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1;
34012937Shelge 		uuc->tu_flag = 0;
34112332Shelge 		wakeup((caddr_t)uuc);
34212857Shelge 		uustart(ui);
34311876Shelge 		break;
34411876Shelge 
34511876Shelge 	/*
34611876Shelge 	 * Only transition from this state
34711876Shelge 	 * is on a "continue", so if we don't
34811876Shelge 	 * get it, reset the world.
34911876Shelge 	 */
35012937Shelge 	case TUS_WAIT:			/* waiting for continue */
35112332Shelge 		switch(c) {
35212332Shelge 		case TUF_CONT:  /* got the expected continue */
35312937Shelge 			uuc->tu_flag = 0;
35412332Shelge 			data->pk_flag = TUF_DATA;
35512937Shelge 			data->pk_mcount = MIN(128, uuc->tu_count);
35612332Shelge 			data->pk_chksum =
35712937Shelge 			    tuchk(*((short *)data), (caddr_t)uuc->tu_addr,
35812332Shelge 				(int)data->pk_mcount);
35912937Shelge 			uuc->tu_state = TUS_SENDH;
36012937Shelge 			uuc->tu_wbptr = (u_char *)data;
36112937Shelge 			uuc->tu_wcnt = 2;
36212857Shelge 			uuxintr(ctlr);
36311876Shelge 			break;
36412332Shelge 
36512332Shelge 		case TUF_CMD:   /* sending us an END packet...error */
36612937Shelge 			uuc->tu_state = TUS_GET;
36712937Shelge 			uuc->tu_rbptr = (u_char *)data;
36813014Shelge 			uuc->tu_rcnt = sizeof (*data) - 1;
36912937Shelge 			uuc->tu_flag = 1;
37012332Shelge 			uuaddr->tcs = 0;
37113014Shelge 			*uuc->tu_rbptr++ = c & UUDB_DMASK;
37213014Shelge 			break;
37312332Shelge 
37412332Shelge 		case TUF_INITF:
37512857Shelge 			uureset(ctlr);
37612332Shelge 			break;
37712332Shelge 
37812332Shelge 		default:        /* something random...bad news */
37912937Shelge 			uuc->tu_state = TUS_INIT1;
38012332Shelge 			break;
38111876Shelge 		}
38211876Shelge 		break;
38311876Shelge 
38412937Shelge 	case TUS_SENDW:
38512937Shelge 		if (c != TUF_CONT && c != TUF_INITF)
38611876Shelge 			goto bad;
38713014Shelge 		uu_restart(ctlr, ui);
38811876Shelge 		break;
38911876Shelge 
39011876Shelge 	/*
39111876Shelge 	 * Got header, now get data; amount to
39211896Shelge 	 * fetch is included in packet.
39313014Shelge 	 * (data packets are handled entirely
39413014Shelge 	 * in uudma)
39511876Shelge 	 */
39612937Shelge 	case TUS_GETH:
39713156Shelge #ifndef UUDMA
39813156Shelge 		if (data->pk_flag == TUF_DATA)
39913156Shelge 			uuc->tu_rbptr = (u_char *)uuc->tu_addr;
40013156Shelge #endif
40112937Shelge 		uuc->tu_rcnt = data->pk_mcount;
40212937Shelge 		uuc->tu_state = TUS_GETD;
40311876Shelge 		break;
40411876Shelge 
40511876Shelge 	/*
40611876Shelge 	 * Got the data, now fetch the checksum.
40711876Shelge 	 */
40812937Shelge 	case TUS_GETD:
40912937Shelge 		uuc->tu_rbptr = (u_char *)&data->pk_chksum;
41012937Shelge 		uuc->tu_rcnt = sizeof (data->pk_chksum);
41112937Shelge 		uuc->tu_state = TUS_GETC;
41211876Shelge 		break;
41311876Shelge 
41412937Shelge 	case TUS_GETC:
41511876Shelge 		/* got entire packet */
41612332Shelge 		if (data->pk_chksum !=
41712937Shelge 		    tuchk(*((short *)data), (u_short *)
41813014Shelge 		     (data->pk_flag == TUF_DATA ?
41913156Shelge 		     (u_short *) uuc->tu_addr : (u_short *)&data->pk_op),
42012332Shelge 		     (int)data->pk_mcount))
42113014Shelge 	case TUS_CHKERR:
42212937Shelge 			uuc->tu_cerrs++;
42313014Shelge 	case TUS_GET:
42412332Shelge 		if (data->pk_flag == TUF_DATA) {
42511876Shelge 			/* data packet, advance to next */
42612937Shelge 			uuc->tu_addr += data->pk_mcount;
42712937Shelge 			uuc->tu_count -= data->pk_mcount;
42812937Shelge 			uuc->tu_state = TUS_GETH;
42912937Shelge 			uuc->tu_rbptr = (u_char *)data;	/* next packet */
43012937Shelge 			uuc->tu_rcnt = 2;
43112332Shelge 		} else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) {
43211876Shelge 			/* end packet, idle and reenable transmitter */
43312937Shelge 			uuc->tu_state = TUS_IDLE;
43412937Shelge 			uuc->tu_flag = 0;
43512937Shelge 			uuaddr->tcs = UUCS_INTR;
43612937Shelge 			if ((bp = uutab->b_actf) == NULL) {
43713156Shelge 				printf("uu%d: no bp, active %d\n",
438*13834Ssam 				    data->pk_unit, uitab[ctlr].b_active);
43912857Shelge 				uustart(ui);
44011876Shelge 				return;
44111876Shelge 			}
44212937Shelge 			unit = UNIT(minor(bp->b_dev));
44312332Shelge 			if (data->pk_mod > 1) {        /* hard error */
44413014Shelge 				printf("uu%d: hard error bn%d,", unit,
445*13834Ssam 				    bp->b_blkno);
44613014Shelge 				printf(" pk_mod %o\n", data->pk_mod&0xff);
44711876Shelge 				bp->b_flags |= B_ERROR;
44812937Shelge 				uuc->tu_herrs++;
44912332Shelge 			} else if (data->pk_mod != 0)	/* soft error */
45012937Shelge 				uuc->tu_serrs++;
45112332Shelge 			uutab->b_active = NULL;
45212937Shelge 			uutab->b_actf = bp->av_forw;
45312937Shelge 			bp->b_resid = uuc->tu_count;
45411876Shelge 			if ((bp->b_flags&B_READ) == 0)
45512937Shelge 				tu_vee(&pcnt[unit]);
45611876Shelge 			iodone(bp);
45712857Shelge 			uustart(ui);
45811876Shelge 		} else {
45913156Shelge 			/*
46013156Shelge 			 * Neither data nor end: data was lost
46113156Shelge 			 * somehow, restart the transfer.
46213156Shelge 			 */
46312332Shelge 			uuaddr->rcs = 0;		/* flush the rest */
46413014Shelge 			uu_restart(ctlr, ui);
46513156Shelge 			uuc->tu_serrs++;
46611876Shelge 		}
46711876Shelge 		break;
46811876Shelge 
46912937Shelge 	case TUS_IDLE:
47012937Shelge 	case TUS_INIT1:
47111876Shelge 		break;
47211876Shelge 
47311876Shelge 	default:
47411876Shelge bad:
47511876Shelge 		if (c == TUF_INITF) {
47613156Shelge 			printf("uu%d protocol error, state=", data->pk_unit);
47712937Shelge 			printstate(uuc->tu_state);
47811876Shelge 			printf(", op=%x, cnt=%d, block=%d\n",
47912332Shelge 			    cmd->pk_op, cmd->pk_count, cmd->pk_block);
48012332Shelge 			uutab->b_active = NULL;
48112332Shelge 			if (bp = uutab->b_actf) {
48211876Shelge 				bp->b_flags |= B_ERROR;
48312937Shelge 				uutab->b_actf = bp->av_forw;
48411876Shelge 				if ((bp->b_flags&B_READ) == 0)
48512937Shelge 					tu_vee(&pcnt[unit]);
48611876Shelge 				iodone(bp);
48711876Shelge 			}
48812937Shelge 			uuc->tu_state = TUS_INIT1;
48911876Shelge 		} else {
49012332Shelge 			printf("uu%d receive state error, state=",
49113156Shelge 				data->pk_unit);
49212937Shelge 			printstate(uuc->tu_state);
49313014Shelge 			printf(", byte=%x\n", c & 0xff);
49411876Shelge #ifdef notdef
49512937Shelge 			uuc->tu_state = TUS_INIT1;
49611876Shelge #endif
49712332Shelge 			wakeup((caddr_t)uuc);
49811876Shelge 		}
49911876Shelge 	}
50011876Shelge }
50111876Shelge 
50212937Shelge 
50312937Shelge /*
50411876Shelge  * TU58 transmitter interrupt
50511876Shelge  */
50612332Shelge uuxintr(ctlr)
50712332Shelge 	int ctlr;
50811876Shelge {
50913014Shelge 	register struct uu_softc *uuc = &uu_softc[ctlr];
51012857Shelge 	register struct uudevice *uuaddr;
51112332Shelge 	register struct packet *data;
51212857Shelge 	struct uba_device *ui = uudinfo[ctlr];
51312332Shelge 	int c;
51411876Shelge 
51512857Shelge 	data = &uudata[ctlr];
51612857Shelge 	uuaddr = (struct uudevice *) ui->ui_addr;
51711876Shelge top:
51812937Shelge 	if (uuc->tu_wcnt) {
51911876Shelge 		/* still stuff to send, send one byte */
52012332Shelge 		while ((uuaddr->tcs & UUCS_READY) == 0)
52111876Shelge 			;
52212937Shelge 		uuaddr->tdb = *uuc->tu_wbptr++;
52312937Shelge 		uuc->tu_wcnt--;
52411876Shelge 		return;
52511876Shelge 	}
52611876Shelge 
52711876Shelge 	/*
52811876Shelge 	 * Last message byte was sent out.
52912937Shelge 	 * Switch on tu_state of transfer.
53011876Shelge 	 */
53112937Shelge 	switch(uuc->tu_state) {
53211876Shelge 
53311876Shelge 	/*
53411876Shelge 	 * Two nulls have been sent, remove break, and send inits
53511876Shelge 	 */
53612937Shelge 	case TUS_INIT1:
53712332Shelge 		uuaddr->tcs = UUCS_INTR;
53812937Shelge 		uuc->tu_state = TUS_INIT2;
53912937Shelge 		uuc->tu_wbptr = uuinit;
54012937Shelge 		uuc->tu_wcnt = sizeof (uuinit);
54111876Shelge 		goto top;
54211876Shelge 
54311876Shelge 	/*
54411876Shelge 	 * Inits have been sent, wait for a continue msg.
54511876Shelge 	 */
54612937Shelge 	case TUS_INIT2:
54712857Shelge 		c = uuaddr->rdb;	/* prevent overrun error */
54812332Shelge 		uuaddr->rcs = UUCS_INTR;
54912937Shelge 		uuc->tu_flag = 1;
55011876Shelge 		break;
55111876Shelge 
55211876Shelge 	/*
55311876Shelge 	 * Read cmd packet sent, get ready for data
55411876Shelge 	 */
55512937Shelge 	case TUS_SENDR:
55612937Shelge 		uuc->tu_state = TUS_GETH;
55712937Shelge 		uuc->tu_rbptr = (u_char *)data;
55812937Shelge 		uuc->tu_rcnt = 2;
55912937Shelge 		uuc->tu_flag = 1;
56012332Shelge 		uuaddr->tcs = 0;	/* disable transmitter interrupts */
56112937Shelge 		uuaddr->rcs = UUCS_INTR;
56211876Shelge 		break;
56311876Shelge 
56411876Shelge 	/*
56511876Shelge 	 * Write cmd packet sent, wait for continue
56611876Shelge 	 */
56712937Shelge 	case TUS_SENDW:
56812937Shelge 		uuc->tu_state = TUS_WAIT;
56912937Shelge 		uuc->tu_flag = 1;
57012332Shelge 		if ((uuaddr->rcs&UUCS_INTR) == 0) {
57111876Shelge 			printf("NO IE\n");
57212332Shelge 			uuaddr->rcs = UUCS_INTR;
57311876Shelge 		}
57411876Shelge 		break;
57511876Shelge 
57611876Shelge 	/*
57711876Shelge 	 * Header sent, send data.
57811876Shelge 	 */
57912937Shelge 	case TUS_SENDH:
58012937Shelge 		uuc->tu_state = TUS_SENDD;
58112937Shelge 		uuc->tu_wbptr = (u_char *)uuc->tu_addr;
58212937Shelge 		uuc->tu_wcnt = data->pk_mcount;
58311876Shelge 		goto top;
58411876Shelge 
58511876Shelge 	/*
58611876Shelge 	 * Data sent, follow with checksum.
58711876Shelge 	 */
58812937Shelge 	case TUS_SENDD:
58912937Shelge 		uuc->tu_state = TUS_SENDC;
59012937Shelge 		uuc->tu_wbptr = (u_char *)&data->pk_chksum;
59112937Shelge 		uuc->tu_wcnt = sizeof (data->pk_chksum);
59211876Shelge 		goto top;
59311876Shelge 
59411876Shelge 	/*
59511876Shelge 	 * Checksum sent, wait for continue.
59611876Shelge 	 */
59712937Shelge 	case TUS_SENDC:
59811876Shelge 		/*
59912937Shelge 		 * Update buffer address and count.
60011876Shelge 		 */
60112937Shelge 		uuc->tu_addr += data->pk_mcount;
60212937Shelge 		uuc->tu_count -= data->pk_mcount;
60312937Shelge 		if (uuc->tu_count) {
60412937Shelge 			uuc->tu_state = TUS_WAIT;
60512937Shelge 			uuc->tu_flag = 1;
60611876Shelge 			break;
60711876Shelge 		}
60811876Shelge 
60911876Shelge 		/*
61011876Shelge 		 * End of transmission, get ready for end packet.
61111876Shelge 		 */
61212937Shelge 		uuc->tu_state = TUS_GET;
61312937Shelge 		uuc->tu_rbptr = (u_char *)data;
61412937Shelge 		uuc->tu_rcnt = sizeof (*data);
61512937Shelge 		uuc->tu_flag = 1;
61612332Shelge 		uuaddr->tcs = 0;		/* disable transm. interrupts */
61711876Shelge 		break;
61811876Shelge 
61911876Shelge 	/*
62012332Shelge 	 * Random interrupt
62111876Shelge 	 */
62213156Shelge 	case TUS_IDLE:		/* stray interrupt? */
62313156Shelge 
62411876Shelge 	default:
62511876Shelge 		break;
62611876Shelge 	}
62712937Shelge }
62812937Shelge 
62912937Shelge uuwatch()
63012937Shelge {
63113014Shelge 	register struct uu_softc *uuc;
63212937Shelge 	register struct uudevice *uuaddr;
63312937Shelge 	struct uba_device *ui;
63412937Shelge 	struct buf *bp, *uutab;
63512937Shelge 	int s, ctlr, active = 0;
63612937Shelge 
63712937Shelge 	for (ctlr=0; ctlr<NUU; ctlr++) {
63812937Shelge 		int i;
63912937Shelge 
64012937Shelge 		uuc = &uu_softc[ctlr];
64112937Shelge 		ui = uudinfo[ctlr];
64212937Shelge 		uuaddr = (struct uudevice *)ui->ui_addr;
64312937Shelge 		uutab = &uitab[ctlr];
64412937Shelge 		if ((uuc->tu_dopen[0] == 0) && (uuc->tu_dopen[1] == 0) &&
64512937Shelge 		    (uutab->b_active == 0)) {
64613156Shelge 			/*
64713156Shelge 			 * If both devices on this controller have
64813156Shelge 			 * been closed and the request queue is
64913156Shelge 			 * empty, mark ths controller not active
65013156Shelge 			 */
65112937Shelge 			uuc->tu_flag = 0;
65212937Shelge 			uuaddr->rcs = 0;
65312937Shelge 			continue;
65412937Shelge 		}
65512937Shelge 		active++;
65612937Shelge 		if (uuc->tu_flag)
65712937Shelge 			uuc->tu_flag++;
65812937Shelge 		if (uuc->tu_flag <= 40)
65912937Shelge 			continue;
66013156Shelge 		printf("uu%d: read stalled\n", uudata[ctlr].pk_unit);
661*13834Ssam #ifdef notdef
66212937Shelge 		printf("%X %X %X %X %X %X %X\n", uuc->tu_rbptr, uuc->tu_rcnt,
66313156Shelge 		       uuc->tu_wbptr, uuc->tu_wcnt, uuc->tu_state, uuc->tu_addr,
66413156Shelge 		       uuc->tu_count);
665*13834Ssam #endif
66612937Shelge 		uuc->tu_flag = 0;
66712937Shelge 		s = splx(UUIPL);
66812937Shelge 		i = uuaddr->rdb;		/* dummy */
66912937Shelge 		uuaddr->rcs = UUCS_INTR;	/* in case we were flushing */
67012937Shelge 		uuaddr->tcs = UUCS_INTR;
67112937Shelge 		uuc->tu_state = TUS_IDLE;
67212937Shelge 		if (!uutab->b_active) {
67312937Shelge 			wakeup((caddr_t)uuc);
67412937Shelge 			goto retry;
67512937Shelge 		}
67612937Shelge 		if (++uutab->b_errcnt <= 1) {
67712937Shelge 			uustart(ui);
67812937Shelge 			goto retry;
67912937Shelge 		}
68012937Shelge 		if (bp = uutab->b_actf) {
68112937Shelge 			bp->b_flags |= B_ERROR;
68212937Shelge 			if ((bp->b_flags&B_READ) == 0)
68312937Shelge 				tu_vee(&pcnt[UNIT(minor(bp->b_dev))]);
68412937Shelge 			iodone(bp);
68512937Shelge 		}
68612937Shelge retry:
68712937Shelge 		(void) splx(s);
68811876Shelge 	}
68912937Shelge 	if (active)
69012937Shelge 		timeout(uuwatch, (caddr_t)0, hz);
69112937Shelge 	else
69212937Shelge 		uuwstart = 0;
69312937Shelge 	return;
69411876Shelge }
69511876Shelge 
69612937Shelge #if !defined(VAX750) && !defined(VAX730)
69711876Shelge /*
69811876Shelge  * Compute checksum TU58 fashion
69911876Shelge  */
70011876Shelge #ifdef lint
70112937Shelge tuchk(word, cp, n)
70211876Shelge 	register word;
70311876Shelge 	register unsigned short *cp;
70411876Shelge 	int n;
70511876Shelge {
70611876Shelge 	register int c = n >> 1;
70711876Shelge 	register long temp;
70811876Shelge 
70911876Shelge 	do {
71011876Shelge 		temp = *cp++;	/* temp, only because vax cc won't *r++ */
71111876Shelge 		word += temp;
71211876Shelge 	} while (--c > 0);
71311876Shelge 	if (n & 1)
71411876Shelge 		word += *(unsigned char *)cp;
71511876Shelge 	while (word & 0xffff0000)
71611876Shelge 		word = (word & 0xffff) + ((word >> 16) & 0xffff);
71711876Shelge 	return (word);
71811876Shelge }
71911876Shelge #else
72012937Shelge tuchk(word0, wp, n)
72111896Shelge 	register int word0;			/* r11 */
72211896Shelge 	register char *wp;			/* r10 */
72311896Shelge 	register int n;				/* r9 */
72411876Shelge {
72511876Shelge 	asm("loop:");
72611896Shelge 	asm("	addw2	(r10)+,r11");		/* add a word to sum */
72711896Shelge 	asm("	adwc	$0,r11");		/* add in carry, end-around */
72811876Shelge 	asm("	acbl	$2,$-2,r9,loop");	/* done yet? */
72911896Shelge 	asm("	blbc	r9,ok");		/* odd byte count? */
73011896Shelge 	asm("	movzbw	(r10),r10");		/* yes, get last byte */
73111896Shelge 	asm("	addw2	r10,r11");		/* add it in */
73211896Shelge 	asm("	adwc	$0,r11");		/* and the carry */
73311876Shelge 	asm("ok:");
73411896Shelge 	asm("	movl	r11,r0");		/* return sum */
73511876Shelge }
73611876Shelge #endif
73711876Shelge 
73812937Shelge tu_pee(cp)
73912332Shelge char *cp;
74012332Shelge {
74112332Shelge 	register int s;
74212332Shelge 
74312857Shelge 	s = splx(UUIPL);
74412332Shelge 	if (++(*cp) > NTUQ) {
74512332Shelge 		sleep(cp, PRIBIO);
74611876Shelge 	}
74712332Shelge 	splx(s);
74812332Shelge }
74912332Shelge 
75012937Shelge tu_vee(cp)
75112332Shelge char *cp;
75212332Shelge {
75312332Shelge 	register int s;
75412332Shelge 
75512857Shelge 	s = splx(UUIPL);
75612332Shelge 	if (--(*cp) <= NTUQ) {
75712332Shelge 		wakeup(cp);
75811876Shelge 	}
75911876Shelge 	splx(s);
76011876Shelge }
76111876Shelge #endif
76212332Shelge 
76312937Shelge uuioctl(dev, cmd, data, flag)
76412937Shelge 	dev_t dev;
76512937Shelge 	caddr_t data;
76612937Shelge {
76712937Shelge 	/*
76813156Shelge 	 * add code to wind/rewind cassette here
76912937Shelge 	 */
77012937Shelge 	return (ENXIO);
77112937Shelge }
77212937Shelge 
77312937Shelge #endif
77412937Shelge 
77513014Shelge uu_restart(ctlr, ui)
77613014Shelge 	int ctlr;
77713014Shelge 	struct uba_device *ui;
77813014Shelge {
77913014Shelge 	uureset(ctlr);
78013014Shelge 	timeout(uustart, (caddr_t)ui, hz * 3);
78113014Shelge }
782