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

unix.superglobalmegacorp.com

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