|
|
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: * %W% (Berkeley) %D%
7: */
8:
9: /*
10: * up.c, driver for Emulex SC21, SC31 disk controllers
11: * with support for disklabels.
12: * UNTESTED.
13: */
14:
15: #ifdef UPDEBUG
16: int updebug;
17: #endif
18: #ifdef UPBDEBUG
19: int upbdebug;
20: #endif
21:
22: #include "up.h"
23: #if NSC > 0
24: /*
25: * UNIBUS disk driver with:
26: * overlapped seeks,
27: * ECC recovery, and
28: * bad sector forwarding.
29: *
30: * TODO:
31: * Check that offset recovery code works
32: */
33: #include "../machine/pte.h"
34:
35: #include "param.h"
36: #include "systm.h"
37: #include "dkstat.h"
38: #include "dkbad.h"
39: #include "ioctl.h"
40: #include "disklabel.h"
41: #include "buf.h"
42: #include "conf.h"
43: #include "dir.h"
44: #include "file.h"
45: #include "user.h"
46: #include "map.h"
47: #include "vm.h"
48: #include "cmap.h"
49: #include "uio.h"
50: #include "kernel.h"
51: #include "syslog.h"
52: #include "stat.h"
53:
54: #include "../vax/mtpr.h"
55: #include "../vax/cpu.h"
56: #include "../vax/nexus.h"
57: #include "ubavar.h"
58: #include "ubareg.h"
59: #include "upreg.h"
60:
61: #define COMPAT_42
62: #define B_FORMAT B_XXX
63:
64: #define upunit(dev) (minor(dev) >> 3)
65: #define uppart(dev) (minor(dev) & 07)
66: #define upminor(unit, part) (((unit) << 3) | (part))
67:
68: int upprobe(), upslave(), upattach(), updgo(), upintr();
69: struct uba_ctlr *upminfo[NSC];
70: struct uba_device *updinfo[NUP];
71: #define UPIPUNITS 8
72: struct uba_device *upip[NSC][UPIPUNITS]; /* fuji w/fixed head gives n,n+4 */
73:
74: u_short upstd[] = { 0776700, 0774400, 0776300, 0 };
75: struct uba_driver scdriver =
76: { upprobe, upslave, upattach, updgo, upstd, "up", updinfo, "sc", upminfo };
77:
78: struct buf uputab[NUP];
79: char upinit[NUP];
80:
81: u_char up_offset[16] = {
82: UPOF_P400, UPOF_M400, UPOF_P400, UPOF_M400,
83: UPOF_P800, UPOF_M800, UPOF_P800, UPOF_M800,
84: UPOF_P1200, UPOF_M1200, UPOF_P1200, UPOF_M1200,
85: 0, 0, 0, 0
86: };
87:
88: struct buf bupbuf[NUP];
89: struct dkbad upbad[NUP];
90:
91: struct upsoftc {
92: u_char sc_recal; /* recalibrate state */
93: u_char sc_doseeks; /* perform explicit seeks */
94: #ifdef COMPAT_42
95: u_char sc_hdr; /* next i/o includes header */
96: #endif
97: short sc_state; /* open fsm */
98: short sc_wlabel; /* label sector is currently writeable */
99: u_long sc_openpart; /* bit mask of open subunits */
100: u_long sc_copenpart; /* bit mask of open character subunits */
101: u_long sc_bopenpart; /* bit mask of open block subunits */
102: int sc_blkdone; /* amount sucessfully transfered */
103: daddr_t sc_badbn; /* replacement block number */
104: short sc_softas; /* bitmask of drives needing attention */
105: short sc_ndrive; /* count of drives */
106: int sc_wticks; /* watchdog timer */
107: int sc_status; /* copy of drive status reg after format */
108: int sc_upds; /* copy of upds reg after format */
109: int sc_er1; /* copy of error reg 1 after format */
110: int sc_er2; /* copy of error reg 2 after format */
111: } upsoftc[NSC];
112:
113: /*
114: * Drive states. Used during steps of open/initialization.
115: * States < OPEN (> 0) are transient, during an open operation.
116: * OPENRAW is used for unlabeled disks,
117: * to inhibit bad-sector forwarding or allow format operations.
118: */
119: #define CLOSED 0 /* disk is closed. */
120: #define WANTOPEN 1 /* open requested, not started */
121: #define WANTOPENRAW 2 /* open requested, no label */
122: #define RDLABEL 3 /* reading pack label */
123: #define RDBADTBL 4 /* reading bad-sector table */
124: #define OPEN 5 /* initialized and ready */
125: #define OPENRAW 6 /* open, no label or badsect */
126:
127: #define b_cylin b_resid /* cyl number, for disksort */
128: #define b_bufsiz b_bdone /* amount done, in ui_tab only */
129:
130: int upwstart, upwatch(); /* Have started guardian */
131: int upseek;
132: int upwaitdry;
133:
134: upprobe(reg)
135: caddr_t reg;
136: {
137: register int br, cvec;
138:
139: #ifdef lint
140: br = 0; cvec = br; br = cvec; upintr(0);
141: #endif
142: ((struct updevice *)reg)->upcs1 = UP_IE|UP_RDY;
143: DELAY(10);
144: ((struct updevice *)reg)->upcs1 = 0;
145: return (sizeof (struct updevice));
146: }
147:
148: upslave(ui, reg)
149: struct uba_device *ui;
150: caddr_t reg;
151: {
152: register struct updevice *upaddr = (struct updevice *)reg;
153:
154: upaddr->upcs1 = 0; /* conservative */
155: upaddr->upcs2 = ui->ui_slave;
156: upaddr->upcs1 = UP_NOP|UP_GO;
157: if (upaddr->upcs2&UPCS2_NED) {
158: upaddr->upcs1 = UP_DCLR|UP_GO;
159: return (0);
160: }
161: return (1);
162: }
163:
164: upattach(ui)
165: register struct uba_device *ui;
166: {
167: register int unit = ui->ui_unit;
168:
169: if (upwstart == 0) {
170: timeout(upwatch, (caddr_t)0, hz);
171: upwstart++;
172: }
173: upip[ui->ui_ctlr][ui->ui_slave] = ui;
174: up_softc[ui->ui_ctlr].sc_ndrive++;
175:
176: /*
177: * Try to initialize device and read pack label.
178: */
179: if (upinit(upminor(unit, 0), 0) == 0) {
180: printf(": %s", uplabel[unit].d_typename);
181: #ifdef notyet
182: addswap(makedev(UPMAJOR, upminor(unit, 0)), &uplabel[unit]);
183: #endif
184: } else
185: printf(": offline");
186: }
187:
188: upopen(dev, flags, fmt)
189: dev_t dev;
190: int flags, fmt;
191: {
192: register int unit = upunit(dev);
193: register struct upsoftc *sc;
194: register struct disklabel *lp;
195: register struct partition *pp;
196: struct uba_device *ui;
197: int s, error, part = uppart(dev), mask = 1 << part;
198: daddr_t start, end;
199:
200: if (unit >= NUP || (ui = updinfo[unit]) == 0 || ui->ui_alive == 0)
201: return (ENXIO);
202:
203: sc = &upsoftc[unit];
204: lp = &uplabel[unit];
205:
206: s = spl5();
207: while (sc->sc_state != OPEN && sc->sc_state != OPENRAW &&
208: sc->sc_state != CLOSED)
209: sleep ((caddr_t)sc, PZERO+1);
210: splx(s);
211: if (sc->sc_state != OPEN && sc->sc_state != OPENRAW)
212: if (error = upinit(dev, flags))
213: return (error);
214: if (part >= lp->d_npartitions)
215: return (ENXIO);
216: /*
217: * Warn if a partion is opened
218: * that overlaps another partition which is open
219: * unless one is the "raw" partition (whole disk).
220: */
221: #define RAWPART 2 /* 'c' partition */ /* XXX */
222: if ((sc->sc_openpart & mask) == 0 && part != RAWPART) {
223: pp = &lp->d_partitions[part];
224: start = pp->p_offset;
225: end = pp->p_offset + pp->p_size;
226: for (pp = lp->d_partitions;
227: pp < &lp->d_partitions[lp->d_npartitions]; pp++) {
228: if (pp->p_offset + pp->p_size <= start ||
229: pp->p_offset >= end)
230: continue;
231: if ((s = pp - lp->d_partitions) == RAWPART)
232: continue;
233: if (sc->sc_openpart & (1 << s))
234: log(LOG_WARNING,
235: "up%d%c: overlaps open partition (%c)\n",
236: unit, part + 'a', s + 'a');
237: }
238: }
239: switch (fmt) {
240: case S_IFCHR:
241: sc->sc_copenpart |= mask;
242: break;
243: case S_IFBLK:
244: sc->sc_bopenpart |= mask;
245: break;
246: }
247: sc->sc_openpart |= mask;
248: return (0);
249: }
250:
251: /* ARGSUSED */
252: upclose(dev, flags, fmt)
253: dev_t dev;
254: int flags, fmt;
255: {
256: register int unit = upunit(dev);
257: register struct upsoftc *sc = &upsoftc[unit];
258: struct uba_device *ui = updinfo[unit];
259: int s;
260:
261: switch (fmt) {
262: case S_IFCHR:
263: sc->sc_copenpart &= ~(1 << uppart(dev));
264: break;
265: case S_IFBLK:
266: sc->sc_bopenpart &= ~(1 << uppart(dev));
267: break;
268: }
269: if (sc->sc_openpart)
270: sc->sc_openpart = sc->sc_copenpart | sc->sc_bopenpart;
271:
272: /*
273: * If this was the last open partition on the drive, then
274: * we must wait for the i/o to complete (so caller knows its
275: * ok to turn the drive off). If not the last, no problem,
276: * as some other partition must still be active. (Potential
277: * problem is some part of the "drive" can be spun down
278: * while leaving other part of same drive running ..)
279: *
280: * (this will also happen if we have disabled the drive because
281: * of an unanticipated pack change, but no harm there)
282: */
283: if (sc->sc_openpart == 0) {
284: s = spl5();
285: while (ui->ui_tab.b_actf)
286: sleep((caddr_t)sc, PZERO - 1);
287: splx(s);
288: sc->sc_state = CLOSED;
289: }
290: return (0);
291: }
292:
293: upinit(dev, flags)
294: dev_t dev;
295: int flags;
296: {
297: register struct upsoftc *sc;
298: register struct buf *bp;
299: register struct disklabel *lp;
300: struct uba_device *ui;
301: struct dkbad *db;
302: char *msg, *readdisklabel();
303: int unit, i, error = 0;
304: extern int cold;
305:
306: unit = upunit(dev);
307: sc = &upsoftc[unit];
308: lp = &uplabel[unit];
309: ui = updinfo[unit];
310:
311: sc->sc_state = WANTOPEN;
312:
313: /*
314: * Obtain the physical drive characteristics from the
315: * controller, for use until the label overrides them.
316: */
317: upphysical(ui->ui_addr, lp);
318:
319: if (flags & O_NDELAY)
320: goto raw;
321:
322: /*
323: * Preset, pack acknowledge will be done in upstart
324: * during first read operation.
325: */
326: if (msg = readdisklabel(dev, upstrategy, lp)) {
327: if (cold)
328: printf(": %s", msg);
329: else
330: log(LOG_ERR, "up%d: %s\n", unit, msg);
331: #ifdef COMPAT_42
332: if (upmaptype(ui, lp) == 0)
333: #endif
334: goto raw;
335: }
336:
337: /*
338: * Seconds per word = (60 / rpm) / (nsectors * secsize/2)
339: */
340: if (ui->ui_dk >= 0 && lp->d_rpm)
341: dk_mspw[ui->ui_dk] = 120.0 /
342: (lp->d_rpm * lp->d_nsectors * lp->d_secsize);
343: /*
344: * Read bad sector table into memory.
345: */
346: bp = geteblk(DEV_BSIZE); /* max sector size */
347: bp->b_dev = dev;
348: sc->sc_state = RDBADTBL;
349: i = 0;
350: do {
351: u.u_error = 0; /* XXX */
352: bp->b_flags = B_BUSY | B_READ;
353: bp->b_blkno = lp->d_secperunit - lp->d_nsectors + i;
354: bp->b_bcount = lp->d_secsize;
355: bp->b_cylin = lp->d_ncylinders - 1;
356: upstrategy(bp);
357: biowait(bp);
358: } while ((bp->b_flags & B_ERROR) && (i += 2) < 10 &&
359: i < lp->d_nsectors);
360: db = (struct dkbad *)(bp->b_un.b_addr);
361: if ((bp->b_flags & B_ERROR) == 0 && db->bt_mbz == 0 &&
362: db->bt_flag == 0) {
363: upbad[unit] = *db;
364: sc->sc_state = OPEN;
365: } else {
366: log(LOG_ERR, "up%d: %s bad-sector file\n", unit,
367: (bp->b_flags & B_ERROR) ? "can't read" : "format error in");
368: u.u_error = 0; /* XXX */
369: sc->sc_state = OPENRAW;
370: }
371: bp->b_flags = B_INVAL | B_AGE;
372: brelse(bp);
373: done:
374: wakeup((caddr_t)sc);
375: return (error);
376:
377: raw:
378: sc->sc_state = OPENRAW;
379: wakeup((caddr_t)sc);
380: return (error);
381: }
382:
383: /*
384: * obtain the physical drive layout from the controller prom
385: * (we know this isn't a dec controller, so we can assume sanity)
386: */
387: upphysical(upaddr, lp)
388: register struct updevice *upaddr;
389: register struct disklabel *lp;
390: {
391: upaddr->upcs1 = 0;
392: upaddr->upcs2 = ui->ui_slave;
393:
394: upaddr->uphr = UPHR_MAXTRAK;
395: lp->d_ntracks = upaddr->uphr + 1;
396:
397: upaddr->uphr = UPHR_MAXSECT;
398: lp->d_nsectors = upaddr->uphr + 1;
399:
400: upaddr->uphr = UPHR_MAXCYL;
401: lp->d_ncylinders = upaddr->uphr + 1;
402:
403: lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
404: lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
405:
406: lp->d_npartitions = 1; /* ??? (allow label write) */
407: lp->d_partitions[0].p_offset = 0;
408: lp->d_partitions[0].p_size = lp->d_secperunit;
409:
410: lp->d_secsize = DEV_BSIZE; /* assume this */
411:
412: upaddr->upcs2 = UPCS2_CLR;
413: }
414:
415: upstrategy(bp)
416: register struct buf *bp;
417: {
418: register struct uba_device *ui;
419: register struct disklabel *lp;
420: register struct upsoftc *sc;
421: register int unit;
422: register struct buf *dp;
423: long bn, sz;
424: daddr_t maxsz;
425: int xunit = uppart(bp->b_dev);
426: int s;
427:
428: sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
429: unit = hpunit(bp->b_dev);
430: if (unit >= NUP) {
431: bp->b_error = ENXIO;
432: goto bad;
433: }
434: ui = updinfo[unit];
435: if (ui == 0 || ui->ui_alive == 0) {
436: bp->b_error = ENXIO;
437: goto bad;
438: }
439: sc = &upsoftc[unit];
440: lp = &uplabel[unit];
441: if (sc->sc_state < OPEN)
442: goto q;
443: if ((sc->sc_openpart & (1 << xunit)) == 0) {
444: bp->b_error = ENODEV;
445: goto bad;
446: }
447: maxsz = lp->d_partitions[xunit].p_size;
448: if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
449: if (bp->b_blkno == maxsz) {
450: bp->b_resid = bp->b_bcount;
451: goto done;
452: }
453: sz = maxsz - bp->b_blkno;
454: if (sz <= 0) {
455: bp->b_error = EINVAL;
456: goto bad;
457: }
458: bp->b_bcount = sz << DEV_BSHIFT;
459: }
460: bp->b_cylin = (bp->b_blkno + lp->d_partitions[xunit].p_offset) /
461: lp->d_secpercyl;
462: q:
463: s = spl5();
464: dp = &uputab[ui->ui_unit];
465: disksort(dp, bp);
466: if (dp->b_active == 0) {
467: (void) upustart(ui);
468: bp = &ui->ui_mi->um_tab;
469: if (bp->b_actf && bp->b_active == 0)
470: (void) upstart(ui->ui_mi);
471: }
472: splx(s);
473: return;
474:
475: bad:
476: bp->b_flags |= B_ERROR;
477: done:
478: biodone(bp);
479: return;
480: }
481:
482: /*
483: * Unit start routine.
484: * Seek the drive to be where the data is
485: * and then generate another interrupt
486: * to actually start the transfer.
487: * If there is only one drive on the controller,
488: * or we are very close to the data, don't
489: * bother with the search. If called after
490: * searching once, don't bother to look where
491: * we are, just queue for transfer (to avoid
492: * positioning forever without transferrring.)
493: */
494: upustart(ui)
495: register struct uba_device *ui;
496: {
497: register struct buf *bp, *dp;
498: register struct uba_ctlr *um;
499: register struct updevice *upaddr;
500: register struct disklabel *lp;
501: struct upsoftc *sc = &upsoftc[ui->ui_unit];
502: daddr_t bn;
503: int sn, tn, dist;
504: /*
505: * The SC21 cancels commands if you just say
506: * cs1 = UP_IE
507: * so we are cautious about handling of cs1.
508: * Also don't bother to clear as bits other than in upintr().
509: */
510: int didie = 0;
511:
512: if (ui == 0)
513: return (0);
514: um = ui->ui_mi;
515: dk_busy &= ~(1<<ui->ui_dk);
516: dp = &uputab[ui->ui_unit];
517: retry:
518: if ((bp = dp->b_actf) == NULL)
519: return (0);
520: /*
521: * If the controller is active, just remember
522: * that this device would like to be positioned...
523: * if we tried to position now we would confuse the SC21.
524: */
525: if (um->um_tab.b_active) {
526: up_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave;
527: return (0);
528: }
529: /*
530: * If we have already positioned this drive,
531: * then just put it on the ready queue.
532: */
533: if (dp->b_active)
534: goto done;
535: dp->b_active = 1;
536:
537: lp = &uplabel[ui->ui_unit];
538: upaddr = (struct updevice *)um->um_addr;
539: upaddr->upcs2 = ui->ui_slave;
540:
541: switch (sc->sc_recal) {
542:
543: case 1:
544: (void)HPWAIT(mi, hpaddr);
545: upaddr->updc = bp->b_cylin;
546: upaddr->upcs1 = UP_IE|UP_SEEK|UP_GO;
547: sc->sc_recal++;
548: return (1);
549: case 2:
550: break;
551: }
552: sc->sc_recal = 0;
553: /*
554: * If drive has just come up,
555: * setup the pack.
556: */
557: if ((upaddr->upds & UPDS_VV) == 0) {
558: struct buf *bbp = &bupbuf[ui->ui_unit];
559:
560: if (sc->sc_state == OPEN && lp->d_flags & D_REMOVABLE) {
561: if (sc->sc_openpart)
562: log(LOG_ERR, "up%d: volume changed\n",
563: ui->ui_unit);
564: sc->sc_openpart = 0;
565: do {
566: dp->b_actf = bp->b_forw;
567: bp->b_flags |= B_ERROR;
568: bp->b_errno = ENXIO;
569: iodone(bp);
570: } while (bp = dp->b_actf);
571: return (0);
572: }
573: upaddr->upcs1 = UP_IE|UP_DCLR|UP_GO;
574: upaddr->upcs1 = UP_IE|UP_PRESET|UP_GO;
575: upaddr->upof = UPOF_FMT22;
576: if (sc->sc_state == WANTOPENRAW) {
577: sc->sc_state = OPENRAW;
578: return (1);
579: }
580: if (sc->sc_state == WANTOPEN)
581: sc->sc_state = RDLABEL;
582: didie = 1;
583: }
584: /*
585: * If drive is offline, forget about positioning.
586: */
587: if ((upaddr->upds & (UPDS_DPR|UPDS_MOL)) != (UPDS_DPR|UPDS_MOL))
588: goto done;
589: /*
590: * If there is only one drive,
591: * dont bother searching.
592: */
593: if (up_softc[um->um_ctlr].sc_ndrive == 1)
594: goto done;
595: /*
596: * Figure out where this transfer is going to
597: * and see if we are close enough to justify not searching.
598: */
599: st = &upst[ui->ui_type];
600: bn = bp->b_blkno;
601: sn = bn % lp->d_secpercyl;
602: tn = sn / lp->d_nsectors;
603: sn = sn % lp->d_nsectors;
604: if (bp->b_cylin == upaddr->updc) {
605: if (sc->sc_doseeks)
606: goto done; /* Ok just to be on-cylinder */
607: dist = sn - (upaddr->upla>>6) - 1;
608: if (dist < 0)
609: dist += lp->d_nsectors;
610: if (dist <= lp->d_maxdist && dist >= lp->d_mindist)
611: goto done;
612: } else
613: upaddr->updc = bp->b_cylin;
614: /*
615: * Not on cylinder at correct position,
616: * seek/search.
617: */
618: if (sc->sc_doseeks)
619: upaddr->upcs1 = UP_IE|UP_SEEK|UP_GO;
620: else {
621: sn = (sn + lp->d_nsectors - lp->d_sdist) % lp->d_nsectors;
622: upaddr->upda = sn;
623: upaddr->upcs1 = UP_IE|UP_SEARCH|UP_GO;
624: }
625: didie = 1;
626: /*
627: * Mark unit busy for iostat.
628: */
629: if (ui->ui_dk >= 0) {
630: dk_busy |= 1<<ui->ui_dk;
631: dk_seek[ui->ui_dk]++;
632: }
633: goto out;
634: done:
635: /*
636: * Device is ready to go.
637: * Put it on the ready queue for the controller
638: * (unless its already there.)
639: */
640: if (dp->b_active != 2) {
641: dp->b_forw = NULL;
642: if (um->um_tab.b_actf == NULL)
643: um->um_tab.b_actf = dp;
644: else
645: um->um_tab.b_actl->b_forw = dp;
646: um->um_tab.b_actl = dp;
647: dp->b_active = 2;
648: }
649: out:
650: return (didie);
651: }
652:
653: /*
654: * Start up a transfer on a drive.
655: */
656: upstart(um)
657: register struct uba_ctlr *um;
658: {
659: register struct buf *bp, *dp;
660: register struct uba_device *ui;
661: register struct updevice *upaddr;
662: register struct disklabel *lp = &uplabel[ui->ui_unit];
663: struct upsoftc *sc = &upsoftc[ui->ui_unit];
664: daddr_t bn;
665: int cn, dn, sn, tn, cmd, waitdry;
666:
667: loop:
668: /*
669: * Pull a request off the controller queue
670: */
671: if ((dp = um->um_tab.b_actf) == NULL)
672: return (0);
673: if ((bp = dp->b_actf) == NULL) {
674: um->um_tab.b_actf = dp->b_forw;
675: goto loop;
676: }
677: /*
678: * Mark controller busy, and
679: * determine destination of this request.
680: */
681: um->um_tab.b_active++;
682: ui = updinfo[upunit(bp->b_dev)];
683: bn = bp->b_blkno;
684: dn = ui->ui_slave;
685: st = &upst[ui->ui_type];
686: sn = bn%st->nspc;
687: tn = sn/st->nsect;
688: sn %= st->nsect;
689: upaddr = (struct updevice *)ui->ui_addr;
690: /*
691: * Select drive if not selected already.
692: */
693: if ((upaddr->upcs2&07) != dn)
694: upaddr->upcs2 = dn;
695: /*
696: * Check that it is ready and online
697: */
698: waitdry = 0;
699: while ((upaddr->upds&UPDS_DRY) == 0) {
700: log(LOG_ERR, "up%d: ds wait ds=%o\n", upunit(bp->b_dev),
701: upaddr->upds);
702: if (++waitdry > 512)
703: break;
704: upwaitdry++;
705: }
706: if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) {
707: /*
708: * this should be "log()", but log with split
709: * messages is very messy, and we also depend here
710: * on there being a real (measureable) time taken
711: * doing the printf, to give the drive a chance to
712: * recover .. printf polls the terminal, so takes ages
713: */
714: printf("up%d: not ready", upunit(bp->b_dev));
715: if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) {
716: printf("\n");
717: um->um_tab.b_active = 0;
718: um->um_tab.b_errcnt = 0;
719: dp->b_actf = bp->av_forw;
720: dp->b_active = 0;
721: bp->b_flags |= B_ERROR;
722: iodone(bp);
723: goto loop;
724: }
725: /*
726: * Oh, well, sometimes this
727: * happens, for reasons unknown.
728: */
729: printf(" (flakey)\n");
730: }
731: /*
732: * Setup for the transfer, and get in the
733: * UNIBUS adaptor queue.
734: */
735: if (bp->b_flags & B_BAD) {
736: bn = sc->sc_badbn;
737: cn = bn / lp->d_secpercyl;
738: } else {
739: bn = bp->b_blkno;
740: cn = bp->b_cylin;
741: }
742: sn = bn % lp->d_secpercyl;
743: if ((bp->b_flags & B_BAD) == 0)
744: sn += sc->sc_blkdone;
745: tn = sn / lp->d_nsectors;
746: sn %= lp->d_nsectors;
747: cn += tn / lp->d_ntracks;
748: tn %= lp->d_ntracks;
749: upaddr->updc = cn;
750: upaddr->upda = (tn << 8) + sn;
751:
752: if (bp->b_bcount >= 0)
753: upaddr->upwc = (-bp->b_bcount + ui->ui_tab.b_bdone) /
754: sizeof (short);
755: else
756: upaddr->upwc = (bp->b_wcount + ui->ui_tab.b_bdone) /
757: sizeof (short);
758:
759: switch (bp->b_flags & (B_READ|B_WRITE|B_FORMAT)) {
760: case B_READ:
761: cmd = UP_IE|UP_RCOM|UP_GO;
762: break;
763: case B_WRITE:
764: cmd = UP_IE|UP_WCOM|UP_GO;
765: break;
766: case B_READ|B_FORMAT:
767: cmd = UP_IE|UP_RHDR|UP_GO;
768: break;
769: case B_WRITE|B_FORMAT:
770: cmd = UP_IE|UP_WHDR|UP_GO;
771: break;
772: }
773: um->um_cmd = cmd;
774: ui->ui_tab.b_bdone = dbtob(sc->sc_blkdone);
775: (void) ubago(ui);
776: return (1);
777: }
778:
779: /*
780: * Now all ready to go, stuff the registers.
781: */
782: updgo(um)
783: struct uba_ctlr *um;
784: {
785: register struct updevice *upaddr = (struct updevice *)um->um_addr;
786:
787: um->um_tab.b_active = 2; /* should now be 2 */
788: upaddr->upba = um->um_ubinfo;
789: upaddr->upcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300);
790: }
791:
792: /*
793: * Handle a disk interrupt.
794: */
795: upintr(sc21)
796: register sc21;
797: {
798: register struct buf *bp, *dp;
799: register struct uba_ctlr *um = upminfo[sc21];
800: register struct uba_device *ui;
801: register struct updevice *upaddr = (struct updevice *)um->um_addr;
802: register unit;
803: struct up_softc *sc = &up_softc[um->um_ctlr];
804: int as = (upaddr->upas & 0377) | sc->sc_softas;
805: int needie = 1, waitdry;
806:
807: sc->sc_wticks = 0;
808: sc->sc_softas = 0;
809: /*
810: * If controller wasn't transferring, then this is an
811: * interrupt for attention status on seeking drives.
812: * Just service them.
813: */
814: if (um->um_tab.b_active != 2 && !sc->sc_recal) {
815: if (upaddr->upcs1 & UP_TRE)
816: upaddr->upcs1 = UP_TRE;
817: goto doattn;
818: }
819: um->um_tab.b_active = 1;
820: /*
821: * Get device and block structures, and a pointer
822: * to the uba_device for the drive. Select the drive.
823: */
824: dp = um->um_tab.b_actf;
825: bp = dp->b_actf;
826: ui = updinfo[upunit(bp->b_dev)];
827: dk_busy &= ~(1 << ui->ui_dk);
828: if ((upaddr->upcs2&07) != ui->ui_slave)
829: upaddr->upcs2 = ui->ui_slave;
830:
831: /*
832: * Check for and process errors on
833: * either the drive or the controller.
834: */
835: if ((upaddr->upds&UPDS_ERR) || (upaddr->upcs1&UP_TRE)) {
836: er1 = upaddr->uper1;
837: er2 = upaddr->uper2;
838: if (bp->b_flags & B_BAD) {
839: npf = bp->b_error;
840: bn = sc->sc_badbn;
841: } else {
842: npf = btop(bp->b_bcount + upaddr->upwc * sizeof(short));
843: if (er1 & (UPER_DCK | UPER_ECH))
844: npf--;
845: bn = bp->b_blkno + npf;
846: }
847: if (UPWAIT(upaddr, upunit(bp->b_dev)) == 0)
848: goto hard;
849: #ifdef UPDEBUG
850: if (updebug) {
851: log(LOG_DEBUG,
852: "uperr: bp %x cyl %d blk %d blkdone %d as %o dc %x da %x\n",
853: bp, bp->b_cylin, bn, sc->sc_blkdone,
854: upaddr->upas, upaddr->updc, upaddr->upda);
855: log(LOG_DEBUG,
856: "errcnt %d er1 %b er2 %b wc -%d (bc %d)\n",
857: um->um_tab.b_errcnt, er1, UPER1_BITS,
858: er2, UPER2_BITS, -up->upwc,-up->upwc*sizeof(short));
859: }
860: #endif
861: if (er1 & UPER1_HCRC) {
862: er1 &= ~(UPER1_HCE|UPER1_FER);
863: er2 &= ~UPER2_BSE;
864: }
865: if (er1 & UPER1_WLE) {
866: /*
867: * Give up on write locked devices
868: * immediately.
869: */
870: log(LOG_WARNING, "up%d: write locked\n",
871: upunit(bp->b_dev));
872: bp->b_flags |= B_ERROR;
873: } else if (bp->b_flags & B_FORMAT) {
874: goto hard;
875: } else if (er2 & UPER2_BSE) {
876: if (upecc(ui, BSW))
877: return;
878: goto hard;
879: } else if ((er1 & (UPER1_DCK|UPER1_ECH)) == UPER1_DCK &&
880: um->um_tab.b_errcnt >= 3) {
881: if (upecc(ui, ECC))
882: return;
883: /* see comment in hp.c */
884: if (ui->ui_tab.b_errcnt == 3)
885: ui->ui_tab.b_errcnt = 0;
886: } else if (er1 & UPER1_HCRC && upecc(ui, BSE)) {
887: return;
888: } else if (++um->um_tab.b_errcnt > 27 || er1 & HPER1_HARD) {
889: hard:
890: bp->b_blkno = bn; /* XXX */
891: harderr(bp, "up");
892: printf("cn=%d tn=%d sn=%d cs2=%b er1=%b er2=%b",
893: upaddr->updc, ((upaddr->upda)>>8)&077,
894: (upaddr->upda)&037,
895: upaddr->upcs2, UPCS2_BITS,
896: upaddr->uper1, UPER1_BITS,
897: upaddr->uper2, UPER2_BITS);
898: if (bp->b_flags & B_FORMAT)
899: printf(" (hdr i/o)");
900: printf("\n");
901: bp->b_flags |= B_ERROR;
902: bp->b_flags &= ~B_BAD;
903: } else
904: um->um_tab.b_active = 0; /* force retry */
905: /*
906: * Clear drive error and, every eight attempts,
907: * (starting with the fourth)
908: * recalibrate to clear the slate.
909: */
910: upaddr->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO;
911: needie = 0;
912: if ((um->um_tab.b_errcnt&07) == 4 && um->um_tab.b_active == 0) {
913: upaddr->upcs1 = UP_RECAL|UP_IE|UP_GO;
914: sc->sc_recal = 0;
915: goto nextrecal;
916: }
917: }
918: #ifdef UPDEBUG
919: else if (updebug && sc->sc_recal) {
920: log(LOG_DEBUG, "up: recal %d errcnt %d er1=%b er2=%b\n",
921: sc->sc_recal, um->um_tab.b_errcnt,
922: upaddr->uper1, UPER1_BITS,
923: upaddr->uper2, UPER2_BITS);
924: }
925: #endif
926: /*
927: * Advance recalibration finite state machine
928: * if recalibrate in progress, through
929: * RECAL
930: * SEEK
931: * OFFSET (optional)
932: * RETRY
933: */
934: switch (sc->sc_recal) {
935:
936: case 1:
937: upaddr->updc = bp->b_cylin;
938: upaddr->upcs1 = UP_SEEK|UP_IE|UP_GO;
939: goto nextrecal;
940: case 2:
941: if (um->um_tab.b_errcnt < 16 || (bp->b_flags&B_READ) == 0)
942: goto donerecal;
943: upaddr->upof = up_offset[um->um_tab.b_errcnt&017] | UPOF_FMT22;
944: upaddr->upcs1 = UP_IE|UP_OFFSET|UP_GO;
945: goto nextrecal;
946: nextrecal:
947: sc->sc_recal++;
948: um->um_tab.b_active = 1;
949: return;
950: donerecal:
951: case 3:
952: sc->sc_recal = 0;
953: um->um_tab.b_active = 0;
954: break;
955: }
956: /*
957: * If still ``active'', then don't need any more retries.
958: */
959: if (um->um_tab.b_active) {
960: /*
961: * If we were offset positioning,
962: * return to centerline.
963: */
964: if (um->um_tab.b_errcnt >= 16) {
965: upaddr->upof = UPOF_FMT22;
966: upaddr->upcs1 = UP_RTC|UP_GO|UP_IE;
967: while (upaddr->upds & UPDS_PIP)
968: DELAY(25);
969: needie = 0;
970: }
971: um->um_tab.b_active = 0;
972: um->um_tab.b_errcnt = 0;
973: um->um_tab.b_actf = dp->b_forw;
974: dp->b_active = 0;
975: dp->b_errcnt = 0;
976: dp->b_actf = bp->av_forw;
977: bp->b_resid = (-upaddr->upwc * sizeof(short));
978: sc->sc_blkdone = 0;
979: if (sc->sc_openpart == 0)
980: wakeup((caddr_t)sc);
981: iodone(bp);
982: /*
983: * If this unit has more work to do,
984: * then start it up right away.
985: */
986: if (dp->b_actf)
987: if (upustart(ui))
988: needie = 0;
989: }
990: as &= ~(1<<ui->ui_slave);
991: /*
992: * Release unibus resources and flush data paths.
993: */
994: ubadone(um);
995: doattn:
996: /*
997: * Process other units which need attention.
998: * For each unit which needs attention, call
999: * the unit start routine to place the slave
1000: * on the controller device queue.
1001: */
1002: while (unit = ffs((long)as)) {
1003: unit--; /* was 1 origin */
1004: as &= ~(1<<unit);
1005: upaddr->upas = 1<<unit;
1006: if (unit < UPIPUNITS && upustart(upip[sc21][unit]))
1007: needie = 0;
1008: }
1009: /*
1010: * If the controller is not transferring, but
1011: * there are devices ready to transfer, start
1012: * the controller.
1013: */
1014: if (um->um_tab.b_actf && um->um_tab.b_active == 0)
1015: if (upstart(um))
1016: needie = 0;
1017: if (needie)
1018: upaddr->upcs1 = UP_IE;
1019: }
1020:
1021: upioctl(dev, cmd, data, flag)
1022: dev_t dev;
1023: int cmd;
1024: caddr_t data;
1025: int flag;
1026: {
1027: int unit = upunit(dev);
1028: register struct disklabel *lp;
1029: register struct format_op *fop;
1030: int error = 0;
1031: int upformat();
1032:
1033: lp = &uplabel[unit];
1034:
1035: switch (cmd) {
1036:
1037: case DIOCGDINFO:
1038: *(struct disklabel *)data = *lp;
1039: break;
1040:
1041: case DIOCGPART:
1042: ((struct partinfo *)data)->disklab = lp;
1043: ((struct partinfo *)data)->part =
1044: &lp->d_partitions[uppart(dev)];
1045: break;
1046:
1047: case DIOCSDINFO:
1048: if ((flag & FWRITE) == 0)
1049: error = EBADF;
1050: else
1051: *lp = *(struct disklabel *)data;
1052: break;
1053:
1054: case DIOCWDINFO:
1055: if ((flag & FWRITE) == 0) {
1056: error = EBADF;
1057: break;
1058: }
1059: {
1060: struct buf *bp;
1061: struct disklabel *dlp;
1062:
1063: *lp = *(struct disklabel *)data;
1064: bp = geteblk(lp->d_secsize);
1065: bp->b_dev = makedev(major(dev), upminor(upunit(dev), 0));
1066: bp->b_blkno = LABELSECTOR;
1067: bp->b_bcount = lp->d_secsize;
1068: bp->b_flags = B_READ;
1069: dlp = (struct disklabel *)(bp->b_un.b_addr + LABELOFFSET);
1070: upstrategy(bp);
1071: biowait(bp);
1072: if (bp->b_flags & B_ERROR) {
1073: error = u.u_error; /* XXX */
1074: u.u_error = 0;
1075: goto bad;
1076: }
1077: *dlp = *lp;
1078: bp->b_flags = B_WRITE;
1079: upstrategy(bp);
1080: biowait(bp);
1081: if (bp->b_flags & B_ERROR) {
1082: error = u.u_error; /* XXX */
1083: u.u_error = 0;
1084: }
1085: bad:
1086: brelse(bp);
1087: break;
1088: }
1089:
1090: #ifdef notyet
1091: case DIOCWFORMAT:
1092: if ((flag & FWRITE) == 0) {
1093: error = EBADF;
1094: break;
1095: }
1096: {
1097: struct uio auio;
1098: struct iovec aiov;
1099:
1100: fop = (struct format_op *)data;
1101: aiov.iov_base = fop->df_buf;
1102: aiov.iov_len = fop->df_count;
1103: auio.uio_iov = &aiov;
1104: auio.uio_iovcnt = 1;
1105: auio.uio_resid = fop->df_count;
1106: auio.uio_segflg = 0;
1107: auio.uio_offset = fop->df_startblk * lp->d_secsize;
1108: error = physio(upformat, &rupbuf[unit], dev, B_WRITE,
1109: minphys, &auio);
1110: fop->df_count -= auio.uio_resid;
1111: fop->df_reg[0] = sc->sc_status;
1112: fop->df_reg[1] = sc->sc_error;
1113: }
1114: break;
1115: #endif
1116:
1117: default:
1118: error = ENOTTY;
1119: break;
1120: }
1121: return (error);
1122: }
1123:
1124: upformat(bp)
1125: struct buf *bp;
1126: {
1127:
1128: bp->b_flags |= B_FORMAT;
1129: return (upstrategy(bp));
1130: }
1131:
1132: /*
1133: * Correct an ECC error, and restart the i/o to complete
1134: * the transfer if necessary. This is quite complicated because
1135: * the transfer may be going to an odd memory address base and/or
1136: * across a page boundary.
1137: */
1138: upecc(ui, flag)
1139: register struct uba_device *ui;
1140: int flag;
1141: {
1142: register struct updevice *up = (struct updevice *)ui->ui_addr;
1143: register struct buf *bp = uputab[ui->ui_unit].b_actf;
1144: register struct uba_ctlr *um = ui->ui_mi;
1145: register struct disklabel *lp = &hplabel[mi->mi_unit];
1146: struct uba_regs *ubp = ui->ui_hd->uh_uba;
1147: struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
1148: register int i;
1149: caddr_t addr;
1150: int reg, bit, byte, npf, mask, o, cmd, ubaddr;
1151: int bn, cn, tn, sn;
1152: int bcr;
1153:
1154: /*
1155: * Npf is the number of sectors transferred before the sector
1156: * containing the ECC error, and reg is the UBA register
1157: * mapping (the first part of) the transfer.
1158: * O is offset within a memory page of the first byte transferred.
1159: */
1160: bcr = -up->upwc * sizeof(short);
1161: if (flag == CONT)
1162: npf = bp->b_error;
1163: else {
1164: npf = bp->b_bcount - bcr;
1165: /*
1166: * Watch out for fractional sector at end of transfer;
1167: * want to round up if finished, otherwise round down.
1168: */
1169: if (bcr == 0)
1170: npf += 511;
1171: npf = btodb(npf);
1172: }
1173: reg = btop(um->um_ubinfo&0x3ffff) + npf;
1174: o = (int)bp->b_un.b_addr & PGOFSET;
1175: mask = up->upec2;
1176: #ifdef UPECCDEBUG
1177: if (upeccdebug)
1178: log(LOG_DEBUG, "npf %d reg %x o %d mask %o pos %d\n",
1179: npf, reg, o, mask, up->upec1);
1180: #endif
1181: bn = bp->b_blkno;
1182: cn = bp->b_cylin;
1183: sn = bn % lp->d_secpercyl + npf;
1184: tn = sn / lp->d_nsectors;
1185: sn %= lp->d_nsectors;
1186: cn += tn / lp->d_ntracks;
1187: tn %= lp->d_ntracks;
1188: bn += npf;
1189: ubapurge(um);
1190: um->um_tab.b_active = 2;
1191: /*
1192: * action taken depends on the flag
1193: */
1194: switch (flag) {
1195: case ECC: {
1196: register int i;
1197: caddr_t addr;
1198: struct pte mpte;
1199: int bit, byte, mask;
1200:
1201: npf--; /* because block in error is previous block */
1202: bn--;
1203: reg--;
1204: if (bp->b_flags & B_BAD)
1205: bn = sc->sc_badbn;
1206: log(LOG_WARNING, "up%d%c: soft ecc sn%d\n", upunit(bp->b_dev),
1207: 'a' + uppart(bp->b_dev), bp->b_blkno + npf);
1208: /*
1209: * Flush the buffered data path, and compute the
1210: * byte and bit position of the error. The variable i
1211: * is the byte offset in the transfer, the variable byte
1212: * is the offset from a page boundary in main memory.
1213: */
1214: i = up->upec1 - 1; /* -1 makes 0 origin */
1215: mask = up->upec2;
1216: bit = i&07;
1217: i = (i&~07)>>3;
1218: byte = i + o;
1219: /*
1220: * Correct while possible bits remain of mask. Since mask
1221: * contains 11 bits, we continue while the bit offset is > -11.
1222: * Also watch out for end of this block and the end of the whole
1223: * transfer.
1224: */
1225: while (i < 512 && (int)dbtob(npf)+i < bp->b_bcount && bit > -11) {
1226: struct pte pte;
1227:
1228: pte = ubp->uba_map[reg + btop(byte)];
1229: addr = ptob(pte.pg_pfnum) + (byte & PGOFSET);
1230: #ifdef UPECCDEBUG
1231: printf("addr %x map reg %x\n",
1232: addr, *(int *)(&ubp->uba_map[reg+btop(byte)]));
1233: printf("old: %x, ", getmemc(addr));
1234: #endif
1235: putmemc(addr, getmemc(addr)^(mask<<bit));
1236: #ifdef UPECCDEBUG
1237: printf("new: %x\n", getmemc(addr));
1238: #endif
1239: byte++;
1240: i++;
1241: bit -= 8;
1242: }
1243: if (bcr == 0)
1244: return (0);
1245: npf++;
1246: reg++;
1247: break;
1248: }
1249:
1250: case BSE:
1251: if (sc->sc_state == OPENRAW)
1252: return (0);
1253: #ifdef UPBDEBUG
1254: if (upbdebug)
1255: log(LOG_DEBUG, "upecc, BSE: bn %d cn %d tn %d sn %d\n",
1256: bn, cn, tn, sn);
1257: #endif
1258: if (bp->b_flags & B_BAD)
1259: return (0);
1260: /*
1261: * if not in bad sector table, return 0
1262: */
1263: if ((bn = isbad(&upbad[ui->ui_unit], cn, tn, sn)) < 0)
1264: return(0);
1265: /*
1266: * flag this one as bad
1267: */
1268: bp->b_flags |= B_BAD;
1269: bp->b_error = npf + 1;
1270: #ifdef UPBDEBUG
1271: if (upbdebug)
1272: log(LOG_DEBUG "BSE: restart at %d\n",npf+1);
1273: #endif
1274: bn = lp->d_ncylinders * lp->d_secpercyl -
1275: lp->d_nsectors - 1 - bn;
1276: sc->sc_badbn = bn;
1277: fixregs:
1278: cn = bn / lp->d_secpercyl;
1279: sn = bn % lp->d_secpercyl;
1280: tn = sn / lp->d_nsectors;
1281: sn %= lp->d_nsectors;
1282: bcr = bp->b_bcount - (int)ptob(npf);
1283: bcr = MIN(bcr, 512);
1284: up->upwc = -bcr;
1285: #ifdef UPBDEBUG
1286: if (upbdebug)
1287: log(LOG_DEBUG, "revector to cn %d tn %d sn %d\n",
1288: cn, tn, sn);
1289: #endif
1290: break;
1291:
1292: case CONT:
1293: #ifdef UPBDEBUG
1294: if (upbdebug)
1295: log(LOG_DEBUG, "upecc, CONT: bn %d cn %d tn %d sn %d\n",
1296: bn, cn, tn, sn);
1297: #endif
1298: bp->b_flags &= ~B_BAD;
1299: if ((int)ptob(npf) >= bp->b_bcount)
1300: return (0);
1301: up->upwc = -((bp->b_bcount - (int)ptob(npf)) / sizeof(short));
1302: break;
1303: }
1304: if (up->upwc == 0) {
1305: um->um_tab.b_active = 0; /* retry */
1306: return (0);
1307: }
1308: /*
1309: * Have to continue the transfer... clear the drive,
1310: * and compute the position where the transfer is to continue.
1311: * We have completed npf+1 sectors of the transfer already;
1312: * restart at offset o of next sector (i.e. in UBA register reg+1).
1313: */
1314: #ifdef notdef
1315: up->uper1 = 0;
1316: up->upcs1 |= UP_GO;
1317: #else
1318: up->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO;
1319: up->updc = cn;
1320: up->upda = (tn << 8) | sn;
1321: ubaddr = (int)ptob(reg) + o;
1322: up->upba = ubaddr;
1323: cmd = (ubaddr >> 8) & 0x300;
1324: cmd |= ((bp->b_flags&B_READ)?UP_RCOM:UP_WCOM)|UP_IE|UP_GO;
1325: um->um_tab.b_errcnt = 0;
1326: up->upcs1 = cmd;
1327: #endif
1328: sc->sc_blkdone = npf;
1329: return (1);
1330: }
1331:
1332: /*
1333: * Reset driver after UBA init.
1334: * Cancel software state of all pending transfers
1335: * and restart all units and the controller.
1336: */
1337: upreset(uban)
1338: int uban;
1339: {
1340: register struct uba_ctlr *um;
1341: register struct uba_device *ui;
1342: register sc21, unit;
1343:
1344: for (sc21 = 0; sc21 < NSC; sc21++) {
1345: if ((um = upminfo[sc21]) == 0 || um->um_ubanum != uban ||
1346: um->um_alive == 0)
1347: continue;
1348: printf(" sc%d", sc21);
1349: um->um_tab.b_active = 0;
1350: um->um_tab.b_actf = um->um_tab.b_actl = 0;
1351: up_softc[sc21].sc_recal = 0;
1352: up_softc[sc21].sc_wticks = 0;
1353: if (um->um_ubinfo) {
1354: printf("<%d>", (um->um_ubinfo>>28)&0xf);
1355: um->um_ubinfo = 0;
1356: }
1357: ((struct updevice *)(um->um_addr))->upcs2 = UPCS2_CLR;
1358: for (unit = 0; unit < NUP; unit++) {
1359: if ((ui = updinfo[unit]) == 0)
1360: continue;
1361: if (ui->ui_alive == 0 || ui->ui_mi != um)
1362: continue;
1363: uputab[unit].b_active = 0;
1364: (void) upustart(ui);
1365: }
1366: (void) upstart(um);
1367: }
1368: }
1369:
1370: /*
1371: * Wake up every second and if an interrupt is pending
1372: * but nothing has happened increment a counter.
1373: * If nothing happens for 20 seconds, reset the UNIBUS
1374: * and begin anew.
1375: */
1376: upwatch()
1377: {
1378: register struct uba_ctlr *um;
1379: register sc21, unit;
1380: register struct up_softc *sc;
1381:
1382: timeout(upwatch, (caddr_t)0, hz);
1383: for (sc21 = 0; sc21 < NSC; sc21++) {
1384: um = upminfo[sc21];
1385: if (um == 0 || um->um_alive == 0)
1386: continue;
1387: sc = &up_softc[sc21];
1388: if (um->um_tab.b_active == 0) {
1389: for (unit = 0; unit < NUP; unit++)
1390: if (uputab[unit].b_active &&
1391: updinfo[unit]->ui_mi == um)
1392: goto active;
1393: sc->sc_wticks = 0;
1394: continue;
1395: }
1396: active:
1397: sc->sc_wticks++;
1398: if (sc->sc_wticks >= 20) {
1399: sc->sc_wticks = 0;
1400: printf("sc%d: lost interrupt\n", sc21);
1401: ubareset(um->um_ubanum);
1402: }
1403: }
1404: }
1405:
1406: #define DBSIZE 20
1407:
1408: updump(dev)
1409: dev_t dev;
1410: {
1411: struct updevice *upaddr;
1412: char *start;
1413: int num, blk, unit;
1414: struct size *sizes;
1415: register struct uba_regs *uba;
1416: register struct uba_device *ui;
1417: register short *rp;
1418: struct upst *st;
1419: register int retry;
1420: register struct disklabel *lp;
1421:
1422: unit = upunit(dev);
1423: if (unit >= NUP)
1424: return (ENXIO);
1425: #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
1426: ui = phys(struct uba_device *, updinfo[unit]);
1427: if (ui == 0 || ui->ui_alive == 0)
1428: return (ENXIO);
1429: uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
1430: ubainit(uba);
1431: upaddr = (struct updevice *)ui->ui_physaddr;
1432: DELAY(5000000);
1433: num = maxfree;
1434: upaddr->upcs2 = unit;
1435: DELAY(100);
1436: upaddr->upcs1 = UP_DCLR|UP_GO;
1437: upaddr->upcs1 = UP_PRESET|UP_GO;
1438: upaddr->upof = UPOF_FMT22;
1439: retry = 0;
1440: do {
1441: DELAY(25);
1442: if (++retry > 527)
1443: break;
1444: } while ((upaddr->upds & UP_RDY) == 0);
1445: if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY)
1446: return (EFAULT);
1447: start = 0;
1448: if (dumplo < 0)
1449: return (EINVAL);
1450: lp = &uplabel[unit];
1451: /* should check uupart(dev) < lp->p_npartitions ? */
1452: if (dumplo + num >= lp->d_partitions[uppart(dev)].p_size)
1453: num = lp->d_partitions[uppart(dev)].p_size - dumplo;
1454: while (num > 0) {
1455: register struct pte *io;
1456: register int i;
1457: int blk, cn, sn, tn;
1458: daddr_t bn;
1459:
1460: blk = num > DBSIZE ? DBSIZE : num;
1461: io = uba->uba_map;
1462: for (i = 0; i < blk; i++)
1463: *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV;
1464: *(int *)io = 0;
1465: bn = dumplo + btop(start);
1466: cn = (bn + lp->d_partitions[hppart(dev)].p_offset) /
1467: lp->d_secpercyl;
1468: sn = bn % lp->d_secpercyl;
1469: tn = sn / lp->d_nsectors;
1470: sn = sn % lp->d_nsectors;
1471: upaddr->updc = cn;
1472: rp = (short *) &upaddr->upda;
1473: *rp = (tn << 8) + sn;
1474: *--rp = 0;
1475: *--rp = -blk*NBPG / sizeof (short);
1476: *--rp = UP_GO|UP_WCOM;
1477: retry = 0;
1478: do {
1479: DELAY(25);
1480: if (++retry > 527)
1481: break;
1482: } while ((upaddr->upcs1 & UP_RDY) == 0);
1483: if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) {
1484: printf("up%d: not ready", unit);
1485: if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) {
1486: printf("\n");
1487: return (EIO);
1488: }
1489: printf(" (flakey)\n");
1490: }
1491: if (upaddr->upds&UPDS_ERR)
1492: return (EIO);
1493: start += blk*NBPG;
1494: num -= blk;
1495: }
1496: return (0);
1497: }
1498:
1499: upsize(dev)
1500: dev_t dev;
1501: {
1502: register int unit = upunit(dev);
1503: struct uba_device *ui;
1504:
1505: if (unit >= NUP || (ui = updinfo[unit]) == 0 || ui->ui_alive == 0 ||
1506: upsoftc[unit].sc_state != OPEN)
1507: return (-1);
1508: return ((int)uplabel[unit].d_partitions[uppart(dev)].p_size);
1509: }
1510:
1511: #ifdef COMPAT_42
1512: /*
1513: * Compatibility code to fake up pack label
1514: * for unlabeled disks.
1515: */
1516: struct size {
1517: daddr_t nblocks;
1518: int cyloff;
1519: } up9300_sizes[8] = {
1520: 15884, 0, /* A=cyl 0 thru 26 */
1521: 33440, 27, /* B=cyl 27 thru 81 */
1522: 495520, 0, /* C=cyl 0 thru 814 */
1523: 15884, 562, /* D=cyl 562 thru 588 */
1524: 55936, 589, /* E=cyl 589 thru 680 */
1525: 81376, 681, /* F=cyl 681 thru 814 */
1526: 153728, 562, /* G=cyl 562 thru 814 */
1527: 291346, 82, /* H=cyl 82 thru 561 */
1528: }, up9766_sizes[8] = {
1529: 15884, 0, /* A=cyl 0 thru 26 */
1530: 33440, 27, /* B=cyl 27 thru 81 */
1531: 500384, 0, /* C=cyl 0 thru 822 */
1532: 15884, 562, /* D=cyl 562 thru 588 */
1533: 55936, 589, /* E=cyl 589 thru 680 */
1534: 86240, 681, /* F=cyl 681 thru 822 */
1535: 158592, 562, /* G=cyl 562 thru 822 */
1536: 291346, 82, /* H=cyl 82 thru 561 */
1537: }, up160_sizes[8] = {
1538: 15884, 0, /* A=cyl 0 thru 49 */
1539: 33440, 50, /* B=cyl 50 thru 154 */
1540: 263360, 0, /* C=cyl 0 thru 822 */
1541: 15884, 155, /* D=cyl 155 thru 204 */
1542: 55936, 205, /* E=cyl 205 thru 379 */
1543: 141664, 380, /* F=cyl 380 thru 822 */
1544: 213664, 155, /* G=cyl 155 thru 822 */
1545: 0, 0,
1546: }, upam_sizes[8] = {
1547: 15884, 0, /* A=cyl 0 thru 31 */
1548: 33440, 32, /* B=cyl 32 thru 97 */
1549: 524288, 0, /* C=cyl 0 thru 1023 */
1550: 15884, 668, /* D=cyl 668 thru 699 */
1551: 55936, 700, /* E=cyl 700 thru 809 */
1552: 109472, 810, /* F=cyl 810 thru 1023 */
1553: 182176, 668, /* G=cyl 668 thru 1023 */
1554: 291346, 98, /* H=cyl 98 thru 667 */
1555: }, up980_sizes[8] = {
1556: 15884, 0, /* A=cyl 0 thru 99 */
1557: 33440, 100, /* B=cyl 100 thru 308 */
1558: 131680, 0, /* C=cyl 0 thru 822 */
1559: 15884, 309, /* D=cyl 309 thru 408 */
1560: 55936, 409, /* E=cyl 409 thru 758 */
1561: 10080, 759, /* F=cyl 759 thru 822 */
1562: 82080, 309, /* G=cyl 309 thru 822 */
1563: 0, 0,
1564: }, upeagle_sizes[8] = {
1565: 15884, 0, /* A=cyl 0 thru 16 */
1566: 66880, 17, /* B=cyl 17 thru 86 */
1567: 808320, 0, /* C=cyl 0 thru 841 */
1568: 15884, 391, /* D=cyl 391 thru 407 */
1569: 307200, 408, /* E=cyl 408 thru 727 */
1570: 109296, 728, /* F=cyl 728 thru 841 */
1571: 432816, 391, /* G=cyl 391 thru 841 */
1572: 291346, 87, /* H=cyl 87 thru 390 */
1573: };
1574:
1575: struct upst {
1576: short nsect; /* # sectors/track */
1577: short ntrak; /* # tracks/cylinder */
1578: short nspc; /* # sectors/cylinder */
1579: short ncyl; /* # cylinders */
1580: struct size *sizes; /* partition tables */
1581: short sdist; /* seek distance metric */
1582: short rdist; /* rotational distance metric */
1583: short mdist; /* min rotation (all guesswork) */
1584: } upst[] = {
1585: { 32, 19, 32*19, 815, up9300_sizes, 3, 4, 1 }, /*9300*/
1586: { 32, 19, 32*19, 823, up9766_sizes, 3, 4, 1 }, /*9766*/
1587: { 32, 10, 32*10, 823, up160_sizes, 3, 4, 1 }, /*fuji160m*/
1588: { 32, 16, 32*16, 1024, upam_sizes, 7, 8, 2 }, /*Capricorn*/
1589: { 32, 5, 32*5, 823, up980_sizes, 3, 4, 1 }, /*DM980*/
1590: { 48, 20, 48*20, 842, upeagle_sizes, 15, 8, 3 }, /*EAGLE*/
1591: { 0, 0, 0, 0, 0, 0, 0, 0 }
1592: };
1593:
1594:
1595: /*
1596: * These variable are all measured in sectors.
1597: * Sdist is how much to "lead" in the search for a desired sector
1598: * (i.e. if want N, search for N-sdist.)
1599: * Maxdist and mindist define the region right before our desired sector within
1600: * which we don't bother searching. We don't search when we are already less
1601: * then maxdist and more than mindist sectors "before" our desired sector.
1602: * Maxdist should be >= sdist.
1603: *
1604: * Beware, sdist, mindist and maxdist are not well tuned
1605: * for many of the drives listed in this table.
1606: * Try patching things with something i/o intensive
1607: * running and watch iostat.
1608: */
1609:
1610: /*
1611: * Map apparent SC[23]1 drive type into manufacturer
1612: * specific configuration.
1613: */
1614: upmaptype(ui, lp)
1615: register struct uba_device *ui;
1616: register struct disklabel *lp;
1617: {
1618: register int type;
1619: register struct upst *st;
1620:
1621: upphysical(ui->ui_addr, lp); /* get the real drive numbers */
1622: for (st = upst, type = 0; st->nsect != 0; st++, type++)
1623: if (lp->d_ntracks == st->ntrak &&
1624: lp->d_nsectors == st->nsect &&
1625: lp->d_ncylinders == st->ncyl)
1626: break;
1627:
1628: if (st->nsect == 0) {
1629: printf(": %dx%dx%d (s,t,c)?", lp->d_nsectors,
1630: lp->d_ntracks, lp->d_ncylinders);
1631: return (0);
1632: }
1633:
1634: ui->ui_type = type;
1635:
1636: /*
1637: * set up minimal disk label.
1638: */
1639: st = &hpst[type];
1640: lp->d_secsize = 512;
1641: lp->d_nsectors = st->nsect;
1642: lp->d_ntracks = st->ntrak;
1643: lp->d_secpercyl = st->nspc;
1644: lp->d_ncylinders = st->ncyl;
1645: lp->d_secperunit = st->nspc * st->ncyl;
1646: lp->d_sdist = st->sdist;
1647: lp->d_mindist = st->rdist;
1648: lp->d_maxdist = st->mdist;
1649: bcopy(hpst[type].name, lp->d_typename, sizeof(lp->d_typename));
1650: lp->d_npartitions = 8;
1651: for (i = 0; i < 8; i++) {
1652: lp->d_partitions[i].p_offset = st->sizes[i].cyloff *
1653: lp->d_secpercyl;
1654: lp->d_partitions[i].p_size = st->sizes[i].nblocks;
1655: }
1656: return (1);
1657: }
1658: #endif /* COMPAT_42 */
1659:
1660: #endif /* NSC > 0 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.