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