xref: /csrg-svn/sys/vax/uba/uu.c (revision 12937)
1*12937Shelge /*	uu.c	4.5	83/06/08	*/
211876Shelge 
312332Shelge #include "uu.h"
412857Shelge #if NUU > 0
511876Shelge /*
611896Shelge  * TU58 DECtape II/DL11 device driver
711876Shelge  *
811896Shelge  * The TU58 * is treated as a block device (only).  Error detection and
911876Shelge  * recovery is almost non-existant.  It is assumed that the
1011876Shelge  * TU58 will follow the RSP protocol exactly, very few protocol
1111896Shelge  * errors are checked for.
1211876Shelge  */
1311896Shelge 
1412332Shelge #include "../machine/pte.h"
1511896Shelge 
1611876Shelge #include "../h/param.h"
1711876Shelge #include "../h/systm.h"
1811876Shelge #include "../h/buf.h"
1911876Shelge #include "../h/conf.h"
2012332Shelge #include "../h/time.h"
2111896Shelge #include "../h/kernel.h"
2211896Shelge #include "../h/errno.h"
2311896Shelge #include "../h/uio.h"
2411896Shelge #include "../h/file.h"
2511876Shelge 
2611876Shelge #include "../vax/cpu.h"
2712332Shelge #include "../vax/nexus.h"
28*12937Shelge #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 */
40*12937Shelge #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 /*
47*12937Shelge  * Driver soft carrier structure
4811876Shelge  */
49*12937Shelge struct uu_softc {
50*12937Shelge 	u_char	*tu_rbptr;	/* pointer to buffer for read */
51*12937Shelge 	int	tu_rcnt;	/* how much to read */
52*12937Shelge 	u_char	*tu_wbptr;	/* pointer to buffer for write */
53*12937Shelge 	int	tu_wcnt;	/* how much to write */
54*12937Shelge 	int	tu_state;	/* current state of tansfer operation */
55*12937Shelge 	int	tu_flag;	/* read in progress flag */
56*12937Shelge 	char	*tu_addr;	/* real buffer data address */
57*12937Shelge 	int	tu_count;	/* real requested count */
58*12937Shelge 	int	tu_serrs;	/* count of soft errors */
59*12937Shelge 	int	tu_cerrs;	/* count of checksum errors */
60*12937Shelge 	int	tu_herrs;	/* count of hard errors */
61*12937Shelge 	char    tu_dopen[2];	/* drive is open */
62*12937Shelge };
6311876Shelge 
64*12937Shelge struct uu_softc uu_softc[NUU];
6511876Shelge 
66*12937Shelge #if defined(VAX750) || defined(VAX730)
67*12937Shelge extern char *tustates[];
68*12937Shelge #else
69*12937Shelge char *tustates[TUS_NSTATES] = {
7011876Shelge 	"INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR",
7111876Shelge 	"SENDW", "GETH", "GETD", "GETC", "GET", "WAIT"
7211876Shelge };
73*12937Shelge #endif
7412332Shelge 
7512857Shelge #define	UNIT(dev)	(minor(dev)>>1)
7611876Shelge 
7711896Shelge u_char	uunull[2] = { 0, 0 };	/* nulls to send for initialization */
7811896Shelge u_char	uuinit[2] = { TUF_INITF, TUF_INITF };	/* inits to send */
7911876Shelge 
8011896Shelge struct	uba_device	*uudinfo[NUU];
8111896Shelge 
8212857Shelge int uuprobe(), uuattach(), uurintr(), uuxintr(), uuwatch();
8312857Shelge u_short uustd[] = { 0176500 };
8412857Shelge struct uba_driver uudriver =
8512857Shelge     { uuprobe, 0, uuattach, 0, uustd, "uu", uudinfo };
8611896Shelge 
8711896Shelge int	uuwstart;
88*12937Shelge static char pcnt[NUX];			/* pee/vee counters, one per drive */
8911896Shelge 
9011876Shelge /*ARGSUSED*/
9111896Shelge uuprobe(reg)
9211896Shelge 	caddr_t reg;
9311876Shelge {
9411896Shelge 	register int br, cvec;			/* value result */
9511896Shelge 	struct uudevice *uuaddr = (struct uudevice *)reg;
9611876Shelge 
9711876Shelge #ifdef lint
9811896Shelge 	br = 0; cvec = br; br = cvec;
9911896Shelge 	uurintr(0); uuxintr(0);
10011876Shelge #endif
10112857Shelge 	uuaddr->tcs = UUCS_INTR;
10212857Shelge 	DELAY(1000);
10312857Shelge 	uuaddr->tcs = 0;
10412857Shelge 	cvec -= 4;		/* since we are using the xmitter intrpt */
10511896Shelge 	return(sizeof (*uuaddr));
10611896Shelge }
10711896Shelge 
10811896Shelge uuattach(ui)
10912857Shelge 	register struct uba_device *ui;
11011896Shelge {
11111896Shelge }
11211896Shelge 
11311896Shelge /*ARGSUSED1*/
11411896Shelge uuopen(dev, flag)
11511896Shelge 	dev_t dev;
11611896Shelge 	int flag;
11711896Shelge {
11811896Shelge 	register struct uba_device *ui;
119*12937Shelge 	register struct tu *uuc;
12011896Shelge 	register struct uudevice *uuaddr;
12112332Shelge 	int ctlr, unit = UNIT(dev), s;
12211896Shelge 
12312857Shelge 	ctlr = unit / NDPC;
12412857Shelge 	if (unit >= NUX || (ui = uudinfo[ctlr]) == 0 || ui->ui_alive == 0)
12511876Shelge 		return (ENXIO);
126*12937Shelge 	uuc = &uu_softc[ctlr];
127*12937Shelge 	if (uuc->tu_dopen[unit&UMASK])
12811896Shelge 		return (EBUSY);
12911896Shelge 	if (uuwstart++ == 0)
13011896Shelge 		timeout(uuwatch, (caddr_t)0, hz);
13111896Shelge 
132*12937Shelge 	uuc->tu_dopen[unit&UMASK]++;
13312857Shelge 	uuaddr = (struct uudevice *)ui->ui_addr;
13412857Shelge 	s = splx(UUIPL);
13511876Shelge 	/*
13611896Shelge 	 * If the unit already initialized,
13711876Shelge 	 * just enable interrupts and return.
13811876Shelge 	 */
139*12937Shelge 	if (uuc->tu_state == TUS_IDLE) {
14011896Shelge 		uuaddr->rcs = UUCS_INTR;
141*12937Shelge 		goto ok;
14211876Shelge 	}
14311876Shelge 
14411876Shelge 	/*
14511876Shelge 	 * Must initialize, reset the cassette
14611876Shelge 	 * and wait for things to settle down.
14711876Shelge 	 */
14811896Shelge 	uureset(ctlr);
14911896Shelge 	sleep((caddr_t)uuc, PZERO+1);
15012857Shelge 	uitab[ctlr].b_active = NULL;
151*12937Shelge 	if (uuc->tu_state != TUS_IDLE) {
152*12937Shelge 		uuc->tu_state = TUS_INIT1;
153*12937Shelge 		uuc->tu_dopen[unit&UMASK] = 0;
154*12937Shelge 		uuc->tu_rcnt = uuc->tu_wcnt = 0;
15511896Shelge 		uuaddr->rcs = 0;
15611896Shelge 		uuaddr->tcs = 0;
15711896Shelge 		splx(s);
158*12937Shelge 		return (EIO);
15911876Shelge 	}
160*12937Shelge ok:
16111876Shelge 	splx(s);
16211876Shelge 	return (0);
16311876Shelge }
16411876Shelge 
16511896Shelge uuclose(dev, flag)
16611896Shelge 	dev_t dev;
16711896Shelge 	int flag;
16811876Shelge {
169*12937Shelge 	register struct tu *uuc;
17012857Shelge 	int unit = UNIT(dev);
171*12937Shelge 	int ctlr = unit/NDPC;
17211876Shelge 
173*12937Shelge 	uuc = &uu_softc[ctlr];
174*12937Shelge 	if (uuc->tu_serrs + uuc->tu_cerrs + uuc->tu_herrs != 0) {
17511876Shelge 		/*
17611876Shelge 		 * A tu58 is like nothing ever seen before;
17711876Shelge 		 * I guess this is appropriate then...
17811876Shelge 		 */
17911876Shelge 		uprintf(
18012857Shelge 		   "uu%d: %d soft errors, %d checksum errors, %d hard errors\n",
181*12937Shelge 		    unit, uuc->tu_serrs, uuc->tu_cerrs, uuc->tu_herrs);
182*12937Shelge 		    uuc->tu_serrs = uuc->tu_cerrs = uuc->tu_herrs = 0;
18311876Shelge 	}
184*12937Shelge 	uuc->tu_dopen[unit&UMASK] = 0;
18511876Shelge }
18611876Shelge 
18711896Shelge uureset(ctlr)
18811896Shelge 	int ctlr;
18911876Shelge {
190*12937Shelge 	register struct tu *uuc = &uu_softc[ctlr];
19112332Shelge 	register struct packet *cmd = &uucmd[ctlr];
19212857Shelge 	struct uba_device *ui = uudinfo[ctlr];
19312857Shelge 	register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr;
19411876Shelge 
19512857Shelge 	printf ("uureset\n");
19612857Shelge 	uitab[ctlr].b_active++;
197*12937Shelge 	uuc->tu_state = TUS_INIT1;
198*12937Shelge 	uuc->tu_wbptr = uunull;
199*12937Shelge 	uuc->tu_wcnt = sizeof (uunull);
20011896Shelge 	cmd->pk_flag = TUF_CMD;
20112332Shelge 	cmd->pk_mcount = sizeof (*cmd) - 4;
20211896Shelge 	cmd->pk_mod = 0;
20311896Shelge 	cmd->pk_seq = 0;
20412332Shelge 	cmd->pk_sw = 0;
20511896Shelge 	uuaddr->rcs = 0;
20611896Shelge 	uuaddr->tcs = UUCS_INTR | UUCS_BREAK;
20711896Shelge 	uuxintr(ctlr);				/* start output */
20811876Shelge }
20911876Shelge 
21011876Shelge /*
21111876Shelge  * Strategy routine for block I/O
21211876Shelge  */
21311896Shelge uustrategy(bp)
21411876Shelge 	register struct buf *bp;
21511876Shelge {
21612332Shelge 	register struct buf *uutab;
21711896Shelge 	struct uba_device *ui;
21812857Shelge 	int s, unit = UNIT(minor(bp->b_dev));
21911876Shelge 
22012857Shelge 	if (unit > NUX)
22111896Shelge 		goto bad;
22211896Shelge 	if (bp->b_blkno >= NTUBLK)
22311896Shelge 		goto bad;
22412857Shelge 	ui = uudinfo[unit/NDPC];
22511896Shelge 	if (ui == 0 || ui->ui_alive == 0)
22611896Shelge 		goto bad;
22712857Shelge 	uutab = &uitab[unit/NDPC];	/* one request queue per controller */
22812332Shelge 	if ((bp->b_flags&B_READ) == 0)
229*12937Shelge 		tu_pee(&pcnt[unit]);
23012857Shelge 	s = splx(UUIPL);
231*12937Shelge 	bp->av_forw = NULL;
23212332Shelge 	if (uutab->b_actf == NULL)
23312332Shelge 		uutab->b_actf = bp;
23412332Shelge 	else
235*12937Shelge 		uutab->b_actl->av_forw = bp;
23612332Shelge 	uutab->b_actl = bp;
23712332Shelge 	if (uutab->b_active == 0)
23812857Shelge 		uustart(ui);
23911876Shelge 	splx(s);
24011896Shelge 	return;
24111896Shelge 
24211896Shelge bad:
24311896Shelge 	bp->b_flags |= B_ERROR;
24412332Shelge 	bp->b_error = ENXIO;
24511896Shelge 	iodone(bp);
24611896Shelge 	return;
24711876Shelge }
24811876Shelge 
24911876Shelge /*
25011876Shelge  * Start the transfer
25111876Shelge  */
25212857Shelge uustart(ui)
25312857Shelge 	register struct uba_device *ui;
25411876Shelge {
25511876Shelge 	register struct buf *bp;
256*12937Shelge 	register struct tu *uuc;
25711896Shelge 	struct packet *cmd;
25812857Shelge 	int ctlr = ui->ui_unit;
25911876Shelge 
26012857Shelge 	if ((bp = uitab[ctlr].b_actf) == NULL)
26111876Shelge 		return;
262*12937Shelge 	uuc = &uu_softc[ctlr];
26312332Shelge 	cmd = &uucmd[ctlr];
264*12937Shelge 	if (uuc->tu_state != TUS_IDLE) {
26512332Shelge 		uureset(ctlr);
26611876Shelge 		return;
26711876Shelge 	}
26812857Shelge 	uitab[ctlr].b_active++;
269*12937Shelge 	uitab[ctlr].b_errcnt = 0;
270*12937Shelge 	uuc->tu_addr = bp->b_un.b_addr;
271*12937Shelge 	uuc->tu_count = cmd->pk_count = bp->b_bcount;
272*12937Shelge 	cmd->pk_block = bp->b_blkno;
273*12937Shelge 	if (bp->b_flags&B_READ) {
274*12937Shelge 		cmd->pk_op = TUOP_READ;
275*12937Shelge 		cmd->pk_mod = 0;
276*12937Shelge 		uuc->tu_state = TUS_SENDR;
277*12937Shelge 	} else {
278*12937Shelge 		cmd->pk_op = TUOP_WRITE;
279*12937Shelge 		cmd->pk_mod = minor(bp->b_dev)&WRV ? TUMD_WRV : 0;
280*12937Shelge 		uuc->tu_state = TUS_SENDW;
281*12937Shelge 	}
28212857Shelge 	cmd->pk_unit = UNIT(minor(bp->b_dev));
28312332Shelge 	cmd->pk_sw = 0;
28411896Shelge 	cmd->pk_chksum =
285*12937Shelge 	    tuchk(*((short *)cmd), (u_short *)&cmd->pk_op, (int)cmd->pk_mcount);
286*12937Shelge 	uuc->tu_wbptr = (u_char *)cmd;
287*12937Shelge 	uuc->tu_wcnt = sizeof (*cmd);
28812332Shelge 	uuxintr(ctlr);
28911876Shelge }
29011876Shelge 
29111876Shelge /*
29211876Shelge  * TU58 receiver interrupt
29311876Shelge  */
29412332Shelge uurintr(ctlr)
29512332Shelge 	int ctlr;
29611876Shelge {
29712857Shelge 	struct uba_device *ui = uudinfo[ctlr];
298*12937Shelge 	register struct tu *uuc = &uu_softc[ctlr];
29912857Shelge 	register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr;
30012857Shelge 	register struct buf *uutab = &uitab[ctlr];
30112332Shelge 	struct packet *data, *cmd;
302*12937Shelge 	struct buf *bp;
303*12937Shelge 	int c, unit;
30411876Shelge 
30512857Shelge 	c = uuaddr->rdb;
306*12937Shelge 	data = &uudata[ctlr];
307*12937Shelge 	if (c & UURDB_ERROR) {
308*12937Shelge 		if (c & UURDB_ORUN)
309*12937Shelge 			printf("uu(%d): data overrun, bytes left: %d",
310*12937Shelge 			  ui->ui_unit,
311*12937Shelge 			  uuc->tu_count + uuc->tu_rcnt - data->pk_mcount);
312*12937Shelge 		else
313*12937Shelge 			printf("uu(%d): break received", ui->ui_unit);
314*12937Shelge 		printf(", device reset, state=");
315*12937Shelge 		printstate(uuc->tu_state);
316*12937Shelge 		uureset(ctlr);
317*12937Shelge 		printf("\n");
318*12937Shelge 		timeout(uustart, (caddr_t)ui, hz/2);	/* start uustart when */
319*12937Shelge 							/* reset is done */
32012332Shelge 		return;
32111876Shelge 	}
32212332Shelge top:
323*12937Shelge 	c &= UUDB_DMASK;
324*12937Shelge 	if (uuc->tu_rcnt) {		/* still waiting for data? */
325*12937Shelge 		*uuc->tu_rbptr++ = c;	/* yup, put it there */
326*12937Shelge 		if (--uuc->tu_rcnt)	/* decrement count, any left? */
32711876Shelge 			return;		/* get some more */
32811876Shelge 	}
329*12937Shelge 	cmd = &uucmd[ctlr];
33011876Shelge 
33111876Shelge 	/*
33211876Shelge 	 * We got all the data we were expecting for now,
333*12937Shelge 	 * switch on the tu_state of the transfer.
33411876Shelge 	 */
335*12937Shelge 	switch(uuc->tu_state) {
33611876Shelge 
33711876Shelge 	/*
33811876Shelge 	 * If we get an unexpected "continue",
33911876Shelge 	 * start all over again...
34011876Shelge 	 */
341*12937Shelge 	case TUS_INIT2:
342*12937Shelge 		uuc->tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1;
343*12937Shelge 		uuc->tu_flag = 0;
34412332Shelge 		wakeup((caddr_t)uuc);
34512857Shelge 		uustart(ui);
34611876Shelge 		break;
34711876Shelge 
34811876Shelge 	/*
34911876Shelge 	 * Only transition from this state
35011876Shelge 	 * is on a "continue", so if we don't
35111876Shelge 	 * get it, reset the world.
35211876Shelge 	 */
353*12937Shelge 	case TUS_WAIT:			/* waiting for continue */
35412332Shelge 		switch(c) {
35512332Shelge 		case TUF_CONT:  /* got the expected continue */
356*12937Shelge 			uuc->tu_flag = 0;
35712332Shelge 			data->pk_flag = TUF_DATA;
358*12937Shelge 			data->pk_mcount = MIN(128, uuc->tu_count);
35912332Shelge 			data->pk_chksum =
360*12937Shelge 			    tuchk(*((short *)data), (caddr_t)uuc->tu_addr,
36112332Shelge 				(int)data->pk_mcount);
362*12937Shelge 			uuc->tu_state = TUS_SENDH;
363*12937Shelge 			uuc->tu_wbptr = (u_char *)data;
364*12937Shelge 			uuc->tu_wcnt = 2;
36512857Shelge 			uuxintr(ctlr);
36611876Shelge 			break;
36712332Shelge 
36812332Shelge 		case TUF_CMD:   /* sending us an END packet...error */
369*12937Shelge 			uuc->tu_state = TUS_GET;
370*12937Shelge 			uuc->tu_rbptr = (u_char *)data;
371*12937Shelge 			uuc->tu_rcnt = sizeof (*data);
372*12937Shelge 			uuc->tu_flag = 1;
37312332Shelge 			uuaddr->tcs = 0;
37412332Shelge 			goto top;
37512332Shelge 
37612332Shelge 		case TUF_INITF:
37712857Shelge 			uureset(ctlr);
37812332Shelge 			break;
37912332Shelge 
38012332Shelge 		default:        /* something random...bad news */
381*12937Shelge 			uuc->tu_state = TUS_INIT1;
38212332Shelge 			break;
38311876Shelge 		}
38411876Shelge 		break;
38511876Shelge 
386*12937Shelge 	case TUS_SENDW:
387*12937Shelge 		if (c != TUF_CONT && c != TUF_INITF)
38811876Shelge 			goto bad;
38912332Shelge 		uureset(ctlr);
39011876Shelge 		break;
39111876Shelge 
39211876Shelge 	/*
39311876Shelge 	 * Got header, now get data; amount to
39411896Shelge 	 * fetch is included in packet.
39511876Shelge 	 */
396*12937Shelge 	case TUS_GETH:
397*12937Shelge 		if (data->pk_flag == TUF_DATA) {
398*12937Shelge 			uu_getblk((u_char *)uuc->tu_addr, data, uuaddr);
399*12937Shelge 			goto getc;
400*12937Shelge 		}
401*12937Shelge 		uuc->tu_rcnt = data->pk_mcount;
402*12937Shelge 		uuc->tu_state = TUS_GETD;
40311876Shelge 		break;
40411876Shelge 
40511876Shelge 	/*
40611876Shelge 	 * Got the data, now fetch the checksum.
40711876Shelge 	 */
408*12937Shelge 	case TUS_GETD:
409*12937Shelge 		uuc->tu_rbptr = (u_char *)&data->pk_chksum;
410*12937Shelge 		uuc->tu_rcnt = sizeof (data->pk_chksum);
411*12937Shelge 		uuc->tu_state = TUS_GETC;
41211876Shelge 		break;
41311876Shelge 
414*12937Shelge 	case TUS_GET:
415*12937Shelge 	case TUS_GETC:
416*12937Shelge getc:
41711876Shelge 		/* got entire packet */
41811876Shelge #ifdef notdef
41912332Shelge 		if (data->pk_chksum !=
420*12937Shelge 		    tuchk(*((short *)data), (u_short *)
421*12937Shelge 		     (data->pk_flag == TUF_DATA ? uuc->tu_addr : &data->pk_op),
42212332Shelge 		     (int)data->pk_mcount))
423*12937Shelge 			uuc->tu_cerrs++;
42411876Shelge #endif
42512332Shelge 		if (data->pk_flag == TUF_DATA) {
42611876Shelge 			/* data packet, advance to next */
427*12937Shelge 			uuc->tu_addr += data->pk_mcount;
428*12937Shelge 			uuc->tu_count -= data->pk_mcount;
429*12937Shelge 			uuc->tu_state = TUS_GETH;
430*12937Shelge 			uuc->tu_rbptr = (u_char *)data;	/* next packet */
431*12937Shelge 			uuc->tu_rcnt = 2;
43212332Shelge 		} else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) {
43311876Shelge 			/* end packet, idle and reenable transmitter */
434*12937Shelge 			uuc->tu_state = TUS_IDLE;
435*12937Shelge 			uuc->tu_flag = 0;
436*12937Shelge 			uuaddr->tcs = UUCS_INTR;
437*12937Shelge 			if ((bp = uutab->b_actf) == NULL) {
43812857Shelge 				printf("uu(%d): no bp, active %d\n",
439*12937Shelge 					ui->ui_unit, uitab[ctlr].b_active);
44012857Shelge 				uustart(ui);
44111876Shelge 				return;
44211876Shelge 			}
443*12937Shelge 			unit = UNIT(minor(bp->b_dev));
44412332Shelge 			if (data->pk_mod > 1) {        /* hard error */
44511876Shelge 				bp->b_flags |= B_ERROR;
446*12937Shelge 				uuc->tu_herrs++;
44711896Shelge 				harderr(bp, "uu");
44812332Shelge 				printf(" pk_mod %o\n", data->pk_mod&0xff);
44912332Shelge 			} else if (data->pk_mod != 0)	/* soft error */
450*12937Shelge 				uuc->tu_serrs++;
45112332Shelge 			uutab->b_active = NULL;
452*12937Shelge 			uutab->b_actf = bp->av_forw;
453*12937Shelge 			bp->b_resid = uuc->tu_count;
45411876Shelge 			if ((bp->b_flags&B_READ) == 0)
455*12937Shelge 				tu_vee(&pcnt[unit]);
45611876Shelge 			iodone(bp);
457*12937Shelge 			printf(".");
45812857Shelge 			uustart(ui);
45911876Shelge 		} else {
46011876Shelge 			printf("neither data nor end: %o %o\n",
46112332Shelge 			    data->pk_flag&0xff, data->pk_op&0xff);
46212332Shelge 			uuaddr->rcs = 0;		/* flush the rest */
463*12937Shelge 			uuc->tu_state = TUS_INIT1;
46411876Shelge 		}
46511876Shelge 		break;
46611876Shelge 
467*12937Shelge 	case TUS_IDLE:
468*12937Shelge 	case TUS_INIT1:
46911876Shelge 		break;
47011876Shelge 
47111876Shelge 	default:
47211876Shelge bad:
47311876Shelge 		if (c == TUF_INITF) {
47412857Shelge 			printf("uu%d protocol error, state=", unit);
475*12937Shelge 			printstate(uuc->tu_state);
47611876Shelge 			printf(", op=%x, cnt=%d, block=%d\n",
47712332Shelge 			    cmd->pk_op, cmd->pk_count, cmd->pk_block);
47812332Shelge 			uutab->b_active = NULL;
47912332Shelge 			if (bp = uutab->b_actf) {
48011876Shelge 				bp->b_flags |= B_ERROR;
481*12937Shelge 				uutab->b_actf = bp->av_forw;
48211876Shelge 				if ((bp->b_flags&B_READ) == 0)
483*12937Shelge 					tu_vee(&pcnt[unit]);
48411876Shelge 				iodone(bp);
48511876Shelge 			}
486*12937Shelge 			uuc->tu_state = TUS_INIT1;
48711876Shelge 		} else {
48812332Shelge 			printf("uu%d receive state error, state=",
48912857Shelge 				unit);
490*12937Shelge 			printstate(uuc->tu_state);
49111876Shelge 			printf(", byte=%x\n", c);
49211876Shelge #ifdef notdef
493*12937Shelge 			uuc->tu_state = TUS_INIT1;
49411876Shelge #endif
49512332Shelge 			wakeup((caddr_t)uuc);
49611876Shelge 		}
49711876Shelge 	}
49811876Shelge }
49911876Shelge 
50011876Shelge /*
501*12937Shelge  * Simulate DMA input from the TU58,
502*12937Shelge  * usually 128 bytes plus the 2 byte checksum
503*12937Shelge  * will be read, leaving the CPU `dead' for
504*12937Shelge  * approximately 0.135 seconds @ 9600 baud
505*12937Shelge  */
506*12937Shelge uu_getblk(buffer, data, uuaddr)
507*12937Shelge 	register u_char *buffer;
508*12937Shelge 	register struct uudevice *uuaddr;
509*12937Shelge 	struct packet *data;
510*12937Shelge {
511*12937Shelge 	int s;
512*12937Shelge 	int count = (unsigned) data->pk_mcount + 2;
513*12937Shelge 
514*12937Shelge 	s = spl5();		/* make sure we don't get interrupted by */
515*12937Shelge 				/* disk i/o */
516*12937Shelge 	uuaddr->rcs = 0;	/* disable interrupts temporarily */
517*12937Shelge 	while (count--) {
518*12937Shelge 		while ((uuaddr->rcs & UUCS_READY) == 0)
519*12937Shelge 			;
520*12937Shelge 		*buffer++ = uuaddr->rdb & UUDB_DMASK;
521*12937Shelge 		if (count == 2)
522*12937Shelge 			buffer = (u_char *)&data->pk_chksum;
523*12937Shelge 	}
524*12937Shelge 	uuaddr->rcs = UUCS_INTR;
525*12937Shelge 	(void) splx(s);
526*12937Shelge }
527*12937Shelge 
528*12937Shelge /*
52911876Shelge  * TU58 transmitter interrupt
53011876Shelge  */
53112332Shelge uuxintr(ctlr)
53212332Shelge 	int ctlr;
53311876Shelge {
534*12937Shelge 	register struct tu *uuc = &uu_softc[ctlr];
53512857Shelge 	register struct uudevice *uuaddr;
53612332Shelge 	register struct packet *data;
53712857Shelge 	struct uba_device *ui = uudinfo[ctlr];
53812332Shelge 	int c;
53911876Shelge 
54012857Shelge 	data = &uudata[ctlr];
54112857Shelge 	uuaddr = (struct uudevice *) ui->ui_addr;
54211876Shelge top:
543*12937Shelge 	if (uuc->tu_wcnt) {
54411876Shelge 		/* still stuff to send, send one byte */
54512332Shelge 		while ((uuaddr->tcs & UUCS_READY) == 0)
54611876Shelge 			;
547*12937Shelge 		uuaddr->tdb = *uuc->tu_wbptr++;
548*12937Shelge 		uuc->tu_wcnt--;
54911876Shelge 		return;
55011876Shelge 	}
55111876Shelge 
55211876Shelge 	/*
55311876Shelge 	 * Last message byte was sent out.
554*12937Shelge 	 * Switch on tu_state of transfer.
55511876Shelge 	 */
556*12937Shelge 	switch(uuc->tu_state) {
55711876Shelge 
55811876Shelge 	/*
55911876Shelge 	 * Two nulls have been sent, remove break, and send inits
56011876Shelge 	 */
561*12937Shelge 	case TUS_INIT1:
56212332Shelge 		uuaddr->tcs = UUCS_INTR;
563*12937Shelge 		uuc->tu_state = TUS_INIT2;
564*12937Shelge 		uuc->tu_wbptr = uuinit;
565*12937Shelge 		uuc->tu_wcnt = sizeof (uuinit);
56611876Shelge 		goto top;
56711876Shelge 
56811876Shelge 	/*
56911876Shelge 	 * Inits have been sent, wait for a continue msg.
57011876Shelge 	 */
571*12937Shelge 	case TUS_INIT2:
57212857Shelge 		c = uuaddr->rdb;	/* prevent overrun error */
57312332Shelge 		uuaddr->rcs = UUCS_INTR;
574*12937Shelge 		uuc->tu_flag = 1;
57511876Shelge 		break;
57611876Shelge 
577*12937Shelge 	case TUS_IDLE:		/* stray interrupt? */
57811876Shelge 		break;
57911876Shelge 
58011876Shelge 	/*
58111876Shelge 	 * Read cmd packet sent, get ready for data
58211876Shelge 	 */
583*12937Shelge 	case TUS_SENDR:
584*12937Shelge 		uuc->tu_state = TUS_GETH;
585*12937Shelge 		uuc->tu_rbptr = (u_char *)data;
586*12937Shelge 		uuc->tu_rcnt = 2;
587*12937Shelge 		uuc->tu_flag = 1;
58812332Shelge 		uuaddr->tcs = 0;	/* disable transmitter interrupts */
589*12937Shelge 		uuaddr->rcs = UUCS_INTR;
59011876Shelge 		break;
59111876Shelge 
59211876Shelge 	/*
59311876Shelge 	 * Write cmd packet sent, wait for continue
59411876Shelge 	 */
595*12937Shelge 	case TUS_SENDW:
596*12937Shelge 		uuc->tu_state = TUS_WAIT;
597*12937Shelge 		uuc->tu_flag = 1;
59812332Shelge 		if ((uuaddr->rcs&UUCS_INTR) == 0) {
59911876Shelge 			printf("NO IE\n");
60012332Shelge 			uuaddr->rcs = UUCS_INTR;
60111876Shelge 		}
60211876Shelge 		break;
60311876Shelge 
60411876Shelge 	/*
60511876Shelge 	 * Header sent, send data.
60611876Shelge 	 */
607*12937Shelge 	case TUS_SENDH:
608*12937Shelge 		uuc->tu_state = TUS_SENDD;
609*12937Shelge 		uuc->tu_wbptr = (u_char *)uuc->tu_addr;
610*12937Shelge 		uuc->tu_wcnt = data->pk_mcount;
61111876Shelge 		goto top;
61211876Shelge 
61311876Shelge 	/*
61411876Shelge 	 * Data sent, follow with checksum.
61511876Shelge 	 */
616*12937Shelge 	case TUS_SENDD:
617*12937Shelge 		uuc->tu_state = TUS_SENDC;
618*12937Shelge 		uuc->tu_wbptr = (u_char *)&data->pk_chksum;
619*12937Shelge 		uuc->tu_wcnt = sizeof (data->pk_chksum);
62011876Shelge 		goto top;
62111876Shelge 
62211876Shelge 	/*
62311876Shelge 	 * Checksum sent, wait for continue.
62411876Shelge 	 */
625*12937Shelge 	case TUS_SENDC:
62611876Shelge 		/*
627*12937Shelge 		 * Update buffer address and count.
62811876Shelge 		 */
629*12937Shelge 		uuc->tu_addr += data->pk_mcount;
630*12937Shelge 		uuc->tu_count -= data->pk_mcount;
631*12937Shelge 		if (uuc->tu_count) {
632*12937Shelge 			uuc->tu_state = TUS_WAIT;
633*12937Shelge 			uuc->tu_flag = 1;
63411876Shelge 			break;
63511876Shelge 		}
63611876Shelge 
63711876Shelge 		/*
63811876Shelge 		 * End of transmission, get ready for end packet.
63911876Shelge 		 */
640*12937Shelge 		uuc->tu_state = TUS_GET;
641*12937Shelge 		uuc->tu_rbptr = (u_char *)data;
642*12937Shelge 		uuc->tu_rcnt = sizeof (*data);
643*12937Shelge 		uuc->tu_flag = 1;
64412332Shelge 		uuaddr->tcs = 0;		/* disable transm. interrupts */
64511876Shelge 		break;
64611876Shelge 
64711876Shelge 	/*
64812332Shelge 	 * Random interrupt
64911876Shelge 	 */
65011876Shelge 	default:
65111876Shelge 		break;
65211876Shelge 	}
653*12937Shelge }
654*12937Shelge 
655*12937Shelge uuwatch()
656*12937Shelge {
657*12937Shelge 	register struct tu *uuc;
658*12937Shelge 	register struct uudevice *uuaddr;
659*12937Shelge 	struct uba_device *ui;
660*12937Shelge 	struct buf *bp, *uutab;
661*12937Shelge 	int s, ctlr, active = 0;
662*12937Shelge 
663*12937Shelge 	for (ctlr=0; ctlr<NUU; ctlr++) {
664*12937Shelge 		int i;
665*12937Shelge 
666*12937Shelge 		uuc = &uu_softc[ctlr];
667*12937Shelge 		ui = uudinfo[ctlr];
668*12937Shelge 		uuaddr = (struct uudevice *)ui->ui_addr;
669*12937Shelge 		uutab = &uitab[ctlr];
670*12937Shelge 		if ((uuc->tu_dopen[0] == 0) && (uuc->tu_dopen[1] == 0) &&
671*12937Shelge 		    (uutab->b_active == 0)) {
672*12937Shelge 			uuc->tu_flag = 0;
673*12937Shelge 			uuaddr->rcs = 0;
674*12937Shelge 			continue;
675*12937Shelge 		}
676*12937Shelge 		active++;
677*12937Shelge 		if (uuc->tu_flag)
678*12937Shelge 			uuc->tu_flag++;
679*12937Shelge 		if (uuc->tu_flag <= 40)
680*12937Shelge 			continue;
681*12937Shelge 		printf("uu(%d): read stalled\n", ctlr);
682*12937Shelge 		printf("%X %X %X %X %X %X %X\n", uuc->tu_rbptr, uuc->tu_rcnt,
683*12937Shelge 		       uuc->tu_wbptr, uuc->tu_wcnt, uuc->tu_state, uuc->tu_addr, uuc->tu_count);
684*12937Shelge 		uuc->tu_flag = 0;
685*12937Shelge 		s = splx(UUIPL);
686*12937Shelge 		i = uuaddr->rdb;		/* dummy */
687*12937Shelge 		uuaddr->rcs = UUCS_INTR;	/* in case we were flushing */
688*12937Shelge 		uuaddr->tcs = UUCS_INTR;
689*12937Shelge 		uuc->tu_state = TUS_IDLE;
690*12937Shelge 		if (!uutab->b_active) {
691*12937Shelge 			wakeup((caddr_t)uuc);
692*12937Shelge 			goto retry;
693*12937Shelge 		}
694*12937Shelge 		if (++uutab->b_errcnt <= 1) {
695*12937Shelge 			uustart(ui);
696*12937Shelge 			goto retry;
697*12937Shelge 		}
698*12937Shelge 		if (bp = uutab->b_actf) {
699*12937Shelge 			bp->b_flags |= B_ERROR;
700*12937Shelge 			if ((bp->b_flags&B_READ) == 0)
701*12937Shelge 				tu_vee(&pcnt[UNIT(minor(bp->b_dev))]);
702*12937Shelge 			iodone(bp);
703*12937Shelge 		}
704*12937Shelge retry:
705*12937Shelge 		(void) splx(s);
70611876Shelge 	}
707*12937Shelge 	if (active)
708*12937Shelge 		timeout(uuwatch, (caddr_t)0, hz);
709*12937Shelge 	else
710*12937Shelge 		uuwstart = 0;
711*12937Shelge 	return;
71211876Shelge }
71311876Shelge 
714*12937Shelge #if !defined(VAX750) && !defined(VAX730)
71511876Shelge /*
71611876Shelge  * Compute checksum TU58 fashion
71711876Shelge  */
71811876Shelge #ifdef lint
719*12937Shelge tuchk(word, cp, n)
72011876Shelge 	register word;
72111876Shelge 	register unsigned short *cp;
72211876Shelge 	int n;
72311876Shelge {
72411876Shelge 	register int c = n >> 1;
72511876Shelge 	register long temp;
72611876Shelge 
72711876Shelge 	do {
72811876Shelge 		temp = *cp++;	/* temp, only because vax cc won't *r++ */
72911876Shelge 		word += temp;
73011876Shelge 	} while (--c > 0);
73111876Shelge 	if (n & 1)
73211876Shelge 		word += *(unsigned char *)cp;
73311876Shelge 	while (word & 0xffff0000)
73411876Shelge 		word = (word & 0xffff) + ((word >> 16) & 0xffff);
73511876Shelge 	return (word);
73611876Shelge }
73711876Shelge #else
738*12937Shelge tuchk(word0, wp, n)
73911896Shelge 	register int word0;			/* r11 */
74011896Shelge 	register char *wp;			/* r10 */
74111896Shelge 	register int n;				/* r9 */
74211876Shelge {
74311876Shelge 	asm("loop:");
74411896Shelge 	asm("	addw2	(r10)+,r11");		/* add a word to sum */
74511896Shelge 	asm("	adwc	$0,r11");		/* add in carry, end-around */
74611876Shelge 	asm("	acbl	$2,$-2,r9,loop");	/* done yet? */
74711896Shelge 	asm("	blbc	r9,ok");		/* odd byte count? */
74811896Shelge 	asm("	movzbw	(r10),r10");		/* yes, get last byte */
74911896Shelge 	asm("	addw2	r10,r11");		/* add it in */
75011896Shelge 	asm("	adwc	$0,r11");		/* and the carry */
75111876Shelge 	asm("ok:");
75211896Shelge 	asm("	movl	r11,r0");		/* return sum */
75311876Shelge }
75411876Shelge #endif
75511876Shelge 
756*12937Shelge tu_pee(cp)
75712332Shelge char *cp;
75812332Shelge {
75912332Shelge 	register int s;
76012332Shelge 
76112857Shelge 	s = splx(UUIPL);
76212332Shelge 	if (++(*cp) > NTUQ) {
76312332Shelge 		sleep(cp, PRIBIO);
76411876Shelge 	}
76512332Shelge 	splx(s);
76612332Shelge }
76712332Shelge 
768*12937Shelge tu_vee(cp)
76912332Shelge char *cp;
77012332Shelge {
77112332Shelge 	register int s;
77212332Shelge 
77312857Shelge 	s = splx(UUIPL);
77412332Shelge 	if (--(*cp) <= NTUQ) {
77512332Shelge 		wakeup(cp);
77611876Shelge 	}
77711876Shelge 	splx(s);
77811876Shelge }
77911876Shelge #endif
78012332Shelge 
781*12937Shelge uuioctl(dev, cmd, data, flag)
782*12937Shelge 	dev_t dev;
783*12937Shelge 	caddr_t data;
784*12937Shelge {
785*12937Shelge 	/*
786*12937Shelge 	 * to be added later
787*12937Shelge 	 */
788*12937Shelge 	return (ENXIO);
789*12937Shelge }
790*12937Shelge 
791*12937Shelge #endif
792*12937Shelge 
793