|
|
1.1 root 1: /* rl.c 6.1 83/07/29 */
2:
3: #include "rl.h"
4: #if NRL > 0
5: /*
6: * UNIBUS RL02 disk driver
7: */
8: #include "../machine/pte.h"
9:
10: #include "../h/param.h"
11: #include "../h/systm.h"
12: #include "../h/dk.h"
13: #include "../h/dkbad.h"
14: #include "../h/buf.h"
15: #include "../h/conf.h"
16: #include "../h/dir.h"
17: #include "../h/user.h"
18: #include "../h/map.h"
19: #include "../h/vm.h"
20: #include "../h/cmap.h"
21: #include "../h/uio.h"
22: #include "../h/kernel.h"
23:
24: #include "../vax/cpu.h"
25: #include "../vax/nexus.h"
26: #include "../vaxuba/ubavar.h"
27: #include "../vaxuba/ubareg.h"
28: #include "../vaxuba/rlreg.h"
29:
30: /* Pending Controller items and statistics */
31: struct rl_softc {
32: int rl_softas; /* Attention sumary, (seeks pending) */
33: int rl_ndrive; /* Number of drives on controller */
34: int rl_wticks; /* Monitor time for function */
35: } rl_softc[NHL];
36:
37: /*
38: * State of controller from last transfer.
39: * Since only one transfer can be done at a time per
40: * controller, only allocate one for each controller.
41: */
42: struct rl_stat {
43: short rl_cyl[4]; /* Current cylinder for each drive */
44: short rl_dn; /* drive number currently transferring */
45: short rl_cylnhd; /* current cylinder and head of transfer */
46: u_short rl_bleft; /* bytes left to transfer */
47: u_short rl_bpart; /* bytes transferred */
48: } rl_stat[NHL];
49:
50: /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
51: /* Last cylinder not used. Saved for Bad Sector File */
52: struct size {
53: daddr_t nblocks;
54: int cyloff;
55: } rl02_sizes[8] = {
56: 15884, 0, /* A=cyl 0 thru 397 */
57: 4520, 398, /* B=cyl 398 thru 510 */
58: -1, 0, /* C=cyl 0 thru 511 */
59: 4520, 398, /* D=cyl 398 thru 510 */
60: 0, 0, /* F= Not Defined */
61: 20440, 0, /* G=cyl 0 thru 510 */
62: 0, 0, /* H= Not Defined */
63: };
64: /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
65:
66: int rlprobe(), rlslave(), rlattach(), rldgo(), rlintr();
67: struct uba_ctlr *rlminfo[NHL];
68: struct uba_device *rldinfo[NRL];
69: struct uba_device *rlip[NHL][4];
70:
71: /* RL02 driver structure */
72: u_short rlstd[] = { 0174400 };
73: struct uba_driver hldriver =
74: { rlprobe, rlslave, rlattach, rldgo, rlstd, "rl", rldinfo, "hl", rlminfo };
75:
76: /* User table per controller */
77: struct buf rlutab[NRL];
78:
79: /* RL02 drive structure */
80: struct RL02 {
81: short nbpt; /* Number of 512 byte blocks/track */
82: short ntrak;
83: short nbpc; /* Number of 512 byte blocks/cylinder */
84: short ncyl;
85: short btrak; /* Number of bytes/track */
86: struct size *sizes;
87: } rl02 = {
88: 20, 2, 40, 512, 20*512, rl02_sizes /* rl02/DEC*/
89: };
90:
91: struct buf rrlbuf[NRL];
92:
93: #define b_cylin b_resid /* Last seek as CYL<<1 | HD */
94:
95: #ifdef INTRLVE
96: daddr_t dkblock();
97: #endif
98:
99: int rlwstart, rlwatch(); /* Have started guardian */
100:
101: /* Check that controller exists */
102: /*ARGSUSED*/
103: rlprobe(reg)
104: caddr_t reg;
105: {
106: register int br, cvec;
107:
108: #ifdef lint
109: br = 0; cvec = br; br = cvec;
110: rlintr(0);
111: #endif
112: ((struct rldevice *)reg)->rlcs = RL_IE | RL_NOOP;
113: DELAY(10);
114: ((struct rldevice *)reg)->rlcs &= ~RL_IE;
115: return (sizeof (struct rldevice));
116: }
117:
118: rlslave(ui, reg)
119: struct uba_device *ui;
120: caddr_t reg;
121: {
122: register struct rldevice *rladdr = (struct rldevice *)reg;
123: short ctr = 0;
124:
125: /*
126: * DEC reports that:
127: * For some unknown reason the RL02 (seems to be only drive 1)
128: * does not return a valid drive status the first time that a
129: * GET STATUS request is issued for the drive, in fact it can
130: * take up to three or more GET STATUS requests to obtain the
131: * correct status.
132: * In order to overcome this, the driver has been modified to
133: * issue a GET STATUS request and validate the drive status
134: * returned. If a valid status is not returned after eight
135: * attempts, then an error message is printed.
136: */
137: do {
138: rladdr->rlda.getstat = RL_RESET;
139: rladdr->rlcs = (ui->ui_slave <<8) | RL_GETSTAT; /* Get status*/
140: rlwait(rladdr);
141: } while ((rladdr->rlmp.getstat&RLMP_STATUS) != RLMP_STATOK && ++ctr<8);
142: if ((rladdr->rlcs & RL_DE) || (ctr >= 8))
143: return (0);
144: if ((rladdr->rlmp.getstat & RLMP_DT) == 0 ) {
145: printf("rl%d: rl01's not supported\n", ui->ui_slave);
146: return(0);
147: }
148: return (1);
149: }
150:
151: rlattach(ui)
152: register struct uba_device *ui;
153: {
154: register struct rldevice *rladdr;
155:
156: if (rlwstart == 0) {
157: timeout(rlwatch, (caddr_t)0, hz);
158: rlwstart++;
159: }
160: /* Initialize iostat values */
161: if (ui->ui_dk >= 0)
162: dk_mspw[ui->ui_dk] = .000003906; /* 16bit transfer time? */
163: rlip[ui->ui_ctlr][ui->ui_slave] = ui;
164: rl_softc[ui->ui_ctlr].rl_ndrive++;
165: rladdr = (struct rldevice *)ui->ui_addr;
166: /* reset controller */
167: rladdr->rlda.getstat = RL_RESET; /* SHOULD BE REPEATED? */
168: rladdr->rlcs = (ui->ui_slave << 8) | RL_GETSTAT; /* Reset DE bit */
169: rlwait(rladdr);
170: /* determine disk posistion */
171: rladdr->rlcs = (ui->ui_slave << 8) | RL_RHDR;
172: rlwait(rladdr);
173: /* save disk drive posistion */
174: rl_stat[ui->ui_ctlr].rl_cyl[ui->ui_slave] =
175: (rladdr->rlmp.readhdr & 0177700) >> 6;
176: rl_stat[ui->ui_ctlr].rl_dn = -1;
177: }
178:
179: rlopen(dev)
180: dev_t dev;
181: {
182: register int unit = minor(dev) >> 3;
183: register struct uba_device *ui;
184:
185: if (unit >= NRL || (ui = rldinfo[unit]) == 0 || ui->ui_alive == 0)
186: return (ENXIO);
187: return (0);
188: }
189:
190: rlstrategy(bp)
191: register struct buf *bp;
192: {
193: register struct uba_device *ui;
194: register int drive;
195: register struct buf *dp;
196: int partition = minor(bp->b_dev) & 07, s;
197: long bn, sz;
198:
199: sz = (bp->b_bcount+511) >> 9;
200: drive = dkunit(bp);
201: if (drive >= NRL)
202: goto bad;
203: ui = rldinfo[drive];
204: if (ui == 0 || ui->ui_alive == 0)
205: goto bad;
206: if (bp->b_blkno < 0 ||
207: (bn = dkblock(bp))+sz > rl02.sizes[partition].nblocks)
208: goto bad;
209: /* bn is in 512 byte block size */
210: bp->b_cylin = bn/rl02.nbpc + rl02.sizes[partition].cyloff;
211: s = spl5();
212: dp = &rlutab[ui->ui_unit];
213: disksort(dp, bp);
214: if (dp->b_active == 0) {
215: rlustart(ui);
216: bp = &ui->ui_mi->um_tab;
217: if (bp->b_actf && bp->b_active == 0)
218: rlstart(ui->ui_mi);
219: }
220: splx(s);
221: return;
222:
223: bad:
224: bp->b_flags |= B_ERROR;
225: iodone(bp);
226: return;
227: }
228:
229: /*
230: * Unit start routine.
231: * Seek the drive to be where the data is
232: * and then generate another interrupt
233: * to actually start the transfer.
234: */
235: rlustart(ui)
236: register struct uba_device *ui;
237: {
238: register struct buf *bp, *dp;
239: register struct uba_ctlr *um;
240: register struct rldevice *rladdr;
241: daddr_t bn;
242: short hd, diff;
243:
244: if (ui == 0)
245: return;
246: um = ui->ui_mi;
247: dk_busy &= ~(1 << ui->ui_dk);
248: dp = &rlutab[ui->ui_unit];
249: if ((bp = dp->b_actf) == NULL)
250: return;
251: /*
252: * If the controller is active, just remember
253: * that this device has to be positioned...
254: */
255: if (um->um_tab.b_active) {
256: rl_softc[um->um_ctlr].rl_softas |= 1<<ui->ui_slave;
257: return;
258: }
259: /*
260: * If we have already positioned this drive,
261: * then just put it on the ready queue.
262: */
263: if (dp->b_active)
264: goto done;
265: dp->b_active = 1; /* positioning drive */
266: rladdr = (struct rldevice *)um->um_addr;
267:
268: /*
269: * Figure out where this transfer is going to
270: * and see if we are seeked correctly.
271: */
272: bn = dkblock(bp); /* Block # desired */
273: /*
274: * Map 512 byte logical disk blocks
275: * to 256 byte sectors (rl02's are stupid).
276: */
277: hd = (bn / rl02.nbpt) & 1; /* Get head required */
278: diff = (rl_stat[um->um_ctlr].rl_cyl[ui->ui_slave] >> 1) - bp->b_cylin;
279: if ( diff == 0 && (rl_stat[um->um_ctlr].rl_cyl[ui->ui_slave] & 1) == hd)
280: goto done; /* on cylinder and head */
281: /*
282: * Not at correct position.
283: */
284: rl_stat[um->um_ctlr].rl_cyl[ui->ui_slave] = (bp->b_cylin << 1) | hd;
285: if (diff < 0)
286: rladdr->rlda.seek = -diff << 7 | RLDA_HGH | hd << 4;
287: else
288: rladdr->rlda.seek = diff << 7 | RLDA_LOW | hd << 4;
289: rladdr->rlcs = (ui->ui_slave << 8) | RL_SEEK;
290:
291: /*
292: * Mark unit busy for iostat.
293: */
294: if (ui->ui_dk >= 0) {
295: dk_busy |= 1<<ui->ui_dk;
296: dk_seek[ui->ui_dk]++;
297: }
298: rlwait(rladdr);
299: done:
300: /*
301: * Device is ready to go.
302: * Put it on the ready queue for the controller
303: * (unless its already there.)
304: */
305: if (dp->b_active != 2) {
306: dp->b_forw = NULL;
307: if (um->um_tab.b_actf == NULL)
308: um->um_tab.b_actf = dp;
309: else
310: um->um_tab.b_actl->b_forw = dp;
311: um->um_tab.b_actl = dp;
312: dp->b_active = 2; /* Request on ready queue */
313: }
314: }
315:
316: /*
317: * Start up a transfer on a drive.
318: */
319: rlstart(um)
320: register struct uba_ctlr *um;
321: {
322: register struct buf *bp, *dp;
323: register struct uba_device *ui;
324: register struct rldevice *rladdr;
325: register struct rl_stat *st = &rl_stat[um->um_ctlr];
326: daddr_t bn;
327: short sn, cyl, cmd;
328:
329: loop:
330: if ((dp = um->um_tab.b_actf) == NULL) {
331: st->rl_dn = -1;
332: st->rl_cylnhd = 0;
333: st->rl_bleft = 0;
334: st->rl_bpart = 0;
335: return;
336: }
337: if ((bp = dp->b_actf) == NULL) {
338: um->um_tab.b_actf = dp->b_forw;
339: goto loop;
340: }
341: /*
342: * Mark controller busy, and
343: * determine destination.
344: */
345: um->um_tab.b_active++;
346: ui = rldinfo[dkunit(bp)]; /* Controller */
347: bn = dkblock(bp); /* 512 byte Block number */
348: cyl = bp->b_cylin << 1; /* Cylinder */
349: cyl |= (bn / rl02.nbpt) & 1; /* Get head required */
350: sn = (bn % rl02.nbpt) << 1; /* Sector number */
351: rladdr = (struct rldevice *)ui->ui_addr;
352: rlwait(rladdr);
353: rladdr->rlda.rw = cyl<<6 | sn;
354: /* save away current transfers drive status */
355: st->rl_dn = ui->ui_slave;
356: st->rl_cylnhd = cyl;
357: st->rl_bleft = bp->b_bcount;
358: st->rl_bpart = rl02.btrak - (sn * NRLBPSC);
359: /*
360: * RL02 must seek between cylinders and between tracks,
361: * determine maximum data transfer at this time.
362: */
363: if (st->rl_bleft < st->rl_bpart)
364: st->rl_bpart = st->rl_bleft;
365: rladdr->rlmp.rw = -(st->rl_bpart >> 1);
366: if (bp->b_flags & B_READ)
367: cmd = RL_IE | RL_READ | (ui->ui_slave << 8);
368: else
369: cmd = RL_IE | RL_WRITE | (ui->ui_slave << 8);
370: um->um_cmd = cmd;
371: (void) ubago(ui);
372: }
373:
374: rldgo(um)
375: register struct uba_ctlr *um;
376: {
377: register struct rldevice *rladdr = (struct rldevice *)um->um_addr;
378:
379: rladdr->rlba = um->um_ubinfo;
380: rladdr->rlcs = um->um_cmd|((um->um_ubinfo>>12)&RL_BAE);
381: }
382:
383: /*
384: * Handle a disk interrupt.
385: */
386: rlintr(rl21)
387: register rl21;
388: {
389: register struct buf *bp, *dp;
390: register struct uba_ctlr *um = rlminfo[rl21];
391: register struct uba_device *ui;
392: register struct rldevice *rladdr = (struct rldevice *)um->um_addr;
393: register unit;
394: struct rl_softc *rl = &rl_softc[um->um_ctlr];
395: struct rl_stat *st = &rl_stat[um->um_ctlr];
396: int as = rl->rl_softas, status;
397:
398: rl->rl_wticks = 0;
399: rl->rl_softas = 0;
400: dp = um->um_tab.b_actf;
401: bp = dp->b_actf;
402: ui = rldinfo[dkunit(bp)];
403: dk_busy &= ~(1 << ui->ui_dk);
404:
405: /*
406: * Check for and process errors on
407: * either the drive or the controller.
408: */
409: if (rladdr->rlcs & RL_ERR) {
410: u_short err;
411: rlwait(rladdr);
412: err = rladdr->rlcs;
413: /* get staus and reset controller */
414: rladdr->rlda.getstat = RL_GSTAT;
415: rladdr->rlcs = (ui->ui_slave << 8) | RL_GETSTAT;
416: rlwait(rladdr);
417: status = rladdr->rlmp.getstat;
418: /* reset drive */
419: rladdr->rlda.getstat = RL_RESET;
420: rladdr->rlcs = (ui->ui_slave <<8) | RL_GETSTAT; /* Get status*/
421: rlwait(rladdr);
422: if ((status & RLMP_WL) == RLMP_WL) {
423: /*
424: * Give up on write protected devices
425: * immediately.
426: */
427: printf("rl%d: write protected\n", dkunit(bp));
428: bp->b_flags |= B_ERROR;
429: } else if (++um->um_tab.b_errcnt > 10) {
430: /*
431: * After 10 retries give up.
432: */
433: harderr(bp, "rl");
434: printf("cs=%b mp=%b\n", err, RLCS_BITS,
435: status, RLER_BITS);
436: bp->b_flags |= B_ERROR;
437: } else
438: um->um_tab.b_active = 0; /* force retry */
439: /* determine disk position */
440: rladdr->rlcs = (ui->ui_slave << 8) | RL_RHDR;
441: rlwait(rladdr);
442: /* save disk drive position */
443: st->rl_cyl[ui->ui_slave] =
444: (rladdr->rlmp.readhdr & 0177700) >> 6;
445: }
446: /*
447: * If still ``active'', then don't need any more retries.
448: */
449: if (um->um_tab.b_active) {
450: /* RL02 check if more data from previous request */
451: if ((bp->b_flags & B_ERROR) == 0 &&
452: (int)(st->rl_bleft -= st->rl_bpart) > 0) {
453: /*
454: * The following code was modeled from the rk07
455: * driver when an ECC error occured. It has to
456: * fix the bits then restart the transfer which is
457: * what we have to do (restart transfer).
458: */
459: int reg, npf, o, cmd, ubaddr, diff, head;
460:
461: /* seek to next head/track */
462: /* increment head and/or cylinder */
463: st->rl_cylnhd++;
464: diff = (st->rl_cyl[ui->ui_slave] >> 1) -
465: (st->rl_cylnhd >> 1);
466: st->rl_cyl[ui->ui_slave] = st->rl_cylnhd;
467: head = st->rl_cylnhd & 1;
468: rlwait(rladdr);
469: if (diff < 0)
470: rladdr->rlda.seek =
471: -diff << 7 | RLDA_HGH | head << 4;
472: else
473: rladdr->rlda.seek =
474: diff << 7 | RLDA_LOW | head << 4;
475: rladdr->rlcs = (ui->ui_slave << 8) | RL_SEEK;
476: npf = btop( bp->b_bcount - st->rl_bleft );
477: reg = btop(um->um_ubinfo&0x3ffff) + npf;
478: o = (int)bp->b_un.b_addr & PGOFSET;
479: ubapurge(um);
480: um->um_tab.b_active++;
481: rlwait(rladdr);
482: rladdr->rlda.rw = st->rl_cylnhd << 6;
483: if (st->rl_bleft < (st->rl_bpart = rl02.btrak))
484: st->rl_bpart = st->rl_bleft;
485: rladdr->rlmp.rw = -(st->rl_bpart >> 1);
486: cmd = (bp->b_flags&B_READ ? RL_READ : RL_WRITE) |
487: RL_IE | (ui->ui_slave << 8);
488: ubaddr = (int)ptob(reg) + o;
489: cmd |= ((ubaddr >> 12) & RL_BAE);
490: rladdr->rlba = ubaddr;
491: rladdr->rlcs = cmd;
492: return;
493: }
494: um->um_tab.b_active = 0;
495: um->um_tab.b_errcnt = 0;
496: dp->b_active = 0;
497: dp->b_errcnt = 0;
498: /* "b_resid" words remaining after error */
499: bp->b_resid = st->rl_bleft;
500: um->um_tab.b_actf = dp->b_forw;
501: dp->b_actf = bp->av_forw;
502: st->rl_dn = -1;
503: st->rl_bpart = st->rl_bleft = 0;
504: iodone(bp);
505: /*
506: * If this unit has more work to do,
507: * then start it up right away.
508: */
509: if (dp->b_actf)
510: rlustart(ui);
511: as &= ~(1<<ui->ui_slave);
512: } else
513: as |= (1<<ui->ui_slave);
514: ubadone(um);
515: /* reset state info */
516: st->rl_dn = -1;
517: st->rl_cylnhd = st->rl_bpart = st->rl_bleft = 0;
518: /*
519: * Process other units which need attention.
520: * For each unit which needs attention, call
521: * the unit start routine to place the slave
522: * on the controller device queue.
523: */
524: while (unit = ffs(as)) {
525: unit--; /* was 1 origin */
526: as &= ~(1<<unit);
527: rlustart(rlip[rl21][unit]);
528: }
529: /*
530: * If the controller is not transferring, but
531: * there are devices ready to transfer, start
532: * the controller.
533: */
534: if (um->um_tab.b_actf && um->um_tab.b_active == 0)
535: rlstart(um);
536: }
537:
538: rlwait(rladdr)
539: register struct rldevice *rladdr;
540: {
541:
542: while ((rladdr->rlcs & RL_CRDY) == 0)
543: ;
544: }
545:
546: rlread(dev, uio)
547: dev_t dev;
548: struct uio *uio;
549: {
550: register int unit = minor(dev) >> 3;
551:
552: if (unit >= NRL)
553: return (ENXIO);
554: return (physio(rlstrategy, &rrlbuf[unit], dev, B_READ, minphys, uio));
555: }
556:
557: rlwrite(dev, uio)
558: dev_t dev;
559: struct uio *uio;
560: {
561: register int unit = minor(dev) >> 3;
562:
563: if (unit >= NRL)
564: return (ENXIO);
565: return (physio(rlstrategy, &rrlbuf[unit], dev, B_WRITE, minphys, uio));
566: }
567:
568: /*
569: * Reset driver after UBA init.
570: * Cancel software state of all pending transfers
571: * and restart all units and the controller.
572: */
573: rlreset(uban)
574: int uban;
575: {
576: register struct uba_ctlr *um;
577: register struct uba_device *ui;
578: register struct rldevice *rladdr;
579: register struct rl_stat *st;
580: register int rl21, unit;
581:
582: for (rl21 = 0; rl21 < NHL; rl21++) {
583: if ((um = rlminfo[rl21]) == 0 || um->um_ubanum != uban ||
584: um->um_alive == 0)
585: continue;
586: printf(" hl%d", rl21);
587: rladdr = (struct rldevice *)um->um_addr;
588: st = &rl_stat[rl21];
589: um->um_tab.b_active = 0;
590: um->um_tab.b_actf = um->um_tab.b_actl = 0;
591: if (um->um_ubinfo) {
592: printf("<%d>", (um->um_ubinfo>>28)&0xf);
593: um->um_ubinfo = 0;
594: }
595: /* reset controller */
596: st->rl_dn = -1;
597: st->rl_cylnhd = 0;
598: st->rl_bleft = 0;
599: st->rl_bpart = 0;
600: rlwait(rladdr);
601: for (unit = 0; unit < NRL; unit++) {
602: rladdr->rlcs = (unit << 8) | RL_GETSTAT;
603: rlwait(rladdr);
604: /* Determine disk posistion */
605: rladdr->rlcs = (unit << 8) | RL_RHDR;
606: rlwait(rladdr);
607: /* save disk drive posistion */
608: st->rl_cyl[unit] =
609: (rladdr->rlmp.readhdr & 0177700) >> 6;
610: if ((ui = rldinfo[unit]) == 0)
611: continue;
612: if (ui->ui_alive == 0 || ui->ui_mi != um)
613: continue;
614: rlutab[unit].b_active = 0;
615: rlustart(ui);
616: }
617: rlstart(um);
618: }
619: }
620:
621: /*
622: * Wake up every second and if an interrupt is pending
623: * but nothing has happened increment a counter.
624: * If nothing happens for 20 seconds, reset the UNIBUS
625: * and begin anew.
626: */
627: rlwatch()
628: {
629: register struct uba_ctlr *um;
630: register rl21, unit;
631: register struct rl_softc *rl;
632:
633: timeout(rlwatch, (caddr_t)0, hz);
634: for (rl21 = 0; rl21 < NHL; rl21++) {
635: um = rlminfo[rl21];
636: if (um == 0 || um->um_alive == 0)
637: continue;
638: rl = &rl_softc[rl21];
639: if (um->um_tab.b_active == 0) {
640: for (unit = 0; unit < NRL; unit++)
641: if (rlutab[unit].b_active &&
642: rldinfo[unit]->ui_mi == um)
643: goto active;
644: rl->rl_wticks = 0;
645: continue;
646: }
647: active:
648: rl->rl_wticks++;
649: if (rl->rl_wticks >= 20) {
650: rl->rl_wticks = 0;
651: printf("hl%d: lost interrupt\n", rl21);
652: ubareset(um->um_ubanum);
653: }
654: }
655: }
656:
657: /*ARGSUSED*/
658: rldump(dev)
659: dev_t dev;
660: {
661:
662: /* don't think there is room on swap for it anyway. */
663: }
664:
665: rlsize(dev)
666: dev_t dev;
667: {
668: register int unit = minor(dev) >> 3;
669: register struct uba_device *ui;
670:
671: if (unit >= NRL || (ui = rldinfo[unit]) == 0 || ui->ui_alive == 0)
672: return (-1);
673: return (rl02.sizes[minor(dev) & 07].nblocks);
674: }
675: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.