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

Annotation of sys/arch/vax/mscp/mscp_disk.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: mscp_disk.c,v 1.24 2007/06/20 18:15:46 deraadt Exp $  */
        !             2: /*     $NetBSD: mscp_disk.c,v 1.30 2001/11/13 07:38:28 lukem Exp $     */
        !             3: /*
        !             4:  * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
        !             5:  * Copyright (c) 1988 Regents of the University of California.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to Berkeley by
        !             9:  * Chris Torek.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. Neither the name of the University nor the names of its contributors
        !            20:  *    may be used to endorse or promote products derived from this software
        !            21:  *    without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            33:  * SUCH DAMAGE.
        !            34:  *
        !            35:  *     @(#)uda.c       7.32 (Berkeley) 2/13/91
        !            36:  */
        !            37:
        !            38: /*
        !            39:  * RA disk device driver
        !            40:  * RX MSCP floppy disk device driver
        !            41:  */
        !            42:
        !            43: /*
        !            44:  * TODO
        !            45:  *     write bad block forwarding code
        !            46:  */
        !            47:
        !            48: #include <sys/cdefs.h>
        !            49:
        !            50: #include <sys/param.h>
        !            51: #include <sys/buf.h>
        !            52: #include <sys/device.h>
        !            53: #include <sys/disk.h>
        !            54: #include <sys/disklabel.h>
        !            55: #include <sys/ioctl.h>
        !            56: #include <sys/stat.h>
        !            57: #include <sys/fcntl.h>
        !            58: #include <sys/reboot.h>
        !            59: #include <sys/proc.h>
        !            60: #include <sys/systm.h>
        !            61:
        !            62: #include <ufs/ufs/dinode.h>
        !            63: #include <ufs/ffs/fs.h>
        !            64:
        !            65: #include <machine/bus.h>
        !            66: #include <machine/cpu.h>
        !            67:
        !            68: #include <arch/vax/mscp/mscp.h>
        !            69: #include <arch/vax/mscp/mscpreg.h>
        !            70: #include <arch/vax/mscp/mscpvar.h>
        !            71:
        !            72: #include "ra.h"
        !            73:
        !            74: struct cfdriver ra_cd = {
        !            75:        NULL, "ra", DV_DISK
        !            76: };
        !            77:
        !            78: struct cfdriver rx_cd = {
        !            79:        NULL, "rx", DV_DISK
        !            80: };
        !            81:
        !            82: #define RAMAJOR 9      /* RA major device number XXX */
        !            83:
        !            84: /*
        !            85:  * Drive status, per drive
        !            86:  */
        !            87: struct ra_softc {
        !            88:        struct  device ra_dev;  /* Autoconf struct */
        !            89:        struct  disk ra_disk;
        !            90:        int     ra_state;       /* open/closed state */
        !            91:        u_long  ra_mediaid;     /* media id */
        !            92:        int     ra_hwunit;      /* Hardware unit number */
        !            93:        int     ra_havelabel;   /* true if we have a label */
        !            94:        int     ra_wlabel;      /* label sector is currently writable */
        !            95: };
        !            96:
        !            97: #define rx_softc ra_softc
        !            98:
        !            99: void   rxattach(struct device *, struct device *, void *);
        !           100: int    rx_putonline(struct rx_softc *);
        !           101: void   rrmakelabel(struct disklabel *, long);
        !           102:
        !           103: #if NRA
        !           104:
        !           105: int    ramatch(struct device *, struct cfdata *, void *);
        !           106: void   raattach(struct device *, struct device *, void *);
        !           107: int    raopen(dev_t, int, int, struct proc *);
        !           108: int    raclose(dev_t, int, int, struct proc *);
        !           109: void   rastrategy(struct buf *);
        !           110: int    raread(dev_t, struct uio *);
        !           111: int    rawrite(dev_t, struct uio *);
        !           112: int    raioctl(dev_t, int, caddr_t, int, struct proc *);
        !           113: int    radump(dev_t, daddr64_t, caddr_t, size_t);
        !           114: daddr64_t      rasize(dev_t);
        !           115: int    ra_putonline(struct ra_softc *);
        !           116:
        !           117: struct cfattach ra_ca = {
        !           118:        sizeof(struct ra_softc), (cfmatch_t)ramatch, rxattach
        !           119: };
        !           120:
        !           121: /*
        !           122:  * More driver definitions, for generic MSCP code.
        !           123:  */
        !           124:
        !           125: int
        !           126: ramatch(parent, cf, aux)
        !           127:        struct  device *parent;
        !           128:        struct  cfdata *cf;
        !           129:        void    *aux;
        !           130: {
        !           131:        struct  drive_attach_args *da = aux;
        !           132:        struct  mscp *mp = da->da_mp;
        !           133:
        !           134:        if ((da->da_typ & MSCPBUS_DISK) == 0)
        !           135:                return 0;
        !           136:        if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != mp->mscp_unit)
        !           137:                return 0;
        !           138:        /*
        !           139:         * Check if this disk is a floppy; then don't configure it.
        !           140:         * Seems to be a safe way to test it per Chris Torek.
        !           141:         */
        !           142:        if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@')
        !           143:                return 0;
        !           144:        return 1;
        !           145: }
        !           146:
        !           147: /*
        !           148:  * (Try to) put the drive online. This is done the first time the
        !           149:  * drive is opened, or if it har fallen offline.
        !           150:  */
        !           151: int
        !           152: ra_putonline(ra)
        !           153:        struct ra_softc *ra;
        !           154: {
        !           155:        struct  disklabel *dl;
        !           156:        char *msg;
        !           157:
        !           158:        if (rx_putonline(ra) != MSCP_DONE)
        !           159:                return MSCP_FAILED;
        !           160:
        !           161:        dl = ra->ra_disk.dk_label;
        !           162:
        !           163:        ra->ra_state = DK_RDLABEL;
        !           164:        printf("%s", ra->ra_dev.dv_xname);
        !           165:        if ((msg = readdisklabel(MAKEDISKDEV(RAMAJOR, ra->ra_dev.dv_unit,
        !           166:            RAW_PART), rastrategy, dl, 0)) != NULL) {
        !           167:                /*printf(": %s", msg);*/
        !           168:        } else {
        !           169:                ra->ra_havelabel = 1;
        !           170:                ra->ra_state = DK_OPEN;
        !           171:        }
        !           172:
        !           173:        printf(": size %lld sectors\n", DL_GETDSIZE(dl));
        !           174:
        !           175:        return MSCP_DONE;
        !           176: }
        !           177:
        !           178: /*
        !           179:  * Open a drive.
        !           180:  */
        !           181: /*ARGSUSED*/
        !           182: int
        !           183: raopen(dev, flag, fmt, p)
        !           184:        dev_t dev;
        !           185:        int flag, fmt;
        !           186:        struct  proc *p;
        !           187: {
        !           188:        struct ra_softc *ra;
        !           189:        int part, unit, mask;
        !           190:        /*
        !           191:         * Make sure this is a reasonable open request.
        !           192:         */
        !           193:        unit = DISKUNIT(dev);
        !           194:        if (unit >= ra_cd.cd_ndevs)
        !           195:                return ENXIO;
        !           196:        ra = ra_cd.cd_devs[unit];
        !           197:        if (ra == 0)
        !           198:                return ENXIO;
        !           199:
        !           200:        /*
        !           201:         * If this is the first open; we must first try to put
        !           202:         * the disk online (and read the label).
        !           203:         */
        !           204:        if (ra->ra_state == DK_CLOSED)
        !           205:                if (ra_putonline(ra) == MSCP_FAILED)
        !           206:                        return ENXIO;
        !           207:
        !           208:        /* If the disk has no label; allow writing everywhere */
        !           209:        if (ra->ra_havelabel == 0)
        !           210:                ra->ra_wlabel = 1;
        !           211:
        !           212:        part = DISKPART(dev);
        !           213:        if (part >= ra->ra_disk.dk_label->d_npartitions)
        !           214:                return ENXIO;
        !           215:
        !           216:        /*
        !           217:         * Wait for the state to settle
        !           218:         */
        !           219: #if notyet
        !           220:        while (ra->ra_state != DK_OPEN)
        !           221:                if ((error = tsleep((caddr_t)ra, (PZERO + 1) | PCATCH,
        !           222:                    "devopen", 0))) {
        !           223:                        splx(s);
        !           224:                        return (error);
        !           225:                }
        !           226: #endif
        !           227:
        !           228:        mask = 1 << part;
        !           229:
        !           230:        switch (fmt) {
        !           231:        case S_IFCHR:
        !           232:                ra->ra_disk.dk_copenmask |= mask;
        !           233:                break;
        !           234:        case S_IFBLK:
        !           235:                ra->ra_disk.dk_bopenmask |= mask;
        !           236:                break;
        !           237:        }
        !           238:        ra->ra_disk.dk_openmask |= mask;
        !           239:        return 0;
        !           240: }
        !           241:
        !           242: /* ARGSUSED */
        !           243: int
        !           244: raclose(dev, flags, fmt, p)
        !           245:        dev_t dev;
        !           246:        int flags, fmt;
        !           247:        struct  proc *p;
        !           248: {
        !           249:        int unit = DISKUNIT(dev);
        !           250:        struct ra_softc *ra = ra_cd.cd_devs[unit];
        !           251:        int mask = (1 << DISKPART(dev));
        !           252:
        !           253:        switch (fmt) {
        !           254:        case S_IFCHR:
        !           255:                ra->ra_disk.dk_copenmask &= ~mask;
        !           256:                break;
        !           257:        case S_IFBLK:
        !           258:                ra->ra_disk.dk_bopenmask &= ~mask;
        !           259:                break;
        !           260:        }
        !           261:        ra->ra_disk.dk_openmask =
        !           262:            ra->ra_disk.dk_copenmask | ra->ra_disk.dk_bopenmask;
        !           263:
        !           264:        /*
        !           265:         * Should wait for I/O to complete on this partition even if
        !           266:         * others are open, but wait for work on blkflush().
        !           267:         */
        !           268: #if notyet
        !           269:        if (ra->ra_openpart == 0) {
        !           270:                s = spluba();
        !           271:                while (BUFQ_FIRST(&udautab[unit]) != NULL)
        !           272:                        (void) tsleep(&udautab[unit], PZERO - 1,
        !           273:                            "raclose", 0);
        !           274:                splx(s);
        !           275:                ra->ra_state = CLOSED;
        !           276:                ra->ra_wlabel = 0;
        !           277:        }
        !           278: #endif
        !           279:        return (0);
        !           280: }
        !           281:
        !           282: /*
        !           283:  * Queue a transfer request, and if possible, hand it to the controller.
        !           284:  */
        !           285: void
        !           286: rastrategy(bp)
        !           287:        struct buf *bp;
        !           288: {
        !           289:        int unit;
        !           290:        struct ra_softc *ra;
        !           291:        int s;
        !           292:
        !           293:        /*
        !           294:         * Make sure this is a reasonable drive to use.
        !           295:         */
        !           296:        unit = DISKUNIT(bp->b_dev);
        !           297:        if (unit >= ra_cd.cd_ndevs || (ra = ra_cd.cd_devs[unit]) == NULL) {
        !           298:                bp->b_error = ENXIO;
        !           299:                bp->b_flags |= B_ERROR;
        !           300:                goto done;
        !           301:        }
        !           302:        /*
        !           303:         * If drive is open `raw' or reading label, let it at it.
        !           304:         */
        !           305:        if (ra->ra_state == DK_RDLABEL) {
        !           306:                mscp_strategy(bp, ra->ra_dev.dv_parent);
        !           307:                return;
        !           308:        }
        !           309:
        !           310:        /* If disk is not online, try to put it online */
        !           311:        if (ra->ra_state == DK_CLOSED)
        !           312:                if (ra_putonline(ra) == MSCP_FAILED) {
        !           313:                        bp->b_flags |= B_ERROR;
        !           314:                        bp->b_error = EIO;
        !           315:                        goto done;
        !           316:                }
        !           317:
        !           318:        /*
        !           319:         * Determine the size of the transfer, and make sure it is
        !           320:         * within the boundaries of the partition.
        !           321:         */
        !           322:        if (bounds_check_with_label(bp, ra->ra_disk.dk_label,
        !           323:            ra->ra_wlabel) <= 0)
        !           324:                goto done;
        !           325:
        !           326:        /* Make some statistics... /bqt */
        !           327:        s = splbio();
        !           328:        disk_busy(&ra->ra_disk);
        !           329:        splx(s);
        !           330:        mscp_strategy(bp, ra->ra_dev.dv_parent);
        !           331:        return;
        !           332:
        !           333: done:
        !           334:        s = splbio();
        !           335:        biodone(bp);
        !           336:        splx(s);
        !           337: }
        !           338:
        !           339: int
        !           340: raread(dev, uio)
        !           341:        dev_t dev;
        !           342:        struct uio *uio;
        !           343: {
        !           344:
        !           345:        return (physio(rastrategy, NULL, dev, B_READ, minphys, uio));
        !           346: }
        !           347:
        !           348: int
        !           349: rawrite(dev, uio)
        !           350:        dev_t dev;
        !           351:        struct uio *uio;
        !           352: {
        !           353:
        !           354:        return (physio(rastrategy, NULL, dev, B_WRITE, minphys, uio));
        !           355: }
        !           356:
        !           357: /*
        !           358:  * I/O controls.
        !           359:  */
        !           360: int
        !           361: raioctl(dev, cmd, data, flag, p)
        !           362:        dev_t dev;
        !           363:        int cmd;
        !           364:        caddr_t data;
        !           365:        int flag;
        !           366:        struct proc *p;
        !           367: {
        !           368:        int unit = DISKUNIT(dev);
        !           369:        struct disklabel *lp, *tp;
        !           370:        struct ra_softc *ra = ra_cd.cd_devs[unit];
        !           371:        int error = 0;
        !           372:
        !           373:        lp = ra->ra_disk.dk_label;
        !           374:
        !           375:        switch (cmd) {
        !           376:
        !           377:        case DIOCGDINFO:
        !           378:                bcopy(lp, data, sizeof (struct disklabel));
        !           379:                break;
        !           380:
        !           381:        case DIOCGPART:
        !           382:                ((struct partinfo *)data)->disklab = lp;
        !           383:                ((struct partinfo *)data)->part =
        !           384:                    &lp->d_partitions[DISKPART(dev)];
        !           385:                break;
        !           386:
        !           387:        case DIOCWDINFO:
        !           388:        case DIOCSDINFO:
        !           389:                tp = (struct disklabel *)data;
        !           390:
        !           391:                if ((flag & FWRITE) == 0)
        !           392:                        error = EBADF;
        !           393:                else {
        !           394:                        error = setdisklabel(lp, tp, 0);
        !           395:                        if (error == 0 && cmd == DIOCWDINFO) {
        !           396:                                ra->ra_wlabel = 1;
        !           397:                                error = writedisklabel(dev, rastrategy, lp);
        !           398:                                ra->ra_wlabel = 0;
        !           399:                        }
        !           400:                }
        !           401:                break;
        !           402:
        !           403:        case DIOCWLABEL:
        !           404:                if ((flag & FWRITE) == 0)
        !           405:                        error = EBADF;
        !           406:                else
        !           407:                        ra->ra_wlabel = 1;
        !           408:                break;
        !           409:
        !           410:        default:
        !           411:                error = ENOTTY;
        !           412:                break;
        !           413:        }
        !           414:        return (error);
        !           415: }
        !           416:
        !           417:
        !           418: int
        !           419: radump(dev, blkno, va, size)
        !           420:        dev_t   dev;
        !           421:        daddr64_t blkno;
        !           422:        caddr_t va;
        !           423:        size_t  size;
        !           424: {
        !           425:        return ENXIO;
        !           426: }
        !           427:
        !           428: /*
        !           429:  * Return the size of a partition, if known, or -1 if not.
        !           430:  */
        !           431: daddr64_t
        !           432: rasize(dev)
        !           433:        dev_t dev;
        !           434: {
        !           435:        int unit = DISKUNIT(dev);
        !           436:        struct ra_softc *ra;
        !           437:
        !           438:        if (unit >= ra_cd.cd_ndevs || ra_cd.cd_devs[unit] == 0)
        !           439:                return -1;
        !           440:
        !           441:        ra = ra_cd.cd_devs[unit];
        !           442:
        !           443:        if (ra->ra_state == DK_CLOSED)
        !           444:                if (ra_putonline(ra) == MSCP_FAILED)
        !           445:                        return -1;
        !           446:
        !           447:        return DL_GETPSIZE(&ra->ra_disk.dk_label->d_partitions[DISKPART(dev)]) *
        !           448:            (ra->ra_disk.dk_label->d_secsize / DEV_BSIZE);
        !           449: }
        !           450:
        !           451: #endif /* NRA */
        !           452:
        !           453: #if NRX
        !           454:
        !           455: int    rxmatch(struct device *, struct cfdata *, void *);
        !           456: int    rxopen(dev_t, int, int, struct proc *);
        !           457: int    rxclose(dev_t, int, int, struct proc *);
        !           458: void   rxstrategy(struct buf *);
        !           459: int    rxread(dev_t, struct uio *);
        !           460: int    rxwrite(dev_t, struct uio *);
        !           461: int    rxioctl(dev_t, int, caddr_t, int, struct proc *);
        !           462: int    rxdump(dev_t, daddr64_t, caddr_t, size_t);
        !           463: daddr64_t      rxsize(dev_t);
        !           464:
        !           465: struct cfattach rx_ca = {
        !           466:        sizeof(struct rx_softc), (cfmatch_t)rxmatch, rxattach
        !           467: };
        !           468:
        !           469: /*
        !           470:  * More driver definitions, for generic MSCP code.
        !           471:  */
        !           472:
        !           473: int
        !           474: rxmatch(parent, cf, aux)
        !           475:        struct  device *parent;
        !           476:        struct  cfdata *cf;
        !           477:        void    *aux;
        !           478: {
        !           479:        struct  drive_attach_args *da = aux;
        !           480:        struct  mscp *mp = da->da_mp;
        !           481:
        !           482:        if ((da->da_typ & MSCPBUS_DISK) == 0)
        !           483:                return 0;
        !           484:        if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != mp->mscp_unit)
        !           485:                return 0;
        !           486:        /*
        !           487:         * Check if this disk is a floppy; then configure it.
        !           488:         * Seems to be a safe way to test it per Chris Torek.
        !           489:         */
        !           490:        if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@')
        !           491:                return 1;
        !           492:        return 0;
        !           493: }
        !           494:
        !           495: #endif /* NRX */
        !           496:
        !           497: /*
        !           498:  * The attach routine only checks and prints drive type.
        !           499:  * Bringing the disk online is done when the disk is accessed
        !           500:  * the first time.
        !           501:  */
        !           502: void
        !           503: rxattach(parent, self, aux)
        !           504:        struct  device *parent, *self;
        !           505:        void    *aux;
        !           506: {
        !           507:        struct  rx_softc *rx = (void *)self;
        !           508:        struct  drive_attach_args *da = aux;
        !           509:        struct  mscp *mp = da->da_mp;
        !           510:        struct  mscp_softc *mi = (void *)parent;
        !           511:        struct  disklabel *dl;
        !           512:
        !           513:        rx->ra_mediaid = mp->mscp_guse.guse_mediaid;
        !           514:        rx->ra_state = DK_CLOSED;
        !           515:        rx->ra_hwunit = mp->mscp_unit;
        !           516:        mi->mi_dp[mp->mscp_unit] = self;
        !           517:
        !           518:        rx->ra_disk.dk_name = rx->ra_dev.dv_xname;
        !           519:        disk_attach((struct disk *)&rx->ra_disk);
        !           520:
        !           521:        /* Fill in what we know. The actual size is gotten later */
        !           522:        dl = rx->ra_disk.dk_label;
        !           523:
        !           524:        dl->d_secsize = DEV_BSIZE;
        !           525:        dl->d_nsectors = mp->mscp_guse.guse_nspt;
        !           526:        dl->d_ntracks = mp->mscp_guse.guse_ngpc * mp->mscp_guse.guse_group;
        !           527:        dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks;
        !           528:        disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid);
        !           529: #ifdef DEBUG
        !           530:        printf("%s: nspt %d group %d ngpc %d rct %d nrpt %d nrct %d\n",
        !           531:            self->dv_xname, mp->mscp_guse.guse_nspt, mp->mscp_guse.guse_group,
        !           532:            mp->mscp_guse.guse_ngpc, mp->mscp_guse.guse_rctsize,
        !           533:            mp->mscp_guse.guse_nrpt, mp->mscp_guse.guse_nrct);
        !           534: #endif
        !           535: }
        !           536:
        !           537: /*
        !           538:  * (Try to) put the drive online. This is done the first time the
        !           539:  * drive is opened, or if it har fallen offline.
        !           540:  */
        !           541: int
        !           542: rx_putonline(rx)
        !           543:        struct rx_softc *rx;
        !           544: {
        !           545:        struct  mscp *mp;
        !           546:        struct  mscp_softc *mi = (struct mscp_softc *)rx->ra_dev.dv_parent;
        !           547:        volatile int i;
        !           548:
        !           549:        rx->ra_state = DK_CLOSED;
        !           550:        mp = mscp_getcp(mi, MSCP_WAIT);
        !           551:        mp->mscp_opcode = M_OP_ONLINE;
        !           552:        mp->mscp_unit = rx->ra_hwunit;
        !           553:        mp->mscp_cmdref = 1;
        !           554:        *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
        !           555:        DELAY(10000);           /* XXX SIMH needs this. */
        !           556:
        !           557:        /* Poll away */
        !           558:        i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
        !           559:        if (tsleep(&rx->ra_dev.dv_unit, PRIBIO, "rxonline", 100*100))
        !           560:                rx->ra_state = DK_CLOSED;
        !           561:
        !           562:        if (rx->ra_state == DK_CLOSED)
        !           563:                return MSCP_FAILED;
        !           564:
        !           565:        return MSCP_DONE;
        !           566: }
        !           567:
        !           568: #if NRX
        !           569:
        !           570: /*
        !           571:  * Open a drive.
        !           572:  */
        !           573: /*ARGSUSED*/
        !           574: int
        !           575: rxopen(dev, flag, fmt, p)
        !           576:        dev_t dev;
        !           577:        int flag, fmt;
        !           578:        struct  proc *p;
        !           579: {
        !           580:        struct rx_softc *rx;
        !           581:        int unit;
        !           582:
        !           583:        /*
        !           584:         * Make sure this is a reasonable open request.
        !           585:         */
        !           586:        unit = DISKUNIT(dev);
        !           587:        if (unit >= rx_cd.cd_ndevs)
        !           588:                return ENXIO;
        !           589:        rx = rx_cd.cd_devs[unit];
        !           590:        if (rx == 0)
        !           591:                return ENXIO;
        !           592:
        !           593:        /*
        !           594:         * If this is the first open; we must first try to put
        !           595:         * the disk online (and read the label).
        !           596:         */
        !           597:        if (rx->ra_state == DK_CLOSED)
        !           598:                if (rx_putonline(rx) == MSCP_FAILED)
        !           599:                        return ENXIO;
        !           600:
        !           601:        return 0;
        !           602: }
        !           603:
        !           604: /* ARGSUSED */
        !           605: int
        !           606: rxclose(dev, flags, fmt, p)
        !           607:        dev_t dev;
        !           608:        int flags, fmt;
        !           609:        struct  proc *p;
        !           610: {
        !           611:        return (0);
        !           612: }
        !           613:
        !           614: /*
        !           615:  * Queue a transfer request, and if possible, hand it to the controller.
        !           616:  *
        !           617:  * This routine is broken into two so that the internal version
        !           618:  * udastrat1() can be called by the (nonexistent, as yet) bad block
        !           619:  * revectoring routine.
        !           620:  */
        !           621: void
        !           622: rxstrategy(bp)
        !           623:        struct buf *bp;
        !           624: {
        !           625:        int unit;
        !           626:        struct rx_softc *rx;
        !           627:        int s;
        !           628:
        !           629:        /*
        !           630:         * Make sure this is a reasonable drive to use.
        !           631:         */
        !           632:        unit = DISKUNIT(bp->b_dev);
        !           633:        if (unit >= rx_cd.cd_ndevs || (rx = rx_cd.cd_devs[unit]) == NULL) {
        !           634:                bp->b_error = ENXIO;
        !           635:                bp->b_flags |= B_ERROR;
        !           636:                goto done;
        !           637:        }
        !           638:
        !           639:        /* If disk is not online, try to put it online */
        !           640:        if (rx->ra_state == DK_CLOSED)
        !           641:                if (rx_putonline(rx) == MSCP_FAILED) {
        !           642:                        bp->b_flags |= B_ERROR;
        !           643:                        bp->b_error = EIO;
        !           644:                        goto done;
        !           645:                }
        !           646:
        !           647:        /*
        !           648:         * Determine the size of the transfer, and make sure it is
        !           649:         * within the boundaries of the partition.
        !           650:         */
        !           651:        if (bp->b_blkno >= DL_GETDSIZE(rx->ra_disk.dk_label)) {
        !           652:                bp->b_resid = bp->b_bcount;
        !           653:                goto done;
        !           654:        }
        !           655:
        !           656:        /* Make some statistics... /bqt */
        !           657:        s = splbio();
        !           658:        disk_busy(&rx->ra_disk);
        !           659:        splx(s);
        !           660:        mscp_strategy(bp, rx->ra_dev.dv_parent);
        !           661:        return;
        !           662:
        !           663: done:
        !           664:        s = splbio();
        !           665:        biodone(bp);
        !           666:        splx(s);
        !           667: }
        !           668:
        !           669: int
        !           670: rxread(dev, uio)
        !           671:        dev_t dev;
        !           672:        struct uio *uio;
        !           673: {
        !           674:
        !           675:        return (physio(rxstrategy, NULL, dev, B_READ, minphys, uio));
        !           676: }
        !           677:
        !           678: int
        !           679: rxwrite(dev, uio)
        !           680:        dev_t dev;
        !           681:        struct uio *uio;
        !           682: {
        !           683:
        !           684:        return (physio(rxstrategy, NULL, dev, B_WRITE, minphys, uio));
        !           685: }
        !           686:
        !           687: /*
        !           688:  * I/O controls.
        !           689:  */
        !           690: int
        !           691: rxioctl(dev, cmd, data, flag, p)
        !           692:        dev_t dev;
        !           693:        int cmd;
        !           694:        caddr_t data;
        !           695:        int flag;
        !           696:        struct proc *p;
        !           697: {
        !           698:        int unit = DISKUNIT(dev);
        !           699:        struct disklabel *lp;
        !           700:        struct rx_softc *rx = rx_cd.cd_devs[unit];
        !           701:        int error = 0;
        !           702:
        !           703:        lp = rx->ra_disk.dk_label;
        !           704:
        !           705:        switch (cmd) {
        !           706:
        !           707:        case DIOCGDINFO:
        !           708:                bcopy(lp, data, sizeof (struct disklabel));
        !           709:                break;
        !           710:
        !           711:        case DIOCGPART:
        !           712:                ((struct partinfo *)data)->disklab = lp;
        !           713:                ((struct partinfo *)data)->part =
        !           714:                    &lp->d_partitions[DISKPART(dev)];
        !           715:                break;
        !           716:
        !           717:
        !           718:        case DIOCWDINFO:
        !           719:        case DIOCSDINFO:
        !           720:        case DIOCWLABEL:
        !           721:                break;
        !           722:
        !           723:        default:
        !           724:                error = ENOTTY;
        !           725:                break;
        !           726:        }
        !           727:        return (error);
        !           728: }
        !           729:
        !           730: int
        !           731: rxdump(dev, blkno, va, size)
        !           732:        dev_t dev;
        !           733:        daddr64_t blkno;
        !           734:        caddr_t va;
        !           735:        size_t size;
        !           736: {
        !           737:
        !           738:        /* Not likely. */
        !           739:        return ENXIO;
        !           740: }
        !           741:
        !           742: daddr64_t
        !           743: rxsize(dev)
        !           744:        dev_t dev;
        !           745: {
        !           746:
        !           747:        return -1;
        !           748: }
        !           749:
        !           750: #endif /* NRX */
        !           751:
        !           752: void   rrdgram(struct device *, struct mscp *, struct mscp_softc *);
        !           753: void   rriodone(struct device *, struct buf *);
        !           754: int    rronline(struct device *, struct mscp *);
        !           755: int    rrgotstatus(struct device *, struct mscp *);
        !           756: void   rrreplace(struct device *, struct mscp *);
        !           757: int    rrioerror(struct device *, struct mscp *, struct buf *);
        !           758: void   rrfillin(struct buf *, struct mscp *);
        !           759: void   rrbb(struct device *, struct mscp *, struct buf *);
        !           760:
        !           761:
        !           762: struct mscp_device ra_device = {
        !           763:        rrdgram,
        !           764:        rriodone,
        !           765:        rronline,
        !           766:        rrgotstatus,
        !           767:        rrreplace,
        !           768:        rrioerror,
        !           769:        rrbb,
        !           770:        rrfillin,
        !           771: };
        !           772:
        !           773: /*
        !           774:  * Handle an error datagram.
        !           775:  * This can come from an unconfigured drive as well.
        !           776:  */
        !           777: void
        !           778: rrdgram(usc, mp, mi)
        !           779:        struct device *usc;
        !           780:        struct mscp *mp;
        !           781:        struct mscp_softc *mi;
        !           782: {
        !           783:        if (mscp_decodeerror(usc == NULL?"unconf disk" : usc->dv_xname, mp, mi))
        !           784:                return;
        !           785:        /*
        !           786:         * SDI status information bytes 10 and 11 are the microprocessor
        !           787:         * error code and front panel code respectively.  These vary per
        !           788:         * drive type and are printed purely for field service information.
        !           789:         */
        !           790:        if (mp->mscp_format == M_FM_SDI)
        !           791:                printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n",
        !           792:                        mp->mscp_erd.erd_sdistat[10],
        !           793:                        mp->mscp_erd.erd_sdistat[11]);
        !           794: }
        !           795:
        !           796: void
        !           797: rriodone(usc, bp)
        !           798:        struct device *usc;
        !           799:        struct buf *bp;
        !           800: {
        !           801:        int s;
        !           802:
        !           803:        s = splbio();
        !           804:        biodone(bp);
        !           805:        splx(s);
        !           806: }
        !           807:
        !           808: /*
        !           809:  * A drive came on line.  Check its type and size.  Return DONE if
        !           810:  * we think the drive is truly on line.         In any case, awaken anyone
        !           811:  * sleeping on the drive on-line-ness.
        !           812:  */
        !           813: int
        !           814: rronline(usc, mp)
        !           815:        struct device *usc;
        !           816:        struct mscp *mp;
        !           817: {
        !           818:        struct rx_softc *rx = (struct rx_softc *)usc;
        !           819:        struct disklabel *dl;
        !           820:
        !           821:        wakeup((caddr_t)&usc->dv_unit);
        !           822:        if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
        !           823:                printf("%s: attempt to bring on line failed: ", usc->dv_xname);
        !           824:                mscp_printevent(mp);
        !           825:                return (MSCP_FAILED);
        !           826:        }
        !           827:
        !           828:        rx->ra_state = DK_OPEN;
        !           829:
        !           830:        dl = rx->ra_disk.dk_label;
        !           831:        DL_SETDSIZE(dl, mp->mscp_onle.onle_unitsize);
        !           832:
        !           833:        if (dl->d_secpercyl) {
        !           834:                dl->d_ncylinders = DL_GETDSIZE(dl) / dl->d_secpercyl;
        !           835:                dl->d_type = DTYPE_MSCP;
        !           836:                dl->d_rpm = 3600;
        !           837:        } else {
        !           838:                dl->d_type = DTYPE_FLOPPY;
        !           839:                dl->d_rpm = 300;
        !           840:        }
        !           841:        rrmakelabel(dl, rx->ra_mediaid);
        !           842:
        !           843:        return (MSCP_DONE);
        !           844: }
        !           845:
        !           846: void
        !           847: rrmakelabel(dl, type)
        !           848:        struct disklabel *dl;
        !           849:        long type;
        !           850: {
        !           851:        int n, p = 0;
        !           852:
        !           853:        dl->d_bbsize = BBSIZE;
        !           854:        dl->d_sbsize = SBSIZE;
        !           855:
        !           856:        /* Create the disk name for disklabel. Phew... */
        !           857:        dl->d_typename[p++] = MSCP_MID_CHAR(2, type);
        !           858:        dl->d_typename[p++] = MSCP_MID_CHAR(1, type);
        !           859:        if (MSCP_MID_ECH(0, type))
        !           860:                dl->d_typename[p++] = MSCP_MID_CHAR(0, type);
        !           861:        n = MSCP_MID_NUM(type);
        !           862:        if (n > 99) {
        !           863:                dl->d_typename[p++] = '1';
        !           864:                n -= 100;
        !           865:        }
        !           866:        if (n > 9) {
        !           867:                dl->d_typename[p++] = (n / 10) + '0';
        !           868:                n %= 10;
        !           869:        }
        !           870:        dl->d_typename[p++] = n + '0';
        !           871:        dl->d_typename[p] = 0;
        !           872:        dl->d_npartitions = MAXPARTITIONS;
        !           873:        DL_SETPSIZE(&dl->d_partitions[0], DL_GETDSIZE(dl));
        !           874:        DL_SETPSIZE(&dl->d_partitions[2], DL_GETDSIZE(dl));
        !           875:        DL_SETPOFFSET(&dl->d_partitions[0], 0);
        !           876:        DL_SETPOFFSET(&dl->d_partitions[2], 0);
        !           877:        dl->d_interleave = dl->d_headswitch = 1;
        !           878:        dl->d_version = 1;
        !           879:        dl->d_magic = dl->d_magic2 = DISKMAGIC;
        !           880:        dl->d_checksum = dkcksum(dl);
        !           881: }
        !           882:
        !           883: /*
        !           884:  * We got some (configured) unit's status.  Return DONE if it succeeded.
        !           885:  */
        !           886: int
        !           887: rrgotstatus(usc, mp)
        !           888:        struct device *usc;
        !           889:        struct mscp *mp;
        !           890: {
        !           891:        if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
        !           892:                printf("%s: attempt to get status failed: ", usc->dv_xname);
        !           893:                mscp_printevent(mp);
        !           894:                return (MSCP_FAILED);
        !           895:        }
        !           896:        /* record for (future) bad block forwarding and whatever else */
        !           897: #ifdef notyet
        !           898:        uda_rasave(ui->ui_unit, mp, 1);
        !           899: #endif
        !           900:        return (MSCP_DONE);
        !           901: }
        !           902:
        !           903: /*
        !           904:  * A replace operation finished.
        !           905:  */
        !           906: /*ARGSUSED*/
        !           907: void
        !           908: rrreplace(usc, mp)
        !           909:        struct device *usc;
        !           910:        struct mscp *mp;
        !           911: {
        !           912:
        !           913:        panic("udareplace");
        !           914: }
        !           915:
        !           916: /*
        !           917:  * A transfer failed.  We get a chance to fix or restart it.
        !           918:  * Need to write the bad block forwaring code first....
        !           919:  */
        !           920: /*ARGSUSED*/
        !           921: int
        !           922: rrioerror(usc, mp, bp)
        !           923:        struct device *usc;
        !           924:        struct mscp *mp;
        !           925:        struct buf *bp;
        !           926: {
        !           927:        struct ra_softc *ra = (void *)usc;
        !           928:        int code = mp->mscp_event;
        !           929:
        !           930:        switch (code & M_ST_MASK) {
        !           931:        /* The unit has fallen offline. Try to figure out why. */
        !           932:        case M_ST_OFFLINE:
        !           933:                bp->b_flags |= B_ERROR;
        !           934:                bp->b_error = EIO;
        !           935:                ra->ra_state = DK_CLOSED;
        !           936:                if (code & M_OFFLINE_UNMOUNTED)
        !           937:                        printf("%s: not mounted/spun down\n", usc->dv_xname);
        !           938:                if (code & M_OFFLINE_DUPLICATE)
        !           939:                        printf("%s: duplicate unit number!!!\n", usc->dv_xname);
        !           940:                return MSCP_DONE;
        !           941:
        !           942:        case M_ST_AVAILABLE:
        !           943:                ra->ra_state = DK_CLOSED; /* Force another online */
        !           944:                return MSCP_DONE;
        !           945:
        !           946:        default:
        !           947:                printf("%s:", usc->dv_xname);
        !           948:                break;
        !           949:        }
        !           950:        return (MSCP_FAILED);
        !           951: }
        !           952:
        !           953: /*
        !           954:  * Fill in disk addresses in a mscp packet waiting for transfer.
        !           955:  */
        !           956: void
        !           957: rrfillin(bp, mp)
        !           958:        struct buf *bp;
        !           959:        struct mscp *mp;
        !           960: {
        !           961:        struct rx_softc *rx = 0; /* Wall */
        !           962:        struct disklabel *lp;
        !           963:        int unit = DISKUNIT(bp->b_dev);
        !           964:        int part = DISKPART(bp->b_dev);
        !           965:
        !           966: #if NRA
        !           967:        if (major(bp->b_dev) == RAMAJOR)
        !           968:                rx = ra_cd.cd_devs[unit];
        !           969: #endif
        !           970: #if NRX
        !           971:        if (major(bp->b_dev) != RAMAJOR)
        !           972:                rx = rx_cd.cd_devs[unit];
        !           973: #endif
        !           974:        lp = rx->ra_disk.dk_label;
        !           975:
        !           976:        mp->mscp_seq.seq_lbn = DL_GETPOFFSET(&lp->d_partitions[part]) + bp->b_blkno;
        !           977:        mp->mscp_unit = rx->ra_hwunit;
        !           978:        mp->mscp_seq.seq_bytecount = bp->b_bcount;
        !           979: }
        !           980:
        !           981: /*
        !           982:  * A bad block related operation finished.
        !           983:  */
        !           984: /*ARGSUSED*/
        !           985: void
        !           986: rrbb(usc, mp, bp)
        !           987:        struct device *usc;
        !           988:        struct mscp *mp;
        !           989:        struct buf *bp;
        !           990: {
        !           991:
        !           992:        panic("udabb");
        !           993: }

CVSweb