summaryrefslogtreecommitdiff
path: root/sys/arch/sparc
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/sparc')
-rw-r--r--sys/arch/sparc/conf/GENERIC5
-rw-r--r--sys/arch/sparc/conf/files.sparc9
-rw-r--r--sys/arch/sparc/dev/presto.c407
-rw-r--r--sys/arch/sparc/include/conf.h5
-rw-r--r--sys/arch/sparc/sparc/conf.c8
5 files changed, 427 insertions, 7 deletions
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,