[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     ! 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