|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1990 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Van Jacobson of Lawrence Berkeley Laboratory. ! 7: * ! 8: * Redistribution is only permitted until one year after the first shipment ! 9: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 10: * binary forms are permitted provided that: (1) source distributions retain ! 11: * this entire copyright notice and comment, and (2) distributions including ! 12: * binaries display the following acknowledgement: This product includes ! 13: * software developed by the University of California, Berkeley and its ! 14: * contributors'' in the documentation or other materials provided with the ! 15: * distribution and in all advertising materials mentioning features or use ! 16: * of this software. Neither the name of the University nor the names of ! 17: * its contributors may be used to endorse or promote products derived from ! 18: * this software without specific prior written permission. ! 19: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 20: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 21: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 22: * ! 23: * @(#)sd.c 7.2 (Berkeley) 5/15/90 ! 24: */ ! 25: ! 26: /* ! 27: * SCSI CCS (Command Command Set) disk driver. ! 28: */ ! 29: #include "sd.h" ! 30: #if NSD > 0 ! 31: ! 32: #ifndef lint ! 33: static char rcsid[] = "$Header: sd.c,v 1.5 90/01/10 16:06:12 mike Locked $"; ! 34: #endif ! 35: ! 36: #include "param.h" ! 37: #include "systm.h" ! 38: #include "buf.h" ! 39: #include "errno.h" ! 40: #include "dkstat.h" ! 41: #include "disklabel.h" ! 42: #include "device.h" ! 43: #include "malloc.h" ! 44: #include "scsireg.h" ! 45: ! 46: #include "user.h" ! 47: #include "proc.h" ! 48: #include "uio.h" ! 49: ! 50: extern int scsi_test_unit_rdy(); ! 51: extern int scsi_request_sense(); ! 52: extern int scsi_inquiry(); ! 53: extern int scsi_read_capacity(); ! 54: extern int scsi_tt_write(); ! 55: extern int scsireq(); ! 56: extern int scsiustart(); ! 57: extern int scsigo(); ! 58: extern void scsifree(); ! 59: extern void scsireset(); ! 60: ! 61: extern void printf(); ! 62: extern void bcopy(); ! 63: extern void disksort(); ! 64: extern int splbio(); ! 65: extern void splx(); ! 66: extern void biodone(); ! 67: extern int physio(); ! 68: extern void TBIS(); ! 69: ! 70: int sdinit(); ! 71: void sdstrategy(), sdstart(), sdustart(), sdgo(), sdintr(); ! 72: ! 73: struct driver sddriver = { ! 74: sdinit, "sd", (int (*)())sdstart, (int (*)())sdgo, (int (*)())sdintr, ! 75: }; ! 76: ! 77: struct size { ! 78: u_long strtblk; ! 79: u_long endblk; ! 80: int nblocks; ! 81: }; ! 82: ! 83: struct sdinfo { ! 84: struct size part[8]; ! 85: }; ! 86: ! 87: /* ! 88: * since the SCSI standard tends to hide the disk structure, we define ! 89: * partitions in terms of DEV_BSIZE blocks. The default partition table ! 90: * (for an unlabeled disk) reserves 512K for a boot area, has an 8 meg ! 91: * root and 32 meg of swap. The rest of the space on the drive goes in ! 92: * the G partition. As usual, the C partition covers the entire disk ! 93: * (including the boot area). ! 94: */ ! 95: struct sdinfo sddefaultpart = { ! 96: 1024, 17408, 16384 , /* A */ ! 97: 17408, 82944, 65536 , /* B */ ! 98: 0, 0, 0 , /* C */ ! 99: 17408, 115712, 98304 , /* D */ ! 100: 115712, 218112, 102400 , /* E */ ! 101: 218112, 0, 0 , /* F */ ! 102: 82944, 0, 0 , /* G */ ! 103: 115712, 0, 0 , /* H */ ! 104: }; ! 105: ! 106: struct sd_softc { ! 107: struct hp_device *sc_hd; ! 108: struct devqueue sc_dq; ! 109: int sc_format_pid; /* process using "format" mode */ ! 110: short sc_flags; ! 111: short sc_type; /* drive type */ ! 112: short sc_punit; /* physical unit (scsi lun) */ ! 113: u_short sc_bshift; /* convert device blocks to DEV_BSIZE blks */ ! 114: u_int sc_blks; /* number of blocks on device */ ! 115: int sc_blksize; /* device block size in bytes */ ! 116: u_int sc_wpms; /* average xfer rate in 16 bit wds/sec. */ ! 117: struct sdinfo sc_info; /* drive partition table & label info */ ! 118: } sd_softc[NSD]; ! 119: ! 120: /* sc_flags values */ ! 121: #define SDF_ALIVE 0x1 ! 122: ! 123: #ifdef DEBUG ! 124: int sddebug = 1; ! 125: #define SDB_ERROR 0x01 ! 126: #define SDB_PARTIAL 0x02 ! 127: #endif ! 128: ! 129: struct sdstats { ! 130: long sdresets; ! 131: long sdtransfers; ! 132: long sdpartials; ! 133: } sdstats[NSD]; ! 134: ! 135: struct buf sdtab[NSD]; ! 136: struct buf sdbuf[NSD]; ! 137: struct scsi_fmt_cdb sdcmd[NSD]; ! 138: struct scsi_fmt_sense sdsense[NSD]; ! 139: ! 140: static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT }; ! 141: static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT }; ! 142: ! 143: #define sdunit(x) ((minor(x) >> 3) & 0x7) ! 144: #define sdpart(x) (minor(x) & 0x7) ! 145: #define sdpunit(x) ((x) & 7) ! 146: #define b_cylin b_resid ! 147: #define SDRETRY 2 ! 148: ! 149: /* ! 150: * Table of scsi commands users are allowed to access via "format" ! 151: * mode. 0 means not legal. 1 means "immediate" (doesn't need dma). ! 152: * -1 means needs dma and/or wait for intr. ! 153: */ ! 154: static char legal_cmds[256] = { ! 155: /***** 0 1 2 3 4 5 6 7 8 9 A B C D E F */ ! 156: /*00*/ 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 157: /*10*/ 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, ! 158: /*20*/ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 159: /*30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 160: /*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 161: /*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 162: /*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 163: /*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 164: /*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 165: /*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 166: /*a0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 167: /*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 168: /*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 169: /*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 170: /*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 171: /*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 172: }; ! 173: ! 174: static struct scsi_inquiry inqbuf; ! 175: static struct scsi_fmt_cdb inq = { ! 176: 6, ! 177: CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0 ! 178: }; ! 179: ! 180: static u_char capbuf[8]; ! 181: struct scsi_fmt_cdb cap = { ! 182: 10, ! 183: CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 ! 184: }; ! 185: ! 186: static int ! 187: sdident(sc, hd) ! 188: struct sd_softc *sc; ! 189: struct hp_device *hd; ! 190: { ! 191: int unit; ! 192: register int ctlr, slave; ! 193: register int i; ! 194: register int tries = 10; ! 195: ! 196: ctlr = hd->hp_ctlr; ! 197: slave = hd->hp_slave; ! 198: unit = sc->sc_punit; ! 199: ! 200: /* ! 201: * See if unit exists and is a disk then read block size & nblocks. ! 202: */ ! 203: while ((i = scsi_test_unit_rdy(ctlr, slave, unit)) != 0) { ! 204: if (i == -1 || --tries < 0) ! 205: /* doesn't exist or not a CCS device */ ! 206: return (-1); ! 207: if (i == STS_CHECKCOND) { ! 208: u_char sensebuf[128]; ! 209: struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf; ! 210: ! 211: scsi_request_sense(ctlr, slave, unit, sensebuf, ! 212: sizeof(sensebuf)); ! 213: if (sp->class == 7 && sp->key == 6) ! 214: /* drive doing an RTZ -- give it a while */ ! 215: DELAY(1000000); ! 216: } ! 217: DELAY(1000); ! 218: } ! 219: if (scsi_immed_command(ctlr, slave, unit, &inq, (u_char *)&inqbuf, ! 220: sizeof(inqbuf), B_READ) || ! 221: scsi_immed_command(ctlr, slave, unit, &cap, (u_char *)&capbuf, ! 222: sizeof(capbuf), B_READ)) ! 223: /* doesn't exist or not a CCS device */ ! 224: return (-1); ! 225: ! 226: switch (inqbuf.type) { ! 227: case 0: /* disk */ ! 228: case 4: /* WORM */ ! 229: case 5: /* CD-ROM */ ! 230: case 7: /* Magneto-optical */ ! 231: break; ! 232: default: /* not a disk */ ! 233: return (-1); ! 234: } ! 235: sc->sc_blks = *(u_int *)&capbuf[0]; ! 236: sc->sc_blksize = *(int *)&capbuf[4]; ! 237: ! 238: if (inqbuf.version != 1) ! 239: printf("sd%d: type 0x%x, qual 0x%x, ver %d", hd->hp_unit, ! 240: inqbuf.type, inqbuf.qual, inqbuf.version); ! 241: else { ! 242: char idstr[32]; ! 243: ! 244: bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28); ! 245: for (i = 27; i > 23; --i) ! 246: if (idstr[i] != ' ') ! 247: break; ! 248: idstr[i+1] = 0; ! 249: for (i = 23; i > 7; --i) ! 250: if (idstr[i] != ' ') ! 251: break; ! 252: idstr[i+1] = 0; ! 253: for (i = 7; i >= 0; --i) ! 254: if (idstr[i] != ' ') ! 255: break; ! 256: idstr[i+1] = 0; ! 257: printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8], ! 258: &idstr[24]); ! 259: } ! 260: printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize); ! 261: if (sc->sc_blksize != DEV_BSIZE) { ! 262: if (sc->sc_blksize < DEV_BSIZE) { ! 263: printf("sd%d: need %d byte blocks - drive ignored\n", ! 264: unit, DEV_BSIZE); ! 265: return (-1); ! 266: } ! 267: for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1) ! 268: ++sc->sc_bshift; ! 269: sc->sc_blks <<= sc->sc_bshift; ! 270: } ! 271: sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2); /* XXX */ ! 272: return(inqbuf.type); ! 273: } ! 274: ! 275: int ! 276: sdinit(hd) ! 277: register struct hp_device *hd; ! 278: { ! 279: register struct sd_softc *sc = &sd_softc[hd->hp_unit]; ! 280: ! 281: sc->sc_hd = hd; ! 282: sc->sc_punit = sdpunit(hd->hp_flags); ! 283: sc->sc_type = sdident(sc, hd); ! 284: if (sc->sc_type < 0) ! 285: return(0); ! 286: sc->sc_dq.dq_ctlr = hd->hp_ctlr; ! 287: sc->sc_dq.dq_unit = hd->hp_unit; ! 288: sc->sc_dq.dq_slave = hd->hp_slave; ! 289: sc->sc_dq.dq_driver = &sddriver; ! 290: ! 291: /* ! 292: * If we don't have a disk label, build a default partition ! 293: * table with 'standard' size root & swap and everything else ! 294: * in the G partition. ! 295: */ ! 296: sc->sc_info = sddefaultpart; ! 297: /* C gets everything */ ! 298: sc->sc_info.part[2].nblocks = sc->sc_blks; ! 299: sc->sc_info.part[2].endblk = sc->sc_blks; ! 300: /* G gets from end of B to end of disk */ ! 301: sc->sc_info.part[6].nblocks = sc->sc_blks - sc->sc_info.part[1].endblk; ! 302: sc->sc_info.part[6].endblk = sc->sc_blks; ! 303: /* ! 304: * We also define the D, E and F paritions as an alternative to ! 305: * B and G. D is 48Mb, starts after A and is intended for swapping. ! 306: * E is 50Mb, starts after D and is intended for /usr. F starts ! 307: * after E and is what ever is left. ! 308: */ ! 309: if (sc->sc_blks >= sc->sc_info.part[4].endblk) { ! 310: sc->sc_info.part[5].nblocks = ! 311: sc->sc_blks - sc->sc_info.part[4].endblk; ! 312: sc->sc_info.part[5].endblk = sc->sc_blks; ! 313: } else { ! 314: sc->sc_info.part[5].strtblk = 0; ! 315: sc->sc_info.part[3] = sc->sc_info.part[5]; ! 316: sc->sc_info.part[4] = sc->sc_info.part[5]; ! 317: } ! 318: /* ! 319: * H is a single partition alternative to E and F. ! 320: */ ! 321: if (sc->sc_blks >= sc->sc_info.part[3].endblk) { ! 322: sc->sc_info.part[7].nblocks = ! 323: sc->sc_blks - sc->sc_info.part[3].endblk; ! 324: sc->sc_info.part[7].endblk = sc->sc_blks; ! 325: } else { ! 326: sc->sc_info.part[7].strtblk = 0; ! 327: } ! 328: ! 329: sc->sc_flags = SDF_ALIVE; ! 330: return(1); ! 331: } ! 332: ! 333: void ! 334: sdreset(sc, hd) ! 335: register struct sd_softc *sc; ! 336: register struct hp_device *hd; ! 337: { ! 338: sdstats[hd->hp_unit].sdresets++; ! 339: } ! 340: ! 341: int ! 342: sdopen(dev, flags) ! 343: dev_t dev; ! 344: int flags; ! 345: { ! 346: register int unit = sdunit(dev); ! 347: register struct sd_softc *sc = &sd_softc[unit]; ! 348: ! 349: if (unit >= NSD) ! 350: return(ENXIO); ! 351: if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(u.u_cred, &u.u_acflag)) ! 352: return(ENXIO); ! 353: ! 354: if (sc->sc_hd->hp_dk >= 0) ! 355: dk_wpms[sc->sc_hd->hp_dk] = sc->sc_wpms; ! 356: return(0); ! 357: } ! 358: ! 359: /* ! 360: * This routine is called for partial block transfers and non-aligned ! 361: * transfers (the latter only being possible on devices with a block size ! 362: * larger than DEV_BSIZE). The operation is performed in three steps ! 363: * using a locally allocated buffer: ! 364: * 1. transfer any initial partial block ! 365: * 2. transfer full blocks ! 366: * 3. transfer any final partial block ! 367: */ ! 368: static void ! 369: sdlblkstrat(bp, bsize) ! 370: register struct buf *bp; ! 371: register int bsize; ! 372: { ! 373: register struct buf *cbp = (struct buf *)malloc(sizeof(struct buf), ! 374: M_DEVBUF, M_WAITOK); ! 375: caddr_t cbuf = (caddr_t)malloc(bsize, M_DEVBUF, M_WAITOK); ! 376: register int bn, resid; ! 377: register caddr_t addr; ! 378: ! 379: bzero((caddr_t)cbp, sizeof(*cbp)); ! 380: cbp->b_proc = u.u_procp; ! 381: cbp->b_dev = bp->b_dev; ! 382: bn = bp->b_blkno; ! 383: resid = bp->b_bcount; ! 384: addr = bp->b_un.b_addr; ! 385: #ifdef DEBUG ! 386: if (sddebug & SDB_PARTIAL) ! 387: printf("sdlblkstrat: bp %x flags %x bn %x resid %x addr %x\n", ! 388: bp, bp->b_flags, bn, resid, addr); ! 389: #endif ! 390: ! 391: while (resid > 0) { ! 392: register int boff = dbtob(bn) & (bsize - 1); ! 393: register int count; ! 394: ! 395: if (boff || resid < bsize) { ! 396: sdstats[sdunit(bp->b_dev)].sdpartials++; ! 397: count = MIN(resid, bsize - boff); ! 398: cbp->b_flags = B_BUSY | B_PHYS | B_READ; ! 399: cbp->b_blkno = bn - btodb(boff); ! 400: cbp->b_un.b_addr = cbuf; ! 401: cbp->b_bcount = bsize; ! 402: #ifdef DEBUG ! 403: if (sddebug & SDB_PARTIAL) ! 404: printf(" readahead: bn %x cnt %x off %x addr %x\n", ! 405: cbp->b_blkno, count, boff, addr); ! 406: #endif ! 407: sdstrategy(cbp); ! 408: biowait(cbp); ! 409: if (cbp->b_flags & B_ERROR) { ! 410: bp->b_flags |= B_ERROR; ! 411: bp->b_error = cbp->b_error; ! 412: break; ! 413: } ! 414: if (bp->b_flags & B_READ) { ! 415: bcopy(&cbuf[boff], addr, count); ! 416: goto done; ! 417: } ! 418: bcopy(addr, &cbuf[boff], count); ! 419: #ifdef DEBUG ! 420: if (sddebug & SDB_PARTIAL) ! 421: printf(" writeback: bn %x cnt %x off %x addr %x\n", ! 422: cbp->b_blkno, count, boff, addr); ! 423: #endif ! 424: } else { ! 425: count = resid & ~(bsize - 1); ! 426: cbp->b_blkno = bn; ! 427: cbp->b_un.b_addr = addr; ! 428: cbp->b_bcount = count; ! 429: #ifdef DEBUG ! 430: if (sddebug & SDB_PARTIAL) ! 431: printf(" fulltrans: bn %x cnt %x addr %x\n", ! 432: cbp->b_blkno, count, addr); ! 433: #endif ! 434: } ! 435: cbp->b_flags = B_BUSY | B_PHYS | (bp->b_flags & B_READ); ! 436: sdstrategy(cbp); ! 437: biowait(cbp); ! 438: if (cbp->b_flags & B_ERROR) { ! 439: bp->b_flags |= B_ERROR; ! 440: bp->b_error = cbp->b_error; ! 441: break; ! 442: } ! 443: done: ! 444: bn += btodb(count); ! 445: resid -= count; ! 446: addr += count; ! 447: #ifdef DEBUG ! 448: if (sddebug & SDB_PARTIAL) ! 449: printf(" done: bn %x resid %x addr %x\n", ! 450: bn, resid, addr); ! 451: #endif ! 452: } ! 453: free(cbuf, M_DEVBUF); ! 454: free(cbp, M_DEVBUF); ! 455: } ! 456: ! 457: void ! 458: sdstrategy(bp) ! 459: register struct buf *bp; ! 460: { ! 461: register int part = sdpart(bp->b_dev); ! 462: register int unit = sdunit(bp->b_dev); ! 463: register int bn, sz; ! 464: register struct sd_softc *sc = &sd_softc[unit]; ! 465: register struct buf *dp = &sdtab[unit]; ! 466: register int s; ! 467: ! 468: if (sc->sc_format_pid) { ! 469: if (sc->sc_format_pid != u.u_procp->p_pid) { ! 470: bp->b_error = EPERM; ! 471: goto bad; ! 472: } ! 473: bp->b_cylin = 0; ! 474: } else { ! 475: bn = bp->b_blkno; ! 476: sz = (bp->b_bcount + (DEV_BSIZE - 1)) >> DEV_BSHIFT; ! 477: if (bn < 0 || bn + sz > sc->sc_info.part[part].nblocks) { ! 478: if (bn == sc->sc_info.part[part].nblocks) { ! 479: bp->b_resid = bp->b_bcount; ! 480: goto done; ! 481: } ! 482: bp->b_error = EINVAL; ! 483: goto bad; ! 484: } ! 485: /* ! 486: * Non-aligned or partial-block transfers handled specially. ! 487: */ ! 488: s = sc->sc_blksize - 1; ! 489: if ((dbtob(bn) & s) || (bp->b_bcount & s)) { ! 490: sdlblkstrat(bp, sc->sc_blksize); ! 491: goto done; ! 492: } ! 493: bp->b_cylin = (bn + sc->sc_info.part[part].strtblk) >> ! 494: sc->sc_bshift; ! 495: } ! 496: s = splbio(); ! 497: disksort(dp, bp); ! 498: if (dp->b_active == 0) { ! 499: dp->b_active = 1; ! 500: sdustart(unit); ! 501: } ! 502: splx(s); ! 503: return; ! 504: bad: ! 505: bp->b_flags |= B_ERROR; ! 506: done: ! 507: iodone(bp); ! 508: } ! 509: ! 510: void ! 511: sdustart(unit) ! 512: register int unit; ! 513: { ! 514: if (scsireq(&sd_softc[unit].sc_dq)) ! 515: sdstart(unit); ! 516: } ! 517: ! 518: static void ! 519: sderror(unit, sc, hp, stat) ! 520: int unit, stat; ! 521: register struct sd_softc *sc; ! 522: register struct hp_device *hp; ! 523: { ! 524: sdsense[unit].status = stat; ! 525: if (stat & STS_CHECKCOND) { ! 526: struct scsi_xsense *sp; ! 527: ! 528: scsi_request_sense(hp->hp_ctlr, hp->hp_slave, ! 529: sc->sc_punit, sdsense[unit].sense, ! 530: sizeof(sdsense[unit].sense)); ! 531: sp = (struct scsi_xsense *)sdsense[unit].sense; ! 532: printf("sd%d: scsi sense class %d, code %d", unit, ! 533: sp->class, sp->code); ! 534: if (sp->class == 7) { ! 535: printf(", key %d", sp->key); ! 536: if (sp->valid) ! 537: printf(", blk %d", *(int *)&sp->info1); ! 538: } ! 539: printf("\n"); ! 540: } ! 541: } ! 542: ! 543: static void ! 544: sdfinish(unit, sc, bp) ! 545: int unit; ! 546: register struct sd_softc *sc; ! 547: register struct buf *bp; ! 548: { ! 549: sdtab[unit].b_errcnt = 0; ! 550: sdtab[unit].b_actf = bp->b_actf; ! 551: bp->b_resid = 0; ! 552: iodone(bp); ! 553: scsifree(&sc->sc_dq); ! 554: if (sdtab[unit].b_actf) ! 555: sdustart(unit); ! 556: else ! 557: sdtab[unit].b_active = 0; ! 558: } ! 559: ! 560: void ! 561: sdstart(unit) ! 562: register int unit; ! 563: { ! 564: register struct sd_softc *sc = &sd_softc[unit]; ! 565: register struct hp_device *hp = sc->sc_hd; ! 566: ! 567: /* ! 568: * we have the SCSI bus -- in format mode, we may or may not need dma ! 569: * so check now. ! 570: */ ! 571: if (sc->sc_format_pid && legal_cmds[sdcmd[unit].cdb[0]] > 0) { ! 572: register struct buf *bp = sdtab[unit].b_actf; ! 573: register int sts; ! 574: ! 575: sts = scsi_immed_command(hp->hp_ctlr, hp->hp_slave, ! 576: sc->sc_punit, &sdcmd[unit], ! 577: bp->b_un.b_addr, bp->b_bcount, ! 578: bp->b_flags & B_READ); ! 579: sdsense[unit].status = sts; ! 580: if (sts & 0xfe) { ! 581: sderror(unit, sc, hp, sts); ! 582: bp->b_flags |= B_ERROR; ! 583: bp->b_error = EIO; ! 584: } ! 585: sdfinish(unit, sc, bp); ! 586: ! 587: } else if (scsiustart(hp->hp_ctlr)) ! 588: sdgo(unit); ! 589: } ! 590: ! 591: void ! 592: sdgo(unit) ! 593: register int unit; ! 594: { ! 595: register struct sd_softc *sc = &sd_softc[unit]; ! 596: register struct hp_device *hp = sc->sc_hd; ! 597: register struct buf *bp = sdtab[unit].b_actf; ! 598: register int pad; ! 599: register struct scsi_fmt_cdb *cmd; ! 600: ! 601: if (sc->sc_format_pid) { ! 602: cmd = &sdcmd[unit]; ! 603: pad = 0; ! 604: } else { ! 605: cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd; ! 606: *(int *)(&cmd->cdb[2]) = bp->b_cylin; ! 607: pad = howmany(bp->b_bcount, sc->sc_blksize); ! 608: *(u_short *)(&cmd->cdb[7]) = pad; ! 609: pad = (bp->b_bcount & (sc->sc_blksize - 1)) != 0; ! 610: #ifdef DEBUG ! 611: if (pad) ! 612: printf("sd%d: partial block xfer -- %x bytes\n", ! 613: unit, bp->b_bcount); ! 614: #endif ! 615: sdstats[unit].sdtransfers++; ! 616: } ! 617: if (scsigo(hp->hp_ctlr, hp->hp_slave, sc->sc_punit, bp, cmd, pad) == 0) { ! 618: if (hp->hp_dk >= 0) { ! 619: dk_busy |= 1 << hp->hp_dk; ! 620: ++dk_seek[hp->hp_dk]; ! 621: ++dk_xfer[hp->hp_dk]; ! 622: dk_wds[hp->hp_dk] += bp->b_bcount >> 6; ! 623: } ! 624: return; ! 625: } ! 626: #ifdef DEBUG ! 627: if (sddebug & SDB_ERROR) ! 628: printf("sd%d: sdstart: %s adr %d blk %d len %d ecnt %d\n", ! 629: unit, bp->b_flags & B_READ? "read" : "write", ! 630: bp->b_un.b_addr, bp->b_cylin, bp->b_bcount, ! 631: sdtab[unit].b_errcnt); ! 632: #endif ! 633: bp->b_flags |= B_ERROR; ! 634: bp->b_error = EIO; ! 635: sdfinish(unit, sc, bp); ! 636: } ! 637: ! 638: void ! 639: sdintr(unit, stat) ! 640: register int unit; ! 641: int stat; ! 642: { ! 643: register struct sd_softc *sc = &sd_softc[unit]; ! 644: register struct buf *bp = sdtab[unit].b_actf; ! 645: register struct hp_device *hp = sc->sc_hd; ! 646: ! 647: if (bp == NULL) { ! 648: printf("sd%d: bp == NULL\n", unit); ! 649: return; ! 650: } ! 651: if (hp->hp_dk >= 0) ! 652: dk_busy &=~ (1 << hp->hp_dk); ! 653: if (stat) { ! 654: #ifdef DEBUG ! 655: if (sddebug & SDB_ERROR) ! 656: printf("sd%d: sdintr: bad scsi status 0x%x\n", ! 657: unit, stat); ! 658: #endif ! 659: sderror(unit, sc, hp, stat); ! 660: bp->b_flags |= B_ERROR; ! 661: bp->b_error = EIO; ! 662: } ! 663: sdfinish(unit, sc, bp); ! 664: } ! 665: ! 666: int ! 667: sdread(dev, uio) ! 668: dev_t dev; ! 669: struct uio *uio; ! 670: { ! 671: register int unit = sdunit(dev); ! 672: register int pid; ! 673: ! 674: if ((pid = sd_softc[unit].sc_format_pid) && pid != u.u_procp->p_pid) ! 675: return (EPERM); ! 676: ! 677: return(physio(sdstrategy, &sdbuf[unit], dev, B_READ, minphys, uio)); ! 678: } ! 679: ! 680: int ! 681: sdwrite(dev, uio) ! 682: dev_t dev; ! 683: struct uio *uio; ! 684: { ! 685: register int unit = sdunit(dev); ! 686: register int pid; ! 687: ! 688: if ((pid = sd_softc[unit].sc_format_pid) && pid != u.u_procp->p_pid) ! 689: return (EPERM); ! 690: ! 691: return(physio(sdstrategy, &sdbuf[unit], dev, B_WRITE, minphys, uio)); ! 692: } ! 693: ! 694: int ! 695: sdioctl(dev, cmd, data, flag) ! 696: dev_t dev; ! 697: int cmd; ! 698: caddr_t data; ! 699: int flag; ! 700: { ! 701: register int unit = sdunit(dev); ! 702: register struct sd_softc *sc = &sd_softc[unit]; ! 703: ! 704: switch (cmd) { ! 705: default: ! 706: return (EINVAL); ! 707: ! 708: case SDIOCSFORMAT: ! 709: /* take this device into or out of "format" mode */ ! 710: if (suser(u.u_cred, &u.u_acflag)) ! 711: return(EPERM); ! 712: ! 713: if (*(int *)data) { ! 714: if (sc->sc_format_pid) ! 715: return (EPERM); ! 716: sc->sc_format_pid = u.u_procp->p_pid; ! 717: } else ! 718: sc->sc_format_pid = 0; ! 719: return (0); ! 720: ! 721: case SDIOCGFORMAT: ! 722: /* find out who has the device in format mode */ ! 723: *(int *)data = sc->sc_format_pid; ! 724: return (0); ! 725: ! 726: case SDIOCSCSICOMMAND: ! 727: /* ! 728: * Save what user gave us as SCSI cdb to use with next ! 729: * read or write to the char device. ! 730: */ ! 731: if (sc->sc_format_pid != u.u_procp->p_pid) ! 732: return (EPERM); ! 733: if (legal_cmds[((struct scsi_fmt_cdb *)data)->cdb[0]] == 0) ! 734: return (EINVAL); ! 735: bcopy(data, (caddr_t)&sdcmd[unit], sizeof(sdcmd[0])); ! 736: return (0); ! 737: ! 738: case SDIOCSENSE: ! 739: /* ! 740: * return the SCSI sense data saved after the last ! 741: * operation that completed with "check condition" status. ! 742: */ ! 743: bcopy((caddr_t)&sdsense[unit], data, sizeof(sdsense[0])); ! 744: return (0); ! 745: ! 746: } ! 747: /*NOTREACHED*/ ! 748: } ! 749: ! 750: int ! 751: sdsize(dev) ! 752: dev_t dev; ! 753: { ! 754: register int unit = sdunit(dev); ! 755: register struct sd_softc *sc = &sd_softc[unit]; ! 756: ! 757: if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0) ! 758: return(-1); ! 759: ! 760: return(sc->sc_info.part[sdpart(dev)].nblocks); ! 761: } ! 762: ! 763: #include "machine/pte.h" ! 764: #include "machine/vmparam.h" ! 765: #include "../sys/vmmac.h" ! 766: ! 767: /* ! 768: * Non-interrupt driven, non-dma dump routine. ! 769: */ ! 770: int ! 771: sddump(dev) ! 772: dev_t dev; ! 773: { ! 774: int part = sdpart(dev); ! 775: int unit = sdunit(dev); ! 776: register struct sd_softc *sc = &sd_softc[unit]; ! 777: register struct hp_device *hp = sc->sc_hd; ! 778: register daddr_t baddr; ! 779: register int maddr; ! 780: register int pages, i; ! 781: int stat; ! 782: extern int lowram; ! 783: ! 784: /* ! 785: * Hmm... all vax drivers dump maxfree pages which is physmem minus ! 786: * the message buffer. Is there a reason for not dumping the ! 787: * message buffer? Savecore expects to read 'dumpsize' pages of ! 788: * dump, where dumpsys() sets dumpsize to physmem! ! 789: */ ! 790: pages = physmem; ! 791: ! 792: /* is drive ok? */ ! 793: if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0) ! 794: return (ENXIO); ! 795: /* dump parameters in range? */ ! 796: if (dumplo < 0 || dumplo >= sc->sc_info.part[part].nblocks) ! 797: return (EINVAL); ! 798: if (dumplo + ctod(pages) > sc->sc_info.part[part].nblocks) ! 799: pages = dtoc(sc->sc_info.part[part].nblocks - dumplo); ! 800: maddr = lowram; ! 801: baddr = dumplo + sc->sc_info.part[part].strtblk; ! 802: /* scsi bus idle? */ ! 803: if (!scsireq(&sc->sc_dq)) { ! 804: scsireset(hp->hp_ctlr); ! 805: sdreset(sc, sc->sc_hd); ! 806: printf("[ drive %d reset ] ", unit); ! 807: } ! 808: for (i = 0; i < pages; i++) { ! 809: #define NPGMB (1024*1024/NBPG) ! 810: /* print out how many Mbs we have dumped */ ! 811: if (i && (i % NPGMB) == 0) ! 812: printf("%d ", i / NPGMB); ! 813: #undef NPBMG ! 814: mapin(mmap, (u_int)vmmap, btop(maddr), PG_URKR|PG_CI|PG_V); ! 815: stat = scsi_tt_write(hp->hp_ctlr, hp->hp_slave, sc->sc_punit, ! 816: vmmap, NBPG, baddr, sc->sc_bshift); ! 817: if (stat) { ! 818: printf("sddump: scsi write error 0x%x\n", stat); ! 819: return (EIO); ! 820: } ! 821: maddr += NBPG; ! 822: baddr += ctod(1); ! 823: } ! 824: return (0); ! 825: } ! 826: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.