xref: /csrg-svn/sys/vax/uba/uu.c (revision 11876)
1*11876Shelge /*	tu.c	4.13	83/02/10	*/
2*11876Shelge 
3*11876Shelge #if defined(VAX750) || defined(VAX730)
4*11876Shelge /*
5*11876Shelge  * TU58 DECtape II device driver
6*11876Shelge  *
7*11876Shelge  * This driver controls the console TU58s on a VAX-11/750 or VAX-11/730.
8*11876Shelge  * It could be easily modified for a Unibus TU58.  The TU58
9*11876Shelge  * is treated as a block device (only).  Error detection and
10*11876Shelge  * recovery is almost non-existant.  It is assumed that the
11*11876Shelge  * TU58 will follow the RSP protocol exactly, very few protocol
12*11876Shelge  * errors are checked for.  It is assumed that the 750 uses standard
13*11876Shelge  * RSP while the 730 uses Modified RSP (MRSP).  At the time when 750's
14*11876Shelge  * are converted to MRSP (by replacing EPROMS in the TU58), the tests
15*11876Shelge  * based on MRSP can be removed.
16*11876Shelge  */
17*11876Shelge #include "../h/param.h"
18*11876Shelge #include "../h/systm.h"
19*11876Shelge #include "../h/buf.h"
20*11876Shelge #include "../h/conf.h"
21*11876Shelge #include "../h/dir.h"
22*11876Shelge #include "../h/user.h"
23*11876Shelge #include "../h/kernel.h"
24*11876Shelge 
25*11876Shelge #include "../vax/cpu.h"
26*11876Shelge #include "../vax/mtpr.h"
27*11876Shelge 
28*11876Shelge #define	printd	if(tudebug) printf
29*11876Shelge #ifdef	printd
30*11876Shelge int	tudebug;	/* printd */
31*11876Shelge #endif	printd
32*11876Shelge 
33*11876Shelge #define	NTU	((cpu == VAX_750) ? 1 : 2)
34*11876Shelge #define DNUM    01      /* mask for drive number (should match NTU) */
35*11876Shelge #if !defined(MRSP) || lint
36*11876Shelge #define	MRSP	(cpu != VAX_750)
37*11876Shelge #endif
38*11876Shelge #define	NTUBLK	512		/* number of blocks on a TU58 cassette */
39*11876Shelge #define WRV     02              /* bit in minor dev => write w. read verify */
40*11876Shelge #define NTUQ    2               /* # of blocks which can be queued up */
41*11876Shelge #define	TUIPL	((cpu == VAX_750) ? 0x17 : 0x14)
42*11876Shelge 
43*11876Shelge /*
44*11876Shelge  * Device register bits
45*11876Shelge  */
46*11876Shelge #define	READY	0200		/* transmitter ready */
47*11876Shelge #define	DONE	0200		/* receiver done */
48*11876Shelge #define	IE	0100		/* interrupt enable */
49*11876Shelge #define	BREAK	1		/* send break */
50*11876Shelge 
51*11876Shelge /*
52*11876Shelge  * Structure of a command packet
53*11876Shelge  */
54*11876Shelge struct packet {
55*11876Shelge 	u_char	pk_flag;	/* indicates packet type (cmd, data, etc.) */
56*11876Shelge 	u_char	pk_mcount;	/* length of packet (bytes) */
57*11876Shelge 	u_char	pk_op;		/* operation to perform (read, write, etc.) */
58*11876Shelge 	u_char	pk_mod;		/* modifier for op or returned status */
59*11876Shelge 	u_char	pk_unit;	/* unit number */
60*11876Shelge 	u_char	pk_sw;		/* switches */
61*11876Shelge 	u_short	pk_seq;		/* sequence number, always zero */
62*11876Shelge 	u_short	pk_count;	/* requested byte count for read or write */
63*11876Shelge 	u_short	pk_block;	/* block number for read, write, or seek */
64*11876Shelge 	u_short	pk_chksum;	/* checksum, by words with end around carry */
65*11876Shelge };
66*11876Shelge 
67*11876Shelge struct packet tucmd;		/* a command sent to the TU58 */
68*11876Shelge struct packet tudata;		/* a command or data returned from TU58 */
69*11876Shelge 
70*11876Shelge /*
71*11876Shelge  * State information
72*11876Shelge  */
73*11876Shelge struct tu {
74*11876Shelge 	u_char	*tu_rbptr;	/* pointer to buffer for read */
75*11876Shelge 	int	tu_rcnt;	/* how much to read */
76*11876Shelge 	u_char	*tu_wbptr;	/* pointer to buffer for write */
77*11876Shelge 	int	tu_wcnt;	/* how much to write */
78*11876Shelge 	int	tu_state;	/* current tu_state of tansfer operation */
79*11876Shelge 	int	tu_flag;	/* read in progress flag */
80*11876Shelge 	char	*tu_addr;	/* real buffer data address */
81*11876Shelge 	int	tu_count;	/* real requested count */
82*11876Shelge 	int	tu_serrs;	/* count of soft errors */
83*11876Shelge 	int	tu_cerrs;	/* count of checksum errors */
84*11876Shelge 	int	tu_herrs;	/* count of hard errors */
85*11876Shelge 	char    tu_dopen[2];	/* drive is open */
86*11876Shelge } tu;
87*11876Shelge 
88*11876Shelge /*
89*11876Shelge  * States
90*11876Shelge  */
91*11876Shelge #define	TUS_INIT1	0	/* sending nulls */
92*11876Shelge #define	TUS_INIT2	1	/* sending inits */
93*11876Shelge #define	TUS_IDLE	2	/* initialized, no transfer in progress */
94*11876Shelge #define	TUS_SENDH	3	/* sending header */
95*11876Shelge #define	TUS_SENDD	4	/* sending data */
96*11876Shelge #define	TUS_SENDC	5	/* sending checksum */
97*11876Shelge #define	TUS_SENDR	6	/* sending read command packet */
98*11876Shelge #define	TUS_SENDW	7	/* sending write command packet */
99*11876Shelge #define	TUS_GETH	8	/* reading header */
100*11876Shelge #define	TUS_GETD	9	/* reading data */
101*11876Shelge #define	TUS_GETC	10	/* reading checksum */
102*11876Shelge #define	TUS_GET		11	/* reading an entire packet */
103*11876Shelge #define	TUS_WAIT	12	/* waiting for continue */
104*11876Shelge 
105*11876Shelge #define	TUS_NSTATES	13
106*11876Shelge char *tustates[TUS_NSTATES] = {
107*11876Shelge 	"INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR",
108*11876Shelge 	"SENDW", "GETH", "GETD", "GETC", "GET", "WAIT"
109*11876Shelge };
110*11876Shelge #define	printstate(state) \
111*11876Shelge 	if ((state) < TUS_NSTATES) \
112*11876Shelge 		printf("%s", tustates[(state)]); \
113*11876Shelge 	else \
114*11876Shelge 		printf("%d", (state));
115*11876Shelge 
116*11876Shelge /*
117*11876Shelge  * Packet Flags
118*11876Shelge  */
119*11876Shelge #define	TUF_DATA	1		/* data packet */
120*11876Shelge #define	TUF_CMD		2		/* command packet */
121*11876Shelge #define	TUF_INITF	4		/* initialize */
122*11876Shelge #define	TUF_CONT	020		/* continue */
123*11876Shelge #define	TUF_XOFF	023		/* flow control */
124*11876Shelge 
125*11876Shelge /*
126*11876Shelge  * Op Codes
127*11876Shelge  */
128*11876Shelge #define	TUOP_INIT	1		/* initialize */
129*11876Shelge #define	TUOP_READ	2		/* read block */
130*11876Shelge #define	TUOP_WRITE	3		/* write block */
131*11876Shelge #define	TUOP_SEEK	5		/* seek to block */
132*11876Shelge #define TUOP_DIAGNOSE	7		/* run micro-diagnostics */
133*11876Shelge #define	TUOP_END	0100		/* end packet */
134*11876Shelge 
135*11876Shelge /*
136*11876Shelge  * Mod Flags
137*11876Shelge  */
138*11876Shelge #define TUMD_WRV        1               /* write with read verify */
139*11876Shelge 
140*11876Shelge /*
141*11876Shelge  * Switches
142*11876Shelge  */
143*11876Shelge #define	TUSW_MRSP	010		/* use Modified RSP */
144*11876Shelge 
145*11876Shelge u_char	tunull[2] = { 0, 0 };	/* nulls to send for initialization */
146*11876Shelge u_char	tuinit[2] = { TUF_INITF, TUF_INITF };	/* inits to send */
147*11876Shelge static char pcnt[2];            /* pee/vee counters */
148*11876Shelge int	tutimer = 0;
149*11876Shelge struct buf tutab;		/* I/O queue header */
150*11876Shelge 
151*11876Shelge /*
152*11876Shelge  * Open the TU58
153*11876Shelge  */
154*11876Shelge /*ARGSUSED*/
155*11876Shelge tuopen(dev, flag)
156*11876Shelge {
157*11876Shelge 	extern int tuwatch();
158*11876Shelge 	register s;
159*11876Shelge 
160*11876Shelge #ifdef lint
161*11876Shelge 	turintr(); tuwintr();
162*11876Shelge #endif
163*11876Shelge 	if ((minor(dev)&DNUM) >= NTU || tu.tu_dopen[minor(dev)&DNUM])
164*11876Shelge 		return (ENXIO);
165*11876Shelge 	if (tutimer == 0) {
166*11876Shelge 		tutimer++;
167*11876Shelge 		timeout(tuwatch, (caddr_t)0, hz);
168*11876Shelge 	}
169*11876Shelge 	tu.tu_dopen[minor(dev)&DNUM]++;
170*11876Shelge 	s = splx(TUIPL);
171*11876Shelge 	/*
172*11876Shelge 	 * If the cassette's already initialized,
173*11876Shelge 	 * just enable interrupts and return.
174*11876Shelge 	 */
175*11876Shelge 	if (tu.tu_state == TUS_IDLE) {
176*11876Shelge 		mtpr(CSRS, IE);
177*11876Shelge 		splx(s);
178*11876Shelge 		return (0);
179*11876Shelge 	}
180*11876Shelge 
181*11876Shelge 	/*
182*11876Shelge 	 * Must initialize, reset the cassette
183*11876Shelge 	 * and wait for things to settle down.
184*11876Shelge 	 */
185*11876Shelge 	tureset();
186*11876Shelge 	sleep((caddr_t)&tu, PZERO+1);
187*11876Shelge 	tutab.b_active = NULL;
188*11876Shelge 	if (tu.tu_state != TUS_IDLE) {
189*11876Shelge 		u.u_error = ENXIO;
190*11876Shelge 		tu.tu_state = TUS_INIT1;
191*11876Shelge 		tu.tu_dopen[minor(dev)&DNUM] = 0;
192*11876Shelge 		tu.tu_rcnt = tu.tu_wcnt = 0;
193*11876Shelge 		mtpr(CSTS, 0);
194*11876Shelge 		mtpr(CSRS, 0);
195*11876Shelge 	}
196*11876Shelge 	splx(s);
197*11876Shelge 	return (0);
198*11876Shelge }
199*11876Shelge 
200*11876Shelge /*
201*11876Shelge  * Close the TU58
202*11876Shelge  */
203*11876Shelge tuclose(dev)
204*11876Shelge {
205*11876Shelge 
206*11876Shelge 	if (tutab.b_active == 0) {
207*11876Shelge 		mtpr(CSRS, 0);
208*11876Shelge 		tutimer = 0;
209*11876Shelge 	}
210*11876Shelge 	if (tu.tu_serrs + tu.tu_cerrs + tu.tu_herrs != 0) {
211*11876Shelge 		/*
212*11876Shelge 		 * A tu58 is like nothing ever seen before;
213*11876Shelge 		 * I guess this is appropriate then...
214*11876Shelge 		 */
215*11876Shelge 		uprintf(
216*11876Shelge 		   "tu%d: %d soft errors, %d chksum errors, %d hard errors\n",
217*11876Shelge 			minor(dev), tu.tu_serrs, tu.tu_cerrs, tu.tu_herrs);
218*11876Shelge 		tu.tu_serrs = tu.tu_cerrs = tu.tu_herrs = 0;
219*11876Shelge 	}
220*11876Shelge 	tu.tu_dopen[minor(dev)&DNUM] = 0;
221*11876Shelge }
222*11876Shelge 
223*11876Shelge /*
224*11876Shelge  * Reset the TU58
225*11876Shelge  */
226*11876Shelge tureset()
227*11876Shelge {
228*11876Shelge 
229*11876Shelge 	tu.tu_state = TUS_INIT1;
230*11876Shelge 	tu.tu_wbptr = tunull;
231*11876Shelge 	tu.tu_wcnt = sizeof (tunull);
232*11876Shelge 	tucmd.pk_flag = TUF_CMD;
233*11876Shelge 	tucmd.pk_mcount = sizeof (tucmd) - 4;
234*11876Shelge 	tucmd.pk_mod = 0;
235*11876Shelge 	tucmd.pk_seq = 0;
236*11876Shelge 	tucmd.pk_sw = MRSP ? TUSW_MRSP : 0;
237*11876Shelge 	tutab.b_active++;
238*11876Shelge 	mtpr(CSRS, 0);
239*11876Shelge 	mtpr(CSTS, IE|BREAK);
240*11876Shelge 	tuxintr();		/* start output */
241*11876Shelge }
242*11876Shelge 
243*11876Shelge /*
244*11876Shelge  * Strategy routine for block I/O
245*11876Shelge  */
246*11876Shelge tustrategy(bp)
247*11876Shelge 	register struct buf *bp;
248*11876Shelge {
249*11876Shelge 	register int s;
250*11876Shelge 
251*11876Shelge 	if (bp->b_blkno >= NTUBLK) {
252*11876Shelge 		bp->b_flags |= B_ERROR;
253*11876Shelge 		iodone(bp);
254*11876Shelge 		return;
255*11876Shelge 	}
256*11876Shelge 	if ((bp->b_flags&B_READ) == 0)
257*11876Shelge 		tu_pee(&pcnt[minor(bp->b_dev)&DNUM]);
258*11876Shelge 	bp->av_forw = NULL;
259*11876Shelge 	s = splx(TUIPL);
260*11876Shelge 	if (tutab.b_actf == NULL)
261*11876Shelge 		tutab.b_actf = bp;
262*11876Shelge 	else
263*11876Shelge 		tutab.b_actl->av_forw = bp;
264*11876Shelge 	tutab.b_actl = bp;
265*11876Shelge 	if (tutab.b_active == NULL)
266*11876Shelge 		tustart();
267*11876Shelge 	splx(s);
268*11876Shelge }
269*11876Shelge 
270*11876Shelge /*
271*11876Shelge  * Start the transfer
272*11876Shelge  */
273*11876Shelge tustart()
274*11876Shelge {
275*11876Shelge 	register struct buf *bp;
276*11876Shelge 
277*11876Shelge 	if ((bp = tutab.b_actf) == NULL)
278*11876Shelge 		return;
279*11876Shelge 	if (tu.tu_state != TUS_IDLE) {
280*11876Shelge 		tureset();
281*11876Shelge 		return;
282*11876Shelge 	}
283*11876Shelge 	tutab.b_active++;
284*11876Shelge 	tutab.b_errcnt = 0;
285*11876Shelge 	tucmd.pk_op = bp->b_flags&B_READ ? TUOP_READ : TUOP_WRITE;
286*11876Shelge 	tucmd.pk_mod = ((bp->b_flags&B_READ) == 0 && (minor(bp->b_dev)&WRV)) ?
287*11876Shelge 	    TUMD_WRV : 0;
288*11876Shelge 	tucmd.pk_unit = (minor(bp->b_dev)&DNUM);
289*11876Shelge 	tucmd.pk_sw = MRSP ? TUSW_MRSP : 0;
290*11876Shelge 	tucmd.pk_count = tu.tu_count = bp->b_bcount;
291*11876Shelge 	tucmd.pk_block = bp->b_blkno;
292*11876Shelge 	tucmd.pk_chksum =
293*11876Shelge 	    tuchk(*((short *)&tucmd), (u_short *)&tucmd.pk_op,
294*11876Shelge 		(int)tucmd.pk_mcount);
295*11876Shelge 	tu.tu_state = bp->b_flags&B_READ ? TUS_SENDR : TUS_SENDW;
296*11876Shelge 	tu.tu_addr = bp->b_un.b_addr;
297*11876Shelge 	tu.tu_count = bp->b_bcount;
298*11876Shelge 	tu.tu_wbptr = (u_char *)&tucmd;
299*11876Shelge 	tu.tu_wcnt = sizeof (tucmd);
300*11876Shelge 	tuxintr();
301*11876Shelge }
302*11876Shelge 
303*11876Shelge /*
304*11876Shelge  * TU58 receiver interrupt
305*11876Shelge  */
306*11876Shelge turintr()
307*11876Shelge {
308*11876Shelge 	register struct buf *bp;
309*11876Shelge 	register int c;
310*11876Shelge 
311*11876Shelge 	c = mfpr(CSRD)&0xff;		/* get the char, clear the interrupt */
312*11876Shelge 	if (MRSP) {
313*11876Shelge 		while ((mfpr(CSTS)&READY) == 0)
314*11876Shelge 			;
315*11876Shelge 		mtpr(CSTD, TUF_CONT);	/* ACK */
316*11876Shelge 	}
317*11876Shelge 	if (tu.tu_rcnt) {		/* still waiting for data? */
318*11876Shelge 		*tu.tu_rbptr++ = c;	/* yup, put it there */
319*11876Shelge 		if (--tu.tu_rcnt)	/* decrement count, any left? */
320*11876Shelge 			return;		/* get some more */
321*11876Shelge 	}
322*11876Shelge 
323*11876Shelge 	/*
324*11876Shelge 	 * We got all the data we were expecting for now,
325*11876Shelge 	 * switch on the tu_state of the transfer.
326*11876Shelge 	 */
327*11876Shelge 	switch(tu.tu_state) {
328*11876Shelge 
329*11876Shelge 	/*
330*11876Shelge 	 * If we get an unexpected "continue",
331*11876Shelge 	 * start all over again...
332*11876Shelge 	 */
333*11876Shelge 	case TUS_INIT2:
334*11876Shelge 		tu.tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1;
335*11876Shelge 		tu.tu_flag = 0;
336*11876Shelge 		wakeup((caddr_t)&tu);
337*11876Shelge 		tustart();
338*11876Shelge 		break;
339*11876Shelge 
340*11876Shelge 	/*
341*11876Shelge 	 * Only transition from this state
342*11876Shelge 	 * is on a "continue", so if we don't
343*11876Shelge 	 * get it, reset the world.
344*11876Shelge 	 */
345*11876Shelge 	case TUS_WAIT:			/* waiting for continue */
346*11876Shelge 		if (c != TUF_CONT) {
347*11876Shelge 			tu.tu_state = TUS_INIT1;
348*11876Shelge 			break;
349*11876Shelge 		}
350*11876Shelge 		tu.tu_flag = 0;
351*11876Shelge 		tudata.pk_flag = TUF_DATA;
352*11876Shelge 		tudata.pk_mcount = MIN(128, tu.tu_count);
353*11876Shelge 		tudata.pk_chksum =
354*11876Shelge 		    tuchk(*((short *)&tudata), (u_short *)tu.tu_addr,
355*11876Shelge 			(int)tudata.pk_mcount);
356*11876Shelge 		tu.tu_state = TUS_SENDH;
357*11876Shelge 		tu.tu_wbptr = (u_char *)&tudata;
358*11876Shelge 		tu.tu_wcnt = 2;
359*11876Shelge 		tuxintr();
360*11876Shelge 		break;
361*11876Shelge 
362*11876Shelge 	case TUS_SENDW:
363*11876Shelge 		if (c != TUF_CONT)
364*11876Shelge 			goto bad;
365*11876Shelge 		tureset();
366*11876Shelge 		break;
367*11876Shelge 
368*11876Shelge 	/*
369*11876Shelge 	 * Got header, now get data; amount to
370*11876Shelge 	 * fetch is include in packet.
371*11876Shelge 	 */
372*11876Shelge 	case TUS_GETH:
373*11876Shelge 		if (tudata.pk_flag == TUF_DATA)
374*11876Shelge 			tu.tu_rbptr = (u_char *)tu.tu_addr;
375*11876Shelge 		tu.tu_rcnt = tudata.pk_mcount;
376*11876Shelge 		tu.tu_state = TUS_GETD;
377*11876Shelge 		break;
378*11876Shelge 
379*11876Shelge 	/*
380*11876Shelge 	 * Got the data, now fetch the checksum.
381*11876Shelge 	 */
382*11876Shelge 	case TUS_GETD:
383*11876Shelge 		tu.tu_rbptr = (u_char *)&tudata.pk_chksum;
384*11876Shelge 		tu.tu_rcnt = sizeof (tudata.pk_chksum);
385*11876Shelge 		tu.tu_state = TUS_GETC;
386*11876Shelge 		break;
387*11876Shelge 
388*11876Shelge 	case TUS_GET:
389*11876Shelge 	case TUS_GETC:
390*11876Shelge 		/* got entire packet */
391*11876Shelge #ifdef notdef
392*11876Shelge 		if (tudata.pk_chksum !=
393*11876Shelge 		    tuchk(*((short *)&tudata), (u_short *)
394*11876Shelge 		     (tudata.pk_flag == TUF_DATA ? tu.tu_addr : &tudata.pk_op),
395*11876Shelge 		     (int)tudata.pk_mcount))
396*11876Shelge 			tu.tu_cerrs++;
397*11876Shelge #endif
398*11876Shelge 		if (tudata.pk_flag == TUF_DATA) {
399*11876Shelge 			/* data packet, advance to next */
400*11876Shelge 			tu.tu_addr += tudata.pk_mcount;
401*11876Shelge 			tu.tu_count -= tudata.pk_mcount;
402*11876Shelge 			tu.tu_state = TUS_GETH;
403*11876Shelge 			tu.tu_rbptr = (u_char *)&tudata; /* next packet */
404*11876Shelge 			tu.tu_rcnt = 2;
405*11876Shelge 		} else if (tudata.pk_flag==TUF_CMD && tudata.pk_op==TUOP_END) {
406*11876Shelge 			/* end packet, idle and reenable transmitter */
407*11876Shelge 			tu.tu_state = TUS_IDLE;
408*11876Shelge 			tu.tu_flag = 0;
409*11876Shelge 			mtpr(CSTS, IE);
410*11876Shelge 			printd("ON ");
411*11876Shelge 			if ((bp = tutab.b_actf) == NULL) {
412*11876Shelge 				printf("tu: no bp, active %d\n",tutab.b_active);
413*11876Shelge 				tustart();
414*11876Shelge 				return;
415*11876Shelge 			}
416*11876Shelge 			if (tudata.pk_mod > 1) {        /* hard error */
417*11876Shelge 				bp->b_flags |= B_ERROR;
418*11876Shelge 				tu.tu_herrs++;
419*11876Shelge 				harderr(bp, "tu");
420*11876Shelge 				printf("  pk_mod %o\n", tudata.pk_mod&0377);
421*11876Shelge 			} else if (tudata.pk_mod != 0)	/* soft error */
422*11876Shelge 				tu.tu_serrs++;
423*11876Shelge 			tutab.b_active = NULL;
424*11876Shelge 			tutab.b_actf = bp->av_forw;
425*11876Shelge 			bp->b_resid = tu.tu_count;
426*11876Shelge 			if ((bp->b_flags&B_READ) == 0)
427*11876Shelge 				tu_vee(&pcnt[minor(bp->b_dev)&DNUM]);
428*11876Shelge 			iodone(bp);
429*11876Shelge 			tustart();
430*11876Shelge 		} else {
431*11876Shelge 			printf("neither data nor end: %o %o\n",
432*11876Shelge 			    tudata.pk_flag&0xff, tudata.pk_op&0xff);
433*11876Shelge 			mtpr(CSRS, 0);		/* flush the rest */
434*11876Shelge 			tu.tu_state = TUS_INIT1;
435*11876Shelge 		}
436*11876Shelge 		break;
437*11876Shelge 
438*11876Shelge 	case TUS_IDLE:
439*11876Shelge 	case TUS_INIT1:
440*11876Shelge 		break;
441*11876Shelge 
442*11876Shelge 	default:
443*11876Shelge bad:
444*11876Shelge 		if (c == TUF_INITF) {
445*11876Shelge 			printf("tu protocol error, state=");
446*11876Shelge 			printstate(tu.tu_state);
447*11876Shelge 			printf(", op=%x, cnt=%d, block=%d\n",
448*11876Shelge 			    tucmd.pk_op, tucmd.pk_count, tucmd.pk_block);
449*11876Shelge 			tutab.b_active = NULL;
450*11876Shelge 			if (bp = tutab.b_actf) {
451*11876Shelge 				bp->b_flags |= B_ERROR;
452*11876Shelge 				tutab.b_actf = bp->av_forw;
453*11876Shelge 				if ((bp->b_flags&B_READ) == 0)
454*11876Shelge 					tu_vee(&pcnt[minor(bp->b_dev)&DNUM]);
455*11876Shelge 				iodone(bp);
456*11876Shelge 			}
457*11876Shelge 			tu.tu_state = TUS_INIT1;
458*11876Shelge 		} else {
459*11876Shelge 			printf("tu receive state error, state=");
460*11876Shelge 			printf(", byte=%x\n", c);
461*11876Shelge #ifdef notdef
462*11876Shelge 			tu.tu_state = TUS_INIT1; */
463*11876Shelge #endif
464*11876Shelge 			wakeup((caddr_t)&tu);
465*11876Shelge 		}
466*11876Shelge 	}
467*11876Shelge }
468*11876Shelge 
469*11876Shelge /*
470*11876Shelge  * TU58 transmitter interrupt
471*11876Shelge  */
472*11876Shelge tuxintr()
473*11876Shelge {
474*11876Shelge 
475*11876Shelge top:
476*11876Shelge 	if (tu.tu_wcnt) {
477*11876Shelge 		/* still stuff to send, send one byte */
478*11876Shelge 		while ((mfpr(CSTS) & READY) == 0)
479*11876Shelge 			;
480*11876Shelge 		mtpr(CSTD, *tu.tu_wbptr++);
481*11876Shelge 		tu.tu_wcnt--;
482*11876Shelge 		return;
483*11876Shelge 	}
484*11876Shelge 
485*11876Shelge 	/*
486*11876Shelge 	 * Last message byte was sent out.
487*11876Shelge 	 * Switch on tu_state of transfer.
488*11876Shelge 	 */
489*11876Shelge 	if (tudebug) {
490*11876Shelge 		printf("tuxintr: state=");
491*11876Shelge 		printstate(tu.tu_state);
492*11876Shelge 	}
493*11876Shelge 	switch(tu.tu_state) {
494*11876Shelge 
495*11876Shelge 	/*
496*11876Shelge 	 * Two nulls have been sent, remove break, and send inits
497*11876Shelge 	 */
498*11876Shelge 	case TUS_INIT1:
499*11876Shelge 		mtpr(CSTS, IE);
500*11876Shelge 		printd("ON2 ");
501*11876Shelge 		tu.tu_state = TUS_INIT2;
502*11876Shelge 		tu.tu_wbptr = tuinit;
503*11876Shelge 		tu.tu_wcnt = sizeof (tuinit);
504*11876Shelge 		goto top;
505*11876Shelge 
506*11876Shelge 	/*
507*11876Shelge 	 * Inits have been sent, wait for a continue msg.
508*11876Shelge 	 */
509*11876Shelge 	case TUS_INIT2:
510*11876Shelge 		(void) mfpr(CSRD);
511*11876Shelge 		mtpr(CSRS, IE);
512*11876Shelge 		tu.tu_flag = 1;
513*11876Shelge 		break;
514*11876Shelge 
515*11876Shelge 	case TUS_IDLE:		/* stray interrupt? */
516*11876Shelge 		break;
517*11876Shelge 
518*11876Shelge 	/*
519*11876Shelge 	 * Read cmd packet sent, get ready for data
520*11876Shelge 	 */
521*11876Shelge 	case TUS_SENDR:
522*11876Shelge 		tu.tu_state = TUS_GETH;
523*11876Shelge 		tu.tu_rbptr = (u_char *)&tudata;
524*11876Shelge 		tu.tu_rcnt = 2;
525*11876Shelge 		tu.tu_flag = 1;
526*11876Shelge 		mtpr(CSTS, 0);	/* disable transmitter interrupts */
527*11876Shelge 		printd("OFF ");
528*11876Shelge 		break;
529*11876Shelge 
530*11876Shelge 	/*
531*11876Shelge 	 * Write cmd packet sent, wait for continue
532*11876Shelge 	 */
533*11876Shelge 	case TUS_SENDW:
534*11876Shelge 		tu.tu_state = TUS_WAIT;
535*11876Shelge 		tu.tu_flag = 1;
536*11876Shelge 		if ((mfpr(CSRS)&IE) == 0) {
537*11876Shelge 			printf("NO IE\n");
538*11876Shelge 			mtpr(CSRS, IE);
539*11876Shelge 		}
540*11876Shelge 		break;
541*11876Shelge 
542*11876Shelge 	/*
543*11876Shelge 	 * Header sent, send data.
544*11876Shelge 	 */
545*11876Shelge 	case TUS_SENDH:
546*11876Shelge 		tu.tu_state = TUS_SENDD;
547*11876Shelge 		tu.tu_wbptr = (u_char *)tu.tu_addr;
548*11876Shelge 		tu.tu_wcnt = tudata.pk_mcount;
549*11876Shelge 		goto top;
550*11876Shelge 
551*11876Shelge 	/*
552*11876Shelge 	 * Data sent, follow with checksum.
553*11876Shelge 	 */
554*11876Shelge 	case TUS_SENDD:
555*11876Shelge 		tu.tu_state = TUS_SENDC;
556*11876Shelge 		tu.tu_wbptr = (u_char *)&tudata.pk_chksum;
557*11876Shelge 		tu.tu_wcnt = sizeof tudata.pk_chksum;
558*11876Shelge 		goto top;
559*11876Shelge 
560*11876Shelge 	/*
561*11876Shelge 	 * Checksum sent, wait for continue.
562*11876Shelge 	 */
563*11876Shelge 	case TUS_SENDC:
564*11876Shelge 		/*
565*11876Shelge 		 * Updata buffer address and count.
566*11876Shelge 		 */
567*11876Shelge 		tu.tu_addr += tudata.pk_mcount;
568*11876Shelge 		tu.tu_count -= tudata.pk_mcount;
569*11876Shelge 		if (tu.tu_count) {
570*11876Shelge 			tu.tu_state = TUS_WAIT;
571*11876Shelge 			tu.tu_flag = 1;
572*11876Shelge 			break;
573*11876Shelge 		}
574*11876Shelge 
575*11876Shelge 		/*
576*11876Shelge 		 * End of transmission, get ready for end packet.
577*11876Shelge 		 */
578*11876Shelge 		tu.tu_state = TUS_GET;
579*11876Shelge 		tu.tu_rbptr = (u_char *)&tudata;
580*11876Shelge 		tu.tu_rcnt = sizeof (tudata);
581*11876Shelge 		tu.tu_flag = 1;
582*11876Shelge 		mtpr(CSTS, 0);
583*11876Shelge 		printd("OFF2 ");
584*11876Shelge 		break;
585*11876Shelge 
586*11876Shelge 	/*
587*11876Shelge 	 * Random interrupt, probably from MRSP ACK
588*11876Shelge 	 */
589*11876Shelge 	default:
590*11876Shelge 		break;
591*11876Shelge 	}
592*11876Shelge 	if (tudebug) {
593*11876Shelge 		printd("  new tu_state=");
594*11876Shelge 		printstate(tu.tu_state);
595*11876Shelge 	}
596*11876Shelge }
597*11876Shelge 
598*11876Shelge /*
599*11876Shelge  * Compute checksum TU58 fashion
600*11876Shelge  */
601*11876Shelge #ifdef lint
602*11876Shelge tuchk(word, cp, n)
603*11876Shelge 	register word;
604*11876Shelge 	register unsigned short *cp;
605*11876Shelge 	int n;
606*11876Shelge {
607*11876Shelge 	register int c = n >> 1;
608*11876Shelge 	register long temp;
609*11876Shelge 
610*11876Shelge 	do {
611*11876Shelge 		temp = *cp++;	/* temp, only because vax cc won't *r++ */
612*11876Shelge 		word += temp;
613*11876Shelge 	} while (--c > 0);
614*11876Shelge 	if (n & 1)
615*11876Shelge 		word += *(unsigned char *)cp;
616*11876Shelge 	while (word & 0xffff0000)
617*11876Shelge 		word = (word & 0xffff) + ((word >> 16) & 0xffff);
618*11876Shelge 	return (word);
619*11876Shelge }
620*11876Shelge #else
621*11876Shelge tuchk(word0, wp, n)
622*11876Shelge 	register int word0;	/* r11 */
623*11876Shelge 	register char *wp;	/* r10 */
624*11876Shelge 	register int n;		/* r9 */
625*11876Shelge {
626*11876Shelge 	asm("loop:");
627*11876Shelge 	asm("	addw2	(r10)+,r11");	/* add a word to sum */
628*11876Shelge 	asm("	adwc	$0,r11");	/* add in carry, end-around */
629*11876Shelge 	asm("	acbl	$2,$-2,r9,loop");	/* done yet? */
630*11876Shelge 	asm("	blbc	r9,ok");	/* odd byte count? */
631*11876Shelge 	asm("	movzbw	(r10),r10");	/* yes, get last byte */
632*11876Shelge 	asm("	addw2	r10,r11");	/* add it in */
633*11876Shelge 	asm("	adwc	$0,r11");	/* and the carry */
634*11876Shelge 	asm("ok:");
635*11876Shelge 	asm("	movl	r11,r0");	/* return sum */
636*11876Shelge }
637*11876Shelge #endif
638*11876Shelge 
639*11876Shelge tuwatch()
640*11876Shelge {
641*11876Shelge 	register int s;
642*11876Shelge 	register struct buf *bp;
643*11876Shelge 
644*11876Shelge 	if (tutimer == 0) {
645*11876Shelge 		tu.tu_flag = 0;
646*11876Shelge 		return;
647*11876Shelge 	}
648*11876Shelge 	if (tu.tu_flag)
649*11876Shelge 		tu.tu_flag++;
650*11876Shelge 	if (tu.tu_flag <= 40) {
651*11876Shelge 		timeout(tuwatch, (caddr_t)0, hz);
652*11876Shelge 		return;
653*11876Shelge 	}
654*11876Shelge 	printf("tu: read stalled\n");
655*11876Shelge 	printf("%X %X %X %X %X %X %X %X\n", tu.tu_rbptr, tu.tu_rcnt,
656*11876Shelge 		tu.tu_wbptr, tu.tu_wcnt, tu.tu_state, tu.tu_flag,
657*11876Shelge 		tu.tu_addr, tu.tu_count);
658*11876Shelge 	tu.tu_flag = 0;
659*11876Shelge 	s = splx(TUIPL);
660*11876Shelge 	(void) mfpr(CSRD);
661*11876Shelge 	mtpr(CSRS, IE);		/* in case we were flushing */
662*11876Shelge 	mtpr(CSTS, IE);
663*11876Shelge 	tu.tu_state = TUS_IDLE;
664*11876Shelge 	if (!tutab.b_active) {
665*11876Shelge 		wakeup((caddr_t)&tu);
666*11876Shelge 		goto retry;
667*11876Shelge 	}
668*11876Shelge 	if (++tutab.b_errcnt <= 1) {
669*11876Shelge 		tustart();
670*11876Shelge 		goto retry;
671*11876Shelge 	}
672*11876Shelge 	if (bp = tutab.b_actf) {
673*11876Shelge 		bp->b_flags |= B_ERROR;
674*11876Shelge 		if ((bp->b_flags&B_READ) == 0)
675*11876Shelge 			tu_vee(&pcnt[minor(bp->b_dev)&DNUM]);
676*11876Shelge 		iodone(bp);
677*11876Shelge 	}
678*11876Shelge retry:
679*11876Shelge 	splx(s);
680*11876Shelge 	timeout(tuwatch, (caddr_t)0, hz);
681*11876Shelge }
682*11876Shelge 
683*11876Shelge tu_pee(cp)
684*11876Shelge 	char *cp;
685*11876Shelge {
686*11876Shelge 	register int s;
687*11876Shelge 
688*11876Shelge 	s = splx(TUIPL);
689*11876Shelge 	if (++(*cp) > NTUQ)
690*11876Shelge 		sleep(cp, PRIBIO);
691*11876Shelge 	splx(s);
692*11876Shelge }
693*11876Shelge 
694*11876Shelge tu_vee(cp)
695*11876Shelge 	char *cp;
696*11876Shelge {
697*11876Shelge 	register int s;
698*11876Shelge 
699*11876Shelge 	s = splx(TUIPL);
700*11876Shelge 	if (--(*cp) <= NTUQ)
701*11876Shelge 		wakeup(cp);
702*11876Shelge 	splx(s);
703*11876Shelge }
704*11876Shelge #endif
705