Annotation of Net2/arch/hp300/dev/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 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

unix.superglobalmegacorp.com

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