[BACK]Return to hp.c CVS log [TXT][DIR] Up to [local] / sys / arch / vax / mba

Annotation of sys/arch/vax/mba/hp.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: hp.c,v 1.18 2007/06/07 05:22:32 deraadt Exp $ */
                      2: /*     $NetBSD: hp.c,v 1.22 2000/02/12 16:09:33 ragge Exp $ */
                      3: /*
                      4:  * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *      This product includes software developed at Ludd, University of
                     18:  *      Lule}, Sweden and its contributors.
                     19:  * 4. The name of the author may not be used to endorse or promote products
                     20:  *    derived from this software without specific prior written permission
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     31:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     32:  */
                     33:
                     34: /*
                     35:  * Simple device driver routine for massbuss disks.
                     36:  * TODO:
                     37:  *  Fix support for Standard DEC BAD144 bad block forwarding.
                     38:  *  Be able to to handle soft/hard transfer errors.
                     39:  *  Handle non-data transfer interrupts.
                     40:  *  Autoconfiguration of disk drives 'on the fly'.
                     41:  *  Handle disk media changes.
                     42:  *  Dual-port operations should be supported.
                     43:  */
                     44: #include <sys/param.h>
                     45: #include <sys/systm.h>
                     46: #include <sys/device.h>
                     47: #include <sys/disklabel.h>
                     48: #include <sys/disk.h>
                     49: #include <sys/dkio.h>
                     50: #include <sys/buf.h>
                     51: #include <sys/stat.h>
                     52: #include <sys/ioccom.h>
                     53: #include <sys/fcntl.h>
                     54: #include <sys/syslog.h>
                     55: #include <sys/reboot.h>
                     56:
                     57: #include <machine/trap.h>
                     58: #include <machine/pte.h>
                     59: #include <machine/mtpr.h>
                     60: #include <machine/cpu.h>
                     61: #include <machine/rpb.h>
                     62:
                     63: #include <vax/mba/mbavar.h>
                     64: #include <vax/mba/mbareg.h>
                     65: #include <vax/mba/hpreg.h>
                     66:
                     67: #define        HPMASK 0xffff
                     68:
                     69: struct hp_softc {
                     70:        struct  device  sc_dev;
                     71:        struct  disk sc_disk;
                     72:        struct  mba_device sc_md;       /* Common struct used by mbaqueue. */
                     73:        int     sc_wlabel;              /* Disklabel area is writable */
                     74:        int     sc_physnr;              /* Physical disk number */
                     75: };
                     76:
                     77: int     hpmatch(struct device *, struct cfdata *, void *);
                     78: void    hpattach(struct device *, struct device *, void *);
                     79: void   hpstrategy(struct buf *);
                     80: void   hpstart(struct mba_device *);
                     81: int    hpattn(struct mba_device *);
                     82: enum   xfer_action hpfinish(struct mba_device *, int, int *);
                     83: int    hpopen(dev_t, int, int);
                     84: int    hpclose(dev_t, int, int);
                     85: int    hpioctl(dev_t, u_long, caddr_t, int, struct proc *);
                     86: int    hpdump(dev_t, daddr64_t, caddr_t, size_t);
                     87: int    hpread(dev_t, struct uio *);
                     88: int    hpwrite(dev_t, struct uio *);
                     89: daddr64_t hpsize(dev_t);
                     90:
                     91: struct cfattach hp_ca = {
                     92:        sizeof(struct hp_softc), hpmatch, hpattach
                     93: };
                     94:
                     95: extern struct cfdriver hp_cd;
                     96:
                     97: /*
                     98:  * Check if this is a disk drive; done by checking type from mbaattach.
                     99:  */
                    100: int
                    101: hpmatch(parent, cf, aux)
                    102:        struct  device *parent;
                    103:        struct  cfdata *cf;
                    104:        void    *aux;
                    105: {
                    106:        struct  mba_attach_args *ma = aux;
                    107:
                    108:        if (cf->cf_loc[MBACF_DRIVE] != MBACF_DRIVE_DEFAULT &&
                    109:            cf->cf_loc[MBACF_DRIVE] != ma->unit)
                    110:                return 0;
                    111:
                    112:        if (ma->devtyp != MB_RP)
                    113:                return 0;
                    114:
                    115:        return 1;
                    116: }
                    117:
                    118: /*
                    119:  * Disk drive found; fake a disklabel and try to read the real one.
                    120:  * If the on-disk label can't be read; we lose.
                    121:  */
                    122: void
                    123: hpattach(parent, self, aux)
                    124:        struct  device *parent, *self;
                    125:        void    *aux;
                    126: {
                    127:        struct  hp_softc *sc = (void *)self;
                    128:        struct  mba_softc *ms = (void *)parent;
                    129:        struct  disklabel *dl;
                    130:        struct  mba_attach_args *ma = aux;
                    131:        char    *msg;
                    132:
                    133:        /*
                    134:         * Init the common struct for both the adapter and its slaves.
                    135:         */
                    136:        BUFQ_INIT(&sc->sc_md.md_q);
                    137:        sc->sc_md.md_softc = (void *)sc;        /* Pointer to this softc */
                    138:        sc->sc_md.md_mba = (void *)parent;      /* Pointer to parent softc */
                    139:        sc->sc_md.md_start = hpstart;           /* Disk start routine */
                    140:        sc->sc_md.md_attn = hpattn;             /* Disk attention routine */
                    141:        sc->sc_md.md_finish = hpfinish;         /* Disk xfer finish routine */
                    142:
                    143:        ms->sc_md[ma->unit] = &sc->sc_md;       /* Per-unit backpointer */
                    144:
                    145:        sc->sc_physnr = ma->unit;
                    146:        /*
                    147:         * Init and attach the disk structure.
                    148:         */
                    149:        sc->sc_disk.dk_name = sc->sc_dev.dv_xname;
                    150:        disk_attach(&sc->sc_disk);
                    151:
                    152:        /*
                    153:         * Fake a disklabel to be able to read in the real label.
                    154:         */
                    155:        dl = sc->sc_disk.dk_label;
                    156:
                    157:        dl->d_secsize = DEV_BSIZE;
                    158:        dl->d_ntracks = 1;
                    159:        dl->d_nsectors = 32;
                    160:        dl->d_secpercyl = 32;
                    161:
                    162:        /*
                    163:         * Read in label.
                    164:         */
                    165:        if ((msg = readdisklabel(makedev(0, self->dv_unit * 8), hpstrategy,
                    166:            dl, NULL)) != NULL) {
                    167:                /*printf(": %s", msg);*/
                    168:        }
                    169:        printf(": %.*s, size = %d sectors\n",
                    170:            (int)sizeof(dl->d_typename), dl->d_typename, DL_GETDSIZE(dl));
                    171:        /*
                    172:         * check if this was what we booted from.
                    173:         */
                    174:        if ((B_TYPE(bootdev) == BDEV_HP) && (ma->unit == B_UNIT(bootdev)) &&
                    175:            (ms->sc_physnr == B_ADAPTOR(bootdev)))
                    176:                booted_from = self;
                    177: }
                    178:
                    179:
                    180: void
                    181: hpstrategy(bp)
                    182:        struct buf *bp;
                    183: {
                    184:        struct  hp_softc *sc;
                    185:        struct  buf *gp;
                    186:        int     unit, s;
                    187:        struct disklabel *lp;
                    188:
                    189:        unit = DISKUNIT(bp->b_dev);
                    190:        sc = hp_cd.cd_devs[unit];
                    191:        lp = sc->sc_disk.dk_label;
                    192:
                    193:        if (bounds_check_with_label(bp, lp, sc->sc_wlabel) <= 0)
                    194:                goto done;
                    195:
                    196:        bp->b_rawblkno =
                    197:            bp->b_blkno + DL_GETPOFFSET(&lp->d_partitions[DISKPART(bp->b_dev)]);
                    198:        bp->b_cylinder = bp->b_rawblkno / lp->d_secpercyl;
                    199:
                    200:        s = splbio();
                    201:
                    202:        gp = BUFQ_FIRST(&sc->sc_md.md_q);
                    203:        disksort_cylinder(&sc->sc_md.md_q, bp);
                    204:        if (gp == 0)
                    205:                mbaqueue(&sc->sc_md);
                    206:
                    207:        splx(s);
                    208:        return;
                    209:
                    210: done:
                    211:        bp->b_resid = bp->b_bcount;
                    212:        s = splbio();
                    213:        biodone(bp);
                    214:        splx(s);
                    215: }
                    216:
                    217: /*
                    218:  * Start transfer on given disk. Called from mbastart().
                    219:  */
                    220: void
                    221: hpstart(md)
                    222:        struct  mba_device *md;
                    223: {
                    224:        struct  hp_softc *sc = md->md_softc;
                    225:        struct  mba_regs *mr = md->md_mba->sc_mbareg;
                    226:        volatile struct hp_regs *hr;
                    227:        struct  disklabel *lp = sc->sc_disk.dk_label;
                    228:        struct  buf *bp = BUFQ_FIRST(&md->md_q);
                    229:        unsigned bn, cn, sn, tn;
                    230:
                    231:        /*
                    232:         * Collect statistics.
                    233:         */
                    234:        disk_busy(&sc->sc_disk);
                    235:        sc->sc_disk.dk_seek++;
                    236:
                    237:        hr = (void *)&mr->mba_md[DISKUNIT(bp->b_dev)];
                    238:
                    239:        bn = bp->b_rawblkno;
                    240:        if (bn) {
                    241:                cn = bn / lp->d_secpercyl;
                    242:                sn = bn % lp->d_secpercyl;
                    243:                tn = sn / lp->d_nsectors;
                    244:                sn = sn % lp->d_nsectors;
                    245:        } else
                    246:                cn = sn = tn = 0;
                    247:
                    248:        hr->hp_dc = cn;
                    249:        hr->hp_da = (tn << 8) | sn;
                    250:        if (bp->b_flags & B_READ)
                    251:                hr->hp_cs1 = HPCS_READ;         /* GO */
                    252:        else
                    253:                hr->hp_cs1 = HPCS_WRITE;
                    254: }
                    255:
                    256: int
                    257: hpopen(dev, flag, fmt)
                    258:        dev_t   dev;
                    259:        int     flag, fmt;
                    260: {
                    261:        struct  hp_softc *sc;
                    262:        int     unit, part;
                    263:
                    264:        unit = DISKUNIT(dev);
                    265:        if (unit >= hp_cd.cd_ndevs)
                    266:                return ENXIO;
                    267:        sc = hp_cd.cd_devs[unit];
                    268:        if (sc == 0)
                    269:                return ENXIO;
                    270:
                    271:        part = DISKPART(dev);
                    272:
                    273:        if (part >= sc->sc_disk.dk_label->d_npartitions)
                    274:                return ENXIO;
                    275:
                    276:        switch (fmt) {
                    277:        case    S_IFCHR:
                    278:                sc->sc_disk.dk_copenmask |= (1 << part);
                    279:                break;
                    280:
                    281:        case    S_IFBLK:
                    282:                sc->sc_disk.dk_bopenmask |= (1 << part);
                    283:                break;
                    284:        }
                    285:        sc->sc_disk.dk_openmask =
                    286:            sc->sc_disk.dk_copenmask | sc->sc_disk.dk_bopenmask;
                    287:
                    288:        return 0;
                    289: }
                    290:
                    291: int
                    292: hpclose(dev, flag, fmt)
                    293:        dev_t   dev;
                    294:        int     flag, fmt;
                    295: {
                    296:        struct  hp_softc *sc;
                    297:        int     unit, part;
                    298:
                    299:        unit = DISKUNIT(dev);
                    300:        sc = hp_cd.cd_devs[unit];
                    301:
                    302:        part = DISKPART(dev);
                    303:
                    304:        switch (fmt) {
                    305:        case    S_IFCHR:
                    306:                sc->sc_disk.dk_copenmask &= ~(1 << part);
                    307:                break;
                    308:
                    309:        case    S_IFBLK:
                    310:                sc->sc_disk.dk_bopenmask &= ~(1 << part);
                    311:                break;
                    312:        }
                    313:        sc->sc_disk.dk_openmask =
                    314:            sc->sc_disk.dk_copenmask | sc->sc_disk.dk_bopenmask;
                    315:
                    316:        return 0;
                    317: }
                    318:
                    319: int
                    320: hpioctl(dev, cmd, addr, flag, p)
                    321:        dev_t   dev;
                    322:        u_long  cmd;
                    323:        caddr_t addr;
                    324:        int     flag;
                    325:        struct  proc *p;
                    326: {
                    327:        struct  hp_softc *sc = hp_cd.cd_devs[DISKUNIT(dev)];
                    328:        struct  disklabel *lp = sc->sc_disk.dk_label;
                    329:        int     error;
                    330:
                    331:        switch (cmd) {
                    332:        case    DIOCGDINFO:
                    333:                bcopy(lp, addr, sizeof (struct disklabel));
                    334:                return 0;
                    335:
                    336:        case    DIOCGPART:
                    337:                ((struct partinfo *)addr)->disklab = lp;
                    338:                ((struct partinfo *)addr)->part =
                    339:                    &lp->d_partitions[DISKPART(dev)];
                    340:                break;
                    341:
                    342:        case    DIOCSDINFO:
                    343:                if ((flag & FWRITE) == 0)
                    344:                        return EBADF;
                    345:
                    346:                return setdisklabel(lp, (struct disklabel *)addr, 0, 0);
                    347:
                    348:        case    DIOCWDINFO:
                    349:                if ((flag & FWRITE) == 0)
                    350:                        error = EBADF;
                    351:                else {
                    352:                        sc->sc_wlabel = 1;
                    353:                        error = writedisklabel(dev, hpstrategy, lp, 0);
                    354:                        sc->sc_wlabel = 0;
                    355:                }
                    356:                return error;
                    357:        case    DIOCWLABEL:
                    358:                if ((flag & FWRITE) == 0)
                    359:                        return EBADF;
                    360:                sc->sc_wlabel = 1;
                    361:                break;
                    362:
                    363:        default:
                    364:                printf("hpioctl: command %x\n", (unsigned int)cmd);
                    365:                return ENOTTY;
                    366:        }
                    367:        return 0;
                    368: }
                    369:
                    370: /*
                    371:  * Called when a transfer is finished. Check if transfer went OK,
                    372:  * Return info about what-to-do-now.
                    373:  */
                    374: enum xfer_action
                    375: hpfinish(md, mbasr, attn)
                    376:        struct  mba_device *md;
                    377:        int     mbasr, *attn;
                    378: {
                    379:        struct  hp_softc *sc = md->md_softc;
                    380:        struct  buf *bp = BUFQ_FIRST(&md->md_q);
                    381:        volatile struct  mba_regs *mr = md->md_mba->sc_mbareg;
                    382:        volatile struct hp_regs *hr = (void *)&mr->mba_md[DISKUNIT(bp->b_dev)];
                    383:        int     er1, er2;
                    384:        volatile int bc; /* to get GCC read whole longword */
                    385:        unsigned byte;
                    386:
                    387:        er1 = hr->hp_er1 & HPMASK;
                    388:        er2 = hr->hp_er2 & HPMASK;
                    389:        hr->hp_er1 = hr->hp_er2 = 0;
                    390: hper1:
                    391:        switch (ffs(er1) - 1) {
                    392:        case -1:
                    393:                hr->hp_er1 = 0;
                    394:                goto hper2;
                    395:
                    396:        case HPER1_DCK: /* Corrected? data read. Just notice. */
                    397:                bc = mr->mba_bc;
                    398:                byte = ~(bc >> 16);
                    399:                diskerr(buf, hp_cd.cd_name, "soft ecc", LOG_PRINTF,
                    400:                    btodb(bp->b_bcount - byte), sc->sc_disk.dk_label);
                    401:                er1 &= ~(1<<HPER1_DCK);
                    402:                er1 &= HPMASK;
                    403:                break;
                    404:
                    405:        default:
                    406:                printf("drive error :%s er1 %x er2 %x\n",
                    407:                    sc->sc_dev.dv_xname, er1, er2);
                    408:                hr->hp_er1 = hr->hp_er2 = 0;
                    409:                goto hper2;
                    410:        }
                    411:        goto hper1;
                    412:
                    413: hper2:
                    414:        mbasr &= ~(MBASR_DTBUSY|MBASR_DTCMP|MBASR_ATTN);
                    415:        if (mbasr)
                    416:                printf("massbuss error :%s %x\n",
                    417:                    sc->sc_dev.dv_xname, mbasr);
                    418:
                    419:        BUFQ_FIRST(&md->md_q)->b_resid = 0;
                    420:        disk_unbusy(&sc->sc_disk, BUFQ_FIRST(&md->md_q)->b_bcount,
                    421:            (BUFQ_FIRST(&md->md_q)->b_flags & B_READ));
                    422:        return XFER_FINISH;
                    423: }
                    424:
                    425: /*
                    426:  * Non-data transfer interrupt; like volume change.
                    427:  */
                    428: int
                    429: hpattn(md)
                    430:        struct  mba_device *md;
                    431: {
                    432:        struct  hp_softc *sc = md->md_softc;
                    433:        struct  mba_softc *ms = (void *)sc->sc_dev.dv_parent;
                    434:        struct  mba_regs *mr = ms->sc_mbareg;
                    435:        struct  hp_regs *hr = (void *)&mr->mba_md[sc->sc_dev.dv_unit];
                    436:        int     er1, er2;
                    437:
                    438:         er1 = hr->hp_er1 & HPMASK;
                    439:         er2 = hr->hp_er2 & HPMASK;
                    440:
                    441:        printf("%s: Attention! er1 %x er2 %x\n",
                    442:                sc->sc_dev.dv_xname, er1, er2);
                    443:        return 0;
                    444: }
                    445:
                    446:
                    447: daddr64_t
                    448: hpsize(dev)
                    449:        dev_t   dev;
                    450: {
                    451:        int     size, unit = DISKUNIT(dev);
                    452:        struct  hp_softc *sc;
                    453:
                    454:        if (unit >= hp_cd.cd_ndevs || hp_cd.cd_devs[unit] == 0)
                    455:                return -1;
                    456:
                    457:        sc = hp_cd.cd_devs[unit];
                    458:        size = DL_GETPSIZE(&sc->sc_disk.dk_label->d_partitions[DISKPART(dev)]) *
                    459:            (sc->sc_disk.dk_label->d_secsize / DEV_BSIZE);
                    460:
                    461:        return size;
                    462: }
                    463:
                    464: int
                    465: hpdump(dev, a1, a2, size)
                    466:        dev_t   dev;
                    467:        daddr64_t a1;
                    468:        caddr_t a2;
                    469:        size_t  size;
                    470: {
                    471:        printf("hpdump: Not implemented yet.\n");
                    472:        return 0;
                    473: }
                    474:
                    475: int
                    476: hpread(dev, uio)
                    477:        dev_t dev;
                    478:        struct uio *uio;
                    479: {
                    480:        return (physio(hpstrategy, NULL, dev, B_READ, minphys, uio));
                    481: }
                    482:
                    483: int
                    484: hpwrite(dev, uio)
                    485:        dev_t dev;
                    486:        struct uio *uio;
                    487: {
                    488:        return (physio(hpstrategy, NULL, dev, B_WRITE, minphys, uio));
                    489: }

CVSweb