|
|
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.