Annotation of Net2/arch/hp300/dev/sd.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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