|
|
1.1 root 1: /*
2: * DSA disk class driver
3: * drives RA-class disks
4: * hooked up through an MSCP port
5: */
6:
7: #include "sys/param.h"
8: #include "sys/buf.h"
9: #include "sys/udaioc.h"
10: #include "sys/ra.h"
11: #include "sys/mscp.h"
12: #include "sys/user.h"
13: #include "sys/file.h"
14: #include "sys/conf.h"
15:
16: extern struct msaddr raaddr[];
17: extern struct radisk radisk[];
18: extern int racnt;
19: static long rarefno; /* ref seq num */
20: extern struct buf rabuf[];
21: static struct buf rctbuf; /* for reading replacement table */
22:
23: static rareplace(), raonline(), rasonl(), racinit();
24:
25: int raopen(), raread(), rawrite(), raioctl(), rastrategy(), raclose();
26: struct bdevsw rabdev = bdinit(raopen, raclose, rastrategy, 0);
27: struct cdevsw racdev = cdinit(raopen, raclose, raread, rawrite, raioctl);
28:
29: /*
30: * UNIT(d) == logical unit number;
31: * the physical unit number is in raaddr[UNIT(d)].unit
32: */
33: #define UNIT(dev) (((dev)>>3) & 07)
34: #define PART(dev) ((dev)&07)
35: #define NPART 8
36: #define HUGE 0x7fffffff /* very large 32-bit number */
37:
38: struct size {
39: daddr_t nblocks;
40: daddr_t blkoff;
41: } ra_sizes[NPART] = {
42: 10240, 0,
43: 20480, 10240,
44: 249848, 30720,
45: 249848, 280568,
46: 249848, 530416,
47: HUGE, 780264,
48: 749544, 30720, /* slices 2,3,4 */
49: HUGE, 0, /* whole drive */
50: };
51:
52: /*
53: * reused bits of buf/iobuf struct
54: */
55:
56: #define b_next av_forw /* next buffer in queue */
57: #define b_pkt av_back /* pointer to mscp command */
58: #define b_crf b_resid /* saved refno for pending command */
59:
60: /*
61: * flags in radisk.flags
62: */
63:
64: #define ONLINE 01 /* drive is online */
65: #define WONLINE 02 /* waiting for online */
66: #define GOTDI 04 /* got unit info */
67: #define RPLOCK 010 /* replacement in progress */
68: #define RPWANT 020 /* want RPLOCK */
69: #define RPDONE 040 /* replacement done */
70: #define SPDOWN 0100 /* spin down on last close */
71:
72: /*
73: * random numbers
74: */
75:
76: #define PRIONL (PZERO-1)
77: #define SECTOR 512 /* size of an MSCP sector */
78: #define IDRA 0 /* connection ID for MSCP */
79:
80: /*
81: * open a drive, if necessary
82: */
83:
84: int raseql(), radg();
85:
86: raopen(dev, flag)
87: dev_t dev;
88: {
89: register int unit;
90: register struct radisk *ra;
91: register struct msaddr *rp;
92:
93: unit = UNIT(dev);
94: if (unit >= racnt) {
95: u.u_error = ENXIO;
96: return;
97: }
98: ra = &radisk[unit];
99: rp = &raaddr[unit];
100: if (ra->open == 0) {
101: if (rp->ctype < 0 || rp->ctype >= nmsport
102: || (ra->port = msportsw[rp->ctype]) == NULL) {
103: u.u_error = ENXIO;
104: return;
105: }
106: ra->di.radsize = HUGE;
107: if ((*ra->port->mp_init)(rp->ctl, rp->ctype, 0, IDRA, raseql, radg) == 0) {
108: u.u_error = ENXIO;
109: return;
110: }
111: racinit(ra, rp);
112: }
113: ra->open |= 1<<PART(dev);
114: spl6();
115: if ((ra->flags & ONLINE) == 0)
116: raonline(ra, rp);
117: spl0();
118: if ((ra->flags & ONLINE) == 0)
119: u.u_error = ENXIO;
120: }
121:
122: raclose(dev)
123: {
124: register struct radisk *ra;
125: register struct msaddr *rp;
126: register struct mscmd *mp;
127:
128: ra = &radisk[UNIT(dev)];
129: rp = &raaddr[UNIT(dev)];
130: ra->open &=~ (1<<PART(dev));
131: if (ra->open || (ra->flags & ONLINE) == 0)
132: return;
133: mp = (*ra->port->mp_get)(rp->ctl);
134: mp->m_crf = ++rarefno;
135: mp->m_unit = rp->unit;
136: mp->m_opcd = OPAVL; /* put it offline */
137: if ((ra->flags & SPDOWN) == 0)
138: mp->m_mod = 0;
139: else {
140: mp->m_mod = MDSPD;
141: ra->flags &=~ SPDOWN;
142: }
143: mp->m_unfl = 0;
144: mp->m_dvpm = 0; /* ? */
145: ra->flags &=~ ONLINE;
146: (*ra->port->mp_send)(rp->ctl, IDRA, mp);
147: }
148:
149: int rastrategy();
150:
151: raread(dev)
152: {
153: physio(rastrategy, &rabuf[UNIT(dev)], dev, B_READ, minphys);
154: }
155:
156: rawrite(dev)
157: {
158: physio(rastrategy, &rabuf[UNIT(dev)], dev, B_WRITE, minphys);
159: }
160:
161: /*
162: * strategy routine;
163: * used as strategy by all port drivers
164: * send the packet right away
165: */
166:
167: rastrategy(bp)
168: register struct buf *bp;
169: {
170: register struct radisk *ra;
171: register struct mscmd *mp;
172: register int unit;
173: register struct size *sp;
174: register struct msaddr *rp;
175: int count;
176: daddr_t limit;
177:
178: unit = UNIT(minor(bp->b_dev));
179: ra = &radisk[unit];
180: rp = &raaddr[unit];
181: sp = &ra_sizes[PART(minor(bp->b_dev))];
182: limit = ra->di.radsize - sp->blkoff;
183: if (limit > sp->nblocks)
184: limit = sp->nblocks;
185: if (bp->b_blkno >= limit && bp != &rctbuf) {
186: if (bp->b_blkno == sp->nblocks)
187: bp->b_resid = bp->b_bcount;
188: else {
189: bp->b_error = ENOSPC;
190: bp->b_flags |= B_ERROR;
191: }
192: iodone(bp);
193: return;
194: }
195: count = bp->b_bcount;
196: if (count/SECTOR + bp->b_blkno > limit && bp != &rctbuf)
197: count = (limit - bp->b_blkno) * SECTOR;
198: spl6();
199: if ((ra->flags & ONLINE) == 0 && raonline(ra, rp) == 0) {
200: bp->b_flags |= B_ERROR;
201: iodone(bp);
202: spl0();
203: return;
204: }
205: mp = (*ra->port->mp_get)(rp->ctl);
206: mp->m_crf = ++rarefno;
207: mp->m_unit = rp->unit;
208: mp->m_opcd = (bp->b_flags & B_READ) ? OPRD : OPWR;
209: mp->m_mod = 0;
210: mp->m_bcnt = count;
211: mp->m_lbn = bp->b_blkno + sp->blkoff;
212: (*ra->port->mp_map)(rp->ctl, mp, bp);
213: bp->b_pkt = (struct buf *)mp;
214: bp->b_crf = mp->m_crf;
215: bp->b_next = NULL;
216: if (ra->actf)
217: ra->actl->b_next = bp;
218: else
219: ra->actf = bp;
220: ra->actl = bp;
221: (*ra->port->mp_send)(rp->ctl, IDRA, mp);
222: spl0();
223: }
224:
225: /*
226: * ioctl
227: * principally for bad block replacement
228: */
229:
230: raioctl(dev, cmd, addr, flag)
231: dev_t dev;
232: caddr_t addr;
233: {
234: register union arg {
235: struct ud_rctbuf r;
236: struct ud_repl b;
237: } *uap;
238: register struct radisk *ra;
239: register int i;
240:
241: ra = &radisk[UNIT(dev)];
242: if ((ra->flags & (ONLINE|GOTDI)) != (ONLINE|GOTDI)) {
243: /* should bring it online here */
244: u.u_error = EIO;
245: return;
246: }
247: uap = (union arg *)addr;
248: switch(cmd) {
249: default:
250: u.u_error = ENOTTY;
251: return;
252:
253: case UIOCHAR:
254: if (copyout((caddr_t)&ra->di, addr, sizeof(struct ud_unit)))
255: u.u_error = EFAULT;
256: return;
257:
258: case UIORRCT:
259: if(uap->r.lbn < 0 || uap->r.lbn > ra->di.rctsize) {
260: u.u_error = EIO;
261: return;
262: }
263: /*
264: * try different copies until one works
265: */
266: for (i = 0; i < ra->di.copies; i++) {
267: u.u_count = SECTOR; /* block size on disk */
268: u.u_offset = ltoL((uap->r.lbn + ra->di.radsize) * SECTOR);
269: u.u_offset = Lladd(u.u_offset,i * ra->di.rctsize * SECTOR);
270: u.u_base = uap->r.buf;
271: u.u_segflg = SEGUDATA;
272: u.u_error = 0;
273: physio(rastrategy, &rctbuf, dev, B_READ, minphys);
274: if (u.u_error == 0)
275: break;
276: }
277: return;
278:
279: case UIOWRCT:
280: if ((flag & FWRITE) == 0) {
281: u.u_error = EBADF;
282: return;
283: }
284: if(uap->r.lbn < 0 || uap->r.lbn > ra->di.rctsize) {
285: u.u_error = EIO;
286: return;
287: }
288: /*
289: * write every copy we can
290: * should do read-after-write
291: */
292: for (i = 0; i < ra->di.copies; i++) {
293: u.u_count = SECTOR; /* block size on disk */
294: u.u_offset = ltoL((uap->r.lbn + ra->di.radsize) * SECTOR);
295: u.u_offset = Lladd(u.u_offset, i * ra->di.rctsize * SECTOR);
296: u.u_base = uap->r.buf;
297: u.u_segflg = SEGUDATA;
298: physio(rastrategy, &rctbuf, dev, B_WRITE, minphys);
299: u.u_error = 0;
300: }
301: return;
302:
303: case UIOREPL:
304: if ((flag & FWRITE) == 0) {
305: u.u_error = EBADF;
306: return;
307: }
308: rareplace(dev, uap->b.lbn, uap->b.replbn, uap->b.prim);
309: return;
310:
311: case UIOSPDW:
312: ra->flags |= SPDOWN;
313: return;
314:
315: case UIORST:
316: (*ra->port->mp_init)(raaddr[UNIT(dev)].ctl, raaddr[UNIT(dev)].ctype, 1, IDRA, raseql, radg);
317: return;
318: }
319:
320: }
321:
322: static
323: rareplace(dev, badlbn, replbn, prim)
324: int dev;
325: daddr_t badlbn;
326: daddr_t replbn;
327: int prim;
328: {
329: register struct mscmd *mp;
330: register struct radisk *ra;
331: register struct msaddr *rp;
332: register int unit;
333:
334: unit = UNIT(minor(dev));
335: ra = &radisk[unit];
336: rp = &raaddr[unit];
337: spl6();
338: while (ra->flags & RPLOCK) {
339: ra->flags |= RPWANT;
340: sleep((caddr_t)&ra->flags, PZERO + 1);
341: }
342: ra->flags |= RPLOCK;
343: printf("ra%d replace %D with %D\n", unit, badlbn, replbn);
344: mp = (*ra->port->mp_get)(rp->ctl);
345: bzero((caddr_t)mp, sizeof(struct mscmd)); /* clear reserved fields */
346: mp->m_crf = ++rarefno;
347: mp->m_unit = rp->unit;
348: mp->m_opcd = OPRPL;
349: mp->m_rbn = replbn;
350: mp->m_lbn = badlbn;
351: mp->m_mod = prim ? MDPRI : 0;
352: ra->cmdcrf = mp->m_crf;
353: ra->cmdopc = OPRPL;
354: (*ra->port->mp_send)(rp->ctl, IDRA, mp);
355: while ((ra->flags & RPDONE) == 0)
356: sleep((caddr_t)&ra->rplret, PZERO);
357: u.u_error = ra->rplret;
358: if (ra->flags & RPWANT)
359: wakeup((caddr_t)&ra->flags);
360: ra->flags &=~ (RPWANT|RPLOCK|RPDONE);
361: spl0();
362:
363: }
364:
365: /*
366: * here when the port gets a sequential message
367: */
368: raseql(ctl, type, ep)
369: int ctl, type;
370: register struct msend *ep;
371: {
372: register struct buf *bp;
373: register struct radisk *ra;
374: register int unit;
375: register struct buf *obp;
376: int sts;
377:
378: if (ep->m_opcd == 0 && ep->m_sts == STRST) {
379: rareset(ctl);
380: return;
381: }
382: for (unit = 0; unit < racnt; unit++)
383: if (raaddr[unit].ctl == ctl
384: && raaddr[unit].ctype == type
385: && raaddr[unit].unit == ep->m_unit)
386: break;
387: if (unit >= racnt) {
388: printf("ra%d ctl%d typ%d: stray mscp packet sts x%x opcode %o\n",
389: ep->m_unit, ctl, type, ep->m_sts, ep->m_opcd);
390: return;
391: }
392: ra = &radisk[unit];
393: sts = ep->m_sts & STMSK;
394: if (sts == STAVL || sts == STOFL)
395: ra->flags &=~ ONLINE; /* help! */
396: illcmd:
397: switch (ep->m_opcd & 0377) {
398: case OPEND: /* eg invalid command */
399: if (ep->m_crf == ra->cmdcrf) {
400: ep->m_opcd = ra->cmdopc | OPEND;
401: goto illcmd;
402: }
403: /* else check for pending read or write */
404: case OPRD|OPEND:
405: case OPWR|OPEND:
406: for (bp = ra->actf, obp = NULL; bp; obp = bp, bp = bp->b_next)
407: if (ep->m_crf == bp->b_crf)
408: break;
409: if (bp == NULL) {
410: printf("ra%d stray end: crf %d sts x%x opcode 0%o\n",
411: unit, ep->m_crf, ep->m_sts, ep->m_opcd & 0377);
412: return;
413: }
414: if (((struct mscmd *)(bp->b_pkt))->m_crf != ep->m_crf)
415: printf("ra%d sent %d got %d crf; flg %x dev %x\n",
416: unit, ((struct mscmd *)(bp->b_pkt))->m_crf,
417: ep->m_crf, bp->b_flags, bp->b_dev);
418: if (obp)
419: obp->b_next = bp->b_next;
420: else
421: ra->actf = bp->b_next;
422: if (bp == ra->actl)
423: ra->actl = obp;
424: bp->b_resid = bp->b_bcount - ep->m_bcnt;
425: if (sts != STSUC) {
426: bp->b_flags |= B_ERROR;
427: if (ep->m_sts == STBCK || ep->m_sts == STBK2) /* optical disk blank check */
428: bp->b_error = ENXIO;
429: else
430: printf("err on ra%d block %D: sts x%x\n", unit, bp->b_blkno, ep->m_sts);
431: }
432: (*ra->port->mp_unmap)(ctl, (struct mscmd *)bp->b_pkt);
433: iodone(bp);
434: return;
435:
436: case OPONL|OPEND:
437: rasonl(ra, ep);
438: return;
439:
440: case OPAVL|OPEND:
441: ra->flags &=~ ONLINE;
442: return;
443:
444: case OPGUS|OPEND:
445: if (sts != STSUC) {
446: printf("ra%d: can't get unit sts x%x\n", unit, ep->m_sts);
447: return;
448: }
449: ra->di.medium = ep->m_medi;
450: ra->di.tracksz = ep->m_trck;
451: ra->di.groupsz = ep->m_grp;
452: ra->di.cylsz = ep->m_cyl;
453: ra->di.rctsize = ep->m_rcts;
454: ra->di.rbns = ep->m_rbns;
455: ra->di.copies = ep->m_rctc;
456: ra->flags |= GOTDI;
457: return;
458:
459: case OPSCC|OPEND:
460: if (sts != STSUC)
461: printf("ra ctl%d typ%d: bad init\n", ctl, type);
462: return;
463:
464: case OPRPL|OPEND:
465: ra->rplret = 0;
466: if (sts != STSUC) {
467: printf("ra%d: rpl sts x%x\n", unit, ep->m_sts);
468: ra->rplret = EIO;
469: }
470: ra->flags |= RPDONE;
471: wakeup((caddr_t)&ra->rplret);
472: return;
473:
474: default:
475: printf("ra%d ctl%d typ%d: stray mscp msg opcd 0%o sts x%x\n",
476: ep->m_unit, ctl, type, ep->m_opcd&0377, ep->m_sts);
477: return;
478: }
479: }
480:
481: /*
482: * controller was reset
483: * discard all pending io,
484: * awake all sleepers,
485: * mark everything offline
486: */
487:
488: rareset(ctl)
489: int ctl;
490: {
491: register int unit;
492: register struct radisk *ra;
493: register struct buf *bp, *nbp;
494:
495: for (unit = 0; unit < racnt; unit++) {
496: if (raaddr[unit].ctl != ctl)
497: continue;
498: ra = &radisk[unit];
499: for (bp = ra->actf; bp; bp = nbp) {
500: nbp = bp->b_next;
501: (*ra->port->mp_unmap)(ctl, (struct mscmd *)bp->b_pkt);
502: bp->b_flags |= B_ERROR;
503: iodone(bp);
504: }
505: ra->actf = ra->actl = NULL;
506: ra->flags &=~ (ONLINE|WONLINE);
507: wakeup((caddr_t)ra);
508: }
509: }
510:
511: /*
512: * here with a datagram message
513: * explanations really shouldn't be in the driver
514: *
515: * the hack for event 8 ignores error packets from
516: * the US Design optical disk controller
517: * that really mean `read a blank spot on the disk
518: */
519:
520: static char *raevents[] = {
521: "ok",
522: "inv cmd",
523: "op aborted",
524: "offline",
525: "available",
526: "med fmt",
527: "write prot",
528: "comp err",
529: "data err",
530: "host buf access err",
531: "cntl err",
532: "drive err",
533: };
534: #define MAXEVT 0xb
535:
536: radg(ctl, type, ep)
537: int ctl, type;
538: register struct mserl *ep;
539: {
540: register u_short *sp; /* for sdi crap */
541: register int i; /* for useless design crap */
542: register unsigned char *cp; /* for useless design crap */
543:
544: if (ep->l_fmt == FMDSK && ep->l_evnt == STBCK && ep->l_flgs == 0)
545: return;
546: printf("ra%d ctl%d typ%d seq %d: %s err; fmt x%x ev x%x fl x%x\n",
547: ep->l_unit, ctl, type, ep->l_seq, /* phys unit, not log */
548: ep->l_flgs&(LFSUC|LFCON) ? "soft" : "hard",
549: ep->l_fmt, ep->l_evnt, ep->l_flgs&0377);
550: if ((ep->l_evnt & STMSK) <= MAXEVT)
551: printf("%s; ", raevents[ep->l_evnt & STMSK]);
552: switch (ep->l_fmt) {
553: case FMCNT:
554: /* now the thing should be marked disastrously bad */
555: printf("oops\n");
556: break;
557:
558: case FMBAD:
559: printf("host mem access; addr x%x\n", ep->l_badr);
560: break;
561:
562: case FMDSK:
563: printf("%sbn %d; lev x%x, retry x%x\n",
564: (ep->l_hdcd & 0xf0000000) == 0 ? "l" : "r",
565: ep->l_hdcd & 0x0fffffff, ep->l_lvl, ep->l_rtry);
566: break;
567:
568: case FMSDI:
569: printf("%sbn %d;",
570: (ep->l_hdcd & 0xf0000000) == 0 ? "l" : "r",
571: ep->l_hdcd & 0x0fffffff);
572: /*
573: * print the bytes in the same order used
574: * by the dec diagnostics
575: */
576: sp = (u_short *)&ep->l_sdi[3];
577: while (sp > (u_short *)ep->l_sdi)
578: printf(" %x", *--sp);
579: printf(" xx\n");
580: break;
581:
582: case FMSMD:
583: printf("cyl %d\n", ep->l_sdi[1]);
584: break;
585:
586: case 0x40: /* hack for useless design */
587: printf("scsi:");
588: cp = (unsigned char *)ep->l_sdi;
589: for(i = 0; i < 10; i++)
590: printf(" %x", *cp++);
591: printf(" [%x %x]\n", cp[0], cp[1]);
592: break;
593:
594: default:
595: printf("\n");
596: break;
597: }
598: }
599:
600: /*
601: * unit is believed offline
602: * try to bring it on
603: */
604:
605: static
606: raonline(ra, rp)
607: register struct radisk *ra;
608: register struct msaddr *rp;
609: {
610: register struct mscmd *mp;
611: int s;
612:
613: s = spl6();
614: if ((ra->flags & WONLINE) == 0) {
615: ra->flags &=~ GOTDI;
616: mp = (*ra->port->mp_get)(rp->ctl);
617: bzero((caddr_t)mp, sizeof(struct mscmd)); /* clear reserved fields */
618: mp->m_crf = ++rarefno;
619: mp->m_unit = rp->unit;
620: mp->m_opcd = OPONL;
621: ra->cmdcrf = mp->m_crf;
622: ra->cmdopc = OPONL;
623: (*ra->port->mp_send)(rp->ctl, IDRA, mp);
624: ra->flags |= WONLINE;
625: }
626: while (ra->flags & WONLINE)
627: tsleep((caddr_t)ra, PRIONL, 60);
628: if ((ra->flags & ONLINE) == 0)
629: return (0);
630: if ((ra->flags & GOTDI) == 0) {
631: mp = (*ra->port->mp_get)(rp->ctl);
632: mp->m_crf = ++rarefno;
633: mp->m_unit = rp->unit;
634: mp->m_opcd = OPGUS;
635: mp->m_mod = 0;
636: mp->m_unfl = 0;
637: mp->m_dvpm = 0; /* ? */
638: (*ra->port->mp_send)(rp->ctl, IDRA, mp);
639: }
640: splx(s);
641: return (1);
642: }
643:
644: static
645: rasonl(ra, ep)
646: register struct radisk *ra;
647: register struct msend *ep;
648: {
649:
650: if (ra->flags & WONLINE) {
651: ra->flags &=~ WONLINE;
652: wakeup((caddr_t)ra);
653: }
654: if ((ep->m_sts & STMSK) != STSUC)
655: return;
656: ra->flags |= ONLINE;
657: if (ra->di.radsize != HUGE && ra->di.radsize != ep->m_unsz)
658: printf("ra%d: changed size %d to %d\n", ra-radisk, ra->di.radsize, ep->m_unsz);
659: ra->di.radsize = ep->m_unsz;
660: }
661:
662: /*
663: * controller init
664: * set characteristics to turn off host timeouts
665: */
666:
667: static
668: racinit(ra, rp)
669: struct radisk *ra;
670: struct msaddr *rp;
671: {
672: register struct mscmd *mp;
673: register int s;
674:
675: mp = (*ra->port->mp_get)(rp->ctl);
676: mp->m_crf = ++rarefno;
677: mp->m_unit = rp->unit;
678: mp->m_opcd = OPSCC;
679: mp->m_mod = 0;
680: mp->m_cntf = CFMSC | CFTHS;
681: mp->m_vrsn = MSCPVER;
682: mp->m_htmo = 0; /* no timeout */
683: mp->m_time[0] = mp->m_time[1] = 0L;
684: s = spl6();
685: (*ra->port->mp_send)(rp->ctl, IDRA, mp);
686: splx(s);
687: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.