diff options
author | Dale S. Rahn <rahnds@cvs.openbsd.org> | 1996-12-23 00:32:58 +0000 |
---|---|---|
committer | Dale S. Rahn <rahnds@cvs.openbsd.org> | 1996-12-23 00:32:58 +0000 |
commit | 4d28f11436de1342c38ec5db96ef30e891b18b66 (patch) | |
tree | 9c2f42588482ca38cd9d87e75526e93d30c08c76 | |
parent | b98ae97fdfd4cae418247cb7fff8c1cf989e83f4 (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.ofw | 38 | ||||
-rw-r--r-- | sys/dev/ofw/ofbus.c | 147 | ||||
-rw-r--r-- | sys/dev/ofw/ofcons.c | 351 | ||||
-rw-r--r-- | sys/dev/ofw/ofdisk.c | 374 | ||||
-rw-r--r-- | sys/dev/ofw/ofnet.c | 456 | ||||
-rw-r--r-- | sys/dev/ofw/ofrtc.c | 260 | ||||
-rw-r--r-- | sys/dev/ofw/openfirm.h | 94 |
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 */ +}; |