summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDale S. Rahn <rahnds@cvs.openbsd.org>1996-12-23 00:32:58 +0000
committerDale S. Rahn <rahnds@cvs.openbsd.org>1996-12-23 00:32:58 +0000
commit4d28f11436de1342c38ec5db96ef30e891b18b66 (patch)
tree9c2f42588482ca38cd9d87e75526e93d30c08c76
parentb98ae97fdfd4cae418247cb7fff8c1cf989e83f4 (diff)
Import of Openfirmware device drivers for PowerPC port.
From NetBSD, with modification to get current time in kernel.
-rw-r--r--sys/dev/ofw/files.ofw38
-rw-r--r--sys/dev/ofw/ofbus.c147
-rw-r--r--sys/dev/ofw/ofcons.c351
-rw-r--r--sys/dev/ofw/ofdisk.c374
-rw-r--r--sys/dev/ofw/ofnet.c456
-rw-r--r--sys/dev/ofw/ofrtc.c260
-rw-r--r--sys/dev/ofw/openfirm.h94
7 files changed, 1720 insertions, 0 deletions
diff --git a/sys/dev/ofw/files.ofw b/sys/dev/ofw/files.ofw
new file mode 100644
index 00000000000..799d1783bb9
--- /dev/null
+++ b/sys/dev/ofw/files.ofw
@@ -0,0 +1,38 @@
+#
+# First cut on Openfirmware interface
+#
+
+define openfirm {}
+
+# Generic disk support
+device ofdisk: disk
+attach ofdisk at openfirm
+file dev/ofw/ofdisk.c ofdisk needs-flag
+
+# Generic net support
+#define ipkdbofn { [ disable = 0 ] }
+#device ofnet: ether, ifnet, ipkdbofn
+device ofnet: ether, ifnet
+#device ipkdbif: ether, ifnet
+attach ofnet at openfirm
+file dev/ofw/ofnet.c ofnet | ipkdb_ofn needs-flag
+#attach ipkdbif at ipkdbofn with ipkdb_ofn
+
+# Generic console support
+device ofcons: tty
+attach ofcons at openfirm
+file dev/ofw/ofcons.c ofcons needs-flag
+
+# Generic RTC support
+device ofrtc
+attach ofrtc at openfirm
+file dev/ofw/ofrtc.c ofrtc needs-flag
+
+# Generic bus support
+device ofbus: openfirm
+attach ofbus at openfirm
+file dev/ofw/ofbus.c openfirm
+
+device ofroot: openfirm
+attach ofroot at root
+
diff --git a/sys/dev/ofw/ofbus.c b/sys/dev/ofw/ofbus.c
new file mode 100644
index 00000000000..1f335dff3dc
--- /dev/null
+++ b/sys/dev/ofw/ofbus.c
@@ -0,0 +1,147 @@
+/* $NetBSD: ofbus.c,v 1.3 1996/10/13 01:38:11 christos Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996 Wolfgang Solfrank.
+ * Copyright (C) 1995, 1996 TooLs GmbH.
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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/device.h>
+
+#include <dev/ofw/openfirm.h>
+
+int ofbprobe __P((struct device *, void *, void *));
+void ofbattach __P((struct device *, struct device *, void *));
+static int ofbprint __P((void *, const char *));
+
+struct cfattach ofbus_ca = {
+ sizeof(struct device), ofbprobe, ofbattach
+};
+
+struct cfdriver ofbus_cd = {
+ NULL, "ofbus", DV_DULL
+};
+
+struct cfattach ofroot_ca = {
+ sizeof(struct device), ofbprobe, ofbattach
+};
+
+struct cfdriver ofroot_cd = {
+ NULL, "ofroot", DV_DULL
+};
+
+static int
+ofbprint(aux, name)
+ void *aux;
+ const char *name;
+{
+ struct ofprobe *ofp = aux;
+ char child[64];
+ int l;
+
+ if ((l = OF_getprop(ofp->phandle, "name", child, sizeof child - 1)) < 0)
+ panic("device without name?");
+ if (l >= sizeof child)
+ l = sizeof child - 1;
+ child[l] = 0;
+
+ if (name)
+ printf("%s at %s", child, name);
+ else
+ printf(" (%s)", child);
+ return UNCONF;
+}
+
+int
+ofbprobe(parent, cf, aux)
+ struct device *parent;
+ void *cf, *aux;
+{
+ struct ofprobe *ofp = aux;
+
+ if (!OF_child(ofp->phandle))
+ return 0;
+ return 1;
+}
+
+void
+ofbattach(parent, dev, aux)
+ struct device *parent, *dev;
+ void *aux;
+{
+ int child;
+ char name[5];
+ struct ofprobe *ofp = aux;
+ struct ofprobe probe;
+ int units;
+
+ if (!parent)
+ ofbprint(aux, 0);
+
+ printf("\n");
+
+ /*
+ * This is a hack to make the probe work on the scsi (and ide) bus.
+ * YES, I THINK IT IS A BUG IN THE OPENFIRMWARE TO NOT PROBE ALL
+ * DEVICES ON THESE BUSSES.
+ */
+ units = 1;
+ if (OF_getprop(ofp->phandle, "name", name, sizeof name) > 0) {
+ if (!strcmp(name, "scsi"))
+ units = 7; /* What about wide or hostid != 7? XXX */
+ else if (!strcmp(name, "ide"))
+ units = 2;
+ }
+ for (child = OF_child(ofp->phandle); child; child = OF_peer(child)) {
+ /*
+ * This is a hack to skip all the entries in the tree
+ * that aren't devices (packages, openfirmware etc.).
+ */
+ if (OF_getprop(child, "device_type", name, sizeof name) < 0)
+ continue;
+ probe.phandle = child;
+ for (probe.unit = 0; probe.unit < units; probe.unit++)
+ config_found(dev, &probe, ofbprint);
+ }
+}
+
+/*
+ * Name matching routine for OpenFirmware
+ */
+int
+ofnmmatch(cp1, cp2)
+ char *cp1, *cp2;
+{
+ int i;
+
+ for (i = 0; *cp2; i++)
+ if (*cp1++ != *cp2++)
+ return 0;
+ return i;
+}
diff --git a/sys/dev/ofw/ofcons.c b/sys/dev/ofw/ofcons.c
new file mode 100644
index 00000000000..58883cfc0b1
--- /dev/null
+++ b/sys/dev/ofw/ofcons.c
@@ -0,0 +1,351 @@
+/* $NetBSD: ofcons.c,v 1.3 1996/10/13 01:38:11 christos Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996 Wolfgang Solfrank.
+ * Copyright (C) 1995, 1996 TooLs GmbH.
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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/device.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/tty.h>
+
+#include <dev/cons.h>
+
+#include <dev/ofw/openfirm.h>
+
+struct ofc_softc {
+ struct device of_dev;
+ struct tty *of_tty;
+ int of_flags;
+};
+/* flags: */
+#define OFPOLL 1
+
+#define OFBURSTLEN 128 /* max number of bytes to write in one chunk */
+
+static int stdin, stdout;
+
+static int ofcmatch __P((struct device *, void *, void *));
+static void ofcattach __P((struct device *, struct device *, void *));
+
+struct cfattach ofcons_ca = {
+ sizeof(struct ofc_softc), ofcmatch, ofcattach
+};
+
+struct cfdriver ofcons_cd = {
+ NULL, "ofcons", DV_TTY
+};
+
+static int ofcprobe __P((void));
+
+static int
+ofcmatch(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct ofprobe *ofp = aux;
+
+ if (!ofcprobe())
+ return 0;
+ return OF_instance_to_package(stdin) == ofp->phandle
+ || OF_instance_to_package(stdout) == ofp->phandle;
+}
+
+static void
+ofcattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ printf("\n");
+}
+
+static void ofcstart __P((struct tty *));
+static int ofcparam __P((struct tty *, struct termios *));
+static void ofcpoll __P((void *));
+
+int
+ofcopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ struct ofc_softc *sc;
+ int unit = minor(dev);
+ struct tty *tp;
+
+ if (unit >= ofcons_cd.cd_ndevs)
+ return ENXIO;
+ sc = ofcons_cd.cd_devs[unit];
+ if (!sc)
+ return ENXIO;
+ if (!(tp = sc->of_tty))
+ sc->of_tty = tp = ttymalloc();
+ tp->t_oproc = ofcstart;
+ tp->t_param = ofcparam;
+ tp->t_dev = dev;
+ if (!(tp->t_state & TS_ISOPEN)) {
+ tp->t_state |= TS_WOPEN;
+ ttychars(tp);
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ tp->t_cflag = TTYDEF_CFLAG;
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
+ ofcparam(tp, &tp->t_termios);
+ ttsetwater(tp);
+ } else if ((tp->t_state&TS_XCLUDE) && suser(p->p_ucred, &p->p_acflag))
+ return EBUSY;
+ tp->t_state |= TS_CARR_ON;
+
+ if (!(sc->of_flags & OFPOLL)) {
+ sc->of_flags |= OFPOLL;
+ timeout(ofcpoll, sc, 1);
+ }
+
+ return (*linesw[tp->t_line].l_open)(dev, tp);
+}
+
+int
+ofcclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ struct ofc_softc *sc = ofcons_cd.cd_devs[minor(dev)];
+ struct tty *tp = sc->of_tty;
+
+ untimeout(ofcpoll, sc);
+ sc->of_flags &= ~OFPOLL;
+ (*linesw[tp->t_line].l_close)(tp, flag);
+ ttyclose(tp);
+ return 0;
+}
+
+int
+ofcread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct ofc_softc *sc = ofcons_cd.cd_devs[minor(dev)];
+ struct tty *tp = sc->of_tty;
+
+ return (*linesw[tp->t_line].l_read)(tp, uio, flag);
+}
+
+int
+ofcwrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct ofc_softc *sc = ofcons_cd.cd_devs[minor(dev)];
+ struct tty *tp = sc->of_tty;
+
+ return (*linesw[tp->t_line].l_write)(tp, uio, flag);
+}
+
+int
+ofcioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ u_long cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ struct ofc_softc *sc = ofcons_cd.cd_devs[minor(dev)];
+ struct tty *tp = sc->of_tty;
+ int error;
+
+ if ((error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p)) >= 0)
+ return error;
+ if ((error = ttioctl(tp, cmd, data, flag, p)) >= 0)
+ return error;
+ return ENOTTY;
+}
+
+struct tty *
+ofctty(dev)
+ dev_t dev;
+{
+ struct ofc_softc *sc = ofcons_cd.cd_devs[minor(dev)];
+
+ return sc->of_tty;
+}
+
+void
+ofcstop(tp, flag)
+ struct tty *tp;
+ int flag;
+{
+}
+
+static void
+ofcstart(tp)
+ struct tty *tp;
+{
+ struct clist *cl;
+ int s, len;
+ u_char buf[OFBURSTLEN];
+
+ s = spltty();
+ if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) {
+ splx(s);
+ return;
+ }
+ tp->t_state |= TS_BUSY;
+ splx(s);
+ cl = &tp->t_outq;
+ len = q_to_b(cl, buf, OFBURSTLEN);
+ OF_write(stdout, buf, len);
+ s = spltty();
+ tp->t_state &= ~TS_BUSY;
+ if (cl->c_cc) {
+ tp->t_state |= TS_TIMEOUT;
+ timeout(ttrstrt, (void *)tp, 1);
+ }
+ if (cl->c_cc <= tp->t_lowat) {
+ if (tp->t_state & TS_ASLEEP) {
+ tp->t_state &= ~TS_ASLEEP;
+ wakeup(cl);
+ }
+ selwakeup(&tp->t_wsel);
+ }
+ splx(s);
+}
+
+static int
+ofcparam(tp, t)
+ struct tty *tp;
+ struct termios *t;
+{
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = t->c_cflag;
+ return 0;
+}
+
+static void
+ofcpoll(aux)
+ void *aux;
+{
+ struct ofc_softc *sc = aux;
+ struct tty *tp = sc->of_tty;
+ char ch;
+
+ while (OF_read(stdin, &ch, 1) > 0) {
+ if (tp && (tp->t_state & TS_ISOPEN))
+ (*linesw[tp->t_line].l_rint)(ch, tp);
+ }
+ timeout(ofcpoll, sc, 1);
+}
+
+static int
+ofcprobe()
+{
+ int chosen;
+
+ if (stdin)
+ return 1;
+ if ((chosen = OF_finddevice("/chosen")) == -1)
+ return 0;
+ if (OF_getprop(chosen, "stdin", &stdin, sizeof stdin) != sizeof stdin
+ || OF_getprop(chosen, "stdout", &stdout, sizeof stdout) != sizeof stdout)
+ return 0;
+ return 1;
+}
+
+void
+ofccnprobe(cd)
+ struct consdev *cd;
+{
+ int maj;
+
+ if (!ofcprobe())
+ return;
+
+ for (maj = 0; maj < nchrdev; maj++)
+ if (cdevsw[maj].d_open == ofcopen)
+ break;
+ cd->cn_dev = makedev(maj, 0);
+ cd->cn_pri = CN_INTERNAL;
+}
+
+void
+ofccninit(cd)
+ struct consdev *cd;
+{
+}
+
+int
+ofccngetc(dev)
+ dev_t dev;
+{
+ unsigned char ch;
+ int l;
+
+ while ((l = OF_read(stdin, &ch, 1)) != 1)
+ if (l != -2)
+ return -1;
+ return ch;
+}
+
+void
+ofccnputc(dev, c)
+ dev_t dev;
+ int c;
+{
+ char ch = c;
+
+ OF_write(stdout, &ch, 1);
+}
+
+void
+ofccnpollc(dev, on)
+ dev_t dev;
+ int on;
+{
+ struct ofc_softc *sc = ofcons_cd.cd_devs[minor(dev)];
+
+ if (!sc)
+ return;
+ if (on) {
+ if (sc->of_flags & OFPOLL)
+ untimeout(ofcpoll, sc);
+ sc->of_flags &= ~OFPOLL;
+ } else {
+ if (!(sc->of_flags & OFPOLL)) {
+ sc->of_flags |= OFPOLL;
+ timeout(ofcpoll, sc, 1);
+ }
+ }
+}
diff --git a/sys/dev/ofw/ofdisk.c b/sys/dev/ofw/ofdisk.c
new file mode 100644
index 00000000000..addefb26dc3
--- /dev/null
+++ b/sys/dev/ofw/ofdisk.c
@@ -0,0 +1,374 @@
+/* $NetBSD: ofdisk.c,v 1.3 1996/10/13 01:38:13 christos Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996 Wolfgang Solfrank.
+ * Copyright (C) 1995, 1996 TooLs GmbH.
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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/buf.h>
+#include <sys/device.h>
+#include <sys/disklabel.h>
+#include <sys/disk.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/systm.h>
+
+#include <dev/ofw/openfirm.h>
+
+struct ofd_softc {
+ struct device sc_dev;
+ int sc_phandle;
+ int sc_unit;
+ struct disk sc_dk;
+ int sc_ihandle;
+ u_long max_transfer;
+ char sc_name[16];
+};
+
+static int ofdprobe __P((struct device *, void *, void *));
+static void ofdattach __P((struct device *, struct device *, void *));
+
+struct cfattach ofdisk_ca = {
+ sizeof(struct ofd_softc), ofdprobe, ofdattach
+};
+
+struct cfdriver ofdisk_cd = {
+ NULL, "ofdisk", DV_DISK
+};
+
+void ofdstrategy __P((struct buf *));
+
+struct dkdriver ofdkdriver = { ofdstrategy };
+
+static int
+ofdprobe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct ofprobe *ofp = aux;
+ char type[8];
+ int l;
+
+ if ((l = OF_getprop(ofp->phandle, "device_type", type, sizeof type - 1)) < 0)
+ return 0;
+ if (l >= sizeof type)
+ return 0;
+ type[l] = 0;
+ return !strcmp(type, "block");
+}
+
+static void
+ofdattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct ofd_softc *of = (void *)self;
+ struct ofprobe *ofp = aux;
+ int l;
+
+ of->sc_phandle = ofp->phandle;
+ of->sc_unit = ofp->unit;
+ of->sc_ihandle = 0;
+ of->sc_dk.dk_driver = &ofdkdriver;
+ of->sc_dk.dk_name = of->sc_name;
+ strcpy(of->sc_name, of->sc_dev.dv_xname);
+ disk_attach(&of->sc_dk);
+ dk_establish(&of->sc_dk, self); /* XXX */
+ printf("\n");
+}
+
+int
+ofdopen(dev, flags, fmt, p)
+ dev_t dev;
+ int flags;
+ int fmt;
+ struct proc *p;
+{
+ int unit = DISKUNIT(dev);
+ struct ofd_softc *of;
+ char path[256];
+ struct disklabel *lp;
+ int l;
+
+ if (unit >= ofdisk_cd.cd_ndevs)
+ return ENXIO;
+ if (!(of = ofdisk_cd.cd_devs[unit]))
+ return ENXIO;
+
+ if (!of->sc_ihandle) {
+
+ if ((l = OF_package_to_path(of->sc_phandle, path, sizeof path - 3)) < 0)
+ return ENXIO;
+ if (l >= sizeof path - 3)
+ return ENXIO;
+ path[l] = 0;
+
+ /*
+ * This is for the benefit of SCSI/IDE disks that don't
+ * have all their childs in the device tree.
+ * YES, I DO THINK THIS IS A BUG IN OPENFIRMWARE!!!
+ * And yes, this is a very gross hack! XXX
+ * See also ofscsi.c
+ */
+ if (!strcmp(path + l - 4, "disk")) {
+ path[l++] = '@';
+ path[l++] = '0' + of->sc_unit;
+ path[l] = 0;
+ }
+
+ strcat(path, ":0");
+
+ if (!(of->sc_ihandle = OF_open(path)))
+ return ENXIO;
+
+ /*
+ * Try to get characteristics of the disk.
+ */
+ of->max_transfer = OF_call_method_1("max-transfer", of->sc_ihandle, 0);
+ if (of->max_transfer > MAXPHYS)
+ of->max_transfer = MAXPHYS;
+
+ lp = of->sc_dk.dk_label;
+ bzero(lp, sizeof *lp);
+
+ lp->d_secsize = OF_call_method_1("block-size", of->sc_ihandle, 0);
+ if (lp->d_secsize == (u_int32_t)-1 || lp->d_secsize > MAXBSIZE)
+ lp->d_secsize = DEV_BSIZE;
+
+ lp->d_secperunit = OF_call_method_1("#blocks", of->sc_ihandle, 0);
+ if (lp->d_secperunit == (u_int32_t)-1)
+ lp->d_secperunit = 0x7fffffff;
+
+ lp->d_secpercyl = 1;
+ lp->d_nsectors = 1;
+ lp->d_ntracks = 1;
+ lp->d_ncylinders = lp->d_secperunit;
+
+ lp->d_partitions[RAW_PART].p_offset = 0;
+ lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
+
+ readdisklabel(MAKEDISKDEV(major(dev), unit, RAW_PART), ofdstrategy,
+ lp, of->sc_dk.dk_cpulabel);
+ }
+
+ switch (fmt) {
+ case S_IFCHR:
+ of->sc_dk.dk_copenmask |= 1 << DISKPART(dev);
+ break;
+ case S_IFBLK:
+ of->sc_dk.dk_bopenmask |= 1 << DISKPART(dev);
+ break;
+ }
+ of->sc_dk.dk_openmask = of->sc_dk.dk_copenmask | of->sc_dk.dk_bopenmask;
+
+ return 0;
+}
+
+int
+ofdclose(dev, flags, fmt, p)
+ dev_t dev;
+ int flags;
+ int fmt;
+ struct proc *p;
+{
+ struct ofd_softc *of = ofdisk_cd.cd_devs[DISKUNIT(dev)];
+
+ switch (fmt) {
+ case S_IFCHR:
+ of->sc_dk.dk_copenmask &= ~(1 << DISKPART(dev));
+ break;
+ case S_IFBLK:
+ of->sc_dk.dk_bopenmask &= ~(1 << DISKPART(dev));
+ break;
+ }
+ of->sc_dk.dk_openmask = of->sc_dk.dk_copenmask | of->sc_dk.dk_bopenmask;
+
+#ifdef FIREPOWERBUGS
+ /*
+ * This is a hack to get the firmware to flush its buffers.
+ */
+ OF_seek(of->sc_ihandle, 0);
+#endif
+ if (!of->sc_dk.dk_openmask) {
+ OF_close(of->sc_ihandle);
+ of->sc_ihandle = 0;
+ }
+
+ return 0;
+}
+
+void
+ofdstrategy(bp)
+ struct buf *bp;
+{
+ struct ofd_softc *of = ofdisk_cd.cd_devs[DISKUNIT(bp->b_dev)];
+ struct partition *p;
+ u_quad_t off;
+ int read;
+ int (*OF_io)(int, void *, int);
+ daddr_t blkno = bp->b_blkno;
+
+ bp->b_resid = 0;
+ if (bp->b_bcount == 0)
+ goto done;
+
+ OF_io = bp->b_flags & B_READ ? OF_read : OF_write;
+
+ if (DISKPART(bp->b_dev) != RAW_PART) {
+ if (bounds_check_with_label(bp, of->sc_dk.dk_label, 0) <= 0) {
+ bp->b_resid = bp->b_bcount;
+ goto done;
+ }
+ p = &of->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)];
+ blkno = bp->b_blkno + p->p_offset;
+ }
+
+ disk_busy(&of->sc_dk);
+
+ off = (u_quad_t)blkno * DEV_BSIZE;
+ read = -1;
+ do {
+ if (OF_seek(of->sc_ihandle, off) < 0)
+ break;
+ read = OF_io(of->sc_ihandle, bp->b_data, bp->b_bcount);
+ } while (read == -2);
+ if (read < 0) {
+ bp->b_error = EIO;
+ bp->b_flags |= B_ERROR;
+ bp->b_resid = bp->b_bcount;
+ } else
+ bp->b_resid = bp->b_bcount - read;
+
+ disk_unbusy(&of->sc_dk, bp->b_bcount - bp->b_resid);
+
+done:
+ biodone(bp);
+}
+
+static void
+ofminphys(bp)
+ struct buf *bp;
+{
+ struct ofd_softc *of = ofdisk_cd.cd_devs[DISKUNIT(bp->b_dev)];
+
+ if (bp->b_bcount > of->max_transfer)
+ bp->b_bcount = of->max_transfer;
+}
+
+int
+ofdread(dev, uio)
+ dev_t dev;
+ struct uio *uio;
+{
+ return physio(ofdstrategy, NULL, dev, B_READ, ofminphys, uio);
+}
+
+int
+ofdwrite(dev, uio)
+ dev_t dev;
+ struct uio *uio;
+{
+ return physio(ofdstrategy, NULL, dev, B_WRITE, ofminphys, uio);
+}
+
+int
+ofdioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ u_long cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ struct ofd_softc *of = ofdisk_cd.cd_devs[DISKUNIT(dev)];
+ int error;
+
+ switch (cmd) {
+ case DIOCGDINFO:
+ *(struct disklabel *)data = *of->sc_dk.dk_label;
+ return 0;
+
+ case DIOCGPART:
+ ((struct partinfo *)data)->disklab = of->sc_dk.dk_label;
+ ((struct partinfo *)data)->part =
+ &of->sc_dk.dk_label->d_partitions[DISKPART(dev)];
+ return 0;
+
+ case DIOCWDINFO:
+ case DIOCSDINFO:
+ if ((flag & FWRITE) == 0)
+ return EBADF;
+
+ error = setdisklabel(of->sc_dk.dk_label,
+ (struct disklabel *)data, /*of->sc_dk.dk_openmask */0,
+ of->sc_dk.dk_cpulabel);
+ if (error == 0 && cmd == DIOCWDINFO)
+ error = writedisklabel(MAKEDISKDEV(major(dev),
+ DISKUNIT(dev), RAW_PART),
+ ofdstrategy,
+ of->sc_dk.dk_label,
+ of->sc_dk.dk_cpulabel);
+
+ return error;
+ default:
+ return ENOTTY;
+ }
+}
+
+int
+ofddump(dev, blkno, va, size)
+ dev_t dev;
+ daddr_t blkno;
+ caddr_t va;
+ size_t size;
+{
+ return EINVAL;
+}
+
+int
+ofdsize(dev)
+ dev_t dev;
+{
+ struct ofd_softc *of;
+ int part;
+ int size;
+
+ if (ofdopen(dev, 0, S_IFBLK) != 0)
+ return -1;
+ of = ofdisk_cd.cd_devs[DISKUNIT(dev)];
+ part = DISKPART(dev);
+ if (of->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
+ size = -1;
+ else
+ size = of->sc_dk.dk_label->d_partitions[part].p_size;
+ if (ofdclose(dev, 0, S_IFBLK) != 0)
+ return -1;
+ return size;
+}
diff --git a/sys/dev/ofw/ofnet.c b/sys/dev/ofw/ofnet.c
new file mode 100644
index 00000000000..6dc62575198
--- /dev/null
+++ b/sys/dev/ofw/ofnet.c
@@ -0,0 +1,456 @@
+/* $NetBSD: ofnet.c,v 1.4 1996/10/16 19:33:21 ws Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996 Wolfgang Solfrank.
+ * Copyright (C) 1995, 1996 TooLs GmbH.
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 "ofnet.h"
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+
+#include <net/if.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include <dev/ofw/openfirm.h>
+
+#if NIPKDB_OFN > 0
+#include <ipkdb/ipkdb.h>
+#include <machine/ipkdb.h>
+
+struct cfattach ipkdb_ofn_ca = {
+ 0, ipkdb_probe, ipkdb_attach
+};
+
+static struct ipkdb_if *kifp;
+static struct ofn_softc *ipkdb_of;
+
+static int ipkdbprobe __P((void *, void *));
+#endif
+
+struct ofn_softc {
+ struct device sc_dev;
+ int sc_phandle;
+ int sc_ihandle;
+ struct arpcom sc_arpcom;
+};
+
+static int ofnprobe __P((struct device *, void *, void *));
+static void ofnattach __P((struct device *, struct device *, void *));
+
+struct cfattach ofnet_ca = {
+ sizeof(struct ofn_softc), ofnprobe, ofnattach
+};
+
+struct cfdriver ofnet_cd = {
+ NULL, "ofnet", DV_IFNET
+};
+
+static void ofnread __P((struct ofn_softc *));
+static void ofntimer __P((struct ofn_softc *));
+static void ofninit __P((struct ofn_softc *));
+static void ofnstop __P((struct ofn_softc *));
+
+static void ofnstart __P((struct ifnet *));
+static int ofnioctl __P((struct ifnet *, u_long, caddr_t));
+static void ofnwatchdog __P((struct ifnet *));
+
+static int
+ofnprobe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct ofprobe *ofp = aux;
+ char type[32];
+ int l;
+
+#if NIPKDB_OFN > 0
+ if (!parent)
+ return ipkdbprobe(match, aux);
+#endif
+ if ((l = OF_getprop(ofp->phandle, "device_type", type, sizeof type - 1)) < 0)
+ return 0;
+ if (l >= sizeof type)
+ return 0;
+ type[l] = 0;
+ if (strcmp(type, "network"))
+ return 0;
+ return 1;
+}
+
+static void
+ofnattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct ofn_softc *of = (void *)self;
+ struct ifnet *ifp = &of->sc_arpcom.ac_if;
+ struct ofprobe *ofp = aux;
+ char path[256];
+ int l;
+
+ of->sc_phandle = ofp->phandle;
+#if NIPKDB_OFN > 0
+ if (kifp
+ && kifp->unit - 1 == of->sc_dev.dv_unit
+ && OF_instance_to_package(kifp->port) == ofp->phandle) {
+ ipkdb_of = of;
+ of->sc_ihandle = kifp->port;
+ } else
+#endif
+ if ((l = OF_package_to_path(ofp->phandle, path, sizeof path - 1)) < 0
+ || l >= sizeof path
+ || (path[l] = 0, !(of->sc_ihandle = OF_open(path))))
+ panic("ofnattach: unable to open");
+ if (OF_getprop(ofp->phandle, "mac-address",
+ of->sc_arpcom.ac_enaddr, sizeof of->sc_arpcom.ac_enaddr)
+ < 0)
+ panic("ofnattach: no max-address");
+ printf(": address %s\n", ether_sprintf(of->sc_arpcom.ac_enaddr));
+
+ bcopy(of->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+ ifp->if_softc = of;
+ ifp->if_start = ofnstart;
+ ifp->if_ioctl = ofnioctl;
+ ifp->if_watchdog = ofnwatchdog;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
+
+ if_attach(ifp);
+ ether_ifattach(ifp);
+
+#if NBPFILTER > 0
+ bpfattach(&of->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB,
+ sizeof(struct ether_header));
+#endif
+
+ dk_establish(0, self); /* XXX */
+}
+
+static char buf[ETHERMTU + sizeof(struct ether_header)];
+
+static void
+ofnread(of)
+ struct ofn_softc *of;
+{
+ struct ifnet *ifp = &of->sc_arpcom.ac_if;
+ struct ether_header *eh;
+ struct mbuf *m, **mp, *head;
+ int l, len;
+ char *bufp;
+
+#if NIPKDB_OFN > 0
+ ipkdbrint(kifp, ifp);
+#endif
+ while (1) {
+ if ((len = OF_read(of->sc_ihandle, buf, sizeof buf)) < 0) {
+ if (len == -2)
+ return;
+ ifp->if_ierrors++;
+ continue;
+ }
+ if (len < sizeof(struct ether_header)) {
+ ifp->if_ierrors++;
+ continue;
+ }
+ bufp = buf;
+
+ /* Allocate a header mbuf */
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == 0) {
+ ifp->if_ierrors++;
+ continue;
+ }
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = len;
+ l = MHLEN;
+ head = 0;
+ mp = &head;
+
+ while (len > 0) {
+ if (head) {
+ MGET(m, M_DONTWAIT, MT_DATA);
+ if (m == 0) {
+ ifp->if_ierrors++;
+ m_freem(head);
+ head = 0;
+ break;
+ }
+ l = MLEN;
+ }
+ if (len >= MINCLSIZE) {
+ MCLGET(m, M_DONTWAIT);
+ if (m->m_flags & M_EXT)
+ l = MCLBYTES;
+ }
+ m->m_len = l = min(len, l);
+ bcopy(bufp, mtod(m, char *), l);
+ bufp += l;
+ len -= l;
+ *mp = m;
+ mp = &m->m_next;
+ }
+ if (head == 0)
+ continue;
+ eh = mtod(head, struct ether_header *);
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf) {
+ bpf->mtap(ifp->if_bpf, m);
+#endif
+ m_adj(head, sizeof(struct ether_header));
+ ifp->if_ipackets++;
+ ether_input(ifp, eh, head);
+ }
+}
+
+static void
+ofntimer(of)
+ struct ofn_softc *of;
+{
+ ofnread(of);
+ timeout(ofntimer, of, 1);
+}
+
+static void
+ofninit(of)
+ struct ofn_softc *of;
+{
+ struct ifnet *ifp = &of->sc_arpcom.ac_if;
+
+ if (ifp->if_flags & IFF_RUNNING)
+ return;
+
+ ifp->if_flags |= IFF_RUNNING;
+ /* Start reading from interface */
+ ofntimer(of);
+ /* Attempt to start output */
+ ofnstart(ifp);
+}
+
+static void
+ofnstop(of)
+ struct ofn_softc *of;
+{
+ untimeout(ofntimer, of);
+ of->sc_arpcom.ac_if.if_flags &= ~IFF_RUNNING;
+}
+
+static void
+ofnstart(ifp)
+ struct ifnet *ifp;
+{
+ struct ofn_softc *of = ifp->if_softc;
+ struct mbuf *m, *m0;
+ char *bufp;
+ int len;
+
+ if (!(ifp->if_flags & IFF_RUNNING))
+ return;
+
+ for (;;) {
+ /* First try reading any packets */
+ ofnread(of);
+
+ /* Now get the first packet on the queue */
+ IF_DEQUEUE(&ifp->if_snd, m0);
+ if (!m0)
+ return;
+
+ if (!(m0->m_flags & M_PKTHDR))
+ panic("ofnstart: no header mbuf");
+ len = m0->m_pkthdr.len;
+
+ if (len > ETHERMTU + sizeof(struct ether_header)) {
+ /* packet too large, toss it */
+ ifp->if_oerrors++;
+ m_freem(m0);
+ continue;
+ }
+
+#if NPBFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtab(ifp->if_bpf, m0);
+#endif
+ for (bufp = buf; m = m0;) {
+ bcopy(mtod(m, char *), bufp, m->m_len);
+ bufp += m->m_len;
+ MFREE(m, m0);
+ }
+ if (OF_write(of->sc_ihandle, buf, bufp - buf) != bufp - buf)
+ ifp->if_oerrors++;
+ else
+ ifp->if_opackets++;
+ }
+}
+
+static int
+ofnioctl(ifp, cmd, data)
+ struct ifnet *ifp;
+ u_long cmd;
+ caddr_t data;
+{
+ struct ofn_softc *of = ifp->if_softc;
+ struct ifaddr *ifa = (struct ifaddr *)data;
+ struct ifreq *ifr = (struct ifreq *)data;
+ int error = 0;
+
+ switch (cmd) {
+ case SIOCSIFADDR:
+ ifp->if_flags |= IFF_UP;
+
+ switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ arp_ifinit(&of->sc_arpcom, ifa);
+ break;
+#endif
+ default:
+ break;
+ }
+ ofninit(of);
+ break;
+ case SIOCSIFFLAGS:
+ if (!(ifp->if_flags & IFF_UP)
+ && (ifp->if_flags & IFF_RUNNING)) {
+ /* If interface is down, but running, stop it. */
+ ofnstop(of);
+ } else if ((ifp->if_flags & IFF_UP)
+ && !(ifp->if_flags & IFF_RUNNING)) {
+ /* If interface is up, but not running, start it. */
+ ofninit(of);
+ } else {
+ /* Other flags are ignored. */
+ }
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ return error;
+}
+
+static void
+ofnwatchdog(ifp)
+ struct ifnet *ifp;
+{
+ struct ofn_softc *of = ifp->if_softc;
+
+ log(LOG_ERR, "%s: device timeout\n", of->sc_dev.dv_xname);
+ of->sc_arpcom.ac_if.if_oerrors++;
+ ofnstop(of);
+ ofninit(of);
+}
+
+#if NIPKDB_OFN > 0
+static void
+ipkdbofstart(kip)
+ struct ipkdb_if *kip;
+{
+ int unit = kip->unit - 1;
+
+ if (ipkdb_of)
+ ipkdbattach(kip, &ipkdb_of->sc_arpcom);
+}
+
+static void
+ipkdbofleave(kip)
+ struct ipkdb_if *kip;
+{
+}
+
+static int
+ipkdbofrcv(kip, buf, poll)
+ struct ipkdb_if *kip;
+ u_char *buf;
+ int poll;
+{
+ int l;
+
+ do {
+ l = OF_read(kip->port, buf, ETHERMTU);
+ if (l < 0)
+ l = 0;
+ } while (!poll && !l);
+ return l;
+}
+
+static void
+ipkdbofsend(kip, buf, l)
+ struct ipkdb_if *kip;
+ u_char *buf;
+ int l;
+{
+ OF_write(kip->port, buf, l);
+}
+
+static int
+ipkdbprobe(match, aux)
+ void *match, *aux;
+{
+ struct cfdata *cf = match;
+ struct ipkdb_if *kip = aux;
+ static char name[256];
+ int len;
+ int phandle;
+
+ kip->unit = cf->cf_unit + 1;
+
+ if (!(kip->port = OF_open("net")))
+ return -1;
+ if ((len = OF_instance_to_path(kip->port, name, sizeof name - 1)) < 0
+ || len >= sizeof name)
+ return -1;
+ name[len] = 0;
+ if ((phandle = OF_instance_to_package(kip->port)) == -1)
+ return -1;
+ if (OF_getprop(phandle, "mac-address", kip->myenetaddr, sizeof kip->myenetaddr)
+ < 0)
+ return -1;
+
+ kip->flags |= IPKDB_MYHW;
+ kip->name = name;
+ kip->start = ipkdbofstart;
+ kip->leave = ipkdbofleave;
+ kip->receive = ipkdbofrcv;
+ kip->send = ipkdbofsend;
+
+ kifp = kip;
+
+ return 0;
+}
+#endif
diff --git a/sys/dev/ofw/ofrtc.c b/sys/dev/ofw/ofrtc.c
new file mode 100644
index 00000000000..d382c5fbb52
--- /dev/null
+++ b/sys/dev/ofw/ofrtc.c
@@ -0,0 +1,260 @@
+/* $NetBSD: ofrtc.c,v 1.3 1996/10/13 01:38:14 christos Exp $ */
+
+/*
+ * Copyright (C) 1996 Wolfgang Solfrank.
+ * Copyright (C) 1996 TooLs GmbH.
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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/device.h>
+
+#include <dev/ofw/openfirm.h>
+
+struct ofrtc_softc {
+ struct device sc_dev;
+ int sc_phandle;
+ int sc_ihandle;
+};
+
+static int ofrtcprobe __P((struct device *, void *, void *));
+static void ofrtcattach __P((struct device *, struct device *, void *));
+
+struct cfattach ofrtc_ca = {
+ sizeof(struct ofrtc_softc), ofrtcprobe, ofrtcattach
+};
+
+struct cfdriver ofrtc_cd = {
+ NULL, "ofrtc", DV_DULL
+};
+
+static int
+ofrtcprobe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct ofprobe *ofp = aux;
+ char type[8];
+ int l;
+
+ if ((l = OF_getprop(ofp->phandle, "device_type", type, sizeof type - 1)) < 0)
+ return 0;
+ if (l >= sizeof type)
+ return 0;
+
+ return !strcmp(type, "rtc");
+}
+
+int OF_clock_read(int *sec, int *min, int *hour, int *day,
+ int *mon, int *yr);
+typedef int (clock_read_t)(int *sec, int *min, int *hour, int *day,
+ int *mon, int *yr);
+extern clock_read_t *clock_read;
+
+static void
+ofrtcattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct ofrtc_softc *of = (void *)self;
+ struct ofprobe *ofp = aux;
+ char name[32];
+ int l;
+
+ clock_read = &OF_clock_read;
+ of->sc_phandle = ofp->phandle;
+ of->sc_ihandle = 0;
+ if ((l = OF_getprop(of->sc_phandle, "name", name, sizeof name - 1)) < 0)
+ panic("Device without name?");
+ if (l >= sizeof name)
+ l = sizeof name - 1;
+ name[l] = 0;
+ printf(": %s\n", name);
+}
+
+int
+ofrtcopen(dev, flags, fmt)
+ dev_t dev;
+ int flags;
+ int fmt;
+{
+ struct ofrtc_softc *of;
+ int unit = minor(dev);
+ char path[256];
+ int l;
+
+ if (unit >= ofrtc_cd.cd_ndevs)
+ return ENXIO;
+ if (!(of = ofrtc_cd.cd_devs[unit]))
+ return ENXIO;
+ if (!of->sc_ihandle) {
+ if ((l = OF_package_to_path(of->sc_phandle, path, sizeof path - 1)) < 0)
+ return ENXIO;
+ if (l >= sizeof path)
+ return ENXIO;
+ path[l] = 0;
+
+ if (!(of->sc_ihandle = OF_open(path))) {
+ if (of->sc_ihandle) {
+ OF_close(of->sc_ihandle);
+ of->sc_ihandle = 0;
+ }
+ return ENXIO;
+ }
+
+ }
+
+ return 0;
+}
+
+int
+ofrtcclose(dev, flags, fmt)
+ dev_t dev;
+ int flags;
+ int fmt;
+{
+ return 0;
+}
+
+static void
+twodigit(bp, i)
+ char *bp;
+ int i;
+{
+ *bp++ = i / 10 + '0';
+ *bp = i % 10 + '0';
+}
+
+static int
+twodigits(bp)
+ char *bp;
+{
+ int i;
+
+ i = *bp++ - '0';
+ return i * 10 + *bp++ - '0';
+}
+
+int
+ofrtcread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct ofrtc_softc *of = ofrtc_cd.cd_devs[minor(dev)];
+ int date[6];
+ char buf[14];
+ int xlen;
+
+ if (uio->uio_offset >= sizeof buf)
+ return 0;
+
+ if (OF_call_method("get-time", of->sc_ihandle, 0, 6,
+ date, date + 1, date + 2,
+ date + 3, date + 4, date + 5))
+ return EIO;
+
+ twodigit(buf, date[5] % 100);
+ twodigit(buf + 2, date[4]);
+ twodigit(buf + 4, date[3]);
+ twodigit(buf + 6, date[2]);
+ twodigit(buf + 8, date[1]);
+ buf[10] = '.';
+ twodigit(buf + 11, date[0]);
+ buf[13] = '\n';
+
+ xlen = sizeof(buf) - uio->uio_offset;
+ if (xlen > uio->uio_resid)
+ xlen = uio->uio_resid;
+
+ return uiomove((caddr_t)buf, xlen, uio);
+}
+
+int
+ofrtcwrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct ofrtc_softc *of = ofrtc_cd.cd_devs[minor(dev)];
+ char buf[14];
+ int cnt, year, error;
+
+ /*
+ * We require atomic updates!
+ */
+ cnt = uio->uio_resid;
+ if (uio->uio_offset || (cnt != sizeof buf && cnt != sizeof buf - 1))
+ return EINVAL;
+
+ if (error = uiomove((caddr_t)buf, sizeof buf, uio))
+ return error;
+
+ if (cnt == sizeof buf && buf[sizeof buf - 1] != '\n')
+ return EINVAL;
+
+ year = twodigits(buf) + 1900;
+ if (year < 1970)
+ year += 100;
+ if (OF_call_method("set-time", of->sc_ihandle, 6, 0,
+ twodigits(buf + 11), twodigits(buf + 8), twodigits(buf + 6),
+ twodigits(buf + 4), twodigits(buf + 2), year))
+ return EIO;
+ return 0;
+}
+
+
+int
+OF_clock_read(int *sec, int *min, int *hour, int *day,
+ int *mon, int *yr)
+{
+ struct ofrtc_softc *of;
+ char path[256];
+ int l;
+
+ if (!(of = ofrtc_cd.cd_devs[0]))
+ return 0;
+ if ((l = OF_package_to_path(of->sc_phandle, path, sizeof path - 1)) < 0)
+ return 0;
+ if (l >= sizeof path)
+ return 0;
+ path[l] = 0;
+
+ if (!(of->sc_ihandle = OF_open(path))) {
+ if (of->sc_ihandle) {
+ OF_close(of->sc_ihandle);
+ of->sc_ihandle = 0;
+ }
+ return 0;
+ }
+ if (OF_call_method("get-time", of->sc_ihandle, 0, 6,
+ sec, min, hour, day, mon, yr))
+ return 0;
+
+ return 1;
+}
diff --git a/sys/dev/ofw/openfirm.h b/sys/dev/ofw/openfirm.h
new file mode 100644
index 00000000000..25f5a494f5e
--- /dev/null
+++ b/sys/dev/ofw/openfirm.h
@@ -0,0 +1,94 @@
+/* $NetBSD: openfirm.h,v 1.1 1996/09/30 16:35:10 ws Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996 Wolfgang Solfrank.
+ * Copyright (C) 1995, 1996 TooLs GmbH.
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
+ */
+/*
+ * Prototypes for OpenFirmware Interface Routines
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+
+int openfirmware __P((void *));
+
+extern char *OF_buf;
+
+int OF_peer __P((int phandle));
+int OF_child __P((int phandle));
+int OF_parent __P((int phandle));
+int OF_instance_to_package __P((int ihandle));
+int OF_getprop __P((int handle, char *prop, void *buf, int buflen));
+int OF_finddevice __P((char *name));
+int OF_instance_to_path __P((int ihandle, char *buf, int buflen));
+int OF_package_to_path __P((int phandle, char *buf, int buflen));
+int OF_call_method_1 __P((char *method, int ihandle, int nargs, ...));
+int OF_call_method __P((char *method, int ihandle, int nargs, int nreturns, ...));
+int OF_open __P((char *dname));
+void OF_close __P((int handle));
+int OF_read __P((int handle, void *addr, int len));
+int OF_write __P((int handle, void *addr, int len));
+int OF_seek __P((int handle, u_quad_t pos));
+void OF_boot __P((char *bootspec)) __attribute__((__noreturn__));
+void OF_enter __P((void));
+void OF_exit __P((void)) __attribute__((__noreturn__));
+void (*OF_set_callback __P((void (*newfunc)(void *)))) ();
+
+/*
+ * Some generic routines for OpenFirmware handling.
+ */
+int ofnmmatch __P((char *cp1, char *cp2));
+
+/*
+ * Generic OpenFirmware probe argument.
+ * This is how all probe structures must start
+ * in order to support generic OpenFirmware device drivers.
+ */
+struct ofprobe {
+ int phandle;
+ /*
+ * Special unit field for disk devices.
+ * This is a KLUDGE to work around the fact that OpenFirmware
+ * doesn't probe the scsi bus completely.
+ * YES, I THINK THIS IS A BUG IN THE OPENFIRMWARE DEFINITION!!! XXX
+ * See also ofdisk.c.
+ */
+ int unit;
+};
+
+/*
+ * The softc structure for devices we might be booted from (i.e. we might
+ * want to set root/swap to) needs to start with these fields: XXX
+ */
+struct ofb_softc {
+ struct device sc_dev;
+ int sc_phandle;
+ int sc_unit; /* Might be missing for non-disk devices */
+};