diff options
-rw-r--r-- | etc/etc.sparc/MAKEDEV.md | 6 | ||||
-rw-r--r-- | sys/arch/sparc/conf/GENERIC | 5 | ||||
-rw-r--r-- | sys/arch/sparc/conf/files.sparc | 9 | ||||
-rw-r--r-- | sys/arch/sparc/dev/presto.c | 407 | ||||
-rw-r--r-- | sys/arch/sparc/include/conf.h | 5 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/conf.c | 8 |
6 files changed, 432 insertions, 8 deletions
diff --git a/etc/etc.sparc/MAKEDEV.md b/etc/etc.sparc/MAKEDEV.md index 174c415f547..4dfa2e2cf56 100644 --- a/etc/etc.sparc/MAKEDEV.md +++ b/etc/etc.sparc/MAKEDEV.md @@ -1,5 +1,5 @@ vers(__file__, - {-$OpenBSD: MAKEDEV.md,v 1.16 2002/12/05 04:30:21 kjc Exp $-}, + {-$OpenBSD: MAKEDEV.md,v 1.17 2003/04/13 22:55:43 miod Exp $-}, etc.MACHINE)dnl dnl dnl Copyright (c) 2001 Todd T. Fries <todd@OpenBSD.org> @@ -52,6 +52,8 @@ _mkdev(s64_czs, cua[a-z], {-u=${i#cua*} *) echo unknown cua device $i ;; esac M cua$u c major_s64_czs_c Add($n, 128) 660 dialer uucp-})dnl +__devitem(presto, presto*, Prestoserve NVRAM memory)dnl +disk_q(presto)dnl dnl dnl *** MAKEDEV itself dnl @@ -73,6 +75,7 @@ _DEV(xd, 42, 10) _DEV(flo, 54, 16) _DEV(vnd, 110, 8) _DEV(ccd, 23, 9) +_DEV(presto, 25, 26) _TITLE(pty) _DEV(tty, 20) _DEV(pty, 21) @@ -137,6 +140,7 @@ target(all, cd, 0, 1)dnl target(all, sd, 0, 1, 2, 3, 4)dnl target(all, vnd, 0, 1, 2, 3)dnl target(all, ccd, 0, 1, 2, 3)dnl +target(all, presto, 0)dnl target(ramd, fd, 0)dnl target(ramd, sd, 0, 1, 2, 3)dnl target(ramd, rd, 0)dnl diff --git a/sys/arch/sparc/conf/GENERIC b/sys/arch/sparc/conf/GENERIC index 5fa3261bdfe..252a82f6edc 100644 --- a/sys/arch/sparc/conf/GENERIC +++ b/sys/arch/sparc/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.62 2003/03/09 02:30:45 miod Exp $ +# $OpenBSD: GENERIC,v 1.63 2003/04/13 22:55:48 miod Exp $ # $NetBSD: GENERIC,v 1.48 1997/08/23 19:19:01 mjacob Exp $ # Machine architecture; required by config(8) @@ -320,4 +320,7 @@ fd* at fdc0 # the drive itself #fvme* at fga0 # FORCE CPU-5V #daadio* at fvme? addr 0x0 level 1 vect 0x1f # Matrix MD-DAADIO board +# Prestoserve NVRAM +#presto* at sbus? slot ? offset ? + #pseudo-device strip 1 # radio clock diff --git a/sys/arch/sparc/conf/files.sparc b/sys/arch/sparc/conf/files.sparc index de9af4e574a..88e554b3b35 100644 --- a/sys/arch/sparc/conf/files.sparc +++ b/sys/arch/sparc/conf/files.sparc @@ -1,4 +1,4 @@ -# $OpenBSD: files.sparc,v 1.50 2003/03/09 02:30:45 miod Exp $ +# $OpenBSD: files.sparc,v 1.51 2003/04/13 22:55:48 miod Exp $ # $NetBSD: files.sparc,v 1.44 1997/08/31 21:29:16 pk Exp $ # @(#)files.sparc 8.1 (Berkeley) 7/19/93 @@ -321,7 +321,7 @@ device mtty attach mtty at magma device mbpp attach mbpp at magma -file arch/sparc/dev/magma.c magma | mtty | mbpp needs-flag +file arch/sparc/dev/magma.c magma | mtty | mbpp needs-flag device spif {} attach spif at sbus @@ -362,3 +362,8 @@ file arch/sparc/dev/daadio.c daadio needs-flag device tctrl {} attach tctrl at obio file arch/sparc/dev/tctrl.c tctrl needs-flag + +# Prestoserve NVRAM +device presto: disk +attach presto at sbus +file arch/sparc/dev/presto.c presto needs-flag diff --git a/sys/arch/sparc/dev/presto.c b/sys/arch/sparc/dev/presto.c new file mode 100644 index 00000000000..31a6b47fc89 --- /dev/null +++ b/sys/arch/sparc/dev/presto.c @@ -0,0 +1,407 @@ +/* $OpenBSD: presto.c,v 1.1 2003/04/13 22:55:49 miod Exp $ */ +/* + * Copyright (c) 2003, Miodrag Vallat. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/device.h> +#include <sys/ioctl.h> +#include <sys/conf.h> +#include <sys/disk.h> +#include <sys/disklabel.h> +#include <sys/dkio.h> +#include <sys/fcntl.h> +#include <sys/stat.h> + +#include <machine/autoconf.h> +#include <machine/conf.h> + +#include <sparc/dev/sbusvar.h> + +struct presto_softc { + struct device sc_dev; + struct sbusdev sc_sd; + struct disk sc_dk; + + vsize_t sc_memsize; /* total NVRAM size */ + caddr_t sc_mem; /* NVRAM kva */ + char sc_model[16]; /* Prestoserve model */ +}; + +/* + * The beginning of the NVRAM contains a few control and status values + */ + +#define PSERVE_BATTERYSTATUS 0x07 +#define PSBAT_CHARGING 0x10 +#define PSBAT_CONNECTED 0x20 +#define PSBAT_FAULT 0x40 + +#define PSERVE_DATASTATUS 0x0b +#define PSDATA_EMPTY 0x00 +#define PSDATA_SAVED 0x01 + +/* reserved area size - needs to be rounded to a sector size for i/o */ +#define PSERVE_RESERVED 0x0010 +#define PSERVE_OFFSET roundup(PSERVE_RESERVED, DEV_BSIZE) + +void prestostrategy(struct buf *); +void presto_attach(struct device *, struct device *, void *); +void presto_getdisklabel(struct presto_softc *); +int presto_match(struct device *, void *, void *); + +struct cfattach presto_ca = { + sizeof(struct presto_softc), presto_match, presto_attach +}; + +struct cfdriver presto_cd = { + NULL, "presto", DV_DULL +}; + +struct dkdriver presto_dk = { + prestostrategy, +}; + +int +presto_match(struct device *parent, void *vcf, void *aux) +{ + struct confargs *ca = aux; + struct romaux *ra = &ca->ca_ra; + + if (strcmp(ra->ra_name, "MMI,prestoserve") != 0) + return (0); + + if (ra->ra_len < PSERVE_OFFSET) /* no usable memory ? */ + return (0); + + return (1); +} + +void +presto_attach(struct device *parent, struct device *self, void *args) +{ + struct presto_softc *sc = (struct presto_softc *)self; + struct confargs *ca = args; + char *model, *submodel; + u_int8_t status; + + /* Get card parameters */ + model = getpropstring(ca->ca_ra.ra_node, "model"); + if (*model == '\0') + submodel = "fictious"; + else { + submodel = memchr(model, ',', strlen(model)); + if (submodel != NULL) + submodel++; + else + submodel = model; + } + strncpy(sc->sc_model, submodel, 16); + sc->sc_memsize = ca->ca_ra.ra_len; + + printf(": %s\n%s: %d MB NVRAM, ", model, + sc->sc_dev.dv_xname, sc->sc_memsize >> 20); + + /* Map memory */ + sc->sc_mem = (void *)mapiodev(ca->ca_ra.ra_reg, 0, sc->sc_memsize); + + /* + * Clear the ``disconnect battery'' bit. + */ + *(u_int8_t *)(sc->sc_mem + PSERVE_BATTERYSTATUS) = 0x00; + + /* + * Clear the ``unflushed data'' status. This way, if the card is + * reused under SunOS, the system will not try to flush whatever + * data the user put in the nvram... + */ + *(u_int8_t *)(sc->sc_mem + PSERVE_DATASTATUS) = 0x00; + + /* + * Decode battery status + */ + status = *(u_int8_t *)(sc->sc_mem + PSERVE_BATTERYSTATUS); + printf("battery status %x ", status); + if (ISSET(status, PSBAT_FAULT)) { + printf("(non-working)"); + } else if (ISSET(status, PSBAT_CONNECTED)) { + if (ISSET(status, PSBAT_CHARGING)) + printf("(charging)"); + else + printf("(ok)"); + } else + printf("(disabled)"); + printf("\n"); + +#ifdef DEBUG + printf("%s: status codes %02.2x, %02.2x, %02.2x, %02.2x\n", + sc->sc_dev.dv_xname, + *(u_int8_t *)(sc->sc_mem + 0x03), *(u_int8_t *)(sc->sc_mem + 0x07), + *(u_int8_t *)(sc->sc_mem + 0x0b), *(u_int8_t *)(sc->sc_mem + 0x0f)); +#endif + + sbus_establish(&sc->sc_sd, &sc->sc_dev); + + sc->sc_dk.dk_driver = &presto_dk; + sc->sc_dk.dk_name = sc->sc_dev.dv_xname; + disk_attach(&sc->sc_dk); + + /* read the disk label immediately */ + presto_getdisklabel(sc); +} + +/* + * Block device i/o operations + */ + +int +prestodump(dev_t dev, daddr_t blkno, caddr_t va, size_t size) +{ + /* + * A dump to nvram is theoretically possible, but its size is + * very likely to be WAY too small. + */ + return (ENXIO); +} + +int +prestosize(dev_t dev) +{ + struct presto_softc *sc; + int unit, part; + + unit = DISKUNIT(dev); + sc = (struct presto_softc *)device_lookup(&presto_cd, unit); + if (sc == NULL) + return (0); + + part = DISKPART(dev); + if (part >= sc->sc_dk.dk_label->d_npartitions) + return (0); + else + return (sc->sc_dk.dk_label->d_partitions[part].p_size * + (sc->sc_dk.dk_label->d_secsize / DEV_BSIZE)); +} + +int +prestoopen(dev_t dev, int flag, int fmt, struct proc *proc) +{ + int unit, part; + struct presto_softc *sc; + + unit = DISKUNIT(dev); + sc = (struct presto_softc *)device_lookup(&presto_cd, unit); + if (sc == NULL) + return (ENXIO); + + /* only allow valid partitions */ + part = DISKPART(dev); + if (part != RAW_PART && + (part >= sc->sc_dk.dk_label->d_npartitions || + sc->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) + return (ENXIO); + + /* update open masks */ + switch (fmt) { + case S_IFCHR: + sc->sc_dk.dk_copenmask |= (1 << part); + break; + case S_IFBLK: + sc->sc_dk.dk_bopenmask |= (1 << part); + break; + } + sc->sc_dk.dk_openmask = sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask; + + return (0); +} + +int +prestoclose(dev_t dev, int flag, int fmt, struct proc *proc) +{ + int unit, part; + struct presto_softc *sc; + + unit = DISKUNIT(dev); + sc = (struct presto_softc *)device_lookup(&presto_cd, unit); + + /* update open masks */ + part = DISKPART(dev); + switch (fmt) { + case S_IFCHR: + sc->sc_dk.dk_copenmask &= ~(1 << part); + break; + case S_IFBLK: + sc->sc_dk.dk_bopenmask &= ~(1 << part); + break; + } + sc->sc_dk.dk_openmask = sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask; + + return (0); +} + +int +prestoread(dev_t dev, struct uio *uio, int flags) +{ + return (physio(prestostrategy, NULL, dev, B_READ, minphys, uio)); +} + +int +prestowrite(dev_t dev, struct uio *uio, int flags) +{ + return (physio(prestostrategy, NULL, dev, B_WRITE, minphys, uio)); +} + +void +prestostrategy(struct buf *bp) +{ + int unit, part; + struct presto_softc *sc; + size_t offset, count; + int s; + + unit = DISKUNIT(bp->b_dev); + sc = (struct presto_softc *)device_lookup(&presto_cd, unit); + + /* Sort rogue requests out */ + if (sc == NULL || bp->b_blkno < 0 || + (bp->b_bcount % sc->sc_dk.dk_label->d_secsize) != 0) { + bp->b_error = EINVAL; + goto bad; + } + + /* Do not write on "no trespassing" areas... */ + part = DISKPART(bp->b_dev); + if (part != RAW_PART && + bounds_check_with_label(bp, sc->sc_dk.dk_label, + sc->sc_dk.dk_cpulabel, 1) <= 0) + goto bad; + + /* Bound the request size, then move data between buf and nvram */ + bp->b_resid = bp->b_bcount; + offset = (bp->b_blkno << DEV_BSHIFT) + PSERVE_OFFSET; + count = bp->b_bcount; + if (count > (sc->sc_memsize - offset)) + count = (sc->sc_memsize - offset); + if (ISSET(bp->b_flags, B_READ)) + bcopy(sc->sc_mem + offset, bp->b_data, count); + else + bcopy(bp->b_data, sc->sc_mem + offset, count); + bp->b_resid -= count; + goto done; + +bad: + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + +done: + s = splbio(); + biodone(bp); + splx(s); +} + +int +prestoioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *proc) +{ + struct presto_softc *sc; + int unit; + int error; + + unit = DISKUNIT(dev); + sc = (struct presto_softc *)device_lookup(&presto_cd, unit); + + switch (cmd) { + case DIOCGDINFO: + bcopy(sc->sc_dk.dk_label, data, sizeof(struct disklabel)); + return (0); + + case DIOCSDINFO: + if ((flag & FWRITE) == 0) + return (EBADF); + + error = setdisklabel(sc->sc_dk.dk_label, + (struct disklabel *)data, /*sd->sc_dk.dk_openmask : */0, + sc->sc_dk.dk_cpulabel); + return (error); + + case DIOCWDINFO: + if ((flag & FWRITE) == 0) + return (EBADF); + + error = setdisklabel(sc->sc_dk.dk_label, + (struct disklabel *)data, /*sd->sc_dk.dk_openmask : */0, + sc->sc_dk.dk_cpulabel); + if (error == 0) { + error = writedisklabel(DISKLABELDEV(dev), + prestostrategy, sc->sc_dk.dk_label, + sc->sc_dk.dk_cpulabel); + } + + return (error); + default: + return (EINVAL); + } +} + +/* + * Read the disklabel. If none is present, use a fictious one instead. + */ +void +presto_getdisklabel(struct presto_softc *sc) +{ + struct disklabel *lp = sc->sc_dk.dk_label; + + bzero(sc->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel)); + bzero(sc->sc_dk.dk_label, sizeof(struct disklabel)); + + lp->d_secsize = 1 << DEV_BSHIFT; + lp->d_ntracks = 1; + lp->d_nsectors = 32; + lp->d_secperunit = (sc->sc_memsize - PSERVE_OFFSET) >> DEV_BSHIFT; + lp->d_ncylinders = lp->d_secperunit / lp->d_nsectors; + lp->d_secpercyl = lp->d_nsectors; + + strncpy(lp->d_typename, "Prestoserve", 16); + lp->d_type = DTYPE_SCSI; /* what better to put here? */ + strncpy(lp->d_packname, sc->sc_model, 16); + lp->d_rpm = 3600; + lp->d_interleave = 1; + lp->d_flags = D_RAMDISK; + + lp->d_partitions[RAW_PART].p_offset = 0; + lp->d_partitions[RAW_PART].p_size = + lp->d_secperunit * (lp->d_secsize / DEV_BSIZE); + lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; + lp->d_npartitions = RAW_PART + 1; + + lp->d_magic = DISKMAGIC; + lp->d_magic2 = DISKMAGIC; + lp->d_checksum = dkcksum(lp); + + readdisklabel(DISKLABELDEV(sc->sc_dev.dv_unit), prestostrategy, + sc->sc_dk.dk_label, sc->sc_dk.dk_cpulabel, 0); +} diff --git a/sys/arch/sparc/include/conf.h b/sys/arch/sparc/include/conf.h index bcd92828dce..bc817336879 100644 --- a/sys/arch/sparc/include/conf.h +++ b/sys/arch/sparc/include/conf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.h,v 1.16 2002/08/12 10:44:04 miod Exp $ */ +/* $OpenBSD: conf.h,v 1.17 2003/04/13 22:55:51 miod Exp $ */ /* $NetBSD: conf.h,v 1.8 1996/12/31 07:12:43 mrg Exp $ */ /* @@ -60,6 +60,9 @@ cdev_decl(xd); bdev_decl(xy); cdev_decl(xy); +bdev_decl(presto); +cdev_decl(presto); + /* open, close, write, ioctl */ #define cdev_bpp_init(c,n) { \ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ diff --git a/sys/arch/sparc/sparc/conf.c b/sys/arch/sparc/sparc/conf.c index 81468843eed..5e68aff6dd6 100644 --- a/sys/arch/sparc/sparc/conf.c +++ b/sys/arch/sparc/sparc/conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.c,v 1.35 2002/12/05 02:49:55 kjc Exp $ */ +/* $OpenBSD: conf.c,v 1.36 2003/04/13 22:55:52 miod Exp $ */ /* $NetBSD: conf.c,v 1.40 1996/04/11 19:20:03 thorpej Exp $ */ /* @@ -70,6 +70,7 @@ #include "st.h" #include "cd.h" #include "rd.h" +#include "presto.h" #include "zstty.h" @@ -123,6 +124,7 @@ struct bdevsw bdevsw[] = bdev_lkm_dummy(), /* 23 */ bdev_lkm_dummy(), /* 24 */ bdev_disk_init(NRAID,raid), /* 25: RAIDframe disk driver */ + bdev_disk_init(NPRESTO,presto), /* 26: Prestoserve NVRAM */ }; int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); @@ -157,7 +159,7 @@ struct cdevsw cdevsw[] = cdev_notdef(), /* 22: was /dev/fb */ cdev_disk_init(NCCD,ccd), /* 23: concatenated disk driver */ cdev_fd_init(1,filedesc), /* 24: file descriptor pseudo-device */ - cdev_notdef(), /* 25 */ + cdev_disk_init(NPRESTO,presto), /* 25: Prestoserve NVRAM */ cdev_notdef(), /* 26 */ cdev_notdef(), /* 27: was /dev/bwtwo */ cdev_notdef(), /* 28 */ @@ -332,7 +334,7 @@ static int chrtoblktbl[] = { /* 22 */ NODEV, /* 23 */ 9, /* 24 */ NODEV, - /* 25 */ NODEV, + /* 25 */ 26, /* 26 */ NODEV, /* 27 */ NODEV, /* 28 */ NODEV, |