Annotation of 43BSDReno/sys/hpdev/sd.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.