|
|
1.1 ! root 1: /* @(#)sf.c 1.1 86/02/03 SMI */ ! 2: ! 3: /* ! 4: * Copyright (c) 1984 by Sun Microsystems, Inc. ! 5: */ ! 6: ! 7: #include "sf.h" ! 8: #if NSF > 0 ! 9: ! 10: /* ! 11: * SCSI driver for SCSI floppy disks. ! 12: */ ! 13: #include "../h/param.h" ! 14: #include "../h/systm.h" ! 15: #include "../h/dk.h" ! 16: #include "../h/buf.h" ! 17: #include "../h/conf.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 "../h/vfs.h" ! 29: *#include "../h/vnode.h" ! 30: */ ! 31: #include "../machine/pte.h" ! 32: #include "../machine/psl.h" ! 33: #include "../machine/mmu.h" ! 34: #include "../machine/cpu.h" ! 35: #include "../sun/dklabel.h" ! 36: #include "../sun/dkio.h" ! 37: /*#include "../pcfs/pc_label.h"*/ ! 38: #include "../sundev/mbvar.h" ! 39: #include "../sundev/screg.h" ! 40: #include "../sundev/sireg.h" ! 41: #include "../sundev/scsi.h" ! 42: ! 43: #define MAX_RETRIES 0 ! 44: #define MAX_RESTORES 1 ! 45: ! 46: #define SFUNIT(dev) (minor(dev)) ! 47: #define SFNUM(un) (un - sfunits) ! 48: ! 49: #define b_cylin b_resid ! 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 sferrlvl = EL_REST; ! 60: ! 61: /* ! 62: * sf specific SCSI commands ! 63: */ ! 64: #define SC_INIT_CHARACTERISTICS 0x0c /* initialize drive characteristics */ ! 65: ! 66: extern struct scsi_unit sfunits[]; ! 67: extern struct scsi_unit_subr scsi_unit_subr[]; ! 68: extern struct scsi_floppy sfloppy[]; ! 69: extern int nsfloppy; ! 70: ! 71: #define SF_LABELGET 0x01 /* getting device label */ ! 72: #define SF_LABELWANT 0x02 /* waiting to get label */ ! 73: ! 74: struct sf_characteristics { ! 75: u_char sfc_ncyl; /* number of cylinders */ ! 76: u_int sfc_trkswtch : 4; /* track switching rate code */ ! 77: u_int sfc_mstart : 12; /* motor start time (msec) */ ! 78: u_char sfc_drive : 4; /* drive type (5 or 8 inch) */ ! 79: u_char sfc_nhead : 4; /* number of heads */ ! 80: u_char sfc_secsize; /* sector size / 256 */ ! 81: u_char sfc_uload; /* head unload time in 1/10 sec */ ! 82: u_char sfc_spt; /* sectors per track */ ! 83: u_char sfc_record; /* recording density code */ ! 84: }; ! 85: ! 86: /* ! 87: * track switching codes ! 88: */ ! 89: #define TS_6MSEC 0 /* 6 msec */ ! 90: #define TS_12MSEC 1 /* 12 msec */ ! 91: #define TS_20MSEC 2 /* 20 msec */ ! 92: #define TS_30MSEC 3 /* 30 msec */ ! 93: ! 94: /* ! 95: * recording density codes ! 96: */ ! 97: #define SDENSITY 0x00 /* single denisity */ ! 98: #define DDENSITY 0xC0 /* double density */ ! 99: ! 100: static struct sf_characteristics default_characteristics = { ! 101: 40, ! 102: TS_6MSEC, ! 103: 500, ! 104: 5, ! 105: 2, ! 106: PC_SECSIZE/256, ! 107: 10, ! 108: 9, ! 109: DDENSITY ! 110: }; ! 111: ! 112: static struct sf_characteristics current_characteristics; ! 113: ! 114: /* ! 115: * Return a pointer to this unit's unit structure. ! 116: */ ! 117: sfunitptr(md) ! 118: register struct mb_device *md; ! 119: { ! 120: return ((int)&sfunits[md->md_unit]); ! 121: } ! 122: ! 123: /* ! 124: * Attach device (boot time). ! 125: */ ! 126: sfattach(md) ! 127: register struct mb_device *md; ! 128: { ! 129: register struct scsi_unit *un; ! 130: ! 131: un = &sfunits[md->md_unit]; ! 132: un->un_md = md; ! 133: un->un_mc = md->md_mc; ! 134: un->un_unit = md->md_unit; ! 135: un->un_target = TARGET(md->md_slave); ! 136: un->un_lun = LUN(md->md_slave); ! 137: un->un_ss = &scsi_unit_subr[TYPE(md->md_flags)]; ! 138: } ! 139: ! 140: static int ! 141: getlabel(dev) ! 142: register dev_t dev; ! 143: { ! 144: register struct scsi_unit *un; ! 145: register char *bufp; ! 146: register struct scsi_floppy *dsi; ! 147: char c; ! 148: ! 149: un = &sfunits[SFUNIT(dev)]; ! 150: dsi = &sfloppy[SFUNIT(dev)]; ! 151: /* ! 152: * We don't want multiple opens going on at the same time. ! 153: */ ! 154: while (dsi->sf_flags & SF_LABELGET) { ! 155: dsi->sf_flags |= SF_LABELWANT; ! 156: sleep((caddr_t)dsi, PRIBIO); ! 157: if (un->un_present) ! 158: return (1); ! 159: } ! 160: dsi->sf_flags |= SF_LABELGET; ! 161: dsi->sf_nblk = 8; ! 162: dsi->sf_spt = 8; ! 163: dsi->sf_nhead = 1; ! 164: if (sfcmd(dev, SC_TEST_UNIT_READY, 0, 0, (caddr_t)0)) { ! 165: uprintf("sf%d: not online\n", SFNUM(un)); ! 166: goto out; ! 167: } ! 168: if (sfcmd(dev, SC_INIT_CHARACTERISTICS, 0, ! 169: sizeof(default_characteristics), ! 170: (caddr_t)&default_characteristics) ) { ! 171: uprintf("sf%d: cannot init drive\n", SFNUM(un)); ! 172: goto out; ! 173: } ! 174: bufp = kmem_alloc(PC_SECSIZE); ! 175: if (sfcmd(dev, SC_READ, PC_FATBLOCK, PC_SECSIZE, bufp)) { ! 176: uprintf("sf%d: error reading label\n", SFNUM(un)); ! 177: kmem_free(bufp, PC_SECSIZE); ! 178: goto out; ! 179: } ! 180: dsi->sf_mdb = bufp[0]; ! 181: c = bufp[1] & bufp[2]; ! 182: kmem_free(bufp, PC_SECSIZE); ! 183: if (c != 0xFF) { ! 184: uprintf("sf%d: bad label\n", SFNUM(un)); ! 185: goto out; ! 186: } ! 187: switch (dsi->sf_mdb) { ! 188: case SS8SPT: ! 189: dsi->sf_spt = 8; ! 190: dsi->sf_nhead = 1; ! 191: dsi->sf_nblk = 320; ! 192: break; ! 193: ! 194: case DS8SPT: ! 195: dsi->sf_spt = 8; ! 196: dsi->sf_nhead = 2; ! 197: dsi->sf_nblk = 640; ! 198: break; ! 199: ! 200: case SS9SPT: ! 201: dsi->sf_spt = 9; ! 202: dsi->sf_nhead = 1; ! 203: dsi->sf_nblk = 360; ! 204: break; ! 205: ! 206: case DS9SPT: ! 207: dsi->sf_spt = 9; ! 208: dsi->sf_nhead = 2; ! 209: dsi->sf_nblk = 720; ! 210: break; ! 211: ! 212: default: ! 213: uprintf("sf%d: bad label\n", SFNUM(un)); ! 214: goto out; ! 215: } ! 216: current_characteristics = default_characteristics; ! 217: current_characteristics.sfc_spt = dsi->sf_spt; ! 218: current_characteristics.sfc_nhead = dsi->sf_nhead; ! 219: if (sfcmd(dev, SC_INIT_CHARACTERISTICS, 0, ! 220: sizeof(current_characteristics), ! 221: (caddr_t)¤t_characteristics)) { ! 222: uprintf("sf%d: cannot reinit drive\n", SFNUM(un)); ! 223: } else { ! 224: un->un_present = 1; ! 225: } ! 226: out: ! 227: dsi->sf_flags &= ~SF_LABELGET; ! 228: if (dsi->sf_flags & SF_LABELWANT) { ! 229: dsi->sf_flags &= ~SF_LABELWANT; ! 230: wakeup((caddr_t)dsi); ! 231: } ! 232: return (un->un_present); ! 233: } ! 234: ! 235: /*ARGSUSED*/ ! 236: sfopen(dev, flag) ! 237: dev_t dev; ! 238: int flag; ! 239: { ! 240: register struct scsi_unit *un; ! 241: register int unit; ! 242: ! 243: unit = SFUNIT(dev); ! 244: if (unit >= nsfloppy) { ! 245: return (ENXIO); ! 246: } ! 247: un = &sfunits[unit]; ! 248: if (un->un_mc == 0) { /* never attached */ ! 249: return (ENXIO); ! 250: } ! 251: if (!un->un_present) { ! 252: if (!getlabel(dev)) { ! 253: return (EIO); ! 254: } ! 255: } ! 256: return (0); ! 257: } ! 258: ! 259: /*ARGSUSED*/ ! 260: sfclose(dev, flag) ! 261: dev_t dev; ! 262: int flag; ! 263: { ! 264: register struct scsi_unit *un; ! 265: ! 266: un = &sfunits[SFUNIT(dev)]; ! 267: /* ! 268: * make the driver get the label again on the next open ! 269: */ ! 270: un->un_present = 0; ! 271: } ! 272: ! 273: sfsize(dev) ! 274: register dev_t dev; ! 275: { ! 276: register struct scsi_unit *un; ! 277: ! 278: un = &sfunits[SFUNIT(dev)]; ! 279: if (!un->un_present) { ! 280: return (-1); ! 281: } ! 282: return (sfloppy[SFUNIT(dev)].sf_nblk); ! 283: } ! 284: ! 285: sfstrategy(bp) ! 286: register struct buf *bp; ! 287: { ! 288: register struct scsi_unit *un; ! 289: register daddr_t bn; ! 290: register int unit, s; ! 291: register struct buf *dp; ! 292: register struct scsi_floppy *dsi; ! 293: ! 294: unit = SFUNIT(bp->b_dev); ! 295: if (unit >= nsfloppy) { ! 296: printf("sf%d: sfstrategy: invalid unit\n", unit); ! 297: bp->b_flags |= B_ERROR; ! 298: iodone(bp); ! 299: return; ! 300: } ! 301: un = &sfunits[unit]; ! 302: dsi = &sfloppy[unit]; ! 303: bn = dkblock(bp); ! 304: if ((!un->un_present && bp != &un->un_sbuf) || (bn > dsi->sf_nblk)) { ! 305: bp->b_flags |= B_ERROR; ! 306: iodone(bp); ! 307: return; ! 308: } ! 309: if (un->un_present) { ! 310: if (bn == dsi->sf_nblk) { /* EOF */ ! 311: bp->b_resid = bp->b_bcount; ! 312: iodone(bp); ! 313: return; ! 314: } ! 315: bp->b_cylin = bn / (dsi->sf_spt * dsi->sf_nhead); ! 316: } else { ! 317: bp->b_cylin = 0; ! 318: } ! 319: dp = &un->un_utab; ! 320: s = splx(pritospl(un->un_mc->mc_intpri)); ! 321: disksort(dp, bp); ! 322: if (dp->b_active == 0) { ! 323: (*un->un_c->c_ss->scs_ustart)(un); ! 324: bp = &un->un_mc->mc_tab; ! 325: if (bp->b_actf && bp->b_active == 0) { ! 326: (*un->un_c->c_ss->scs_start)(un); ! 327: } ! 328: } ! 329: (void) splx(s); ! 330: } ! 331: ! 332: /* ! 333: * Do a special command. ! 334: */ ! 335: sfcmd(dev, cmd, sector, len, addr) ! 336: register dev_t dev; ! 337: register int cmd, sector, len; ! 338: register caddr_t addr; ! 339: { ! 340: register struct scsi_unit *un; ! 341: register struct buf *bp; ! 342: register int s; ! 343: ! 344: un = &sfunits[SFUNIT(dev)]; ! 345: bp = &un->un_sbuf; ! 346: s = splx(pritospl(un->un_mc->mc_intpri)); ! 347: while (bp->b_flags&B_BUSY) { ! 348: bp->b_flags |= B_WANTED; ! 349: sleep((caddr_t)bp, PRIBIO); ! 350: } ! 351: bp->b_flags = B_BUSY|B_READ; ! 352: (void) splx(s); ! 353: un->un_scmd = cmd; ! 354: bp->b_dev = dev; ! 355: bp->b_blkno = sector; ! 356: bp->b_un.b_addr = addr; ! 357: bp->b_bcount = len; ! 358: sfstrategy(bp); ! 359: iowait(bp); ! 360: bp->b_flags &= ~B_BUSY; ! 361: if (bp->b_flags&B_WANTED) ! 362: wakeup((caddr_t)bp); ! 363: return (bp->b_flags & B_ERROR); ! 364: } ! 365: ! 366: /* ! 367: * Set up a transfer for the controller ! 368: */ ! 369: sfstart(bp, un) ! 370: register struct buf *bp; ! 371: register struct scsi_unit *un; ! 372: { ! 373: register int nblk; ! 374: register struct scsi_floppy *dsi; ! 375: ! 376: dsi = &sfloppy[SFUNIT(bp->b_dev)]; ! 377: un->un_blkno = dkblock(bp); ! 378: if (bp == &un->un_sbuf) { ! 379: un->un_cmd = un->un_scmd; ! 380: } else if (bp->b_flags & B_READ) { ! 381: un->un_cmd = SC_READ; ! 382: } else { ! 383: un->un_cmd = SC_WRITE; ! 384: } ! 385: if (un->un_cmd == SC_READ || un->un_cmd == SC_WRITE) { ! 386: nblk = howmany(bp->b_bcount, PC_SECSIZE); ! 387: un->un_count = MIN(nblk, dsi->sf_nblk - bp->b_blkno); ! 388: bp->b_resid = bp->b_bcount - un->un_count * PC_SECSIZE; ! 389: un->un_flags |= SC_UNF_DVMA; ! 390: } else { ! 391: if (un->un_cmd == SC_INIT_CHARACTERISTICS) ! 392: un->un_flags |= SC_UNF_DVMA; ! 393: un->un_count = bp->b_bcount; ! 394: } ! 395: return (1); ! 396: } ! 397: ! 398: /* ! 399: * Make a cdb for disk i/o. ! 400: */ ! 401: sfmkcdb(c, un) ! 402: register struct scsi_ctlr *c; ! 403: struct scsi_unit *un; ! 404: { ! 405: register struct scsi_cdb *cdb; ! 406: ! 407: cdb = &c->c_cdb; ! 408: bzero((caddr_t)cdb, sizeof (*cdb)); ! 409: un->un_dma_addr = 0; ! 410: un->un_dma_count = 0; ! 411: cdb->cmd = un->un_cmd; ! 412: cdb->lun = un->un_lun; ! 413: switch (un->un_cmd) { ! 414: case SC_TEST_UNIT_READY: ! 415: case SC_REZERO_UNIT: ! 416: case SC_REQUEST_SENSE: ! 417: break; ! 418: case SC_SEEK: ! 419: cdbaddr(cdb, un->un_blkno); ! 420: break; ! 421: case SC_READ: ! 422: case SC_WRITE: ! 423: cdbaddr(cdb, un->un_blkno); ! 424: cdb->count = un->un_count; ! 425: un->un_dma_addr = un->un_baddr; ! 426: un->un_dma_count = un->un_count * PC_SECSIZE; ! 427: break; ! 428: case SC_INIT_CHARACTERISTICS: ! 429: un->un_dma_addr = un->un_baddr; ! 430: un->un_dma_count = un->un_count; ! 431: break; ! 432: default: ! 433: panic("sfmkcdb"); ! 434: break; ! 435: } ! 436: } ! 437: ! 438: /* ! 439: * Interrupt processing. ! 440: */ ! 441: sfintr(c, resid, error) ! 442: register struct scsi_ctlr *c; ! 443: register int resid, error; ! 444: { ! 445: register struct scsi_unit *un; ! 446: register struct buf *bp; ! 447: register struct mb_device *md; ! 448: ! 449: un = c->c_un; ! 450: bp = un->un_mc->mc_tab.b_actf->b_actf; ! 451: md = un->un_md; ! 452: if (md->md_dk >= 0) { ! 453: dk_busy &= ~(1 << md->md_dk); ! 454: } ! 455: if (error == SE_FATAL) { ! 456: if (bp == &un->un_sbuf && ! 457: ((un->un_flags & SC_UNF_DVMA) == 0)) { ! 458: (*c->c_ss->scs_done)(un->un_mc); ! 459: } else { ! 460: mbdone(un->un_mc); ! 461: un->un_flags &= ~SC_UNF_DVMA; ! 462: } ! 463: bp->b_flags |= B_ERROR; ! 464: printf("sf%d: SCSI FAILURE\n", SFNUM(un)); ! 465: (*c->c_ss->scs_off)(un); ! 466: return; ! 467: } ! 468: if (error == SE_RETRYABLE || c->c_scb.chk || resid > 0) { ! 469: sferror(c, un, bp); ! 470: return; ! 471: } ! 472: if (c->c_cdb.cmd == SC_REZERO_UNIT && ! 473: !(bp == &un->un_sbuf && ! 474: un->un_scmd == SC_REZERO_UNIT)) { ! 475: /* error recovery */ ! 476: sfmkcdb(c, un); ! 477: if ((*c->c_ss->scs_cmd)(c, un, 1) == 0) { ! 478: printf("sf%d sfintr: scsi cmd failed 1\n", SFNUM(un)); ! 479: (*c->c_ss->scs_off)(un); ! 480: } ! 481: return; ! 482: } ! 483: /* transfer worked */ ! 484: un->un_retries = un->un_restores = 0; ! 485: if (un->un_sec_left) { /* single sector stuff */ ! 486: un->un_sec_left--; ! 487: un->un_baddr += PC_SECSIZE; ! 488: un->un_blkno++; ! 489: sfmkcdb(c, un); ! 490: if ((*c->c_ss->scs_cmd)(c, un, 1) == 0) { ! 491: printf("sf%d: sfintr: scsi cmd failed 2\n", SFNUM(un)); ! 492: (*c->c_ss->scs_off)(un); ! 493: } ! 494: } else if (bp == &un->un_sbuf && ! 495: ((un->un_flags & SC_UNF_DVMA) == 0)) { ! 496: (*c->c_ss->scs_done)(un->un_mc); ! 497: } else { ! 498: mbdone(un->un_mc); ! 499: un->un_flags &= ~SC_UNF_DVMA; ! 500: } ! 501: } ! 502: ! 503: /* ! 504: * Error handling. ! 505: */ ! 506: sferror(c, un, bp) ! 507: register struct scsi_ctlr *c; ! 508: register struct scsi_unit *un; ! 509: register struct buf *bp; ! 510: { ! 511: ! 512: if (un->un_present == 0) { /* error trying to open */ ! 513: bp->b_flags |= B_ERROR; ! 514: if (bp == &un->un_sbuf && ! 515: ((un->un_flags & SC_UNF_DVMA) == 0)) { ! 516: (*c->c_ss->scs_done)(un->un_mc); ! 517: } else { ! 518: mbdone(un->un_mc); ! 519: un->un_flags &= ~SC_UNF_DVMA; ! 520: } ! 521: } else if (un->un_retries++ < MAX_RETRIES) { ! 522: /* retry */ ! 523: if (sferrlvl >= EL_RETRY) { ! 524: sferrmsg(c, un, bp, "retry"); ! 525: } ! 526: if ((*c->c_ss->scs_cmd)(c, un, 1) == 0) { ! 527: printf("sf%d: sferror: scsi cmd failed 2\n", SFNUM(un)); ! 528: (*c->c_ss->scs_off)(un); ! 529: } ! 530: } else if (un->un_restores++ < MAX_RESTORES) { ! 531: /* retries exhausted, try restore */ ! 532: un->un_retries = 0; ! 533: if (sferrlvl >= EL_REST) { ! 534: sferrmsg(c, un, bp, "restore"); ! 535: } ! 536: c->c_cdb.cmd = SC_REZERO_UNIT; ! 537: cdbaddr(&c->c_cdb, 0); ! 538: c->c_cdb.count = 0; ! 539: un->un_dma_addr = un->un_dma_count = 0; ! 540: if ((*c->c_ss->scs_cmd)(c, un, 1) == 0) { ! 541: printf("sf%d: sferror: scsi cmd failed 3\n", SFNUM(un)); ! 542: (*c->c_ss->scs_off)(un); ! 543: } ! 544: } else { ! 545: /* complete failure */ ! 546: if (sferrlvl >= EL_FAIL) { ! 547: sferrmsg(c, un, bp, "failed"); ! 548: } ! 549: (*c->c_ss->scs_off)(un); ! 550: bp->b_flags |= B_ERROR; ! 551: if (bp == &un->un_sbuf && ! 552: ((un->un_flags & SC_UNF_DVMA) == 0)) { ! 553: (*c->c_ss->scs_done)(un->un_mc); ! 554: } else { ! 555: mbdone(un->un_mc); ! 556: un->un_flags &= ~SC_UNF_DVMA; ! 557: } ! 558: } ! 559: } ! 560: ! 561: sfread(dev, uio) ! 562: dev_t dev; ! 563: struct uio *uio; ! 564: { ! 565: ! 566: return (sfrw(dev, uio, B_READ)); ! 567: } ! 568: ! 569: sfrw(dev, uio, direction) ! 570: dev_t dev; ! 571: struct uio *uio; ! 572: int direction; ! 573: { ! 574: register struct scsi_unit *un; ! 575: register int unit; ! 576: ! 577: unit = SFUNIT(dev); ! 578: if (unit >= nsfloppy) { ! 579: return (ENXIO); ! 580: } ! 581: un = &sfunits[unit]; ! 582: if ((uio->uio_offset % DEV_BSIZE) != 0) { ! 583: return (EINVAL); ! 584: } ! 585: if ((uio->uio_iov->iov_len % DEV_BSIZE) != 0) { ! 586: return (EINVAL); ! 587: } ! 588: return (physio(sfstrategy, &un->un_rbuf, dev, direction, minphys,uio)); ! 589: } ! 590: ! 591: sfwrite(dev, uio) ! 592: dev_t dev; ! 593: struct uio *uio; ! 594: { ! 595: ! 596: return (sfrw(dev, uio, B_WRITE)); ! 597: } ! 598: ! 599: /*ARGSUSED*/ ! 600: sfioctl(dev, cmd, data, flag) ! 601: register dev_t dev; ! 602: register caddr_t data; ! 603: { ! 604: register struct scsi_unit *un; ! 605: register struct dk_info *inf; ! 606: register int unit; ! 607: ! 608: unit = SFUNIT(dev); ! 609: if (unit >= nsfloppy) { ! 610: return (ENXIO); ! 611: } ! 612: un = &sfunits[unit]; ! 613: switch (cmd) { ! 614: ! 615: case DKIOCINFO: ! 616: inf = (struct dk_info *)data; ! 617: inf->dki_ctlr = getdevaddr(un->un_mc->mc_addr); ! 618: inf->dki_unit = un->un_md->md_slave; ! 619: inf->dki_ctype = DKC_SCSI; ! 620: inf->dki_flags = DKI_FMTVOL; ! 621: break; ! 622: ! 623: default: ! 624: return (ENOTTY); ! 625: } ! 626: return (0); ! 627: } ! 628: ! 629: static char *sf_class_00_errors[] = { ! 630: "invalid sense code", ! 631: "invalid sense code", ! 632: "no seek complete", ! 633: "invalid sense code", ! 634: "drive not ready", ! 635: "invalid sense code", ! 636: "no track 00", ! 637: "door open", ! 638: "media not loaded", ! 639: }; ! 640: ! 641: static char *sf_class_01_errors[] = { ! 642: "I.D. CRC error", ! 643: "write fault", ! 644: "write protected", ! 645: "invalid sense code", ! 646: "sector not found", ! 647: "seek error", ! 648: "(0x16) unformatted or bad format on drive", ! 649: "(0x17) unformatted or bad format on drive", ! 650: "invalid sense code", ! 651: "two sided error", ! 652: "wrong data mark found", ! 653: "pad error", ! 654: "invalid sense code", ! 655: "lost data in FDC", ! 656: "CRC error", ! 657: "FDC failure", ! 658: }; ! 659: ! 660: static char *sf_class_02_errors[] = { ! 661: "invalid command", ! 662: "illegal block address", ! 663: "invalid cdb", ! 664: "invalid interleave", ! 665: }; ! 666: ! 667: static char *sf_class_03_errors[] = { ! 668: "RAM error", ! 669: "controller program memory checksum error", ! 670: }; ! 671: ! 672: static char **sf_errors[] = { ! 673: sf_class_00_errors, ! 674: sf_class_01_errors, ! 675: sf_class_02_errors, ! 676: sf_class_03_errors, ! 677: }; ! 678: ! 679: int sf_errct[] = { ! 680: sizeof sf_class_00_errors / sizeof (char *), ! 681: sizeof sf_class_01_errors / sizeof (char *), ! 682: sizeof sf_class_02_errors / sizeof (char *), ! 683: sizeof sf_class_03_errors / sizeof (char *), ! 684: }; ! 685: ! 686: char *sf_cmds[] = { ! 687: "test unit ready", ! 688: "rezero unit", ! 689: "bad cmd", ! 690: "request sense", ! 691: "bad cmd", ! 692: "bad cmd", ! 693: "bad cmd", ! 694: "bad cmd", ! 695: "read", ! 696: "bad cmd", ! 697: "write", ! 698: "seek", ! 699: "initialize characteristics", ! 700: }; ! 701: ! 702: /*ARGSUSED*/ ! 703: sferrmsg(c, un, bp, action) ! 704: register struct scsi_ctlr *c; ! 705: struct scsi_unit *un; ! 706: struct buf *bp; ! 707: char *action; ! 708: { ! 709: char *sensemsg, *cmdname; ! 710: register struct scsi_sense *sense; ! 711: register int blkno; ! 712: ! 713: sense = c->c_sense; ! 714: if (c->c_scb.chk == 0) { ! 715: sensemsg = "invalid sense code"; ! 716: } else if (sense->class <= 3) { ! 717: if (sense->code < sf_errct[sense->class]) { ! 718: sensemsg = sf_errors[sense->class][sense->code]; ! 719: } else { ! 720: sensemsg = "invalid sense code"; ! 721: } ! 722: } else { ! 723: sensemsg = "invalid sense class"; ! 724: } ! 725: if (un->un_cmd < sizeof(sf_cmds)) { ! 726: cmdname = sf_cmds[un->un_cmd]; ! 727: } else { ! 728: cmdname = "bad cmd"; ! 729: } ! 730: blkno = (sense->high_addr << 16) | (sense->mid_addr << 8) | ! 731: sense->low_addr; ! 732: printf("sf%d: %s %s (%s) blk %d\n", SFNUM(un), ! 733: cmdname, action, sensemsg, blkno); ! 734: } ! 735: #endif NSF > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.