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