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