[BACK]Return to presto.c CVS log [TXT][DIR] Up to [local] / sys / arch / sparc / dev

Annotation of sys/arch/sparc/dev/presto.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: presto.c,v 1.13 2007/06/20 18:15:47 deraadt Exp $     */
                      2: /*
                      3:  * Copyright (c) 2003, Miodrag Vallat.
                      4:  * All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     16:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     18:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     19:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     20:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     21:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     23:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     24:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     25:  * POSSIBILITY OF SUCH DAMAGE.
                     26:  *
                     27:  */
                     28:
                     29: #include <sys/param.h>
                     30: #include <sys/systm.h>
                     31: #include <sys/buf.h>
                     32: #include <sys/device.h>
                     33: #include <sys/ioctl.h>
                     34: #include <sys/conf.h>
                     35: #include <sys/disk.h>
                     36: #include <sys/disklabel.h>
                     37: #include <sys/dkio.h>
                     38: #include <sys/fcntl.h>
                     39: #include <sys/stat.h>
                     40:
                     41: #include <machine/autoconf.h>
                     42: #include <machine/conf.h>
                     43:
                     44: #include <sparc/dev/sbusvar.h>
                     45:
                     46: struct presto_softc {
                     47:        struct  device  sc_dev;
                     48:        struct  disk    sc_dk;
                     49:
                     50:        vsize_t         sc_memsize;     /* total NVRAM size */
                     51:        caddr_t         sc_mem;         /* NVRAM kva */
                     52:        char            sc_model[16];   /* Prestoserve model */
                     53: };
                     54:
                     55: /*
                     56:  * The beginning of the NVRAM contains a few control and status values
                     57:  */
                     58:
                     59: #define        PSERVE_BATTERYSTATUS    0x07
                     60: #define        PSBAT_CHARGING                  0x10
                     61: #define        PSBAT_CONNECTED                 0x20
                     62: #define        PSBAT_FAULT                     0x40
                     63:
                     64: #define        PSERVE_DATASTATUS       0x0b
                     65: #define        PSDATA_EMPTY                    0x00
                     66: #define        PSDATA_SAVED                    0x01
                     67:
                     68: /* reserved area size - needs to be rounded to a sector size for i/o */
                     69: #define        PSERVE_RESERVED         0x0010
                     70: #define        PSERVE_OFFSET           roundup(PSERVE_RESERVED, DEV_BSIZE)
                     71:
                     72: void   prestostrategy(struct buf *);
                     73: void   presto_attach(struct device *, struct device *, void *);
                     74: void   presto_getdisklabel(dev_t, struct presto_softc *);
                     75: int    presto_match(struct device *, void *, void *);
                     76:
                     77: struct cfattach presto_ca = {
                     78:        sizeof(struct presto_softc), presto_match, presto_attach
                     79: };
                     80:
                     81: struct cfdriver presto_cd = {
                     82:        NULL, "presto", DV_DULL
                     83: };
                     84:
                     85: struct dkdriver        presto_dk = {
                     86:        prestostrategy,
                     87: };
                     88:
                     89: int
                     90: presto_match(struct device *parent, void *vcf, void *aux)
                     91: {
                     92:        struct confargs *ca = aux;
                     93:        struct romaux *ra = &ca->ca_ra;
                     94:
                     95:        if (strcmp(ra->ra_name, "MMI,prestoserve") != 0)
                     96:                return (0);
                     97:
                     98:        if (ra->ra_len < PSERVE_OFFSET) /* no usable memory ? */
                     99:                return (0);
                    100:
                    101:        return (1);
                    102: }
                    103:
                    104: void
                    105: presto_attach(struct device *parent, struct device *self, void *args)
                    106: {
                    107:        struct presto_softc *sc = (struct presto_softc *)self;
                    108:        struct confargs *ca = args;
                    109:        char *model, *submodel;
                    110:        u_int8_t status;
                    111:
                    112:        /* Get card parameters */
                    113:        model = getpropstring(ca->ca_ra.ra_node, "model");
                    114:        if (*model == '\0')
                    115:                submodel = "fictitious";
                    116:        else {
                    117:                submodel = memchr(model, ',', strlen(model));
                    118:                if (submodel != NULL)
                    119:                        submodel++;
                    120:                else
                    121:                        submodel = model;
                    122:        }
                    123:        strncpy(sc->sc_model, submodel, 16);
                    124:        sc->sc_memsize = ca->ca_ra.ra_len;
                    125:
                    126:        printf(": %s\n%s: %d MB NVRAM, ", model,
                    127:            sc->sc_dev.dv_xname, sc->sc_memsize >> 20);
                    128:
                    129:        /* Map memory */
                    130:        sc->sc_mem = (void *)mapiodev(ca->ca_ra.ra_reg, 0, sc->sc_memsize);
                    131:
                    132:        /*
                    133:         * Clear the ``disconnect battery'' bit.
                    134:         */
                    135:        *(u_int8_t *)(sc->sc_mem + PSERVE_BATTERYSTATUS) = 0x00;
                    136:
                    137:        /*
                    138:         * Clear the ``unflushed data'' status. This way, if the card is
                    139:         * reused under SunOS, the system will not try to flush whatever
                    140:         * data the user put in the nvram...
                    141:         */
                    142:        *(u_int8_t *)(sc->sc_mem + PSERVE_DATASTATUS) = 0x00;
                    143:
                    144:        /*
                    145:         * Decode battery status
                    146:         */
                    147:        status = *(u_int8_t *)(sc->sc_mem + PSERVE_BATTERYSTATUS);
                    148:        printf("battery status %x ", status);
                    149:        if (ISSET(status, PSBAT_FAULT)) {
                    150:                printf("(non-working)");
                    151:        } else if (ISSET(status, PSBAT_CONNECTED)) {
                    152:                if (ISSET(status, PSBAT_CHARGING))
                    153:                        printf("(charging)");
                    154:                else
                    155:                        printf("(ok)");
                    156:        } else
                    157:                printf("(disabled)");
                    158:        printf("\n");
                    159:
                    160: #ifdef DEBUG
                    161:        printf("%s: status codes %02.2x, %02.2x, %02.2x, %02.2x\n",
                    162:            sc->sc_dev.dv_xname,
                    163:            *(u_int8_t *)(sc->sc_mem + 0x03), *(u_int8_t *)(sc->sc_mem + 0x07),
                    164:            *(u_int8_t *)(sc->sc_mem + 0x0b), *(u_int8_t *)(sc->sc_mem + 0x0f));
                    165: #endif
                    166:
                    167:        sc->sc_dk.dk_driver = &presto_dk;
                    168:        sc->sc_dk.dk_name = sc->sc_dev.dv_xname;
                    169:        disk_attach(&sc->sc_dk);
                    170: }
                    171:
                    172: /*
                    173:  * Block device i/o operations
                    174:  */
                    175:
                    176: int
                    177: prestodump(dev_t dev, daddr64_t blkno, caddr_t va, size_t size)
                    178: {
                    179:        /*
                    180:         * A dump to nvram is theoretically possible, but its size is
                    181:         * very likely to be WAY too small.
                    182:         */
                    183:        return (ENXIO);
                    184: }
                    185:
                    186: daddr64_t
                    187: prestosize(dev_t dev)
                    188: {
                    189:        struct presto_softc *sc;
                    190:        int unit, part;
                    191:
                    192:        unit = DISKUNIT(dev);
                    193:        sc = (struct presto_softc *)device_lookup(&presto_cd, unit);
                    194:        if (sc == NULL)
                    195:                return (0);
                    196:
                    197:        part = DISKPART(dev);
                    198:        if (part >= sc->sc_dk.dk_label->d_npartitions)
                    199:                return (0);
                    200:        else
                    201:                return (DL_GETPSIZE(&sc->sc_dk.dk_label->d_partitions[part]) *
                    202:                    (sc->sc_dk.dk_label->d_secsize / DEV_BSIZE));
                    203: }
                    204:
                    205: int
                    206: prestoopen(dev_t dev, int flag, int fmt, struct proc *proc)
                    207: {
                    208:        int unit, part;
                    209:        struct presto_softc *sc;
                    210:
                    211:        unit = DISKUNIT(dev);
                    212:        sc = (struct presto_softc *)device_lookup(&presto_cd, unit);
                    213:        if (sc == NULL)
                    214:                return (ENXIO);
                    215:
                    216:        /* read the disk label */
                    217:        presto_getdisklabel(dev, sc);
                    218:
                    219:        /* only allow valid partitions */
                    220:        part = DISKPART(dev);
                    221:        if (part != RAW_PART &&
                    222:            (part >= sc->sc_dk.dk_label->d_npartitions ||
                    223:            sc->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED))
                    224:                return (ENXIO);
                    225:
                    226:        /* update open masks */
                    227:        switch (fmt) {
                    228:        case S_IFCHR:
                    229:                sc->sc_dk.dk_copenmask |= (1 << part);
                    230:                break;
                    231:        case S_IFBLK:
                    232:                sc->sc_dk.dk_bopenmask |= (1 << part);
                    233:                break;
                    234:        }
                    235:        sc->sc_dk.dk_openmask = sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
                    236:
                    237:        return (0);
                    238: }
                    239:
                    240: int
                    241: prestoclose(dev_t dev, int flag, int fmt, struct proc *proc)
                    242: {
                    243:        int unit, part;
                    244:        struct presto_softc *sc;
                    245:
                    246:        unit = DISKUNIT(dev);
                    247:        sc = (struct presto_softc *)device_lookup(&presto_cd, unit);
                    248:
                    249:        /* update open masks */
                    250:        part = DISKPART(dev);
                    251:        switch (fmt) {
                    252:        case S_IFCHR:
                    253:                sc->sc_dk.dk_copenmask &= ~(1 << part);
                    254:                break;
                    255:        case S_IFBLK:
                    256:                sc->sc_dk.dk_bopenmask &= ~(1 << part);
                    257:                break;
                    258:        }
                    259:        sc->sc_dk.dk_openmask = sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
                    260:
                    261:        return (0);
                    262: }
                    263:
                    264: int
                    265: prestoread(dev_t dev, struct uio *uio, int flags)
                    266: {
                    267:        return (physio(prestostrategy, NULL, dev, B_READ, minphys, uio));
                    268: }
                    269:
                    270: int
                    271: prestowrite(dev_t dev, struct uio *uio, int flags)
                    272: {
                    273:        return (physio(prestostrategy, NULL, dev, B_WRITE, minphys, uio));
                    274: }
                    275:
                    276: void
                    277: prestostrategy(struct buf *bp)
                    278: {
                    279:        int unit, part;
                    280:        struct presto_softc *sc;
                    281:        size_t offset, count;
                    282:        int s;
                    283:
                    284:        unit = DISKUNIT(bp->b_dev);
                    285:        sc = (struct presto_softc *)device_lookup(&presto_cd, unit);
                    286:
                    287:        /* Sort rogue requests out */
                    288:        if (sc == NULL || bp->b_blkno < 0 ||
                    289:            (bp->b_bcount % sc->sc_dk.dk_label->d_secsize) != 0) {
                    290:                bp->b_error = EINVAL;
                    291:                goto bad;
                    292:        }
                    293:
                    294:        /* Do not write on "no trespassing" areas... */
                    295:        part = DISKPART(bp->b_dev);
                    296:        if (part != RAW_PART &&
                    297:            bounds_check_with_label(bp, sc->sc_dk.dk_label, 1) <= 0)
                    298:                goto bad;
                    299:
                    300:        /* Bound the request size, then move data between buf and nvram */
                    301:        bp->b_resid = bp->b_bcount;
                    302:        offset = (bp->b_blkno << DEV_BSHIFT) + PSERVE_OFFSET;
                    303:        count = bp->b_bcount;
                    304:        if (count > (sc->sc_memsize - offset))
                    305:                count = (sc->sc_memsize - offset);
                    306:        if (ISSET(bp->b_flags, B_READ))
                    307:                bcopy(sc->sc_mem + offset, bp->b_data, count);
                    308:        else
                    309:                bcopy(bp->b_data, sc->sc_mem + offset, count);
                    310:        bp->b_resid -= count;
                    311:        goto done;
                    312:
                    313: bad:
                    314:        bp->b_flags |= B_ERROR;
                    315:        bp->b_resid = bp->b_bcount;
                    316:
                    317: done:
                    318:        s = splbio();
                    319:        biodone(bp);
                    320:        splx(s);
                    321: }
                    322:
                    323: int
                    324: prestoioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *proc)
                    325: {
                    326:        struct presto_softc *sc;
                    327:        int unit;
                    328:        int error;
                    329:
                    330:        unit = DISKUNIT(dev);
                    331:        sc = (struct presto_softc *)device_lookup(&presto_cd, unit);
                    332:
                    333:        switch (cmd) {
                    334:        case DIOCGDINFO:
                    335:                bcopy(sc->sc_dk.dk_label, data, sizeof(struct disklabel));
                    336:                return (0);
                    337:
                    338:        case DIOCSDINFO:
                    339:                if ((flag & FWRITE) == 0)
                    340:                        return (EBADF);
                    341:
                    342:                error = setdisklabel(sc->sc_dk.dk_label,
                    343:                    (struct disklabel *)data, /*sd->sc_dk.dk_openmask : */0);
                    344:                return (error);
                    345:
                    346:        case DIOCWDINFO:
                    347:                if ((flag & FWRITE) == 0)
                    348:                        return (EBADF);
                    349:
                    350:                error = setdisklabel(sc->sc_dk.dk_label,
                    351:                    (struct disklabel *)data, /*sd->sc_dk.dk_openmask : */0);
                    352:                if (error == 0) {
                    353:                        error = writedisklabel(DISKLABELDEV(dev),
                    354:                            prestostrategy, sc->sc_dk.dk_label);
                    355:                }
                    356:
                    357:                return (error);
                    358:        default:
                    359:                return (EINVAL);
                    360:        }
                    361: }
                    362:
                    363: /*
                    364:  * Read the disklabel. If none is present, use a fictitious one instead.
                    365:  */
                    366: void
                    367: presto_getdisklabel(dev_t dev, struct presto_softc *sc)
                    368: {
                    369:        struct disklabel *lp = sc->sc_dk.dk_label;
                    370:
                    371:        bzero(sc->sc_dk.dk_label, sizeof(struct disklabel));
                    372:
                    373:        lp->d_secsize = DEV_BSIZE;
                    374:        lp->d_ntracks = 1;
                    375:        lp->d_nsectors = 32;
                    376:        DL_SETDSIZE(lp, (sc->sc_memsize - PSERVE_OFFSET) >> DEV_BSHIFT);
                    377:        lp->d_ncylinders = DL_GETDSIZE(lp) / lp->d_nsectors;
                    378:        lp->d_secpercyl = lp->d_nsectors;
                    379:
                    380:        strncpy(lp->d_typename, "Prestoserve", 16);
                    381:        lp->d_type = DTYPE_SCSI;        /* what better to put here? */
                    382:        strncpy(lp->d_packname, sc->sc_model, 16);
                    383:        lp->d_rpm = 3600;
                    384:        lp->d_interleave = 1;
                    385:        lp->d_version = 1;
                    386:
                    387:        lp->d_magic = DISKMAGIC;
                    388:        lp->d_magic2 = DISKMAGIC;
                    389:        lp->d_checksum = dkcksum(lp);
                    390:
                    391:        readdisklabel(DISKLABELDEV(dev), prestostrategy, sc->sc_dk.dk_label, 0);
                    392: }

CVSweb