|
|
1.1 root 1: /* @(#)sd.c 1.1 86/02/03 SMI */
2:
3: /*
4: * Copyright (c) 1984 by Sun Microsystems, Inc.
5: */
6:
7: /*
8: * SCSI driver for SCSI disks.
9: */
10:
11: #include "sd.h"
12: #include "../h/param.h"
13: #include "../h/systm.h"
14: #include "../h/dk.h"
15: #include "../h/buf.h"
16: #include "../h/conf.h"
17: #include "../h/dir.h"
18: #include "../h/user.h"
19: #include "../h/map.h"
20: #include "../h/vmmac.h"
21: /*
22: *#include "../h/ioctl.h"
23: *#include "../h/uio.h"
24: *#include "../h/kernel.h"
25: */
26: #include "../h/dkbad.h"
27:
28: #include "../machine/pte.h"
29: #include "../machine/psl.h"
30: #include "../machine/mmu.h"
31: #include "../machine/cpu.h"
32:
33: #include "../sun/dklabel.h"
34: #include "../sun/dkio.h"
35:
36: #include "../sundev/mbvar.h"
37: #include "../sundev/screg.h"
38: #include "../sundev/sireg.h"
39: #include "../sundev/scsi.h"
40:
41: #define MAX_RETRIES 3
42: #define MAX_RESTORES 1
43:
44: #define LPART(dev) (dev % NLPART)
45: #define SDUNIT(dev) ((dev >> 3) % NUNIT)
46: #define SDNUM(un) (un - sdunits)
47:
48: #define b_cylin b_resid
49: #define SECSIZE 512
50:
51: #define BUSY_RETRY 1000
52:
53: /*
54: * Error message control.
55: */
56: #define EL_RETRY 3
57: #define EL_REST 2
58: #define EL_FAIL 1
59: int sderrlvl = EL_RETRY;
60:
61: extern struct scsi_unit sdunits[];
62: extern struct scsi_unit_subr scsi_unit_subr[];
63: extern struct scsi_disk sdisk[];
64: extern int nsdisk;
65:
66: /*
67: * Return a pointer to this unit's unit structure.
68: */
69: sdunitptr(md)
70: register struct mb_device *md;
71: {
72: return ((int)&sdunits[md->md_unit]);
73: }
74:
75: /*
76: * Attach device (boot time).
77: */
78: sdattach(md)
79: register struct mb_device *md;
80: {
81: register struct scsi_unit *un;
82: register struct dk_label *l;
83: register int nbusy;
84:
85: un = &sdunits[md->md_unit];
86: un->un_md = md;
87: un->un_mc = md->md_mc;
88: un->un_unit = md->md_unit;
89: un->un_target = TARGET(md->md_slave);
90: un->un_lun = LUN(md->md_slave);
91: un->un_ss = &scsi_unit_subr[TYPE(md->md_flags)];
92:
93: nbusy = 0;
94: for (;;) {
95: if (simple(un, SC_TEST_UNIT_READY, 0, 0, 0)) {
96: break;
97: } else if (un->un_c->c_scb.busy && nbusy++ < BUSY_RETRY) {
98: DELAY(5000);
99: continue;
100: } else {
101: if (nbusy >= BUSY_RETRY) {
102: printf("sd%d: scsi continuously busy\n",
103: SDNUM(un));
104: }
105: return;
106: }
107: }
108: /* Allocate space for label in Multibus memory */
109: l = (struct dk_label *)rmalloc(iopbmap, (long)SECSIZE);
110: if (l == NULL) {
111: printf("sd%d: sdattach: no space for disk label\n",
112: SDNUM(un));
113: return;
114: }
115: l->dkl_magic = 0;
116: if (getlabel(un, l) && islabel(un, l)) {
117: uselabel(un, l);
118: }
119: rmfree(iopbmap, (long)SECSIZE, (long)l);
120: }
121:
122: static
123: getlabel(un, l)
124: register struct scsi_unit *un;
125: register struct dk_label *l;
126: {
127: register int retries, restores;
128:
129: for (restores = 0; restores < MAX_RESTORES; restores++) {
130: for (retries = 0; retries < MAX_RETRIES; retries++) {
131: if (simple(un, SC_READ, (char *) l - DVMA, 0, 1)) {
132: return (1);
133: }
134: }
135: (void) simple(un, SC_REZERO_UNIT, 0, 0, 0);
136: }
137: return (0);
138: }
139:
140: static
141: islabel(un, l)
142: register struct scsi_unit *un;
143: register struct dk_label *l;
144: {
145: if (l->dkl_magic != DKL_MAGIC) {
146: return (0);
147: }
148: if (!ck_cksum(l)) {
149: printf("sd%d: corrupt label\n", SDNUM(un));
150: return (0);
151: }
152: return (1);
153: }
154:
155: /*
156: * Check the checksum of the label
157: */
158: static
159: ck_cksum(l)
160: register struct dk_label *l;
161: {
162: short *sp, sum = 0;
163: short count = sizeof(struct dk_label)/sizeof(short);
164:
165: sp = (short *)l;
166: while (count--) {
167: sum ^= *sp++;
168: }
169: return (sum ? 0 : 1);
170: }
171:
172: static
173: uselabel(un, l)
174: register struct scsi_unit *un;
175: register struct dk_label *l;
176: {
177: register int i, intrlv;
178: register struct scsi_disk *dsi;
179:
180: printf("sd%d: <%s>\n", SDNUM(un), l->dkl_asciilabel);
181: un->un_present = 1;
182: dsi = &sdisk[un->un_unit];
183: dsi->un_g.dkg_ncyl = l->dkl_ncyl;
184: dsi->un_g.dkg_bcyl = 0;
185: dsi->un_g.dkg_nhead = l->dkl_nhead;
186: dsi->un_g.dkg_bhead = l->dkl_bhead;
187: dsi->un_g.dkg_nsect = l->dkl_nsect;
188: dsi->un_g.dkg_gap1 = l->dkl_gap1;
189: dsi->un_g.dkg_gap2 = l->dkl_gap2;
190: dsi->un_g.dkg_intrlv = l->dkl_intrlv;
191: for (i = 0; i < NLPART; i++)
192: dsi->un_map[i] = l->dkl_map[i];
193: if (un->un_md->md_dk >= 0) {
194: intrlv = dsi->un_g.dkg_intrlv;
195: if (intrlv <= 0 || intrlv >= dsi->un_g.dkg_nsect) {
196: intrlv = 1;
197: }
198: /*
199: dk_bps[un->un_md->md_dk] = SECSIZE*60*dsi->un_g.dkg_nsect/intrlv;
200: */
201: }
202: }
203:
204: static
205: simple(un, cmd, dma_addr, secno, nsect)
206: register struct scsi_unit *un;
207: register int cmd, dma_addr, secno, nsect;
208: {
209: register struct scsi_cdb *cdb;
210: register struct scsi_ctlr *c;
211: register int count;
212:
213: c = un->un_c;
214: cdb = &c->c_cdb;
215: bzero((caddr_t)cdb, sizeof(struct scsi_cdb));
216: cdb->cmd = cmd;
217: c->c_un = un;
218: cdb->lun = un->un_lun;
219: cdbaddr(cdb, secno);
220: cdb->count = nsect;
221: un->un_dma_addr = dma_addr;
222: un->un_dma_count = nsect * SECSIZE;
223: if ((*c->c_ss->scs_cmd)(c, un, 0)) {
224: if ((*c->c_ss->scs_cmd_wait)(c)) {
225: count = (*c->c_ss->scs_dmacount)(c);
226: * (char *) &c->c_scb = 0;
227: if ((*c->c_ss->scs_getstat)(un, 0)) {
228: if (count == 0) {
229: if (c->c_scb.chk == 0 &&
230: c->c_scb.busy == 0) {
231: return (1);
232: }
233: }
234: }
235: }
236: }
237: return (0);
238: }
239:
240: /*ARGSUSED*/
241: sdopen(dev, flag)
242: dev_t dev;
243: int flag;
244: {
245: register struct scsi_unit *un;
246: register struct dk_label *l;
247: register int unit;
248: register struct scsi_disk *dsi;
249: int memall();
250:
251: unit = SDUNIT(dev);
252: if (unit >= nsdisk) {
253: u.u_error = ENXIO;
254: return;
255: }
256: un = &sdunits[unit];
257: dsi = &sdisk[unit];
258: if (un->un_mc == 0) { /* never attached */
259: u.u_error = ENXIO;
260: return;
261: }
262: if (!un->un_present) {
263: dsi->un_g.dkg_nsect = dsi->un_g.dkg_nhead = 1; /* for strat */
264: if (sdcmd(dev, SC_TEST_UNIT_READY, 0, 0, (caddr_t)0)) {
265: u.u_error = EIO;
266: return;
267: }
268: /* Allocate space for label */
269: l = (struct dk_label *)wmemall(memall, SECSIZE);
270: if (l == NULL) {
271: printf("sd%d: no space for disk label\n",
272: SDNUM(un));
273: u.u_error = EIO;
274: return;
275: }
276: if (sdcmd(dev, SC_READ, 0, SECSIZE, (caddr_t)l)) {
277: uprintf("sd%d: error reading label\n", SDNUM(un));
278: wmemfree((caddr_t)l, SECSIZE);
279: u.u_error = EIO;
280: return;
281: }
282: if (islabel(un, l)) {
283: uselabel(un, l);
284: } else {
285: wmemfree((caddr_t)l, SECSIZE);
286: u.u_error = EIO;
287: return;
288: }
289: wmemfree((caddr_t)l, SECSIZE);
290: }
291: return (0);
292: }
293:
294: sdsize(dev)
295: register dev_t dev;
296: {
297: register struct scsi_unit *un;
298: register struct dk_map *lp;
299: register struct scsi_disk *dsi;
300:
301: un = &sdunits[SDUNIT(dev)];
302: if (!un->un_present) {
303: return (-1);
304: }
305: dsi = &sdisk[SDUNIT(dev)];
306: lp = &dsi->un_map[LPART(dev)];
307: return (lp->dkl_nblk);
308: }
309:
310: sdstrategy(bp)
311: register struct buf *bp;
312: {
313: register struct scsi_unit *un;
314: register struct dk_map *lp;
315: register daddr_t bn;
316: register int unit;
317: register struct buf *dp;
318: register struct scsi_disk *dsi;
319: long sz;
320: int s;
321:
322: sz = bp->b_bcount;
323: sz = (sz+511) >> 9;
324: unit = dkunit(bp);
325: if (unit >= nsdisk)
326: goto bad;
327: un = &sdunits[unit];
328: if (!un->un_present && bp != &un->un_sbuf)
329: goto bad;
330: dsi = &sdisk[unit];
331: lp = &dsi->un_map[LPART(bp->b_dev)];
332: if (bp->b_blkno < 0 || (bn = dkblock(bp))+sz > lp->dkl_nblk)
333: goto bad;
334: bp->b_cylin = bn / (dsi->un_g.dkg_nsect * dsi->un_g.dkg_nhead);
335: bp->b_cylin += lp->dkl_cylno + dsi->un_g.dkg_bcyl;
336: dp = &un->un_utab;
337: s = splx(pritospl(un->un_mc->mc_intpri));
338: disksort(dp, bp);
339: if (dp->b_active == 0) {
340: (*un->un_c->c_ss->scs_ustart)(un);
341: bp = &un->un_mc->mc_tab;
342: if (bp->b_actf && bp->b_active == 0) {
343: (*un->un_c->c_ss->scs_start)(un);
344: }
345: }
346: (void) splx(s);
347: return;
348:
349: bad:
350: bp->b_flags |= B_ERROR;
351: iodone(bp);
352: return;
353: }
354:
355: /*
356: * Do a special command.
357: */
358: sdcmd(dev, cmd, sector, len, addr)
359: register dev_t dev;
360: register int cmd, sector, len;
361: register caddr_t addr;
362: {
363: register struct scsi_unit *un;
364: register struct buf *bp;
365: register int s;
366:
367: un = &sdunits[SDUNIT(dev)];
368: bp = &un->un_sbuf;
369: s = splx(pritospl(un->un_mc->mc_intpri));
370: while (bp->b_flags&B_BUSY) {
371: bp->b_flags |= B_WANTED;
372: sleep((caddr_t)bp, PRIBIO);
373: }
374: bp->b_flags = B_BUSY|B_READ;
375: (void) splx(s);
376: un->un_scmd = cmd;
377: bp->b_dev = dev;
378: bp->b_blkno = sector;
379: bp->b_un.b_addr = addr;
380: bp->b_bcount = len;
381: sdstrategy(bp);
382: iowait(bp);
383: bp->b_flags &= ~B_BUSY;
384: if (bp->b_flags&B_WANTED)
385: wakeup((caddr_t)bp);
386: return (bp->b_flags & B_ERROR);
387: }
388:
389: /*
390: * Set up a transfer for the controller
391: */
392: sdstart(bp, un)
393: register struct buf *bp;
394: register struct scsi_unit *un;
395: {
396: register struct dk_map *lp;
397: register int nblk;
398: register struct scsi_disk *dsi;
399:
400: dsi = &sdisk[dkunit(bp)];
401: lp = &dsi->un_map[LPART(bp->b_dev)];
402: un->un_blkno = dkblock(bp) +
403: lp->dkl_cylno * dsi->un_g.dkg_nhead * dsi->un_g.dkg_nsect;
404: if (bp == &un->un_sbuf) {
405: un->un_cmd = un->un_scmd;
406: } else if (bp->b_flags & B_READ) {
407: un->un_cmd = SC_READ;
408: } else {
409: un->un_cmd = SC_WRITE;
410: }
411: if (un->un_cmd == SC_READ || un->un_cmd == SC_WRITE) {
412: nblk = howmany(bp->b_bcount, SECSIZE);
413: un->un_count = MIN(nblk, lp->dkl_nblk - bp->b_blkno);
414: bp->b_resid = bp->b_bcount - un->un_count * SECSIZE;
415: un->un_flags |= SC_UNF_DVMA;
416: } else {
417: un->un_count = 0;
418: }
419: return (1);
420: }
421:
422: /*
423: * Make a cdb for disk i/o.
424: */
425: sdmkcdb(c, un)
426: register struct scsi_ctlr *c;
427: struct scsi_unit *un;
428: {
429: register struct scsi_cdb *cdb;
430:
431: cdb = &c->c_cdb;
432: bzero((caddr_t)cdb, sizeof (*cdb));
433: cdb->cmd = un->un_cmd;
434: cdb->lun = un->un_lun;
435: cdbaddr(cdb, un->un_blkno);
436: cdb->count = un->un_count;
437: un->un_dma_addr = un->un_baddr;
438: un->un_dma_count = un->un_count * SECSIZE;
439: }
440:
441: /*
442: * Interrupt processing.
443: */
444: sdintr(c, resid, error)
445: register struct scsi_ctlr *c;
446: register int resid, error;
447: {
448: register struct scsi_unit *un;
449: register struct buf *bp;
450: register struct mb_device *md;
451:
452: un = c->c_un;
453: bp = un->un_mc->mc_tab.b_actf->b_actf;
454: md = un->un_md;
455: if (md->md_dk >= 0) {
456: dk_busy &= ~(1 << md->md_dk);
457: }
458: if (error == SE_FATAL) {
459: if (bp == &un->un_sbuf &&
460: ((un->un_flags & SC_UNF_DVMA) == 0)) {
461: (*c->c_ss->scs_done)(un->un_mc);
462: } else {
463: mbdone(un->un_mc);
464: un->un_flags &= ~SC_UNF_DVMA;
465: }
466: bp->b_flags |= B_ERROR;
467: printf("sd%d: SCSI FAILURE\n", SDNUM(un));
468: (*c->c_ss->scs_off)(un);
469: return;
470: }
471: if (error == SE_RETRYABLE || c->c_scb.chk || resid > 0) {
472: sderror(c, un, bp);
473: return;
474: }
475: if (c->c_cdb.cmd == SC_REZERO_UNIT &&
476: !(bp == &un->un_sbuf &&
477: un->un_scmd == SC_REZERO_UNIT)) {
478: /* error recovery */
479: sdmkcdb(c, un);
480: if ((*c->c_ss->scs_cmd)(c, un, 1) == 0) {
481: printf("sd%d sdintr: scsi cmd failed 1\n", SDNUM(un));
482: (*c->c_ss->scs_off)(un);
483: }
484: return;
485: }
486: /* transfer worked */
487: un->un_retries = un->un_restores = 0;
488: if (un->un_sec_left) { /* single sector stuff */
489: un->un_sec_left--;
490: un->un_baddr += SECSIZE;
491: un->un_blkno++;
492: sdmkcdb(c, un);
493: if ((*c->c_ss->scs_cmd)(c, un, 1) == 0) {
494: printf("sd%d: sdintr: scsi cmd failed 2\n", SDNUM(un));
495: (*c->c_ss->scs_off)(un);
496: }
497: } else if (bp == &un->un_sbuf &&
498: ((un->un_flags & SC_UNF_DVMA) == 0)) {
499: (*c->c_ss->scs_done)(un->un_mc);
500: } else {
501: mbdone(un->un_mc);
502: un->un_flags &= ~SC_UNF_DVMA;
503: }
504: }
505:
506: /*
507: * Error handling.
508: */
509: sderror(c, un, bp)
510: register struct scsi_ctlr *c;
511: register struct scsi_unit *un;
512: register struct buf *bp;
513: {
514: if (un->un_present == 0) { /* error trying to open */
515: bp->b_flags |= B_ERROR;
516: if (bp == &un->un_sbuf &&
517: ((un->un_flags & SC_UNF_DVMA) == 0)) {
518: (*c->c_ss->scs_done)(un->un_mc);
519: } else {
520: mbdone(un->un_mc);
521: un->un_flags &= ~SC_UNF_DVMA;
522: }
523: } else if (c->c_scb.chk && c->c_sense->class == 1 &&
524: c->c_sense->code == 5 && un->un_count > 1) {
525: /* Seek errors - try single sectors (Adaptec bug) */
526: un->un_sec_left = un->un_count - 1;
527: un->un_count = 1;
528: sdmkcdb(c, un);
529: if ((*c->c_ss->scs_cmd)(c, un, 1) == 0) {
530: printf("sd%d: sderror: scsi cmd failed 1\n", SDNUM(un));
531: (*c->c_ss->scs_off)(un);
532: }
533: } else if (un->un_retries++ < MAX_RETRIES) {
534: /* retry */
535: if (sderrlvl >= EL_RETRY) {
536: sderrmsg(c, un, bp, "retry");
537: }
538: if ((*c->c_ss->scs_cmd)(c, un, 1) == 0) {
539: printf("sd%d: sderror: scsi cmd failed 2\n", SDNUM(un));
540: (*c->c_ss->scs_off)(un);
541: }
542: } else if (un->un_restores++ < MAX_RESTORES) {
543: /* retries exhausted, try restore */
544: un->un_retries = 0;
545: if (sderrlvl >= EL_REST) {
546: sderrmsg(c, un, bp, "restore");
547: }
548: c->c_cdb.cmd = SC_REZERO_UNIT;
549: cdbaddr(&c->c_cdb, 0);
550: c->c_cdb.count = 0;
551: un->un_dma_addr = un->un_dma_count = 0;
552: if ((*c->c_ss->scs_cmd)(c, un, 1) == 0) {
553: printf("sd%d: sderror: scsi cmd failed 3\n", SDNUM(un));
554: (*c->c_ss->scs_off)(un);
555: }
556: } else {
557: /* complete failure */
558: if (sderrlvl >= EL_FAIL) {
559: sderrmsg(c, un, bp, "failed");
560: }
561: (*c->c_ss->scs_off)(un);
562: bp->b_flags |= B_ERROR;
563: if (bp == &un->un_sbuf &&
564: ((un->un_flags & SC_UNF_DVMA) == 0)) {
565: (*c->c_ss->scs_done)(un->un_mc);
566: } else {
567: mbdone(un->un_mc);
568: un->un_flags &= ~SC_UNF_DVMA;
569: }
570: }
571: }
572:
573: sdread(dev)
574: dev_t dev;
575: {
576: sdrw(dev, B_READ);
577: }
578:
579: sdrw(dev, direction)
580: dev_t dev;
581: int direction;
582: {
583: register struct scsi_unit *un;
584: register int unit;
585:
586: unit = SDUNIT(dev);
587: if (unit >= nsdisk) {
588: u.u_error = ENXIO;
589: }
590: un = &sdunits[unit];
591: physio(sdstrategy, &un->un_rbuf, dev, direction, minphys);
592: }
593:
594: sdwrite(dev)
595: dev_t dev;
596: {
597: sdrw(dev, B_WRITE);
598: }
599:
600: /*ARGSUSED*/
601: sdioctl(dev, cmd, data, flag)
602: register dev_t dev;
603: register caddr_t data;
604: {
605: register struct scsi_unit *un;
606: register struct dk_map *lp;
607: register struct dk_info *inf;
608: register int unit;
609: register struct scsi_disk *dsi;
610:
611: unit = SDUNIT(dev);
612: if (unit >= nsdisk) {
613: return (ENXIO);
614: }
615: un = &sdunits[unit];
616: dsi = &sdisk[unit];
617: lp = &dsi->un_map[LPART(dev)];
618: switch (cmd) {
619:
620: case DKIOCINFO:
621: inf = (struct dk_info *)data;
622: inf->dki_ctlr = getdevaddr(un->un_mc->mc_addr);
623: inf->dki_unit = un->un_md->md_slave;
624: inf->dki_ctype = DKC_SCSI;
625: inf->dki_flags = DKI_FMTVOL;
626: break;
627:
628: case DKIOCGGEOM:
629: *(struct dk_geom *)data = dsi->un_g;
630: break;
631:
632: case DKIOCSGEOM:
633: if (!suser())
634: return (u.u_error);
635: dsi->un_g = *(struct dk_geom *)data;
636: break;
637:
638: case DKIOCGPART:
639: *(struct dk_map *)data = *lp;
640: break;
641:
642: case DKIOCSPART:
643: if (!suser())
644: return (u.u_error);
645: *lp = *(struct dk_map *)data;
646: break;
647:
648: default:
649: return (ENOTTY);
650: }
651: return (0);
652: }
653:
654: sddump(dev, addr, blkno, nblk)
655: register dev_t dev;
656: register caddr_t addr;
657: register daddr_t blkno, nblk;
658: {
659: register struct scsi_unit *un;
660: register struct dk_map *lp;
661: static int first_time = 1;
662: register struct scsi_disk *dsi;
663:
664: un = &sdunits[SDUNIT(dev)];
665: if (un->un_present == 0) {
666: return (ENXIO);
667: }
668: dsi = &sdisk[SDUNIT(dev)];
669: lp = &dsi->un_map[LPART(dev)];
670: if (blkno >= lp->dkl_nblk || (blkno + nblk) > lp->dkl_nblk) {
671: return (EINVAL);
672: }
673: blkno += lp->dkl_cylno * dsi->un_g.dkg_nhead * dsi->un_g.dkg_nsect;
674: if (first_time) {
675: (*un->un_c->c_ss->scs_reset)(un->un_c); /* clr state - prevent err msg */
676: first_time = 0;
677: }
678: if (simple(un, SC_WRITE, (int)(addr-DVMA), (int) blkno, (int) nblk)) {
679: return (0);
680: } else {
681: return (EIO);
682: }
683: }
684:
685: char *class_00_errors[] = {
686: "no sense",
687: "no index signal",
688: "no seek complete",
689: "write fault",
690: "drive not ready",
691: "drive not selected",
692: "no track 00",
693: "multiple drives selected",
694: "no address acknowledged",
695: "media not loaded",
696: "insufficient capacity",
697: };
698:
699: char *class_01_errors[] = {
700: "I.D. CRC error",
701: "unrecoverable data error",
702: "I.D. address mark not found",
703: "data address mark not found",
704: "record not found",
705: "seek error",
706: "DMA timeout error",
707: "write protected",
708: "correctable data check",
709: "bad block found",
710: "interleave error",
711: "data transfer incomplete",
712: "unformatted or bad format on drive",
713: "self test failed",
714: "defective track (media errors)",
715: };
716:
717: char *class_02_errors[] = {
718: "invalid command",
719: "illegal block address",
720: "aborted",
721: "volume overflow",
722: };
723:
724: char **sc_errors[] = {
725: class_00_errors,
726: class_01_errors,
727: class_02_errors,
728: 0, 0, 0, 0,
729: };
730:
731: int sc_errct[] = {
732: sizeof class_00_errors / sizeof (char *),
733: sizeof class_01_errors / sizeof (char *),
734: sizeof class_02_errors / sizeof (char *),
735: 0, 0, 0, 0,
736: };
737:
738: char *sc_ext_sense_keys [] = {
739: "no sense",
740: "recoverable error",
741: "not ready",
742: "media error",
743: "hardware error",
744: "illegal request",
745: "media change",
746: "write protect",
747: "diagnostic unique",
748: "vendor unique",
749: "power up failed",
750: "aborted command",
751: "equal",
752: "volume overflow",
753: };
754:
755: #define N_EXT_SENSE_KEYS \
756: (sizeof(sc_ext_sense_keys)/sizeof(sc_ext_sense_keys[0]))
757:
758: char *sd_cmds[] = {
759: "test unit ready",
760: "rezero unit",
761: "<bad cmd>",
762: "request sense",
763: "<bad cmd>",
764: "<bad cmd>",
765: "<bad cmd>",
766: "<bad cmd>",
767: "read",
768: "<bad cmd>",
769: "write",
770: "seek",
771: };
772:
773: sderrmsg(c, un, bp, action)
774: register struct scsi_ctlr *c;
775: struct scsi_unit *un;
776: struct buf *bp;
777: char *action;
778: {
779: char *sensemsg, *cmdname;
780: register struct scsi_sense *sense;
781: #define ext_sense ((struct scsi_ext_sense* ) sense)
782: register struct dk_map *lp;
783: register int blkno;
784: register struct scsi_disk *dsi;
785:
786: dsi = &sdisk[dkunit(bp)];
787: sense = c->c_sense;
788: if (c->c_scb.chk == 0) {
789: sensemsg = "no sense";
790: } else if (sense->class <= 6) {
791: if (sense->code < sc_errct[sense->class]) {
792: sensemsg = sc_errors[sense->class][sense->code];
793: } else {
794: sensemsg = "invalid sense code";
795: }
796: } else if (sense->class == 7) {
797: if (ext_sense->key < N_EXT_SENSE_KEYS) {
798: sensemsg = sc_ext_sense_keys[ext_sense->key];
799: } else {
800: sensemsg = "invalid sense code";
801: }
802: } else {
803: sensemsg = "invalid sense class";
804: }
805: if (un->un_cmd < sizeof(sd_cmds)) {
806: cmdname = sd_cmds[un->un_cmd];
807: } else {
808: cmdname = "unknown cmd";
809: }
810: blkno = (sense->high_addr << 16) | (sense->mid_addr << 8) |
811: sense->low_addr;
812: lp = &dsi->un_map[LPART(bp->b_dev)];
813: blkno -= lp->dkl_cylno * dsi->un_g.dkg_nhead * dsi->un_g.dkg_nsect;
814: printf("sd%d%c: %s %s (%s) blk %d\n", SDNUM(un),
815: LPART(bp->b_dev) + 'a', cmdname, action, sensemsg, blkno);
816: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.