|
|
1.1 root 1: /* uu.c 6.1 83/07/29 */
2:
3: #include "uu.h"
4: #if NUU > 0
5: /*
6: * TU58 DECtape II/DL11 device driver
7: *
8: * The TU58 is treated as a block device (only). Error detection and
9: * recovery is not very extensive, but sufficient to handle the most
10: * common errors. It is assumed that the TU58 will follow the RSP
11: * protocol exactly, very few protocol errors are checked for.
12: *
13: * To reduce interrupt latency, `options UUDMA' should be specified
14: * in the config file to make sure the `pseudo-DMA' code in locore.s
15: * will be compiled into the system. Otherwise overrun errors will
16: * occur frequently (these errors are not reported).
17: *
18: * TODO:
19: *
20: * - Add ioctl code to wind/rewind cassette
21: *
22: */
23:
24: #include "../machine/pte.h"
25:
26: #include "../h/param.h"
27: #include "../h/systm.h"
28: #include "../h/buf.h"
29: #include "../h/conf.h"
30: #include "../h/time.h"
31: #include "../h/kernel.h"
32: #include "../h/errno.h"
33: #include "../h/file.h"
34:
35: #include "../vax/cpu.h"
36: #include "../vax/nexus.h"
37: #include "../vax/rsp.h"
38:
39: #include "../vaxuba/ubavar.h"
40: #include "../vaxuba/ubareg.h"
41: #include "../vaxuba/uureg.h"
42:
43: #define NTUBLK 512 /* number of blocks on a TU58 cassette */
44: #define WRV 01 /* bit in minor dev => write w. read verify */
45: #define NDPC 02 /* drives per controller */
46: #define NUX NDPC * NUU /* number of drives */
47: #define NUUQ 02 /* # of block which can be queued up */
48: #define UMASK 01 /* unit number mask */
49: #define UUIPL 0x14 /* ipl level to use */
50:
51: struct packet uucmd[NUU]; /* a command sent to the TU58 */
52: struct packet uudata[NUU]; /* a command or data returned from TU58 */
53: struct buf uitab[NUU]; /* buffer queue headers */
54:
55: /*
56: * Driver soft carrier structure
57: */
58: struct uu_softc {
59: u_char *tu_rbptr; /* pointer to buffer for read */
60: int tu_rcnt; /* how much to read */
61: u_char *tu_wbptr; /* pointer to buffer for write */
62: int tu_wcnt; /* how much to write */
63: int tu_state; /* current state of tansfer operation */
64: int tu_flag; /* read in progress flag */
65: char *tu_addr; /* real buffer data address */
66: int tu_count; /* real requested count */
67: int tu_serrs; /* count of soft errors */
68: int tu_cerrs; /* count of checksum errors */
69: int tu_herrs; /* count of hard errors */
70: char tu_dopen[2]; /* drive is open */
71: } uu_softc[NUU];
72:
73: #if defined(VAX750) || defined(VAX730)
74: extern char *tustates[];
75: #else
76: char *tustates[TUS_NSTATES] = {
77: "INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR",
78: "SENDW", "GETH", "GETD", "GETC", "GET", "WAIT", "RCVERR", "CHKERR"
79: };
80: #endif
81:
82: #define UNIT(dev) (minor(dev)>>1)
83:
84: u_char uunull[2] = { 0, 0 }; /* nulls to send for initialization */
85: u_char uuinit[2] = { TUF_INITF, TUF_INITF }; /* inits to send */
86:
87: struct uba_device *uudinfo[NUU];
88:
89: int uuprobe(), uuattach(), uurintr(), uuxintr(), uuwatch();
90: u_short uustd[] = { 0176500 };
91: struct uba_driver uudriver =
92: { uuprobe, 0, uuattach, 0, uustd, "uu", uudinfo };
93:
94: int uuwstart;
95: int uuwake();
96: static char uu_pcnt[NUX]; /* pee/vee counters, one per drive */
97:
98: /*ARGSUSED*/
99: uuprobe(reg)
100: caddr_t reg;
101: {
102: register int br, cvec; /* value result */
103: struct uudevice *uuaddr = (struct uudevice *)reg;
104:
105: #ifdef lint
106: br = 0; cvec = br; br = cvec;
107: uurintr(0); uuxintr(0);
108: #endif
109: uuaddr->tcs = UUCS_INTR;
110: DELAY(1000);
111: uuaddr->tcs = 0;
112: cvec -= 4; /* since we are using the xmitter intrpt */
113: return(sizeof (*uuaddr));
114: }
115:
116: uuattach(ui)
117: register struct uba_device *ui;
118: {
119: }
120:
121: /*ARGSUSED1*/
122: uuopen(dev, flag)
123: dev_t dev;
124: int flag;
125: {
126: register struct uba_device *ui;
127: register struct uu_softc *uuc;
128: register struct uudevice *uuaddr;
129: int ctlr, unit = UNIT(dev), s;
130:
131: ctlr = unit / NDPC;
132: if (unit >= NUX || (ui = uudinfo[ctlr]) == 0 || ui->ui_alive == 0)
133: return (ENXIO);
134: uuc = &uu_softc[ctlr];
135: if (uuc->tu_dopen[unit&UMASK])
136: return (EBUSY);
137: if (uuwstart++ == 0)
138: timeout(uuwatch, (caddr_t)0, hz);
139:
140: uuc->tu_dopen[unit&UMASK]++;
141: uuaddr = (struct uudevice *)ui->ui_addr;
142: s = splx(UUIPL);
143: /*
144: * If the other device on this controller
145: * is already active, no need to initialize
146: */
147: if (uuc->tu_dopen[0] && uuc->tu_dopen[1])
148: goto ok;
149:
150: /*
151: * If the unit already initialized,
152: * just enable interrupts and return.
153: */
154: if (uuc->tu_state == TUS_IDLE) {
155: uuaddr->rcs = UUCS_INTR;
156: goto ok;
157: }
158:
159: /*
160: * Must initialize, reset the cassette
161: * and wait for things to settle down.
162: */
163: uureset(ctlr);
164: sleep((caddr_t)uuc, PZERO+1);
165: uitab[ctlr].b_active = NULL;
166: if (uuc->tu_state != TUS_IDLE) {
167: uuc->tu_state = TUS_INIT1;
168: uuc->tu_dopen[unit&UMASK] = 0;
169: uuc->tu_rcnt = uuc->tu_wcnt = 0;
170: uuaddr->rcs = 0;
171: uuaddr->tcs = 0;
172: splx(s);
173: return (EIO);
174: }
175: ok:
176: splx(s);
177: return (0);
178: }
179:
180: /*
181: * Wait for all outstanding IO on this drive
182: * complete, before closing. If both drives on
183: * this controller are idle, mark the controller
184: * `inactive'.
185: */
186:
187: uuclose(dev, flag)
188: dev_t dev;
189: int flag;
190: {
191: int s, unit = UNIT(dev);
192: register struct uu_softc *uuc = &uu_softc[unit/NDPC];
193: struct buf *bp, *last = NULL;
194: struct uudevice *uuaddr = (struct uudevice *)uudinfo[unit/NDPC]->ui_addr;
195:
196: s = splx(UUIPL);
197: while (uu_pcnt[unit])
198: sleep(&uu_pcnt[unit], PRIBIO);
199: /*
200: * No more writes are pending, scan the
201: * buffer queue for oustanding reads from
202: * this unit.
203: */
204: for (bp = uitab[unit/NDPC].b_actf; bp; bp = bp->b_actf) {
205: if (bp->b_dev == dev)
206: last = bp;
207: }
208: if (last) {
209: last->b_flags |= B_CALL;
210: last->b_iodone = uuwake;
211: sleep((caddr_t)last, PRIBIO);
212: }
213: uuc->tu_dopen[unit&UMASK] = 0;
214: if (!uuc->tu_dopen[0] && !uuc->tu_dopen[1]) {
215: uuc->tu_flag = 0;
216: uuaddr->rcs = 0;
217: }
218: splx(s);
219: }
220:
221: uuwake(bp)
222: struct buf *bp;
223: {
224: wakeup(bp);
225: }
226:
227: uureset(ctlr)
228: int ctlr;
229: {
230: register struct uu_softc *uuc = &uu_softc[ctlr];
231: register struct packet *cmd = &uucmd[ctlr];
232: struct uba_device *ui = uudinfo[ctlr];
233: register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr;
234:
235: uitab[ctlr].b_active++;
236: uuc->tu_state = TUS_INIT1;
237: uuc->tu_wbptr = uunull;
238: uuc->tu_wcnt = sizeof (uunull);
239: uuc->tu_rcnt = 0;
240: cmd->pk_flag = TUF_CMD;
241: cmd->pk_mcount = sizeof (*cmd) - 4;
242: cmd->pk_mod = 0;
243: cmd->pk_seq = 0;
244: cmd->pk_sw = 0;
245: uuaddr->rcs = 0;
246: uuaddr->tcs = UUCS_INTR | UUCS_BREAK;
247: uuxintr(ctlr); /* start output */
248: }
249:
250: /*
251: * Strategy routine for block I/O
252: */
253: uustrategy(bp)
254: register struct buf *bp;
255: {
256: register struct buf *uutab;
257: struct uba_device *ui;
258: int s, unit = UNIT(bp->b_dev);
259:
260: if ((unit > NUX) || (bp->b_blkno >= NTUBLK))
261: goto bad;
262: ui = uudinfo[unit/NDPC];
263: if (ui == 0 || ui->ui_alive == 0)
264: goto bad;
265: uutab = &uitab[unit/NDPC]; /* one request queue per controller */
266: s = splx(UUIPL);
267: if ((bp->b_flags&B_READ) == 0)
268: tu_pee(&uu_pcnt[unit]);
269: bp->b_actf = NULL;
270: if (uutab->b_actf == NULL)
271: uutab->b_actf = bp;
272: else
273: uutab->b_actl->b_actf = bp;
274: uutab->b_actl = bp;
275: if (uutab->b_active == 0)
276: uustart(ui);
277: splx(s);
278: return;
279:
280: bad:
281: bp->b_flags |= B_ERROR;
282: bp->b_error = ENXIO;
283: iodone(bp);
284: return;
285: }
286:
287: /*
288: * Start the transfer
289: */
290: uustart(ui)
291: register struct uba_device *ui;
292: {
293: register struct buf *bp;
294: register struct uu_softc *uuc;
295: struct packet *cmd;
296: int ctlr = ui->ui_unit, s;
297:
298: if ((bp = uitab[ctlr].b_actf) == NULL)
299: return;
300: s = splx(UUIPL);
301: uuc = &uu_softc[ctlr];
302: if (uuc->tu_state != TUS_IDLE) {
303: uureset(ctlr);
304: splx(s);
305: return;
306: }
307: cmd = &uucmd[ctlr];
308: uitab[ctlr].b_active++;
309: uitab[ctlr].b_errcnt = 0;
310: uuc->tu_addr = bp->b_un.b_addr;
311: uuc->tu_count = cmd->pk_count = bp->b_bcount;
312: cmd->pk_block = bp->b_blkno;
313: if (bp->b_flags&B_READ) {
314: cmd->pk_op = TUOP_READ;
315: cmd->pk_mod = 0;
316: uuc->tu_state = TUS_SENDR;
317: } else {
318: cmd->pk_op = TUOP_WRITE;
319: cmd->pk_mod = minor(bp->b_dev)&WRV ? TUMD_WRV : 0;
320: uuc->tu_state = TUS_SENDW;
321: }
322: cmd->pk_unit = UNIT(bp->b_dev)&UMASK;
323: cmd->pk_sw = 0;
324: cmd->pk_chksum =
325: tuchk(*((short *)cmd), (u_short *)&cmd->pk_op, (int)cmd->pk_mcount);
326: uuc->tu_wbptr = (u_char *)cmd;
327: uuc->tu_wcnt = sizeof (*cmd);
328: uuxintr(ctlr);
329: splx(s);
330: }
331:
332: /*
333: * TU58 receiver interrupt, handles whatever condition the
334: * pseudo DMA routine in locore is unable to handle,
335: * or, if UUDMA is undefined, handle all receiver interrupt
336: * processing.
337: */
338: uurintr(ctlr)
339: int ctlr;
340: {
341: struct uba_device *ui = uudinfo[ctlr];
342: register struct uu_softc *uuc = &uu_softc[ctlr];
343: register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr;
344: register struct buf *uutab = &uitab[ctlr];
345: struct packet *data, *cmd;
346: struct buf *bp;
347: int c, unit;
348:
349: c = uuaddr->rdb;
350: data = &uudata[ctlr];
351: cmd = &uucmd[ctlr];
352: #if !defined(UUDMA)
353: if (c & UURDB_ERROR)
354: uuc->tu_state = TUS_RCVERR;
355: else {
356: if (uuc->tu_rcnt) {
357: *uuc->tu_rbptr++ = c;
358: if (--uuc->tu_rcnt)
359: return;
360: }
361: }
362: #endif
363:
364: /*
365: * Switch on the tu_state of the transfer.
366: */
367: switch(uuc->tu_state) {
368:
369: /*
370: * A data error occured in uudma
371: * (either overrun or break)
372: */
373: case TUS_RCVERR:
374: if ((c & UURDB_ORUN) == 0)
375: printf("uu%d: break received, transfer restarted\n",
376: data->pk_unit);
377: #ifdef UUDEBUG
378: else
379: printf("uu%d: data overrun, recovered\n",
380: data->pk_unit);
381: #endif
382: uuc->tu_serrs++;
383: uu_restart(ctlr, ui);
384: break;
385:
386: /*
387: * If we get an unexpected "continue",
388: * start all over again...
389: */
390: case TUS_INIT2:
391: uuc->tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1;
392: uuc->tu_flag = 0;
393: wakeup((caddr_t)uuc);
394: uustart(ui);
395: break;
396:
397: /*
398: * Only transition from this state
399: * is on a "continue", so if we don't
400: * get it, reset the world.
401: */
402: case TUS_WAIT: /* waiting for continue */
403: switch(c) {
404: case TUF_CONT: /* got the expected continue */
405: uuc->tu_flag = 0;
406: data->pk_flag = TUF_DATA;
407: data->pk_mcount = MIN(128, uuc->tu_count);
408: data->pk_chksum =
409: tuchk(*((short *)data), (caddr_t)uuc->tu_addr,
410: (int)data->pk_mcount);
411: uuc->tu_state = TUS_SENDH;
412: uuc->tu_wbptr = (u_char *)data;
413: uuc->tu_wcnt = 2;
414: uuxintr(ctlr);
415: break;
416:
417: case TUF_CMD: /* sending us an END packet...error */
418: uuc->tu_state = TUS_GET;
419: uuc->tu_rbptr = (u_char *)data;
420: uuc->tu_rcnt = sizeof (*data) - 1;
421: uuc->tu_flag = 1;
422: uuaddr->tcs = 0;
423: *uuc->tu_rbptr++ = c & UUDB_DMASK;
424: break;
425:
426: case TUF_INITF:
427: uureset(ctlr);
428: break;
429:
430: default: /* something random...bad news */
431: uuc->tu_state = TUS_INIT1;
432: break;
433: }
434: break;
435:
436: case TUS_SENDW:
437: if (c != TUF_CONT && c != TUF_INITF)
438: goto bad;
439: uu_restart(ctlr, ui);
440: break;
441:
442: /*
443: * Got header, now get data; amount to
444: * fetch is included in packet.
445: * (data packets are handled entirely
446: * in uudma)
447: */
448: case TUS_GETH:
449: #ifndef UUDMA
450: if (data->pk_flag == TUF_DATA)
451: uuc->tu_rbptr = (u_char *)uuc->tu_addr;
452: #endif
453: uuc->tu_rcnt = data->pk_mcount;
454: uuc->tu_state = TUS_GETD;
455: break;
456:
457: /*
458: * Got the data, now fetch the checksum.
459: */
460: case TUS_GETD:
461: uuc->tu_rbptr = (u_char *)&data->pk_chksum;
462: uuc->tu_rcnt = sizeof (data->pk_chksum);
463: uuc->tu_state = TUS_GETC;
464: break;
465:
466: case TUS_GETC:
467: /* got entire packet */
468: if (data->pk_chksum !=
469: tuchk(*((short *)data), (u_short *)
470: (data->pk_flag == TUF_DATA ?
471: (u_short *) uuc->tu_addr : (u_short *)&data->pk_op),
472: (int)data->pk_mcount))
473: case TUS_CHKERR:
474: uuc->tu_cerrs++;
475: case TUS_GET:
476: if (data->pk_flag == TUF_DATA) {
477: /* data packet, advance to next */
478: uuc->tu_addr += data->pk_mcount;
479: uuc->tu_count -= data->pk_mcount;
480: uuc->tu_state = TUS_GETH;
481: uuc->tu_rbptr = (u_char *)data; /* next packet */
482: uuc->tu_rcnt = 2;
483: } else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) {
484: /* end packet, idle and reenable transmitter */
485: uuc->tu_state = TUS_IDLE;
486: uuc->tu_flag = 0;
487: uuaddr->tcs = UUCS_INTR;
488: if ((bp = uutab->b_actf) == NULL) {
489: printf("uu%d: no bp, active %d\n",
490: data->pk_unit, uitab[ctlr].b_active);
491: uustart(ui);
492: return;
493: }
494: unit = UNIT(bp->b_dev);
495: if (data->pk_mod > 1) { /* hard error */
496: printf("uu%d: hard error bn%d,", unit,
497: bp->b_blkno);
498: printf(" pk_mod 0%o\n", data->pk_mod&0xff);
499: bp->b_flags |= B_ERROR;
500: uuc->tu_herrs++;
501: } else if (data->pk_mod) /* soft error */
502: uuc->tu_serrs++;
503: uutab->b_active = NULL;
504: uutab->b_actf = bp->b_actf;
505: bp->b_resid = uuc->tu_count;
506: if ((bp->b_flags&B_READ) == 0)
507: tu_vee(&uu_pcnt[unit]);
508: iodone(bp);
509: uustart(ui);
510: } else {
511: /*
512: * Neither data nor end: data was lost
513: * somehow, flush and restart the transfer.
514: */
515: uuaddr->rcs = 0;
516: uu_restart(ctlr, ui);
517: uuc->tu_serrs++;
518: }
519: break;
520:
521: case TUS_IDLE:
522: case TUS_INIT1:
523: break;
524:
525: default:
526: bad:
527: if (c == TUF_INITF) {
528: printf("uu%d protocol error, state=", data->pk_unit);
529: printstate(uuc->tu_state);
530: printf(", op=%x, cnt=%d, block=%d\n",
531: cmd->pk_op, cmd->pk_count, cmd->pk_block);
532: uutab->b_active = NULL;
533: if (bp = uutab->b_actf) {
534: bp->b_flags |= B_ERROR;
535: uutab->b_actf = bp->b_actf;
536: if ((bp->b_flags&B_READ) == 0)
537: tu_vee(&uu_pcnt[unit]);
538: iodone(bp);
539: }
540: uuc->tu_state = TUS_INIT1;
541: } else {
542: printf("uu%d receive state error, state=",
543: data->pk_unit);
544: printstate(uuc->tu_state);
545: printf(", byte=%x\n", c & 0xff);
546: #ifdef notdef
547: uuc->tu_state = TUS_INIT1;
548: #endif
549: wakeup((caddr_t)uuc);
550: }
551: }
552: }
553:
554:
555: /*
556: * TU58 transmitter interrupt
557: */
558: uuxintr(ctlr)
559: int ctlr;
560: {
561: register struct uu_softc *uuc = &uu_softc[ctlr];
562: register struct uudevice *uuaddr;
563: register struct packet *data;
564: struct uba_device *ui = uudinfo[ctlr];
565: int c;
566:
567: data = &uudata[ctlr];
568: uuaddr = (struct uudevice *) ui->ui_addr;
569: top:
570: if (uuc->tu_wcnt > 0) {
571: /* still stuff to send, send one byte */
572: while ((uuaddr->tcs & UUCS_READY) == 0)
573: ;
574: uuaddr->tdb = *uuc->tu_wbptr++;
575: uuc->tu_wcnt--;
576: return;
577: }
578:
579: /*
580: * Last message byte was sent out.
581: * Switch on tu_state of transfer.
582: */
583: switch(uuc->tu_state) {
584:
585: /*
586: * Two nulls have been sent, remove break, and send inits
587: */
588: case TUS_INIT1:
589: uuc->tu_flag = 0;
590: uuaddr->tcs = UUCS_INTR;
591: uuc->tu_state = TUS_INIT2;
592: uuc->tu_wbptr = uuinit;
593: uuc->tu_wcnt = sizeof (uuinit);
594: goto top;
595:
596: /*
597: * Inits have been sent, wait for a continue msg.
598: */
599: case TUS_INIT2:
600: c = uuaddr->rdb; /* prevent overrun error */
601: uuaddr->rcs = UUCS_INTR;
602: uuc->tu_flag = 1;
603: break;
604:
605: /*
606: * Read cmd packet sent, get ready for data
607: */
608: case TUS_SENDR:
609: uuc->tu_state = TUS_GETH;
610: uuc->tu_rbptr = (u_char *)data;
611: uuc->tu_rcnt = 2;
612: uuc->tu_flag = 1;
613: uuaddr->tcs = 0;
614: uuaddr->rcs = UUCS_INTR;
615: break;
616:
617: /*
618: * Write cmd packet sent, wait for continue
619: */
620: case TUS_SENDW:
621: uuc->tu_state = TUS_WAIT;
622: uuc->tu_flag = 1;
623: if ((uuaddr->rcs&UUCS_INTR) == 0) {
624: printf("NO IE\n");
625: uuaddr->rcs = UUCS_INTR;
626: }
627: break;
628:
629: /*
630: * Header sent, send data.
631: */
632: case TUS_SENDH:
633: uuc->tu_state = TUS_SENDD;
634: uuc->tu_wbptr = (u_char *)uuc->tu_addr;
635: uuc->tu_wcnt = data->pk_mcount;
636: goto top;
637:
638: /*
639: * Data sent, follow with checksum.
640: */
641: case TUS_SENDD:
642: uuc->tu_state = TUS_SENDC;
643: uuc->tu_wbptr = (u_char *)&data->pk_chksum;
644: uuc->tu_wcnt = 2;
645: goto top;
646:
647: /*
648: * Checksum sent, wait for continue.
649: */
650: case TUS_SENDC:
651: /*
652: * Update buffer address and count.
653: */
654: uuc->tu_addr += data->pk_mcount;
655: uuc->tu_count -= data->pk_mcount;
656: if (uuc->tu_count > 0) {
657: uuc->tu_state = TUS_WAIT;
658: uuc->tu_flag = 1;
659: break;
660: }
661:
662: /*
663: * End of transmission, get ready for end packet.
664: */
665: uuc->tu_state = TUS_GET;
666: uuc->tu_rbptr = (u_char *)data;
667: uuc->tu_rcnt = sizeof (*data);
668: uuc->tu_flag = 1;
669: uuaddr->tcs = 0;
670: break;
671:
672: /*
673: * Random interrupt
674: */
675: case TUS_IDLE: /* stray interrupt? */
676:
677: default:
678: break;
679: }
680: }
681:
682: uuwatch()
683: {
684: register struct uu_softc *uuc;
685: register struct uudevice *uuaddr;
686: struct uba_device *ui;
687: struct buf *bp, *uutab;
688: int s, ctlr, active = 0;
689:
690: for (ctlr=0; ctlr<NUU; ctlr++) {
691: int i;
692:
693: uuc = &uu_softc[ctlr];
694:
695: if (uuc->tu_dopen[0] || uuc->tu_dopen[1])
696: active++;
697: if (uuc->tu_flag == 0)
698: /*
699: * If no read is in progress
700: * just skip
701: */
702: continue;
703:
704: ui = uudinfo[ctlr];
705: uuaddr = (struct uudevice *)ui->ui_addr;
706: uutab = &uitab[ctlr];
707: if (uuc->tu_flag++ < 40)
708: continue;
709: printf("uu%d: read stalled\n", uudata[ctlr].pk_unit);
710: #ifdef UUDEBUG
711: printf("%X %X %X %X %X %X %X\n", uuc->tu_rbptr, uuc->tu_rcnt,
712: uuc->tu_wbptr, uuc->tu_wcnt, uuc->tu_state, uuc->tu_addr,
713: uuc->tu_count);
714: #endif
715: s = splx(UUIPL);
716: uuc->tu_flag = 0;
717: i = uuaddr->rdb; /* dummy */
718: uuaddr->rcs = UUCS_INTR; /* in case we were flushing */
719: uuaddr->tcs = UUCS_INTR;
720: uuc->tu_state = TUS_IDLE;
721: if (!uutab->b_active) {
722: wakeup((caddr_t)uuc);
723: goto retry;
724: }
725: if (++uutab->b_errcnt <= 1) {
726: uustart(ui);
727: goto retry;
728: }
729: if (bp = uutab->b_actf) {
730: bp->b_flags |= B_ERROR;
731: if ((bp->b_flags&B_READ) == 0)
732: tu_vee(&uu_pcnt[UNIT(bp->b_dev)]);
733: iodone(bp);
734: }
735: retry:
736: (void) splx(s);
737: }
738: if (active)
739: timeout(uuwatch, (caddr_t)0, hz);
740: else
741: uuwstart = 0;
742: return;
743: }
744:
745: #if !defined(VAX750) && !defined(VAX730)
746: /*
747: * Compute checksum TU58 fashion
748: */
749: #ifdef lint
750: tuchk(word, cp, n)
751: register word;
752: register unsigned short *cp;
753: int n;
754: {
755: register int c = n >> 1;
756: register long temp;
757:
758: do {
759: temp = *cp++; /* temp, only because vax cc won't *r++ */
760: word += temp;
761: } while (--c > 0);
762: if (n & 1)
763: word += *(unsigned char *)cp;
764: while (word & 0xffff0000)
765: word = (word & 0xffff) + ((word >> 16) & 0xffff);
766: return (word);
767: }
768: #else
769: tuchk(word0, wp, n)
770: register int word0; /* r11 */
771: register char *wp; /* r10 */
772: register int n; /* r9 */
773: {
774: asm("loop:");
775: asm(" addw2 (r10)+,r11"); /* add a word to sum */
776: asm(" adwc $0,r11"); /* add in carry, end-around */
777: asm(" acbl $2,$-2,r9,loop"); /* done yet? */
778: asm(" blbc r9,ok"); /* odd byte count? */
779: asm(" movzbw (r10),r10"); /* yes, get last byte */
780: asm(" addw2 r10,r11"); /* add it in */
781: asm(" adwc $0,r11"); /* and the carry */
782: asm("ok:");
783: asm(" movl r11,r0"); /* return sum */
784: }
785: #endif
786:
787: /*
788: * Make sure this incredibly slow device
789: * doesn't eat up all the buffers in the
790: * system by putting the requesting process
791: * (remember: this device is 'single-user')
792: * to sleep if the write-behind queue grows
793: * larger than NUUQ.
794: */
795: tu_pee(cp)
796: char *cp;
797: {
798: register int s;
799:
800: s = splx(UUIPL);
801: if (++(*cp) > NUUQ)
802: sleep(cp, PRIBIO);
803: splx(s);
804: }
805:
806: tu_vee(cp)
807: char *cp;
808: {
809: register int s;
810:
811: s = splx(UUIPL);
812: if (--(*cp) <= NUUQ)
813: wakeup(cp);
814: splx(s);
815: }
816: #endif
817:
818: uuioctl(dev, cmd, data, flag)
819: dev_t dev;
820: caddr_t data;
821: {
822: /*
823: * add code to wind/rewind cassette here
824: */
825: return (ENXIO);
826: }
827:
828: uu_restart(ctlr, ui)
829: int ctlr;
830: struct uba_device *ui;
831: {
832: uureset(ctlr);
833: timeout(uustart, (caddr_t)ui, hz * 3);
834: }
835:
836: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.