Annotation of Net2/arch/hp300/dev/sd.c, revision 1.1.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.