summaryrefslogtreecommitdiff
path: root/sys/arch/mvme88k/dev/nvram.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/mvme88k/dev/nvram.c')
-rw-r--r--sys/arch/mvme88k/dev/nvram.c317
1 files changed, 211 insertions, 106 deletions
diff --git a/sys/arch/mvme88k/dev/nvram.c b/sys/arch/mvme88k/dev/nvram.c
index 6a5a10c32c4..f34640f73f8 100644
--- a/sys/arch/mvme88k/dev/nvram.c
+++ b/sys/arch/mvme88k/dev/nvram.c
@@ -1,28 +1,62 @@
+/* $OpenBSD: nvram.c,v 1.2 1998/12/15 05:52:30 smurph Exp $ */
+
+/*
+ * Copyright (c) 1995 Theo de Raadt
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed under OpenBSD by
+ * Theo de Raadt for Willowglen Singapore.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 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/conf.h>
-#include <sys/ioctl.h>
-#include <sys/proc.h>
-#include <sys/tty.h>
-#include <sys/uio.h>
-#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/ioctl.h>
#include <sys/device.h>
-#include <machine/cpu.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+#include <machine/psl.h>
#include <machine/autoconf.h>
-
+#include <machine/cpu.h>
+#include <machine/mioctl.h>
+#include <machine/vmparam.h>
#include <mvme88k/dev/nvramreg.h>
#include <mvme88k/dev/pcctworeg.h>
+
struct nvramsoftc {
struct device sc_dev;
- caddr_t sc_paddr;
- caddr_t sc_vaddr;
- int sc_size;
- volatile struct clockreg *sc_clockreg;
+ void * sc_paddr;
+ void * sc_vaddr;
+ int sc_len;
+ struct clockreg *sc_regs;
};
-int nvrammatch __P((struct device *, void *, void *));
void nvramattach __P((struct device *, struct device *, void *));
+int nvrammatch __P((struct device *, void *, void *));
struct cfattach nvram_ca = {
sizeof(struct nvramsoftc), nvrammatch, nvramattach
@@ -32,101 +66,86 @@ struct cfdriver nvram_cd = {
NULL, "nvram", DV_DULL, 0
};
-/* ARGSUSED */
int
-nvrammatch(struct device *parent, void *self, void *aux)
-{
- struct confargs *ca = aux;
- struct cfdata *cf = self;
- caddr_t base;
- int ret;
-
-#if 0
- if (cputyp != CPU_167 && cputyp != CPU_166
-#ifdef CPU_187
- && cputyp != CPU_187
-#endif
- )
+nvrammatch(parent, vcf, args)
+ struct device *parent;
+ void *vcf, *args;
{
- return 0;
- }
-#endif /* 0 */
-
- if (cputyp != CPU_187) {
- return 0;
- }
-
- /*
- * If bus or name do not match, fail.
- */
- if (ca->ca_bustype != BUS_PCCTWO ||
- strcmp(cf->cf_driver->cd_name, "nvram")) {
- return 0;
- }
-
-
- /* 3 locators base, size, ipl */
- base = (caddr_t)cf->cf_loc[0];
+ struct cfdata *cf = vcf;
+ struct confargs *ca = args;
- if (badpaddr(base, 1) == -1) {
- return 0;
- }
-
- /*
- * Tell our parent our requirements.
- */
- ca->ca_paddr = (caddr_t)cf->cf_loc[0];
- ca->ca_size = NVRAMSIZE;
- ca->ca_ipl = 0;
-
- return 1;
+/*X*/ if (ca->ca_vaddr == (void *)-1)
+/*X*/ return (1);
+ return (!badvaddr(ca->ca_vaddr, 1));
}
-/* ARGSUSED */
void
-nvramattach(struct device *parent, struct device *self, void *aux)
+nvramattach(parent, self, args)
+ struct device *parent, *self;
+ void *args;
{
+ struct confargs *ca = args;
struct nvramsoftc *sc = (struct nvramsoftc *)self;
- struct confargs *ca = aux;
- sc->sc_clockreg = (struct clockreg *)(ca->ca_vaddr + NVRAM_TOD_OFF);
+ sc->sc_paddr = ca->ca_paddr;
+ sc->sc_vaddr = ca->ca_vaddr;
+
+ sc->sc_len = MK48T08_SIZE;
- printf(": MK48T08\n");
+/*X*/ if (sc->sc_vaddr == (void *)-1)
+/*X*/ sc->sc_vaddr = mapiodev((void *)sc->sc_paddr,
+/*X*/ max(sc->sc_len, NBPG));
+/*X*/ if (sc->sc_vaddr == NULL)
+/*X*/ panic("failed to map!\n");
+
+ sc->sc_regs = (struct clockreg *)(sc->sc_vaddr + sc->sc_len -
+ sizeof(struct clockreg));
+
+ printf(": MK48T0%d len %d\n", sc->sc_len / 1024, sc->sc_len);
}
-#if 0
/*
- * Write en/dis-able clock registers. We coordinate so that several
- * writers can run simultaneously.
+ * Return the best possible estimate of the time in the timeval
+ * to which tvp points. We do this by returning the current time
+ * plus the amount of time since the last clock interrupt (clock.c:clkread).
+ *
+ * Check that this time is no less than any previously-reported time,
+ * which could happen around the time of a clock adjustment. Just for fun,
+ * we guarantee that the time will be greater than the value obtained by a
+ * previous call.
*/
void
-clk_wenable(onoff)
- int onoff;
+microtime(tvp)
+ register struct timeval *tvp;
{
- register int s;
- register vm_prot_t prot;/* nonzero => change prot */
- static int writers;
-
- s = splhigh();
- if (onoff)
- prot = writers++ == 0 ? VM_PROT_READ|VM_PROT_WRITE : 0;
- else
- prot = --writers == 0 ? VM_PROT_READ : 0;
+ int s = splhigh();
+ static struct timeval lasttime;
+
+ *tvp = time;
+ tvp->tv_usec;
+ while (tvp->tv_usec > 1000000) {
+ tvp->tv_sec++;
+ tvp->tv_usec -= 1000000;
+ }
+ if (tvp->tv_sec == lasttime.tv_sec &&
+ tvp->tv_usec <= lasttime.tv_usec &&
+ (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
+ tvp->tv_sec++;
+ tvp->tv_usec -= 1000000;
+ }
+ lasttime = *tvp;
splx(s);
- if (prot)
- pmap_changeprot(pmap_kernel(), (vm_offset_t)clockreg, prot, 1);
}
-#endif /* 0 */
/*
- * BCD to hex and hex to BCD.
+ * BCD to decimal and decimal to BCD.
*/
#define FROMBCD(x) (((x) >> 4) * 10 + ((x) & 0xf))
#define TOBCD(x) (((x) / 10 * 16) + ((x) % 10))
#define SECDAY (24 * 60 * 60)
#define SECYR (SECDAY * 365)
-#define LEAPYEAR(y) (((y) % 4 == 0) && ((y) % 100) != 0 || ((y) % 400) == 0)
+#define LEAPYEAR(y) (((y) & 3) == 0)
/*
* This code is defunct after 2068.
@@ -135,7 +154,9 @@ clk_wenable(onoff)
const short dayyr[12] =
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
-chiptotime(int sec, int min, int hour, int day, int mon, int year)
+static u_long
+chiptotime(sec, min, hour, day, mon, year)
+ register int sec, min, hour, day, mon, year;
{
register int days, yr;
@@ -147,7 +168,7 @@ chiptotime(int sec, int min, int hour, int day, int mon, int year)
year = FROMBCD(year) + YEAR0;
/* simple sanity checks */
- if (year < 70 || mon < 1 || mon > 12 || day < 1 || day > 31)
+ if (year < 70 || year > 164 || mon < 1 || mon > 12 || day < 1 || day > 31)
return (0);
days = 0;
for (yr = 70; yr < year; yr++)
@@ -169,7 +190,8 @@ struct chiptime {
int year;
};
-timetochip(struct chiptime *c)
+timetochip(c)
+ register struct chiptime *c;
{
register int t, t2, t3, now = time.tv_sec;
@@ -216,16 +238,14 @@ timetochip(struct chiptime *c)
/*
* Set up the system's time, given a `reasonable' time value.
*/
-void
-inittodr(time_t base)
+void
+inittodr(base)
+ time_t base;
{
- register struct nvramsoftc *sc;
- register volatile struct clockreg *cl;
+ struct nvramsoftc *sc = (struct nvramsoftc *) nvram_cd.cd_devs[0];
+ register struct clockreg *cl = sc->sc_regs;
int sec, min, hour, day, mon, year;
int badbase = 0, waszero = base == 0;
-
- sc = (struct nvramsoftc *)nvram_cd.cd_devs[0];
- cl = sc->sc_clockreg;
if (base < 5 * SECYR) {
/*
@@ -238,7 +258,6 @@ inittodr(time_t base)
base = 21*SECYR + 186*SECDAY + SECDAY/2;
badbase = 1;
}
-
cl->cl_csr |= CLK_READ; /* enable read (stop time) */
sec = cl->cl_sec;
min = cl->cl_min;
@@ -247,11 +266,8 @@ inittodr(time_t base)
mon = cl->cl_month;
year = cl->cl_year;
cl->cl_csr &= ~CLK_READ; /* time wears on */
-
- time.tv_sec = chiptotime(sec, min, hour, day, mon, year);
-
- if (time.tv_sec == 0) {
- printf("WARNING: bad date in battery clock");
+ if ((time.tv_sec = chiptotime(sec, min, hour, day, mon, year)) == 0) {
+ printf("WARNING: bad date in nvram");
/*
* Believe the time in the file system for lack of
* anything better, resetting the clock.
@@ -278,19 +294,15 @@ inittodr(time_t base)
* and when rebooting. Do nothing if the time is not yet known, e.g.,
* when crashing during autoconfig.
*/
-void
-resettodr()
+void resettodr()
{
- register struct nvramsoftc *sc;
- register volatile struct clockreg *cl;
+ struct nvramsoftc *sc = (struct nvramsoftc *) nvram_cd.cd_devs[0];
+ register struct clockreg *cl = sc->sc_regs;
struct chiptime c;
- sc = (struct nvramsoftc *)nvram_cd.cd_devs[0];
-
- if (!time.tv_sec || (cl = sc->sc_clockreg) == NULL)
+ if (!time.tv_sec || cl == NULL)
return;
timetochip(&c);
-
cl->cl_csr |= CLK_WRITE; /* enable write */
cl->cl_sec = c.sec;
cl->cl_min = c.min;
@@ -301,3 +313,96 @@ resettodr()
cl->cl_year = c.year;
cl->cl_csr &= ~CLK_WRITE; /* load them up */
}
+
+/*ARGSUSED*/
+int
+nvramopen(dev, flag, mode)
+ dev_t dev;
+ int flag, mode;
+{
+ if (minor(dev) >= nvram_cd.cd_ndevs ||
+ nvram_cd.cd_devs[minor(dev)] == NULL)
+ return (ENODEV);
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+nvramclose(dev, flag, mode)
+ dev_t dev;
+ int flag, mode;
+{
+
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+nvramioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ caddr_t data;
+ int cmd, flag;
+ struct proc *p;
+{
+ int unit = minor(dev);
+ struct nvramsoftc *sc = (struct nvramsoftc *) nvram_cd.cd_devs[unit];
+ int error = 0;
+
+ switch (cmd) {
+ case MIOCGSIZ:
+ *(int *)data = sc->sc_len;
+ break;
+ default:
+ error = ENOTTY;
+ break;
+ }
+ return (error);
+}
+
+/*ARGSUSED*/
+int
+nvramread(dev, uio, flags)
+ dev_t dev;
+ struct uio *uio;
+ int flags;
+{
+ int unit = minor(dev);
+ struct nvramsoftc *sc = (struct nvramsoftc *) nvram_cd.cd_devs[unit];
+
+ return (memdevrw(sc->sc_vaddr, sc->sc_len, uio, flags));
+}
+
+/*ARGSUSED*/
+int
+nvramwrite(dev, uio, flags)
+ dev_t dev;
+ struct uio *uio;
+ int flags;
+{
+ int unit = minor(dev);
+ struct nvramsoftc *sc = (struct nvramsoftc *) nvram_cd.cd_devs[unit];
+
+ return (memdevrw(sc->sc_vaddr, sc->sc_len, uio, flags));
+}
+
+/*
+ * If the NVRAM is of the 2K variety, an extra 2K of who-knows-what
+ * will also be mmap'd, due to NBPG being 4K. On the MVME147 the NVRAM
+ * repeats, so userland gets two copies back-to-back.
+ */
+int
+nvrammmap(dev, off, prot)
+ dev_t dev;
+ int off, prot;
+{
+ int unit = minor(dev);
+ struct nvramsoftc *sc = (struct nvramsoftc *) nvram_cd.cd_devs[unit];
+
+ if (minor(dev) != 0)
+ return (-1);
+
+ /* allow access only in RAM */
+ if (off > sc->sc_len)
+ return (-1);
+ return (m88k_btop(sc->sc_paddr + off));
+}