Annotation of researchv9/sys/sundev/sd.c, revision 1.1.1.1

1.1       root        1: /*     @(#)sd.c 1.1 86/02/03 SMI       */
                      2: 
                      3: /*
                      4:  * Copyright (c) 1984 by Sun Microsystems, Inc.
                      5:  */
                      6: 
                      7: /*
                      8:  * SCSI driver for SCSI disks.
                      9:  */
                     10: 
                     11: #include "sd.h"
                     12: #include "../h/param.h"
                     13: #include "../h/systm.h"
                     14: #include "../h/dk.h"
                     15: #include "../h/buf.h"
                     16: #include "../h/conf.h"
                     17: #include "../h/dir.h"
                     18: #include "../h/user.h"
                     19: #include "../h/map.h"
                     20: #include "../h/vmmac.h"
                     21: /*
                     22:  *#include "../h/ioctl.h"
                     23:  *#include "../h/uio.h"
                     24:  *#include "../h/kernel.h"
                     25:  */
                     26: #include "../h/dkbad.h"
                     27: 
                     28: #include "../machine/pte.h"
                     29: #include "../machine/psl.h"
                     30: #include "../machine/mmu.h"
                     31: #include "../machine/cpu.h"
                     32: 
                     33: #include "../sun/dklabel.h"
                     34: #include "../sun/dkio.h"
                     35: 
                     36: #include "../sundev/mbvar.h"
                     37: #include "../sundev/screg.h"
                     38: #include "../sundev/sireg.h"
                     39: #include "../sundev/scsi.h"
                     40: 
                     41: #define        MAX_RETRIES  3
                     42: #define        MAX_RESTORES 1
                     43: 
                     44: #define        LPART(dev)      (dev % NLPART)
                     45: #define        SDUNIT(dev)     ((dev >> 3) % NUNIT)
                     46: #define        SDNUM(un)       (un - sdunits)
                     47: 
                     48: #define b_cylin b_resid
                     49: #define        SECSIZE 512
                     50: 
                     51: #define BUSY_RETRY 1000
                     52: 
                     53: /*
                     54:  * Error message control.
                     55:  */
                     56: #define        EL_RETRY        3
                     57: #define EL_REST                2
                     58: #define        EL_FAIL         1
                     59: int sderrlvl = EL_RETRY;
                     60: 
                     61: extern struct scsi_unit sdunits[];
                     62: extern struct scsi_unit_subr scsi_unit_subr[];
                     63: extern struct scsi_disk sdisk[];
                     64: extern int nsdisk;
                     65: 
                     66: /*
                     67:  * Return a pointer to this unit's unit structure.
                     68:  */
                     69: sdunitptr(md)
                     70:        register struct mb_device *md;
                     71: {
                     72:        return ((int)&sdunits[md->md_unit]);
                     73: }
                     74: 
                     75: /*
                     76:  * Attach device (boot time).
                     77:  */
                     78: sdattach(md)
                     79:        register struct mb_device *md;
                     80: {
                     81:        register struct scsi_unit *un;
                     82:        register struct dk_label *l;
                     83:        register int nbusy;
                     84: 
                     85:        un = &sdunits[md->md_unit];
                     86:        un->un_md = md;
                     87:        un->un_mc = md->md_mc;
                     88:        un->un_unit = md->md_unit;
                     89:        un->un_target = TARGET(md->md_slave);
                     90:        un->un_lun = LUN(md->md_slave);
                     91:        un->un_ss = &scsi_unit_subr[TYPE(md->md_flags)];
                     92: 
                     93:        nbusy = 0;
                     94:        for (;;) {
                     95:                if (simple(un, SC_TEST_UNIT_READY, 0, 0, 0)) {
                     96:                        break;
                     97:                } else if (un->un_c->c_scb.busy && nbusy++ < BUSY_RETRY) {
                     98:                        DELAY(5000);
                     99:                        continue;
                    100:                } else {
                    101:                        if (nbusy >= BUSY_RETRY) {
                    102:                                printf("sd%d: scsi continuously busy\n",
                    103:                                    SDNUM(un));
                    104:                        }
                    105:                        return;
                    106:                }
                    107:        }
                    108:        /* Allocate space for label in Multibus memory */
                    109:        l = (struct dk_label *)rmalloc(iopbmap, (long)SECSIZE);
                    110:        if (l == NULL) {
                    111:                printf("sd%d: sdattach: no space for disk label\n",
                    112:                    SDNUM(un));
                    113:                return;
                    114:        }
                    115:        l->dkl_magic = 0;
                    116:        if (getlabel(un, l) && islabel(un, l)) {
                    117:                uselabel(un, l);
                    118:        }
                    119:        rmfree(iopbmap, (long)SECSIZE, (long)l);
                    120: }
                    121: 
                    122: static
                    123: getlabel(un, l)
                    124:        register struct scsi_unit *un;
                    125:        register struct dk_label *l;
                    126: {
                    127:        register int retries, restores;
                    128: 
                    129:        for (restores = 0; restores < MAX_RESTORES; restores++) {
                    130:                for (retries = 0; retries < MAX_RETRIES; retries++) {
                    131:                        if (simple(un, SC_READ, (char *) l - DVMA, 0, 1)) {
                    132:                                return (1);
                    133:                        }
                    134:                }
                    135:                (void) simple(un, SC_REZERO_UNIT, 0, 0, 0);
                    136:        }
                    137:        return (0);
                    138: }
                    139: 
                    140: static
                    141: islabel(un, l)
                    142:        register struct scsi_unit *un;
                    143:        register struct dk_label *l;
                    144: {
                    145:        if (l->dkl_magic != DKL_MAGIC) {
                    146:                return (0);
                    147:        }
                    148:        if (!ck_cksum(l)) {
                    149:                printf("sd%d: corrupt label\n", SDNUM(un));
                    150:                return (0);
                    151:        }
                    152:        return (1);
                    153: }
                    154: 
                    155: /*
                    156:  * Check the checksum of the label
                    157:  */
                    158: static
                    159: ck_cksum(l)
                    160:        register struct dk_label *l;
                    161: {
                    162:        short *sp, sum = 0;
                    163:        short count = sizeof(struct dk_label)/sizeof(short);
                    164: 
                    165:        sp = (short *)l;
                    166:        while (count--)  {
                    167:                sum ^= *sp++;
                    168:        }
                    169:        return (sum ? 0 : 1);
                    170: }
                    171: 
                    172: static
                    173: uselabel(un, l)
                    174:        register struct scsi_unit *un;
                    175:        register struct dk_label *l;
                    176: {
                    177:        register int i, intrlv;
                    178:        register struct scsi_disk *dsi;
                    179: 
                    180:        printf("sd%d: <%s>\n", SDNUM(un), l->dkl_asciilabel);
                    181:        un->un_present = 1;
                    182:        dsi = &sdisk[un->un_unit];
                    183:        dsi->un_g.dkg_ncyl = l->dkl_ncyl;
                    184:        dsi->un_g.dkg_bcyl = 0;
                    185:        dsi->un_g.dkg_nhead = l->dkl_nhead;
                    186:        dsi->un_g.dkg_bhead = l->dkl_bhead;
                    187:        dsi->un_g.dkg_nsect = l->dkl_nsect;
                    188:        dsi->un_g.dkg_gap1 = l->dkl_gap1;
                    189:        dsi->un_g.dkg_gap2 = l->dkl_gap2;
                    190:        dsi->un_g.dkg_intrlv = l->dkl_intrlv;
                    191:        for (i = 0; i < NLPART; i++)
                    192:                dsi->un_map[i] = l->dkl_map[i];
                    193:        if (un->un_md->md_dk >= 0) {
                    194:                intrlv = dsi->un_g.dkg_intrlv;
                    195:                if (intrlv <= 0 || intrlv >= dsi->un_g.dkg_nsect) {
                    196:                        intrlv = 1;
                    197:                }
                    198: /*
                    199:                dk_bps[un->un_md->md_dk] = SECSIZE*60*dsi->un_g.dkg_nsect/intrlv;
                    200: */
                    201:        }
                    202: }
                    203: 
                    204: static
                    205: simple(un, cmd, dma_addr, secno, nsect)
                    206:        register struct scsi_unit *un;
                    207:        register int cmd, dma_addr, secno, nsect;
                    208: {
                    209:        register struct scsi_cdb *cdb;
                    210:        register struct scsi_ctlr *c;
                    211:        register int count;
                    212: 
                    213:        c = un->un_c;
                    214:        cdb = &c->c_cdb;
                    215:        bzero((caddr_t)cdb, sizeof(struct scsi_cdb));
                    216:        cdb->cmd = cmd;
                    217:        c->c_un = un;
                    218:        cdb->lun = un->un_lun;
                    219:        cdbaddr(cdb, secno);
                    220:        cdb->count = nsect;
                    221:        un->un_dma_addr = dma_addr;
                    222:        un->un_dma_count = nsect * SECSIZE;
                    223:        if ((*c->c_ss->scs_cmd)(c, un, 0)) {
                    224:                if ((*c->c_ss->scs_cmd_wait)(c)) {
                    225:                        count = (*c->c_ss->scs_dmacount)(c);
                    226:                        * (char *) &c->c_scb = 0;
                    227:                        if ((*c->c_ss->scs_getstat)(un, 0)) {
                    228:                                if (count == 0) {
                    229:                                        if (c->c_scb.chk == 0 && 
                    230:                                            c->c_scb.busy == 0) {
                    231:                                                return (1);
                    232:                                        }
                    233:                                }
                    234:                        }
                    235:                }
                    236:        }
                    237:        return (0);
                    238: }
                    239: 
                    240: /*ARGSUSED*/
                    241: sdopen(dev, flag)
                    242:        dev_t dev;
                    243:        int flag;
                    244: {
                    245:        register struct scsi_unit *un;
                    246:        register struct dk_label *l;
                    247:        register int unit;
                    248:        register struct scsi_disk *dsi;
                    249:        int memall();
                    250: 
                    251:        unit = SDUNIT(dev);
                    252:        if (unit >= nsdisk) {
                    253:                u.u_error = ENXIO;
                    254:                return;
                    255:        }
                    256:        un = &sdunits[unit];
                    257:        dsi = &sdisk[unit];
                    258:        if (un->un_mc == 0) {   /* never attached */
                    259:                u.u_error = ENXIO;
                    260:                return;
                    261:        }
                    262:        if (!un->un_present) {
                    263:                dsi->un_g.dkg_nsect = dsi->un_g.dkg_nhead = 1;   /* for strat */
                    264:                if (sdcmd(dev, SC_TEST_UNIT_READY, 0, 0, (caddr_t)0)) {
                    265:                        u.u_error = EIO;
                    266:                        return;
                    267:                }
                    268:                /* Allocate space for label */
                    269:                l = (struct dk_label *)wmemall(memall, SECSIZE);
                    270:                if (l == NULL) {
                    271:                        printf("sd%d: no space for disk label\n",
                    272:                            SDNUM(un));
                    273:                        u.u_error = EIO;
                    274:                        return;
                    275:                }
                    276:                if (sdcmd(dev, SC_READ, 0, SECSIZE, (caddr_t)l)) {
                    277:                        uprintf("sd%d: error reading label\n", SDNUM(un));
                    278:                        wmemfree((caddr_t)l, SECSIZE);
                    279:                        u.u_error = EIO;
                    280:                        return;
                    281:                }
                    282:                if (islabel(un, l)) {
                    283:                        uselabel(un, l);
                    284:                } else {
                    285:                        wmemfree((caddr_t)l, SECSIZE);
                    286:                        u.u_error = EIO;
                    287:                        return;
                    288:                }
                    289:                wmemfree((caddr_t)l, SECSIZE);
                    290:        }
                    291:        return (0);
                    292: }
                    293: 
                    294: sdsize(dev)
                    295:        register dev_t dev;
                    296: {
                    297:        register struct scsi_unit *un;
                    298:        register struct dk_map *lp;
                    299:        register struct scsi_disk *dsi;
                    300: 
                    301:        un = &sdunits[SDUNIT(dev)];
                    302:        if (!un->un_present) {
                    303:                return (-1);
                    304:        }
                    305:        dsi = &sdisk[SDUNIT(dev)];
                    306:        lp = &dsi->un_map[LPART(dev)];
                    307:        return (lp->dkl_nblk);
                    308: }
                    309: 
                    310: sdstrategy(bp)
                    311:        register struct buf *bp;
                    312: {
                    313:        register struct scsi_unit *un;
                    314:        register struct dk_map *lp;
                    315:        register daddr_t bn;
                    316:        register int unit;
                    317:        register struct buf *dp;
                    318:        register struct scsi_disk *dsi;
                    319:        long sz;
                    320:        int s;
                    321: 
                    322:        sz = bp->b_bcount;
                    323:        sz = (sz+511) >> 9;
                    324:        unit = dkunit(bp);
                    325:        if (unit >= nsdisk)
                    326:                goto bad;
                    327:        un = &sdunits[unit];
                    328:        if (!un->un_present && bp != &un->un_sbuf)
                    329:                goto bad;
                    330:        dsi = &sdisk[unit];
                    331:        lp = &dsi->un_map[LPART(bp->b_dev)];
                    332:        if (bp->b_blkno < 0 || (bn = dkblock(bp))+sz > lp->dkl_nblk)
                    333:                goto bad;
                    334:        bp->b_cylin = bn / (dsi->un_g.dkg_nsect * dsi->un_g.dkg_nhead);
                    335:        bp->b_cylin += lp->dkl_cylno + dsi->un_g.dkg_bcyl;
                    336:        dp = &un->un_utab;
                    337:        s = splx(pritospl(un->un_mc->mc_intpri));
                    338:        disksort(dp, bp);
                    339:        if (dp->b_active == 0) {
                    340:                (*un->un_c->c_ss->scs_ustart)(un);
                    341:                bp = &un->un_mc->mc_tab;
                    342:                if (bp->b_actf && bp->b_active == 0) {
                    343:                        (*un->un_c->c_ss->scs_start)(un);
                    344:                }
                    345:        }
                    346:        (void) splx(s);
                    347:        return;
                    348: 
                    349: bad:
                    350:        bp->b_flags |= B_ERROR;
                    351:        iodone(bp);
                    352:        return;
                    353: }
                    354: 
                    355: /*
                    356:  * Do a special command.
                    357:  */
                    358: sdcmd(dev, cmd, sector, len, addr)
                    359:        register dev_t dev;
                    360:        register int cmd, sector, len;
                    361:        register caddr_t addr;
                    362: {
                    363:        register struct scsi_unit *un;
                    364:        register struct buf *bp;
                    365:        register int s;
                    366: 
                    367:        un = &sdunits[SDUNIT(dev)];
                    368:        bp = &un->un_sbuf;
                    369:        s = splx(pritospl(un->un_mc->mc_intpri));
                    370:        while (bp->b_flags&B_BUSY) {
                    371:                bp->b_flags |= B_WANTED;
                    372:                sleep((caddr_t)bp, PRIBIO);
                    373:        }
                    374:        bp->b_flags = B_BUSY|B_READ;
                    375:        (void) splx(s);
                    376:        un->un_scmd = cmd;
                    377:        bp->b_dev = dev;
                    378:        bp->b_blkno = sector;
                    379:        bp->b_un.b_addr = addr;
                    380:        bp->b_bcount = len;
                    381:        sdstrategy(bp);
                    382:        iowait(bp);
                    383:        bp->b_flags &= ~B_BUSY;
                    384:        if (bp->b_flags&B_WANTED)
                    385:                wakeup((caddr_t)bp);
                    386:        return (bp->b_flags & B_ERROR);
                    387: }
                    388: 
                    389: /*
                    390:  * Set up a transfer for the controller
                    391:  */
                    392: sdstart(bp, un)
                    393:        register struct buf *bp;
                    394:        register struct scsi_unit *un;
                    395: {
                    396:        register struct dk_map *lp;
                    397:        register int nblk;
                    398:        register struct scsi_disk *dsi;
                    399: 
                    400:        dsi = &sdisk[dkunit(bp)];
                    401:        lp = &dsi->un_map[LPART(bp->b_dev)];
                    402:        un->un_blkno = dkblock(bp) + 
                    403:                lp->dkl_cylno * dsi->un_g.dkg_nhead * dsi->un_g.dkg_nsect;
                    404:        if (bp == &un->un_sbuf) {
                    405:                un->un_cmd = un->un_scmd;
                    406:        } else if (bp->b_flags & B_READ) {
                    407:                un->un_cmd = SC_READ;
                    408:        } else {
                    409:                un->un_cmd = SC_WRITE;
                    410:        }
                    411:        if (un->un_cmd == SC_READ || un->un_cmd == SC_WRITE) {
                    412:                nblk = howmany(bp->b_bcount, SECSIZE);
                    413:                un->un_count = MIN(nblk, lp->dkl_nblk - bp->b_blkno);
                    414:                bp->b_resid = bp->b_bcount - un->un_count * SECSIZE;
                    415:                un->un_flags |= SC_UNF_DVMA;
                    416:        } else {
                    417:                un->un_count = 0;
                    418:        }
                    419:        return (1);
                    420: }
                    421: 
                    422: /*
                    423:  * Make a cdb for disk i/o.
                    424:  */
                    425: sdmkcdb(c, un)
                    426:        register struct scsi_ctlr *c;
                    427:        struct scsi_unit *un;
                    428: {
                    429:        register struct scsi_cdb *cdb;
                    430: 
                    431:        cdb = &c->c_cdb;
                    432:        bzero((caddr_t)cdb, sizeof (*cdb));
                    433:        cdb->cmd = un->un_cmd;
                    434:        cdb->lun = un->un_lun;
                    435:        cdbaddr(cdb, un->un_blkno);
                    436:        cdb->count = un->un_count;
                    437:        un->un_dma_addr = un->un_baddr;
                    438:        un->un_dma_count = un->un_count * SECSIZE;
                    439: }
                    440: 
                    441: /*
                    442:  * Interrupt processing.
                    443:  */
                    444: sdintr(c, resid, error)
                    445:        register struct scsi_ctlr *c;
                    446:        register int resid, error;
                    447: {
                    448:        register struct scsi_unit *un;
                    449:        register struct buf *bp;
                    450:        register struct mb_device *md;
                    451: 
                    452:        un = c->c_un;
                    453:        bp = un->un_mc->mc_tab.b_actf->b_actf;
                    454:        md = un->un_md;
                    455:        if (md->md_dk >= 0) {
                    456:                dk_busy &= ~(1 << md->md_dk);
                    457:        }
                    458:        if (error == SE_FATAL) {
                    459:                if (bp == &un->un_sbuf  &&
                    460:                    ((un->un_flags & SC_UNF_DVMA) == 0)) {
                    461:                        (*c->c_ss->scs_done)(un->un_mc);
                    462:                } else {
                    463:                        mbdone(un->un_mc);
                    464:                        un->un_flags &= ~SC_UNF_DVMA;
                    465:                }
                    466:                bp->b_flags |= B_ERROR;
                    467:                printf("sd%d: SCSI FAILURE\n", SDNUM(un));
                    468:                (*c->c_ss->scs_off)(un);
                    469:                return;
                    470:        }
                    471:        if (error == SE_RETRYABLE || c->c_scb.chk || resid > 0) {
                    472:                sderror(c, un, bp);
                    473:                return;
                    474:        }
                    475:        if (c->c_cdb.cmd == SC_REZERO_UNIT && 
                    476:            !(bp == &un->un_sbuf && 
                    477:            un->un_scmd == SC_REZERO_UNIT)) {
                    478:                /* error recovery */
                    479:                sdmkcdb(c, un);
                    480:                if ((*c->c_ss->scs_cmd)(c, un, 1) == 0) {
                    481:                        printf("sd%d sdintr: scsi cmd failed 1\n", SDNUM(un));
                    482:                        (*c->c_ss->scs_off)(un);
                    483:                }
                    484:                return;
                    485:        }
                    486:        /* transfer worked */
                    487:        un->un_retries = un->un_restores = 0;
                    488:        if (un->un_sec_left) {  /* single sector stuff */
                    489:                un->un_sec_left--;
                    490:                un->un_baddr += SECSIZE;
                    491:                un->un_blkno++;
                    492:                sdmkcdb(c, un);
                    493:                if ((*c->c_ss->scs_cmd)(c, un, 1) == 0) {
                    494:                        printf("sd%d: sdintr: scsi cmd failed 2\n", SDNUM(un));
                    495:                        (*c->c_ss->scs_off)(un);
                    496:                }
                    497:        } else if (bp == &un->un_sbuf  &&
                    498:            ((un->un_flags & SC_UNF_DVMA) == 0)) {
                    499:                (*c->c_ss->scs_done)(un->un_mc);
                    500:        } else {
                    501:                mbdone(un->un_mc);
                    502:                un->un_flags &= ~SC_UNF_DVMA;
                    503:        }
                    504: }
                    505: 
                    506: /*
                    507:  * Error handling.
                    508:  */
                    509: sderror(c, un, bp)
                    510:        register struct scsi_ctlr *c;
                    511:        register struct scsi_unit *un;
                    512:        register struct buf *bp;
                    513: {
                    514:        if (un->un_present == 0) {      /* error trying to open */
                    515:                bp->b_flags |= B_ERROR;
                    516:                if (bp == &un->un_sbuf &&
                    517:                    ((un->un_flags & SC_UNF_DVMA) == 0)) {
                    518:                        (*c->c_ss->scs_done)(un->un_mc);
                    519:                } else {
                    520:                        mbdone(un->un_mc);
                    521:                        un->un_flags &= ~SC_UNF_DVMA;
                    522:                }
                    523:        } else if (c->c_scb.chk && c->c_sense->class == 1 &&
                    524:            c->c_sense->code == 5 && un->un_count > 1) {
                    525:                /* Seek errors - try single sectors (Adaptec bug) */
                    526:                un->un_sec_left = un->un_count - 1;
                    527:                un->un_count = 1;
                    528:                sdmkcdb(c, un);
                    529:                if ((*c->c_ss->scs_cmd)(c, un, 1) == 0) {
                    530:                        printf("sd%d: sderror: scsi cmd failed 1\n", SDNUM(un));
                    531:                        (*c->c_ss->scs_off)(un);
                    532:                }
                    533:        } else if (un->un_retries++ < MAX_RETRIES) {
                    534:                /* retry */
                    535:                if (sderrlvl >= EL_RETRY) {
                    536:                        sderrmsg(c, un, bp, "retry");
                    537:                }
                    538:                if ((*c->c_ss->scs_cmd)(c, un, 1) == 0) {
                    539:                        printf("sd%d: sderror: scsi cmd failed 2\n", SDNUM(un));
                    540:                        (*c->c_ss->scs_off)(un);
                    541:                }
                    542:        } else if (un->un_restores++ < MAX_RESTORES) {
                    543:                /* retries exhausted, try restore */
                    544:                un->un_retries = 0;
                    545:                if (sderrlvl >= EL_REST) {
                    546:                        sderrmsg(c, un, bp, "restore");
                    547:                }
                    548:                c->c_cdb.cmd = SC_REZERO_UNIT;
                    549:                cdbaddr(&c->c_cdb, 0);
                    550:                c->c_cdb.count = 0;
                    551:                un->un_dma_addr = un->un_dma_count = 0;
                    552:                if ((*c->c_ss->scs_cmd)(c, un, 1) == 0) {
                    553:                        printf("sd%d: sderror: scsi cmd failed 3\n", SDNUM(un));
                    554:                        (*c->c_ss->scs_off)(un);
                    555:                }
                    556:        } else {
                    557:                /* complete failure */
                    558:                if (sderrlvl >= EL_FAIL) {
                    559:                        sderrmsg(c, un, bp, "failed");
                    560:                }
                    561:                (*c->c_ss->scs_off)(un);
                    562:                bp->b_flags |= B_ERROR;
                    563:                if (bp == &un->un_sbuf &&
                    564:                    ((un->un_flags & SC_UNF_DVMA) == 0)) {
                    565:                        (*c->c_ss->scs_done)(un->un_mc);
                    566:                } else {
                    567:                        mbdone(un->un_mc);
                    568:                        un->un_flags &= ~SC_UNF_DVMA;
                    569:                }
                    570:        }
                    571: }
                    572: 
                    573: sdread(dev)
                    574:        dev_t dev;
                    575: {
                    576:        sdrw(dev, B_READ);
                    577: }
                    578: 
                    579: sdrw(dev, direction)
                    580:        dev_t dev;
                    581:        int direction;
                    582: {
                    583:        register struct scsi_unit *un;
                    584:        register int unit;
                    585:        
                    586:        unit = SDUNIT(dev);
                    587:        if (unit >= nsdisk) {
                    588:                u.u_error = ENXIO;
                    589:        }
                    590:        un = &sdunits[unit];
                    591:        physio(sdstrategy, &un->un_rbuf, dev, direction, minphys);
                    592: }
                    593: 
                    594: sdwrite(dev)
                    595:        dev_t dev;
                    596: {
                    597:        sdrw(dev, B_WRITE);
                    598: }
                    599: 
                    600: /*ARGSUSED*/
                    601: sdioctl(dev, cmd, data, flag)
                    602:        register dev_t dev;
                    603:        register caddr_t data;
                    604: {
                    605:        register struct scsi_unit *un;
                    606:        register struct dk_map *lp;
                    607:        register struct dk_info *inf;
                    608:        register int unit;
                    609:        register struct scsi_disk *dsi;
                    610: 
                    611:        unit = SDUNIT(dev);
                    612:        if (unit >= nsdisk) {
                    613:                return (ENXIO);
                    614:        }
                    615:        un = &sdunits[unit];
                    616:        dsi = &sdisk[unit];
                    617:        lp = &dsi->un_map[LPART(dev)];
                    618:        switch (cmd) {
                    619: 
                    620:        case DKIOCINFO:
                    621:                inf = (struct dk_info *)data;
                    622:                inf->dki_ctlr = getdevaddr(un->un_mc->mc_addr);
                    623:                inf->dki_unit = un->un_md->md_slave;
                    624:                inf->dki_ctype = DKC_SCSI;
                    625:                inf->dki_flags = DKI_FMTVOL;
                    626:                break;
                    627: 
                    628:        case DKIOCGGEOM:
                    629:                *(struct dk_geom *)data = dsi->un_g;
                    630:                break;
                    631: 
                    632:        case DKIOCSGEOM:
                    633:                if (!suser())
                    634:                        return (u.u_error);
                    635:                dsi->un_g = *(struct dk_geom *)data;
                    636:                break;
                    637: 
                    638:        case DKIOCGPART:
                    639:                *(struct dk_map *)data = *lp;
                    640:                break;
                    641: 
                    642:        case DKIOCSPART:
                    643:                if (!suser())
                    644:                        return (u.u_error);
                    645:                *lp = *(struct dk_map *)data;
                    646:                break;
                    647: 
                    648:        default:
                    649:                return (ENOTTY);
                    650:        }
                    651:        return (0);
                    652: }
                    653: 
                    654: sddump(dev, addr, blkno, nblk)
                    655:        register dev_t dev;
                    656:        register caddr_t addr;
                    657:        register daddr_t blkno, nblk;
                    658: {
                    659:        register struct scsi_unit *un;
                    660:        register struct dk_map *lp;
                    661:        static int first_time = 1;
                    662:        register struct scsi_disk *dsi;
                    663: 
                    664:        un = &sdunits[SDUNIT(dev)];
                    665:        if (un->un_present == 0) {
                    666:                return (ENXIO);
                    667:        }
                    668:        dsi = &sdisk[SDUNIT(dev)];
                    669:        lp = &dsi->un_map[LPART(dev)];
                    670:        if (blkno >= lp->dkl_nblk || (blkno + nblk) > lp->dkl_nblk) {
                    671:                return (EINVAL);
                    672:        }
                    673:        blkno += lp->dkl_cylno * dsi->un_g.dkg_nhead * dsi->un_g.dkg_nsect;
                    674:        if (first_time) {
                    675:                (*un->un_c->c_ss->scs_reset)(un->un_c); /* clr state - prevent err msg */
                    676:                first_time = 0;
                    677:        }
                    678:        if (simple(un, SC_WRITE, (int)(addr-DVMA), (int) blkno, (int) nblk)) {
                    679:                return (0);
                    680:        } else {
                    681:                return (EIO);
                    682:        }
                    683: }
                    684: 
                    685: char   *class_00_errors[] = {
                    686:        "no sense",
                    687:        "no index signal",
                    688:        "no seek complete",
                    689:        "write fault",
                    690:        "drive not ready",
                    691:        "drive not selected",
                    692:        "no track 00",
                    693:        "multiple drives selected",
                    694:        "no address acknowledged",
                    695:        "media not loaded",
                    696:        "insufficient capacity",
                    697: };
                    698: 
                    699: char   *class_01_errors[] = {
                    700:        "I.D. CRC error",
                    701:        "unrecoverable data error",
                    702:        "I.D. address mark not found",
                    703:        "data address mark not found",
                    704:        "record not found",
                    705:        "seek error",
                    706:        "DMA timeout error",
                    707:        "write protected",
                    708:        "correctable data check",
                    709:        "bad block found",
                    710:        "interleave error",
                    711:        "data transfer incomplete",
                    712:        "unformatted or bad format on drive",
                    713:        "self test failed",
                    714:        "defective track (media errors)",
                    715: };
                    716: 
                    717: char   *class_02_errors[] = {
                    718:        "invalid command",
                    719:        "illegal block address",
                    720:        "aborted",
                    721:        "volume overflow",
                    722: };
                    723: 
                    724: char   **sc_errors[] = {
                    725:        class_00_errors,
                    726:        class_01_errors,
                    727:        class_02_errors,
                    728:        0, 0, 0, 0,
                    729: };
                    730: 
                    731: int    sc_errct[] = {
                    732:        sizeof class_00_errors / sizeof (char *),
                    733:        sizeof class_01_errors / sizeof (char *),
                    734:        sizeof class_02_errors / sizeof (char *),
                    735:        0, 0, 0, 0,
                    736: };
                    737: 
                    738: char   *sc_ext_sense_keys [] = {
                    739:        "no sense",
                    740:        "recoverable error",
                    741:        "not ready",
                    742:        "media error",
                    743:        "hardware error",
                    744:        "illegal request",
                    745:        "media change",
                    746:        "write protect",
                    747:        "diagnostic unique",
                    748:        "vendor unique",
                    749:        "power up failed",
                    750:        "aborted command",
                    751:        "equal",
                    752:        "volume overflow",
                    753: };
                    754: 
                    755: #define N_EXT_SENSE_KEYS \
                    756:        (sizeof(sc_ext_sense_keys)/sizeof(sc_ext_sense_keys[0]))
                    757: 
                    758: char *sd_cmds[] = {
                    759:        "test unit ready",
                    760:        "rezero unit",
                    761:        "<bad cmd>",
                    762:        "request sense",
                    763:        "<bad cmd>",
                    764:        "<bad cmd>",
                    765:        "<bad cmd>",
                    766:        "<bad cmd>",
                    767:        "read",
                    768:        "<bad cmd>",
                    769:        "write",
                    770:        "seek",
                    771: };
                    772: 
                    773: sderrmsg(c, un, bp, action)
                    774:        register struct scsi_ctlr *c;
                    775:        struct scsi_unit *un;
                    776:        struct buf *bp;
                    777:        char *action;
                    778: {
                    779:        char *sensemsg, *cmdname;
                    780:        register struct scsi_sense *sense;
                    781: #define        ext_sense       ((struct scsi_ext_sense* ) sense)
                    782:        register struct dk_map *lp;
                    783:        register int blkno;
                    784:        register struct scsi_disk *dsi;
                    785: 
                    786:        dsi = &sdisk[dkunit(bp)];
                    787:        sense = c->c_sense;
                    788:        if (c->c_scb.chk == 0) {
                    789:                sensemsg = "no sense";
                    790:        } else if (sense->class <= 6) {
                    791:                if (sense->code < sc_errct[sense->class]) {
                    792:                        sensemsg = sc_errors[sense->class][sense->code];
                    793:                } else {
                    794:                        sensemsg = "invalid sense code";
                    795:                }
                    796:        } else if (sense->class == 7) {
                    797:                if (ext_sense->key < N_EXT_SENSE_KEYS) {
                    798:                        sensemsg = sc_ext_sense_keys[ext_sense->key];
                    799:                } else {
                    800:                        sensemsg = "invalid sense code";
                    801:                }
                    802:        } else {
                    803:                sensemsg = "invalid sense class";
                    804:        }
                    805:        if (un->un_cmd < sizeof(sd_cmds)) {
                    806:                cmdname = sd_cmds[un->un_cmd];
                    807:        } else {
                    808:                cmdname = "unknown cmd";
                    809:        }
                    810:        blkno = (sense->high_addr << 16) | (sense->mid_addr << 8) |
                    811:            sense->low_addr;
                    812:        lp = &dsi->un_map[LPART(bp->b_dev)];
                    813:        blkno -= lp->dkl_cylno * dsi->un_g.dkg_nhead * dsi->un_g.dkg_nsect;
                    814:        printf("sd%d%c: %s %s (%s) blk %d\n", SDNUM(un),
                    815:            LPART(bp->b_dev) + 'a', cmdname, action, sensemsg, blkno);
                    816: }

unix.superglobalmegacorp.com

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