diff options
| author | glass <glass@NetBSD.org> | 1993-08-15 23:01:58 +0000 |
|---|---|---|
| committer | glass <glass@NetBSD.org> | 1993-08-15 23:01:58 +0000 |
| commit | 8ff8fa8046501b4988a07f02f42f2ffd76fa044e (patch) | |
| tree | 9bec9eb99be032e892b8c7d3e69a21e52fc504de /sys | |
| parent | 3e94657cf6dba8425790230daaf8b6770823e2af (diff) | |
runs up to and including configure().
todo: exceptions, interrupt support, make isrs affect vector table
kernel/user stacks
Diffstat (limited to 'sys')
38 files changed, 1948 insertions, 308 deletions
diff --git a/sys/arch/sun3/conf/Makefile.sun3 b/sys/arch/sun3/conf/Makefile.sun3 index 9c35b2b1bb4..63f51fff4db 100644 --- a/sys/arch/sun3/conf/Makefile.sun3 +++ b/sys/arch/sun3/conf/Makefile.sun3 @@ -113,9 +113,7 @@ locore.o: ${SUN3}/include/cpu.h ${SUN3}/include/control.h # the following is necessary because autoconf.o depends on #if GENERIC autoconf.o: Makefile -# the following are necessary because the files depend on the types of -# hp cpu's included in the system configuration -clock.o machdep.o autoconf.o conf.o: Makefile +sun3_startup.o: Makefile # depend on network configuration af.o uipc_proto.o locore.o: Makefile diff --git a/sys/arch/sun3/conf/TIMESINK b/sys/arch/sun3/conf/TIMESINK index d80d9c347eb..51835983d58 100644 --- a/sys/arch/sun3/conf/TIMESINK +++ b/sys/arch/sun3/conf/TIMESINK @@ -1,27 +1,31 @@ # +# new config file for TIMESINK # -machine "sun3" -cpu "SUN3_50" -ident TIMESINK -timezone 8 dst -maxusers 16 +include "std.sun3" + +options "SUN3_50" + +makeoptions DEBUG = "-g" +maxusers 4 +options TIMEZONE = 480, DST = 2, MAXFDESCS=2048 # Standard options options "COMPAT_43" options "TCP_COMPAT_42" # Options for all SUN3 machines +options SWAPPAGER, VNODEPAGER, DEVPAGER options KTRACE -#options DDB - +options INET config netbsd swap generic -pseudo-device prom -pseudo-device idprom +le0 at obio? addr ? level 3 +#zs0 at obio? addr 0x00000 level 3 +#zs1 at obio? addr 0x20000 level 3 -pseudo-device swappager -pseudo-device vnodepager -pseudo-device devpager +idprom0 at obctl? addr ? size ? +prom0 at mainbus0 +pseudo-device loop diff --git a/sys/arch/sun3/conf/files.sun3.newconf b/sys/arch/sun3/conf/files.sun3.newconf index 4e377ea45a1..c83d0baba60 100644 --- a/sys/arch/sun3/conf/files.sun3.newconf +++ b/sys/arch/sun3/conf/files.sun3.newconf @@ -1,29 +1,43 @@ # # new style config file for sun3 architecture # -# +# sun3 config 'files' for new config # define sunfb -#device mainbus at root { } -device obio at root {addr = -1, [priority = -1]} -device obmem at root {addr, size, [priority = -1]} +device mainbus at root {} +device obio at mainbus {addr = -1, [level = -1]} +device obmem at mainbus {addr, size, [level = -1]} +device obctl at mainbus {addr, size} #define obio { addr = -1, size = -1, priority = -1, dvma = -1, flags = -1} #define obmem { addr = -1, size = -1} device le at obio: ifnet, ether -file arch/sun3/dev/if_le.c le device-driver needs-count +file arch/sun3/dev/if_le.c le device-driver +file arch/sun3/dev/if_le_subr.c le device zs at obio: tty file arch/sun3/dev/zs.c zs device-driver needs-count device bwtwo at obmem: sunfb -file arch/sun3/dev/bwtwo.c bwtwo +file arch/sun3/dev/bwtwo.c bwtwo device-driver + +device idprom at obctl +file arch/sun3/dev/idprom.c idprom device-driver needs-count + +device prom at mainbus: tty +file arch/sun3/dev/prom.c prom device-driver needs-count + +# "Bus" support code +file arch/sun3/dev/obio.c obio device-driver +file arch/sun3/dev/obctl.c obctl device-driver +file arch/sun3/dev/obmem.c obmem device-driver # # +file arch/sun3/sun3/autoconf.c file arch/sun3/sun3/clock.c file arch/sun3/sun3/conf.c file arch/sun3/sun3/cons.c @@ -32,16 +46,15 @@ file arch/sun3/sun3/control.c file arch/sun3/sun3/db_interface.c ddb file arch/sun3/sun3/db_trace.c ddb file arch/sun3/sun3/disksubr.c +file arch/sun3/sun3/in_cksum.c inet +file arch/sun3/sun3/isr.c file arch/sun3/sun3/machdep.c file arch/sun3/sun3/mem.c -file arch/sun3/sun3/obio.c +file arch/sun3/sun3/ns_cksum.c ns +file arch/sun3/sun3/oc_cksum.s inet file arch/sun3/sun3/pmap.c file arch/sun3/sun3/stub.c file arch/sun3/sun3/sun3_startup.c file arch/sun3/sun3/trap.c file arch/sun3/sun3/vector.c file arch/sun3/sun3/vm_machdep.c -file arch/sun3/dev/idprom.c idprom device-driver -file arch/sun3/dev/prom.c prom device-driver -file arch/sun3/dev/obmem.c obmem device-driver - diff --git a/sys/arch/sun3/conf/std.sun3 b/sys/arch/sun3/conf/std.sun3 index 81e6428462a..d3897a0493e 100644 --- a/sys/arch/sun3/conf/std.sun3 +++ b/sys/arch/sun3/conf/std.sun3 @@ -1,6 +1,9 @@ machine "sun3" -#mainbus0 at root +options NEWCONFIG -obio0 at root -obmem0 at root +mainbus0 at root + +obio0 at mainbus? +obmem0 at mainbus? +obctl0 at mainbus? diff --git a/sys/arch/sun3/dev/README b/sys/arch/sun3/dev/README new file mode 100644 index 00000000000..7dafe89e3f6 --- /dev/null +++ b/sys/arch/sun3/dev/README @@ -0,0 +1,35 @@ + <$Revision: 1.1 $> + +NetBSD/sun3 supports the following busses: + +Bus: +obio - Devices on the motherboard, accessed by having their "registers" + mapped into the kernel's virtual address space +obctl - Devices on the motherboard accessible only via the 'CONTROL' space, + and supporting instructions on the m68k. +obmem - Devices on the motherboard that are mapped into main memory + by the hardware. Only true of some framebuffers. +mainbus - An imaginary bus on which obio, obctl, obmem, and the prom device + all reside. + +Devices supported: + +'obio' Bus: +Device Type Description +--------------------------------------------------------------------------- +zs CHAR zilog 8530 serial ports; used for serial ports, keybd, mouse +le IFNET lance ethernet driver + +'obctl' Bus: +Device Type Description +--------------------------------------------------------------------------- +idprom CHAR makes idprom contents accessible in user-space + + +The 'prom' device is just wierd as it isn't a real device, but enough +wrapping so that the prom input/output routines can be used to make +the prom's idea of the console both a tty, and a console in the netbsd +sense. + +prom CHAR prom-based tty and console support + diff --git a/sys/arch/sun3/dev/idprom.c b/sys/arch/sun3/dev/idprom.c index f56d3d94369..96846c8c6e5 100644 --- a/sys/arch/sun3/dev/idprom.c +++ b/sys/arch/sun3/dev/idprom.c @@ -1,30 +1,71 @@ #include "systm.h" +#include "device.h" + +#include "machine/autoconf.h" +#include "machine/control.h" #include "machine/idprom.h" +#include "machine/obctl.h" + #include "idprom.h" -static int idprom_init = 0; +extern void idpromattach __P((struct device *, struct device *, void *)); + +struct idprom_softc { + struct device idprom_driver; + int idprom_init; + struct idprom idprom_copy; + char *idprom_addr; + int idprom_size; +}; + +struct cfdriver idpromcd = +{ NULL, "idprom", always_match, idpromattach, DV_DULL, + sizeof(struct idprom_softc), 0}; -static struct idprom idprom_copy; +#define IDPROM_CHECK(unit) \ + if (unit >= idpromcd.cd_ndevs || (idpromcd.cd_devs[unit] == NULL)) \ + return ENXIO +#define UNIT_TO_IDP(unit) idpromcd.cd_devs[unit] + + +void idpromattach(parent, self, args) + struct device *parent; + struct device *self; + void *args; +{ + struct idprom_softc *idp = (struct idprom_softc *) self; + struct obctl_cf_loc *obctl_loc = OBCTL_LOC(self); -static int idprom_ok = 0; + idp->idprom_init = 0; -int idprom_open(dev, oflags, devtype, p) + idp->idprom_addr = + OBCTL_DEFAULT_PARAM(char *, obctl_loc->obctl_addr, IDPROM_BASE); + idp->idprom_size = + OBCTL_DEFAULT_PARAM(int, obctl_loc->obctl_size, IDPROM_SIZE); + obctl_print(idp->idprom_addr, idp->idprom_size); + printf("\n"); +} + +int idpromopen(dev, oflags, devtype, p) dev_t dev; int oflags; int devtype; struct proc *p; { - int unit,s; + struct idprom_softc *idp; + int unit, idprom_ok; unit = minor(dev); - if (unit >= NIDPROM) - return ENXIO; - if (!idprom_init) idprom_ok = idprom_fetch(&idprom_copy, IDPROM_VERSION); + IDPROM_CHECK(unit); + idp = UNIT_TO_IDP(unit); + if (!idp->idprom_init) + idprom_ok = idprom_fetch(&idp->idprom_copy, IDPROM_VERSION); if (!idprom_ok) return EIO; + idp->idprom_init = 1; return 0; } -int idprom_close(dev, fflag, devtype, p) +int idpromclose(dev, fflag, devtype, p) dev_t dev; int fflag; int devtype; @@ -33,30 +74,27 @@ int idprom_close(dev, fflag, devtype, p) int unit; unit = minor(dev); - if (unit >= NIDPROM) - return ENXIO; + IDPROM_CHECK(unit); return 0; } -idprom_read(dev, uio, ioflag) +idpromread(dev, uio, ioflag) dev_t dev; struct uio *uio; int ioflag; { - int error, unit,length; - + int error, unit, length; + struct idprom_softc *idp; unit = minor(dev); - - if (unit >= NIDPROM) - return ENXIO; - + IDPROM_CHECK(unit); + idp = UNIT_TO_IDP(unit); + if (!idp->idprom_init) return EIO; error = 0; while (uio->uio_resid > 0) { - if (uio->uio_offset >= IDPROM_SIZE) break; /* past or at end */ - length = min(uio->uio_resid, (IDPROM_SIZE-uio->uio_offset)); - error = uiomove((caddr_t) &idprom_copy, length, uio); + if (uio->uio_offset >= idp->idprom_size) break; /* past or at end */ + length = min(uio->uio_resid, (idp->idprom_size - uio->uio_offset)); + error = uiomove((caddr_t) &idp->idprom_copy, length, uio); } return error; } - diff --git a/sys/arch/sun3/dev/if_le.c b/sys/arch/sun3/dev/if_le.c new file mode 100644 index 00000000000..14a2235a2e5 --- /dev/null +++ b/sys/arch/sun3/dev/if_le.c @@ -0,0 +1,827 @@ +/* + * Copyright (c) 1982, 1990 The Regents of the University of California. + * 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 the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * + * from: @(#)if_le.c 7.6 (Berkeley) 5/8/91 + * if_le.c,v 1.2 1993/05/22 07:56:23 cgd Exp + */ + +#include "bpfilter.h" + +/* + * AMD 7990 LANCE + * + * This driver will generate and accept tailer encapsulated packets even + * though it buys us nothing. The motivation was to avoid incompatibilities + * with VAXen, SUNs, and others that handle and benefit from them. + * This reasoning is dubious. + */ +#include "sys/param.h" +#include "sys/systm.h" +#include "sys/mbuf.h" +#include "sys/buf.h" +#include "sys/protosw.h" +#include "sys/socket.h" +#include "sys/syslog.h" +#include "sys/ioctl.h" +#include "sys/errno.h" +#include "sys/device.h" + +#include "net/if.h" +#include "net/netisr.h" +#include "net/route.h" + +#ifdef INET +#include "netinet/in.h" +#include "netinet/in_systm.h" +#include "netinet/in_var.h" +#include "netinet/ip.h" +#include "netinet/if_ether.h" +#endif + +#ifdef NS +#include "netns/ns.h" +#include "netns/ns_if.h" +#endif + +#ifdef RMP +#include "netrmp/rmp.h" +#include "netrmp/rmp_var.h" +#endif + +#include "machine/autoconf.h" + +#include "if_lereg.h" + +#if NBPFILTER > 0 +#include "../net/bpf.h" +#include "../net/bpfdesc.h" +#endif + +#include "if_le.h" +#include "if_le_subr.h" + +int ledebug = 0; /* console error messages */ + +int leintr(), leinit(), leioctl(), lestart(), ether_output(); +struct mbuf *leget(); +extern struct ifnet loif; + +/* access LANCE registers */ + +void leattach __P((struct device *, struct device *, void *)); +int lematch __P((struct device *, struct cfdata *, void *args)); + +struct cfdriver lecd = +{ NULL, "le", lematch, leattach, DV_DULL, sizeof(struct le_softc), 0}; + +int lematch(parent, cf, args) + struct device *parent; + struct cfdata *cf; + void *args; +{ + return le_machdep_match(parent, cf, args); +} +/* + * Interface exists: make available by filling in network interface + * record. System will initialize the interface when it is ready + * to accept packets. + */ +void leattach(parent, self, args) + struct device *parent; + struct device *self; + void *args; +{ + register struct lereg2 *ler2; + struct lereg2 *lemem = 0; + struct le_softc *le = (struct le_softc *) self; + struct ifnet *ifp = &le->sc_if; + char *cp; + int i, unit; + + unit = le->sc_dev.dv_unit; + if (le_machdep_attach(parent, self, args)) { + printf(": bad attach??\n"); + return; + } + ler2 = le->sc_r2; + printf(": hardware address %s\n", ether_sprintf(le->sc_addr)); + + /* + * Setup for transmit/receive + */ + ler2->ler2_mode = LE_MODE; + ler2->ler2_padr[0] = le->sc_addr[1]; + ler2->ler2_padr[1] = le->sc_addr[0]; + ler2->ler2_padr[2] = le->sc_addr[3]; + ler2->ler2_padr[3] = le->sc_addr[2]; + ler2->ler2_padr[4] = le->sc_addr[5]; + ler2->ler2_padr[5] = le->sc_addr[4]; +#ifdef RMP + /* + * Set up logical addr filter to accept multicast 9:0:9:0:0:4 + * This should be an ioctl() to the driver. (XXX) + */ + ler2->ler2_ladrf0 = 0x00100000; + ler2->ler2_ladrf1 = 0x0; +#else + ler2->ler2_ladrf0 = 0; + ler2->ler2_ladrf1 = 0; +#endif + ler2->ler2_rlen = LE_RLEN; + ler2->ler2_rdra = (int)lemem->ler2_rmd; + ler2->ler2_tlen = LE_TLEN; + ler2->ler2_tdra = (int)lemem->ler2_tmd; + + ifp->if_unit = unit; + ifp->if_name = "le"; + ifp->if_mtu = ETHERMTU; + ifp->if_init = leinit; + ifp->if_ioctl = leioctl; + ifp->if_output = ether_output; + ifp->if_start = lestart; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; +#if NBPFILTER > 0 + bpfattach(&le->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); +#endif + if_attach(ifp); +} + +ledrinit(ler2) + register struct lereg2 *ler2; +{ + register struct lereg2 *lemem = 0; + register int i; + + for (i = 0; i < LERBUF; i++) { + ler2->ler2_rmd[i].rmd0 = (int)lemem->ler2_rbuf[i]; + ler2->ler2_rmd[i].rmd1 = LE_OWN; + ler2->ler2_rmd[i].rmd2 = -LEMTU; + ler2->ler2_rmd[i].rmd3 = 0; + } + for (i = 0; i < LETBUF; i++) { + ler2->ler2_tmd[i].tmd0 = (int)lemem->ler2_tbuf[i]; + ler2->ler2_tmd[i].tmd1 = 0; + ler2->ler2_tmd[i].tmd2 = 0; + ler2->ler2_tmd[i].tmd3 = 0; + } +} + +lereset(unit) + register int unit; +{ + register struct le_softc *le = (struct le_softc *) &lecd.cd_devs[unit]; + register struct lereg1 *ler1 = le->sc_r1; + register struct lereg2 *lemem = 0; + register int timo = 100000; + register int stat; + +#ifdef lint + stat = unit; +#endif +#if NBPFILTER > 0 + if (le->sc_if.if_flags & IFF_PROMISC) + /* set the promiscuous bit */ + le->sc_r2->ler2_mode = LE_MODE|0x8000; + else + le->sc_r2->ler2_mode = LE_MODE; +#endif + LERDWR(le, LE_CSR0, ler1->ler1_rap); + LERDWR(le, LE_STOP, ler1->ler1_rdp); + ledrinit(le->sc_r2); + le->sc_rmd = 0; + LERDWR(le, LE_CSR1, ler1->ler1_rap); + LERDWR(le, (int)&lemem->ler2_mode, ler1->ler1_rdp); + LERDWR(le, LE_CSR2, ler1->ler1_rap); + LERDWR(le, 0, ler1->ler1_rdp); + LERDWR(le, LE_CSR0, ler1->ler1_rap); + LERDWR(le, LE_INIT, ler1->ler1_rdp); + do { + if (--timo == 0) { + printf("le%d: init timeout, stat = 0x%x\n", + unit, stat); + break; + } + LERDWR(le, ler1->ler1_rdp, stat); + } while ((stat & LE_IDON) == 0); + LERDWR(le, LE_STOP, ler1->ler1_rdp); + LERDWR(le, LE_CSR3, ler1->ler1_rap); + LERDWR(le, LE_BSWP, ler1->ler1_rdp); + LERDWR(le, LE_CSR0, ler1->ler1_rap); + LERDWR(le, LE_STRT | LE_INEA, ler1->ler1_rdp); + le->sc_if.if_flags &= ~IFF_OACTIVE; +} + +/* + * Initialization of interface + */ +leinit(unit) + int unit; +{ + struct le_softc *le = lecd.cd_devs[unit]; + register struct ifnet *ifp = &le->sc_if; + int s; + + /* not yet, if address still unknown */ + if (ifp->if_addrlist == (struct ifaddr *)0) + return; + if ((ifp->if_flags & IFF_RUNNING) == 0) { + s = splimp(); + ifp->if_flags |= IFF_RUNNING; + lereset(unit); + (void) lestart(ifp); + splx(s); + } +} + +/* + * Start output on interface. Get another datagram to send + * off of the interface queue, and copy it to the interface + * before starting the output. + */ +lestart(ifp) + struct ifnet *ifp; +{ + register struct le_softc *le = lecd.cd_devs[ifp->if_unit]; + register struct letmd *tmd; + register struct mbuf *m; + int len; + + if ((le->sc_if.if_flags & IFF_RUNNING) == 0) + return (0); + IF_DEQUEUE(&le->sc_if.if_snd, m); + if (m == 0) + return (0); + len = leput(le->sc_r2->ler2_tbuf[0], m); +#if NBPFILTER > 0 + /* + * If bpf is listening on this interface, let it + * see the packet before we commit it to the wire. + */ + if (le->sc_bpf) + bpf_tap(le->sc_bpf, le->sc_r2->ler2_tbuf[0], len); +#endif + tmd = le->sc_r2->ler2_tmd; + tmd->tmd3 = 0; + tmd->tmd2 = -len; + tmd->tmd1 = LE_OWN | LE_STP | LE_ENP; + le->sc_if.if_flags |= IFF_OACTIVE; + return (0); +} + +leintr(unit) + register int unit; +{ + register struct le_softc *le = lecd.cd_devs[unit]; + register struct lereg1 *ler1; + register int stat; + + le_machdep_intrcheck(le, unit); + ler1 = le->sc_r1; + LERDWR(le, ler1->ler1_rdp, stat); + if (stat & LE_SERR) { + leerror(unit, stat); + if (stat & LE_MERR) { + le->sc_merr++; + lereset(unit); + return(1); + } + if (stat & LE_BABL) + le->sc_babl++; + if (stat & LE_CERR) + le->sc_cerr++; + if (stat & LE_MISS) + le->sc_miss++; + LERDWR(le, LE_BABL|LE_CERR|LE_MISS|LE_INEA, ler1->ler1_rdp); + } + if ((stat & LE_RXON) == 0) { + le->sc_rxoff++; + lereset(unit); + return(1); + } + if ((stat & LE_TXON) == 0) { + le->sc_txoff++; + lereset(unit); + return(1); + } + if (stat & LE_RINT) { + /* interrupt is cleared in lerint */ + lerint(unit); + } + if (stat & LE_TINT) { + LERDWR(le, LE_TINT|LE_INEA, ler1->ler1_rdp); + lexint(unit); + } + return(1); +} + +/* + * Ethernet interface transmitter interrupt. + * Start another output if more data to send. + */ +lexint(unit) + register int unit; +{ + register struct le_softc *le = lecd.cd_devs[unit]; + register struct letmd *tmd = le->sc_r2->ler2_tmd; + + if ((le->sc_if.if_flags & IFF_OACTIVE) == 0) { + le->sc_xint++; + return; + } + if (tmd->tmd1 & LE_OWN) { + le->sc_xown++; + return; + } + if (tmd->tmd1 & LE_ERR) { +err: + lexerror(unit); + le->sc_if.if_oerrors++; + if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) { + le->sc_uflo++; + lereset(unit); + } + else if (tmd->tmd3 & LE_LCOL) + le->sc_if.if_collisions++; + else if (tmd->tmd3 & LE_RTRY) + le->sc_if.if_collisions += 16; + } + else if (tmd->tmd3 & LE_TBUFF) + /* XXX documentation says BUFF not included in ERR */ + goto err; + else if (tmd->tmd1 & LE_ONE) + le->sc_if.if_collisions++; + else if (tmd->tmd1 & LE_MORE) + /* what is the real number? */ + le->sc_if.if_collisions += 2; + else + le->sc_if.if_opackets++; + le->sc_if.if_flags &= ~IFF_OACTIVE; + (void) lestart(&le->sc_if); +} + +#define LENEXTRMP \ + if (++bix == LERBUF) bix = 0, rmd = le->sc_r2->ler2_rmd; else ++rmd + +/* + * Ethernet interface receiver interrupt. + * If input error just drop packet. + * Decapsulate packet based on type and pass to type specific + * higher-level input routine. + */ +lerint(unit) + int unit; +{ + register struct le_softc *le = lecd.cd_devs[unit]; + register int bix = le->sc_rmd; + register struct lermd *rmd = &le->sc_r2->ler2_rmd[bix]; + + /* + * Out of sync with hardware, should never happen? + */ + if (rmd->rmd1 & LE_OWN) { + LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp); + return; + } + + /* + * Process all buffers with valid data + */ + while ((rmd->rmd1 & LE_OWN) == 0) { + int len = rmd->rmd3; + + /* Clear interrupt to avoid race condition */ + LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp); + + if (rmd->rmd1 & LE_ERR) { + le->sc_rmd = bix; + lererror(unit, "bad packet"); + le->sc_if.if_ierrors++; + } else if ((rmd->rmd1 & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) { + /* + * Find the end of the packet so we can see how long + * it was. We still throw it away. + */ + do { + LERDWR(le->sc_r0, LE_RINT|LE_INEA, + le->sc_r1->ler1_rdp); + rmd->rmd3 = 0; + rmd->rmd1 = LE_OWN; + LENEXTRMP; + } while (!(rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP))); + le->sc_rmd = bix; + lererror(unit, "chained buffer"); + le->sc_rxlen++; + /* + * If search terminated without successful completion + * we reset the hardware (conservative). + */ + if ((rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)) != + LE_ENP) { + lereset(unit); + return; + } + } else + leread(unit, le->sc_r2->ler2_rbuf[bix], len); + rmd->rmd3 = 0; + rmd->rmd1 = LE_OWN; + LENEXTRMP; + } + le->sc_rmd = bix; +} + +leread(unit, buf, len) + int unit; + char *buf; + int len; +{ + register struct le_softc *le = lecd.cd_devs[unit]; + register struct ether_header *et; + struct mbuf *m; + int off, resid; + + le->sc_if.if_ipackets++; + et = (struct ether_header *)buf; + et->ether_type = ntohs((u_short)et->ether_type); + /* adjust input length to account for header and CRC */ + len = len - sizeof(struct ether_header) - 4; + +#ifdef RMP + /* (XXX) + * + * If Ethernet Type field is < MaxPacketSize, we probably have + * a IEEE802 packet here. Make sure that the size is at least + * that of the HP LLC. Also do sanity checks on length of LLC + * (old Ethernet Type field) and packet length. + * + * Provided the above checks succeed, change `len' to reflect + * the length of the LLC (i.e. et->ether_type) and change the + * type field to ETHERTYPE_IEEE so we can switch() on it later. + * Yes, this is a hack and will eventually be done "right". + */ + if (et->ether_type <= IEEE802LEN_MAX && len >= sizeof(struct hp_llc) && + len >= et->ether_type && len >= IEEE802LEN_MIN) { + len = et->ether_type; + et->ether_type = ETHERTYPE_IEEE; /* hack! */ + } +#endif + +#define ledataaddr(et, off, type) ((type)(((caddr_t)((et)+1)+(off)))) + if (et->ether_type >= ETHERTYPE_TRAIL && + et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { + off = (et->ether_type - ETHERTYPE_TRAIL) * 512; + if (off >= ETHERMTU) + return; /* sanity */ + et->ether_type = ntohs(*ledataaddr(et, off, u_short *)); + resid = ntohs(*(ledataaddr(et, off+2, u_short *))); + if (off + resid > len) + return; /* sanity */ + len = off + resid; + } else + off = 0; + + if (len <= 0) { + if (ledebug) + log(LOG_WARNING, + "le%d: ierror(runt packet): from %s: len=%d\n", + unit, ether_sprintf(et->ether_shost), len); + le->sc_runt++; + le->sc_if.if_ierrors++; + return; + } +#if NBPFILTER > 0 + /* + * Check if there's a bpf filter listening on this interface. + * If so, hand off the raw packet to bpf, which must deal with + * trailers in its own way. + */ + if (le->sc_bpf) { + bpf_tap(le->sc_bpf, buf, len + sizeof(struct ether_header)); + + /* + * Note that the interface cannot be in promiscuous mode if + * there are no bpf listeners. And if we are in promiscuous + * mode, we have to check if this packet is really ours. + * + * XXX This test does not support multicasts. + */ + if ((le->sc_if.if_flags & IFF_PROMISC) + && bcmp(et->ether_dhost, le->sc_addr, + sizeof(et->ether_dhost)) != 0 + && bcmp(et->ether_dhost, etherbroadcastaddr, + sizeof(et->ether_dhost)) != 0) + return; + } +#endif + /* + * Pull packet off interface. Off is nonzero if packet + * has trailing header; leget will then force this header + * information to be at the front, but we still have to drop + * the type and length which are at the front of any trailer data. + */ + m = leget(buf, len, off, &le->sc_if); + if (m == 0) + return; +#ifdef RMP + /* + * (XXX) + * This needs to be integrated with the ISO stuff in ether_input() + */ + if (et->ether_type == ETHERTYPE_IEEE) { + /* + * Snag the Logical Link Control header (IEEE 802.2). + */ + struct hp_llc *llc = &(mtod(m, struct rmp_packet *)->hp_llc); + + /* + * If the DSAP (and HP's extended DXSAP) indicate this + * is an RMP packet, hand it to the raw input routine. + */ + if (llc->dsap == IEEE_DSAP_HP && llc->dxsap == HPEXT_DXSAP) { + static struct sockproto rmp_sp = {AF_RMP,RMPPROTO_BOOT}; + static struct sockaddr rmp_src = {AF_RMP}; + static struct sockaddr rmp_dst = {AF_RMP}; + + bcopy(et->ether_shost, rmp_src.sa_data, + sizeof(et->ether_shost)); + bcopy(et->ether_dhost, rmp_dst.sa_data, + sizeof(et->ether_dhost)); + + raw_input(m, &rmp_sp, &rmp_src, &rmp_dst); + return; + } + } +#endif + ether_input(&le->sc_if, et, m); +} + +/* + * Routine to copy from mbuf chain to transmit + * buffer in board local memory. + */ +leput(lebuf, m) + register char *lebuf; + register struct mbuf *m; +{ + register struct mbuf *mp; + register int len, tlen = 0; + + for (mp = m; mp; mp = mp->m_next) { + len = mp->m_len; + if (len == 0) + continue; + tlen += len; + bcopy(mtod(mp, char *), lebuf, len); + lebuf += len; + } + m_freem(m); + if (tlen < LEMINSIZE) { + bzero(lebuf, LEMINSIZE - tlen); + tlen = LEMINSIZE; + } + return(tlen); +} + +/* + * Routine to copy from board local memory into mbufs. + */ +struct mbuf * +leget(lebuf, totlen, off0, ifp) + char *lebuf; + int totlen, off0; + struct ifnet *ifp; +{ + register struct mbuf *m; + struct mbuf *top = 0, **mp = ⊤ + register int off = off0, len; + register char *cp; + char *epkt; + + lebuf += sizeof (struct ether_header); + cp = lebuf; + epkt = cp + totlen; + if (off) { + cp += off + 2 * sizeof(u_short); + totlen -= 2 * sizeof(u_short); + } + + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == 0) + return (0); + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = totlen; + m->m_len = MHLEN; + + while (totlen > 0) { + if (top) { + MGET(m, M_DONTWAIT, MT_DATA); + if (m == 0) { + m_freem(top); + return (0); + } + m->m_len = MLEN; + } + len = min(totlen, epkt - cp); + if (len >= MINCLSIZE) { + MCLGET(m, M_DONTWAIT); + if (m->m_flags & M_EXT) + m->m_len = len = min(len, MCLBYTES); + else + len = m->m_len; + } else { + /* + * Place initial small packet/header at end of mbuf. + */ + if (len < m->m_len) { + if (top == 0 && len + max_linkhdr <= m->m_len) + m->m_data += max_linkhdr; + m->m_len = len; + } else + len = m->m_len; + } + bcopy(cp, mtod(m, caddr_t), (unsigned)len); + cp += len; + *mp = m; + mp = &m->m_next; + totlen -= len; + if (cp == epkt) + cp = lebuf; + } + return (top); +} + +/* + * Process an ioctl request. + */ +leioctl(ifp, cmd, data) + register struct ifnet *ifp; + int cmd; + caddr_t data; +{ + register struct ifaddr *ifa = (struct ifaddr *)data; + struct le_softc *le = (struct le_softc *) lecd.cd_devs[ifp->if_unit]; + struct lereg1 *ler1 = le->sc_r1; + int s = splimp(), error = 0; + + switch (cmd) { + + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP; + switch (ifa->ifa_addr->sa_family) { +#ifdef INET + case AF_INET: + leinit(ifp->if_unit); /* before arpwhohas */ + ((struct arpcom *)ifp)->ac_ipaddr = + IA_SIN(ifa)->sin_addr; + arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); + break; +#endif +#ifdef NS + case AF_NS: + { + register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); + + if (ns_nullhost(*ina)) + ina->x_host = *(union ns_host *)(le->sc_addr); + else { + /* + * The manual says we can't change the address + * while the receiver is armed, + * so reset everything + */ + ifp->if_flags &= ~IFF_RUNNING; + bcopy((caddr_t)ina->x_host.c_host, + (caddr_t)le->sc_addr, sizeof(le->sc_addr)); + } + leinit(ifp->if_unit); /* does le_setaddr() */ + break; + } +#endif + default: + leinit(ifp->if_unit); + break; + } + break; + + case SIOCSIFFLAGS: + if ((ifp->if_flags & IFF_UP) == 0 && + ifp->if_flags & IFF_RUNNING) { + LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp); + ifp->if_flags &= ~IFF_RUNNING; + } else if (ifp->if_flags & IFF_UP && + (ifp->if_flags & IFF_RUNNING) == 0) + leinit(ifp->if_unit); + /* + * If the state of the promiscuous bit changes, the interface + * must be reset to effect the change. + */ + if (((ifp->if_flags ^ le->sc_iflags) & IFF_PROMISC) && + (ifp->if_flags & IFF_RUNNING)) { + le->sc_iflags = ifp->if_flags; + lereset(ifp->if_unit); + lestart(ifp); + } + break; + + default: + error = EINVAL; + } + splx(s); + return (error); +} + +leerror(unit, stat) + int unit; + int stat; +{ + struct le_softc *le = NULL; + + + if (!ledebug) + return; + + le = (struct le_softc *) lecd.cd_devs[unit]; + /* + * Not all transceivers implement heartbeat + * so we only log CERR once. + */ + if ((stat & LE_CERR) && le->sc_cerr) + return; + log(LOG_WARNING, + "le%d: error: stat=%b\n", unit, + stat, + "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT"); +} + +lererror(unit, msg) + int unit; + char *msg; +{ + register struct le_softc *le = lecd.cd_devs[unit]; + register struct lermd *rmd; + int len; + + if (!ledebug) + return; + + rmd = &le->sc_r2->ler2_rmd[le->sc_rmd]; + len = rmd->rmd3; + log(LOG_WARNING, + "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n", + unit, msg, + len > 11 ? ether_sprintf(&le->sc_r2->ler2_rbuf[le->sc_rmd][6]) : "unknown", + le->sc_rmd, len, + rmd->rmd1, + "\20\20OWN\17ERR\16FRAM\15OFLO\14CRC\13RBUF\12STP\11ENP"); +} + +lexerror(unit) + int unit; +{ + register struct le_softc *le = lecd.cd_devs[unit]; + register struct letmd *tmd; + int len; + + if (!ledebug) + return; + + tmd = le->sc_r2->ler2_tmd; + len = -tmd->tmd2; + log(LOG_WARNING, + "le%d: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b\n", + unit, + len > 5 ? ether_sprintf(&le->sc_r2->ler2_tbuf[0][0]) : "unknown", + 0, len, + tmd->tmd1, + "\20\20OWN\17ERR\16RES\15MORE\14ONE\13DEF\12STP\11ENP", + tmd->tmd3, + "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY"); +} diff --git a/sys/arch/sun3/dev/if_le.h b/sys/arch/sun3/dev/if_le.h new file mode 100644 index 00000000000..87e04603e0f --- /dev/null +++ b/sys/arch/sun3/dev/if_le.h @@ -0,0 +1,34 @@ +/* + * Ethernet software status per interface. + * + * Each interface is referenced by a network interface structure, + * le_if, which the routing code uses to locate the interface. + * This structure contains the output queue for the interface, its address, ... + */ +struct le_softc { + struct device sc_dev; + struct arpcom sc_ac; /* common Ethernet structures */ +#define sc_if sc_ac.ac_if /* network-visible interface */ +#define sc_addr sc_ac.ac_enaddr /* hardware Ethernet address */ + char *sc_machdep; /* machine dependent pointer */ + struct lereg1 *sc_r1; /* LANCE registers */ + struct lereg2 *sc_r2; /* dual-port RAM */ + int sc_rmd; /* predicted next rmd to process */ + int sc_runt; + int sc_jab; + int sc_merr; + int sc_babl; + int sc_cerr; + int sc_miss; + int sc_xint; + int sc_xown; + int sc_uflo; + int sc_rxlen; + int sc_rxoff; + int sc_txoff; + int sc_busy; + short sc_iflags; +#if NBPFILTER > 0 + caddr_t sc_bpf; +#endif +}; diff --git a/sys/arch/sun3/dev/if_le_subr.c b/sys/arch/sun3/dev/if_le_subr.c new file mode 100644 index 00000000000..476ec71233c --- /dev/null +++ b/sys/arch/sun3/dev/if_le_subr.c @@ -0,0 +1,82 @@ +#include "sys/param.h" +#include "sys/systm.h" +#include "sys/protosw.h" +#include "sys/socket.h" +#include "sys/device.h" +#include "net/if.h" + +#ifdef INET +#include "netinet/in.h" +#include "netinet/in_systm.h" +#include "netinet/in_var.h" +#include "netinet/ip.h" +#include "netinet/if_ether.h" +#endif + +#include "machine/autoconf.h" +#include "machine/cpu.h" +#include "machine/isr.h" +#include "machine/mtpr.h" +#include "machine/obio.h" +#include "machine/idprom.h" + +#include "bpfilter.h" + +#include "if_lereg.h" +#include "if_le.h" + +/* + * things to do: + * allocate dvma area memory for dual access + * use/default config parameters for lance configuration + * setup isr handler + * set ethernet address + * set meta address + * + */ + +int le_machdep_attach(parent, self, args) + struct device *parent; + struct device *self; + void *args; +{ + caddr_t dvma_malloc(), le_addr; + int level, leintr(), unit = DEVICE_UNIT(self); + struct le_softc *le = (struct le_softc *) self; + struct obio_cf_loc *obio_loc = OBIO_LOC(self); + + /* allocate "shared" memory */ + le->sc_r2 = + (struct lereg2 *) dvma_malloc(sizeof(struct lereg2)); + if (!le->sc_r2) { + printf(": not enough dvma space\n"); + return 1; + } + idprom_etheraddr(le->sc_addr); /* ethernet addr */ + le_addr = OBIO_DEFAULT_PARAM(caddr_t, obio_loc->obio_addr, OBIO_AMD_ETHER); + + /* register access */ + le->sc_r1 = (struct lereg1 *) + obio_alloc(le_addr, (caddr_t) OBIO_AMD_ETHER_SIZE, OBIO_WRITE); + if (!le->sc_r1) { + printf(": not enough obio space\n"); + return 1; + } + level = OBIO_DEFAULT_PARAM(int, obio_loc->obio_level, 3); + obio_print(le_addr, level); + le->sc_machdep = NULL; + isr_add(level, leintr, unit); + return 0; +} + +int le_machdep_match(parent, cf, args) + struct device *parent; + struct cfdata *cf; + void *args; +{ + caddr_t le_addr; + struct obio_cf_loc *obio_loc = (struct obio_cf_loc *) CFDATA_LOC(cf); + + le_addr = OBIO_DEFAULT_PARAM(caddr_t, obio_loc->obio_addr, OBIO_AMD_ETHER); + return /* !obio_probe_byte(le_addr)*/ 1; +} diff --git a/sys/arch/sun3/dev/if_le_subr.h b/sys/arch/sun3/dev/if_le_subr.h new file mode 100644 index 00000000000..1ac7f2f0471 --- /dev/null +++ b/sys/arch/sun3/dev/if_le_subr.h @@ -0,0 +1,5 @@ +/* access LANCE registers */ + +#define LERDWR(cntl, src, dst) (dst) = (src) + +#define le_machdep_intrcheck(le, unit) diff --git a/sys/arch/sun3/dev/if_lereg.h b/sys/arch/sun3/dev/if_lereg.h new file mode 100644 index 00000000000..6e8bb775b47 --- /dev/null +++ b/sys/arch/sun3/dev/if_lereg.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1982, 1990 The Regents of the University of California. + * 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 the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * + * from: @(#)if_lereg.h 7.1 (Berkeley) 5/8/90 + * if_lereg.h,v 1.2 1993/05/22 07:56:25 cgd Exp + */ + +#define LEID 21 + +#define LEMTU 1518 +#define LEMINSIZE 60 /* should be 64 if mode DTCR is set */ +#define LERBUF 8 +#define LERBUFLOG2 3 +#define LE_RLEN (LERBUFLOG2 << 13) +#define LETBUF 1 +#define LETBUFLOG2 0 +#define LE_TLEN (LETBUFLOG2 << 13) + +#define vu_char volatile u_char + +/* + * LANCE registers. + */ + +struct lereg1 { + u_short ler1_rdp; /* data port */ + u_short ler1_rap; /* register select port */ +}; + +/* + * Overlayed on 16K dual-port RAM. + * Current size is 13,758 bytes with 8 x 1518 receive buffers and + * 1 x 1518 transmit buffer. + */ +struct lereg2 { + /* init block */ + u_short ler2_mode; /* +0x0000 */ + u_char ler2_padr[6]; /* +0x0002 */ + u_long ler2_ladrf0; /* +0x0008 */ + u_long ler2_ladrf1; /* +0x000C */ + u_short ler2_rdra; /* +0x0010 */ + u_short ler2_rlen; /* +0x0012 */ + u_short ler2_tdra; /* +0x0014 */ + u_short ler2_tlen; /* +0x0016 */ + /* receive message descriptors */ + struct lermd { /* +0x0018 */ + u_short rmd0; + u_short rmd1; + short rmd2; + u_short rmd3; + } ler2_rmd[LERBUF]; + /* transmit message descriptors */ + struct letmd { /* +0x0058 */ + u_short tmd0; + u_short tmd1; + short tmd2; + u_short tmd3; + } ler2_tmd[LETBUF]; + char ler2_rbuf[LERBUF][LEMTU]; /* +0x0060 */ + char ler2_tbuf[LETBUF][LEMTU]; /* +0x2FD0 */ +}; + +/* + * Control and status bits -- lereg0 + */ +#define LE_IE 0x80 /* interrupt enable */ +#define LE_IR 0x40 /* interrupt requested */ +#define LE_LOCK 0x08 /* lock status register */ +#define LE_ACK 0x04 /* ack of lock */ +#define LE_JAB 0x02 /* loss of tx clock (???) */ +#define LE_IPL(x) ((((x) >> 4) & 0x3) + 3) + +/* + * Control and status bits -- lereg1 + */ +#define LE_CSR0 0 +#define LE_CSR1 1 +#define LE_CSR2 2 +#define LE_CSR3 3 + +#define LE_SERR 0x8000 +#define LE_BABL 0x4000 +#define LE_CERR 0x2000 +#define LE_MISS 0x1000 +#define LE_MERR 0x0800 +#define LE_RINT 0x0400 +#define LE_TINT 0x0200 +#define LE_IDON 0x0100 +#define LE_INTR 0x0080 +#define LE_INEA 0x0040 +#define LE_RXON 0x0020 +#define LE_TXON 0x0010 +#define LE_TDMD 0x0008 +#define LE_STOP 0x0004 +#define LE_STRT 0x0002 +#define LE_INIT 0x0001 + +#define LE_BSWP 0x4 +#define LE_MODE 0x0 + +/* + * Control and status bits -- lereg2 + */ +#define LE_OWN 0x8000 +#define LE_ERR 0x4000 +#define LE_STP 0x0200 +#define LE_ENP 0x0100 + +#define LE_FRAM 0x2000 +#define LE_OFLO 0x1000 +#define LE_CRC 0x0800 +#define LE_RBUFF 0x0400 +#define LE_MORE 0x1000 +#define LE_ONE 0x0800 +#define LE_DEF 0x0400 +#define LE_TBUFF 0x8000 +#define LE_UFLO 0x4000 +#define LE_LCOL 0x1000 +#define LE_LCAR 0x0800 +#define LE_RTRY 0x0400 diff --git a/sys/arch/sun3/dev/obctl.c b/sys/arch/sun3/dev/obctl.c new file mode 100644 index 00000000000..0558f24b73d --- /dev/null +++ b/sys/arch/sun3/dev/obctl.c @@ -0,0 +1,38 @@ +#include "sys/systm.h" +#include "sys/device.h" + +#include "machine/autoconf.h" +#include "machine/obctl.h" +#include "machine/param.h" + +extern void obctlattach __P((struct device *, struct device *, void *)); + +struct obctl_softc { + struct device obctl_dev; +}; + +struct cfdriver obctlcd = +{ NULL, "obctl", always_match, obctlattach, DV_DULL, + sizeof(struct obctl_softc), 0}; + +void obctl_print(addr, size) + caddr_t addr; + int size; +{ + printf(" addr 0x%x size 0x%x", addr, size); +} + +void obctlattach(parent, self, args) + struct device *parent; + struct device *self; + void *args; +{ + struct cfdata *new_match; + + printf("\n"); + while (1) { + new_match = config_search(NULL, self, NULL); + if (!new_match) break; + config_attach(self, new_match, NULL, NULL); + } +} diff --git a/sys/arch/sun3/dev/obio.c b/sys/arch/sun3/dev/obio.c index 944cdee02e4..2b139c9f786 100644 --- a/sys/arch/sun3/dev/obio.c +++ b/sys/arch/sun3/dev/obio.c @@ -1,18 +1,20 @@ -#include "systm.h" +#include "sys/systm.h" +#include "sys/device.h" +#include "machine/autoconf.h" #include "machine/obio.h" #include "machine/pte.h" #include "machine/param.h" #include "machine/mon.h" +#include "machine/isr.h" #define ALL 0xFF extern vm_offset_t intersil_va; - -char *interrupt_reg; -vm_offset_t eeprom_va; -vm_offset_t memerr_va; +char *interrupt_reg = NULL; +vm_offset_t eeprom_va = NULL; +vm_offset_t memerr_va = NULL; static struct obio_internal { vm_offset_t *obio_internal_va; @@ -29,6 +31,39 @@ static struct obio_internal { /* {&ecc_va, OBIO_MEMERR, ALL, OBIO_MEMERR_SIZE }, */ }; +extern void obioattach __P((struct device *, struct device *, void *)); + +struct obio_softc { + struct device obio_dev; +}; + +struct cfdriver obiocd = +{ NULL, "obio", always_match, obioattach, DV_DULL, + sizeof(struct obio_softc), 0}; + +void obio_print(addr, level) + caddr_t addr; + int level; +{ + printf(" addr 0x%x", addr); + if (level >=0) + printf(" level %d", level); +} + +void obioattach(parent, self, args) + struct device *parent; + struct device *self; + void *args; +{ + struct cfdata *new_match; + + printf("\n"); + while (1) { + new_match = config_search(NULL, self, NULL); + if (!new_match) break; + config_attach(self, new_match, NULL, NULL); + } +} /* * this routine "configures" any internal OBIO devices which must be @@ -48,7 +83,7 @@ void obio_internal_configure() for (oip = obio_internal_dev; oip->obio_internal_va; oip++) { if ((cpu_machine_id & oip->obio_cpu_mask) == 0) continue; - npages = (sun3_round_page(oip->obio_size)) >>PGSHIFT; + npages = PA_PGNUM(sun3_round_page(oip->obio_size)); va = high_segment_alloc(npages); if (!va) mon_panic("obio_internal_configure: short pages for internal devs"); @@ -58,6 +93,35 @@ void obio_internal_configure() pte_proto |= PG_WRITE; obio_pa = oip->obio_addr; for (; npages != 0; npages--, va += NBPG, obio_pa += NBPG) - set_pte(va, pte_proto | (obio_pa >> PGSHIFT)); + set_pte(va, pte_proto | PA_PGNUM(obio_pa)); } } + +caddr_t obio_alloc(obio_addr, obio_size, obio_flags) + caddr_t obio_addr; + caddr_t obio_size; + int obio_flags; +{ + int npages; + vm_offset_t va, high_segment_alloc(), obio_pa, obio_va, pte_proto; + + npages = PA_PGNUM(sun3_round_page(obio_size)); + if (!npages) + panic("obio_alloc: attempt to allocate 0 pages for obio"); + va = high_segment_alloc(npages); + if (!va) + va = (vm_offset_t) obio_vm_alloc(npages); + if (!va) + panic("obio_alloc: unable to allocate va for obio mapping"); + pte_proto = PG_VALID|PG_SYSTEM|PG_OBIO; + if ((obio_flags & OBIO_CACHE) == 0) + pte_proto |= PG_NC; + if (obio_flags & OBIO_WRITE) + pte_proto |= PG_WRITE; + obio_va = va; + obio_pa = (vm_offset_t) obio_addr; + for (; npages ; npages--, obio_va += NBPG, obio_pa += NBPG) + set_pte(obio_va, pte_proto | PA_PGNUM(obio_pa)); + return (caddr_t) va; +} + diff --git a/sys/arch/sun3/dev/obmem.c b/sys/arch/sun3/dev/obmem.c new file mode 100644 index 00000000000..095cce6bfbd --- /dev/null +++ b/sys/arch/sun3/dev/obmem.c @@ -0,0 +1,42 @@ +#include "sys/systm.h" +#include "sys/device.h" + +#include "machine/autoconf.h" +#include "machine/obmem.h" +#include "machine/param.h" + +extern void obmemattach __P((struct device *, struct device *, void *)); + +struct obmem_softc { + struct device obmem_dev; +}; + +struct cfdriver obmemcd = +{ NULL, "obmem", always_match, obmemattach, DV_DULL, + sizeof(struct obmem_softc), 0}; + +void obmem_print(addr, size, level) + caddr_t addr; + int size; + int level; +{ + printf(" addr 0x%x size 0x%x", addr, size); + if (level <0) + printf(" level %d\n", level); +} + +void obmemattach(parent, self, args) + struct device *parent; + struct device *self; + void *args; +{ + struct cfdata *new_match; + + printf("\n"); + while (1) { + new_match = config_search(NULL, self, NULL); + if (!new_match) break; + config_attach(self, new_match, NULL, NULL); + } + +} diff --git a/sys/arch/sun3/dev/prom.c b/sys/arch/sun3/dev/prom.c index 46cabadc001..f610dd4d66d 100644 --- a/sys/arch/sun3/dev/prom.c +++ b/sys/arch/sun3/dev/prom.c @@ -6,21 +6,43 @@ #include "sys/tty.h" #include "sys/file.h" #include "sys/conf.h" +#include "device.h" +#include "machine/autoconf.h" #include "machine/mon.h" #include "../sun3/cons.h" #include "prom.h" +void promattach __P((struct device *, struct device *, void *)); + struct prom_softc { int flags; int nopen; struct tty t; -} prom_softc[NPROM]; +}; + +struct cfdriver promcd = +{ NULL, "prom", always_match, promattach, + DV_TTY, sizeof(struct prom_softc), 0}; -#if NPROM > 1 -error: "Can not configure more than one prom tty" -#endif +#define PROM_CHECK(unit) \ + if (unit >= promcd.cd_ndevs || (promcd.cd_devs[unit] == NULL)) \ + return ENXIO +#define UNIT_TO_PROMP(unit) promcd.cd_devs[unit] + +void promattach(parent, self, args) + struct device *parent; + struct device *self; + void *args; +{ + struct prom_softc *prom; + + prom = (struct prom_softc *) self; + prom->flags = 0; + prom->nopen = 0; + printf("\n"); +} int promstart __P((struct tty *)); @@ -35,9 +57,8 @@ int promopen(dev, flag, mode, p) int s,error=0; unit = minor(dev); - if (unit >= NPROM) - return ENXIO; - prom = &prom_softc[unit]; + PROM_CHECK(unit); + prom = UNIT_TO_PROMP(unit); bzero(&prom->t, sizeof(struct tty)); tp = &prom->t; tp->t_oproc = promstart; @@ -80,9 +101,8 @@ promclose(dev, flag, mode, p) struct prom_softc *prom; unit = minor(dev); - if (unit >= NPROM) - return ENXIO; - prom = &prom_softc[unit]; + PROM_CHECK(unit); + prom = UNIT_TO_PROMP(unit); tp = &prom->t; (*linesw[tp->t_line].l_close)(tp, flag); ttyclose(tp); @@ -93,36 +113,30 @@ promread(dev, uio, flag) dev_t dev; struct uio *uio; { - register struct tty *tp = &prom_softc[minor(dev)].t; - - return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); + int unit; + register struct tty *tp; + struct prom_softc *prom; + + unit = minor(dev); + PROM_CHECK(unit); + prom = UNIT_TO_PROMP(unit); + tp = &prom->t; + return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); } promwrite(dev, uio, flag) dev_t dev; struct uio *uio; { - register struct tty *tp = &prom_softc[minor(dev)].t; - - return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); -} - - -promcnprobe(cp) - struct consdev *cp; -{ - int prommajor; - - mon_printf("prom console probed (start)\n"); - /* locate the major number */ - for (prommajor = 0; prommajor < nchrdev; prommajor++) - if (cdevsw[prommajor].d_open == promopen) - break; + int unit; + register struct tty *tp; + struct prom_softc *prom; - cp->cn_dev = makedev(prommajor, 0); - cp->cn_pri = CN_NORMAL; /* will always exist but you don't - * want to use it unless you have to - */ - mon_printf("prom console probed (end)\n"); + unit = minor(dev); + PROM_CHECK(unit); + prom = UNIT_TO_PROMP(unit); + tp = &prom->t; + + return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); } int promstart(tp) @@ -167,16 +181,33 @@ promstop(tp, flag) splx(s); } +/* prom console support */ + +promcnprobe(cp) + struct consdev *cp; +{ + int prommajor; + + mon_printf("prom console probed (start)\n"); + /* locate the major number */ + for (prommajor = 0; prommajor < nchrdev; prommajor++) + if (cdevsw[prommajor].d_open == promopen) + break; + cp->cn_dev = makedev(prommajor, 0); + cp->cn_pri = CN_NORMAL; /* will always exist but you don't + * want to use it unless you have to + */ + mon_printf("prom console probed (end)\n"); +} promcninit(cp) struct consdev *cp; { - cp->cn_tp = &prom_softc[0].t; + cp->cn_tp = NULL; mon_printf("prom console initialized\n"); } - promcngetc(dev) dev_t dev; { @@ -194,4 +225,3 @@ promcnputc(dev, c) mon_printf("non unit 0 prom console???\n"); mon_putchar(c); } - diff --git a/sys/arch/sun3/include/autoconf.h b/sys/arch/sun3/include/autoconf.h new file mode 100644 index 00000000000..6a05f015779 --- /dev/null +++ b/sys/arch/sun3/include/autoconf.h @@ -0,0 +1,5 @@ + +int always_match __P((struct device *, struct cfdata *, void *)); + +#define DEVICE_UNIT(device) (device->dv_unit) +#define CFDATA_LOC(cfdata) (cfdata->cf_loc) diff --git a/sys/arch/sun3/include/idprom.h b/sys/arch/sun3/include/idprom.h index cf1578a84c0..595da273b43 100644 --- a/sys/arch/sun3/include/idprom.h +++ b/sys/arch/sun3/include/idprom.h @@ -8,15 +8,15 @@ struct idprom { unsigned char idp_format; unsigned char idp_machtype; - unsigned char idp_etheraddr; + unsigned char idp_etheraddr[6]; long idp_date; unsigned char idp_serialnum[3]; unsigned char idp_checksum; - unsigned char ipd_reserved[16]; + unsigned char idp_reserved[16]; }; #define IDPROM_VERSION 1 #define IDPROM_SIZE (sizeof(struct idprom)) -int idprom_fetch __P((struct idprom *, int version)); - +int idprom_fetch __P((struct idprom *, int)); +void idprom_etheraddr __P((u_char *)); diff --git a/sys/arch/sun3/include/isr.h b/sys/arch/sun3/include/isr.h index 085ecb2ecd5..60f124cd6f3 100644 --- a/sys/arch/sun3/include/isr.h +++ b/sys/arch/sun3/include/isr.h @@ -42,5 +42,7 @@ struct isr { int isr_ipl; }; -#define NISR 3 -#define ISRIPL(x) ((x) - 3) +#define NISR 8 + +void isr_init __P((void)); +void isr_add __P((int, int (*handler)(), int )); diff --git a/sys/arch/sun3/include/obctl.h b/sys/arch/sun3/include/obctl.h new file mode 100644 index 00000000000..de9da66abdd --- /dev/null +++ b/sys/arch/sun3/include/obctl.h @@ -0,0 +1,12 @@ + +struct obctl_cf_loc { + int obctl_addr; + int obctl_size; +}; + +#define OBCTL_DEFAULT_PARAM(cast, arg, default) \ + (cast) (arg == -1 ? default : arg) + +#define OBCTL_LOC(device) (struct obctl_cf_loc *) device->dv_cfdata->cf_loc + + diff --git a/sys/arch/sun3/include/obio.h b/sys/arch/sun3/include/obio.h index eea575d230d..84d42087ede 100644 --- a/sys/arch/sun3/include/obio.h +++ b/sys/arch/sun3/include/obio.h @@ -39,6 +39,26 @@ #define OBIO_DES_SIZE 0x00004 #define OBIO_ECCREG_SIZE 0x00100 +/* flags to obio_alloc() */ +#define OBIO_CACHE 0x1 +#define OBIO_WRITE 0x2 + +struct obio_cf_loc { + int obio_addr; + int obio_level; +}; + +caddr_t obio_alloc __P((caddr_t, caddr_t, int)); +caddr_t obio_vm_alloc __P((int)); +void obio_print __P((caddr_t addr, int level)); +void obio_probe __P((caddr_t addr)); + + +#define OBIO_DEFAULT_PARAM(cast, arg, default) \ + (cast) (arg == -1 ? default : arg) + +#define OBIO_LOC(device) (struct obio_cf_loc *) device->dv_cfdata->cf_loc + #ifdef KERNEL extern char *interrupt_reg; diff --git a/sys/arch/sun3/include/obmem.h b/sys/arch/sun3/include/obmem.h new file mode 100644 index 00000000000..026e84bdba5 --- /dev/null +++ b/sys/arch/sun3/include/obmem.h @@ -0,0 +1,9 @@ +/* put something in here about framebuffers... */ + +struct obmem_cf_loc { + int obmem_cf_addr; + int obmem_cf_size; + int obmem_cf_level; +}; + + diff --git a/sys/arch/sun3/include/vmparam.h b/sys/arch/sun3/include/vmparam.h index c29d6715cd7..7fa2e065dfd 100644 --- a/sys/arch/sun3/include/vmparam.h +++ b/sys/arch/sun3/include/vmparam.h @@ -68,6 +68,9 @@ #define SAFERSS 4 /* nominal ``small'' resident set size protected against replacement */ +#define DVMA_SPACE_SIZE 0x00100000 +#define DVMA_SPACE_START 0x0FD00000 +#define DVMA_SPACE_END 0x0FE00000 /* mon start */ /* * Mach derived constants @@ -78,7 +81,7 @@ #define VM_MAXUSER_ADDRESS ((vm_offset_t)0x0E000000) #define VM_MAX_ADDRESS ((vm_offset_t)0xFFF00000) #define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)0x0E004000) -#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0x0FE00000) /* mon start */ +#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0x0FD00000) /* mon start */ /* virtual sizes (bytes) for various kernel submaps */ #define VM_MBUF_SIZE (NMBCLUSTERS*MCLBYTES) diff --git a/sys/arch/sun3/include/vmparam3.h b/sys/arch/sun3/include/vmparam3.h index c29d6715cd7..7fa2e065dfd 100644 --- a/sys/arch/sun3/include/vmparam3.h +++ b/sys/arch/sun3/include/vmparam3.h @@ -68,6 +68,9 @@ #define SAFERSS 4 /* nominal ``small'' resident set size protected against replacement */ +#define DVMA_SPACE_SIZE 0x00100000 +#define DVMA_SPACE_START 0x0FD00000 +#define DVMA_SPACE_END 0x0FE00000 /* mon start */ /* * Mach derived constants @@ -78,7 +81,7 @@ #define VM_MAXUSER_ADDRESS ((vm_offset_t)0x0E000000) #define VM_MAX_ADDRESS ((vm_offset_t)0xFFF00000) #define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)0x0E004000) -#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0x0FE00000) /* mon start */ +#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0x0FD00000) /* mon start */ /* virtual sizes (bytes) for various kernel submaps */ #define VM_MBUF_SIZE (NMBCLUSTERS*MCLBYTES) diff --git a/sys/arch/sun3/sun3/TODO b/sys/arch/sun3/sun3/TODO index 84cbb787da8..b3265726e85 100644 --- a/sys/arch/sun3/sun3/TODO +++ b/sys/arch/sun3/sun3/TODO @@ -1,9 +1,4 @@ - move idprom.h into include and out of dev - start thinking about autoconfig - add idprom to SOLIPSIST config file - figure out spl layout figure out stack issues - fix sun3_vm_init()->pmap_bootstraping->sys/vm interfacing problems figure out how much of process.s we are going to rewrite because we have a different mmu diff --git a/sys/arch/sun3/sun3/autoconf.c b/sys/arch/sun3/sun3/autoconf.c index 4de6446a610..959470ba19c 100644 --- a/sys/arch/sun3/sun3/autoconf.c +++ b/sys/arch/sun3/sun3/autoconf.c @@ -1,47 +1,4 @@ /* - * Copyright (c) 1988 University of Utah. - * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * the Systems Programming Group of the University of Utah Computer - * Science Department. - * - * 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 the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. - * - * from: Utah $Hdr: autoconf.c 1.31 91/01/21$ - * - * from: @(#)autoconf.c 7.5 (Berkeley) 5/7/91 - * autoconf.c,v 1.4 1993/07/07 06:26:59 cgd Exp - */ - -/* * Setup the system to run on the current machine. * * Configure() is called at boot time. Available @@ -57,17 +14,54 @@ #include "sys/conf.h" #include "sys/dmap.h" #include "sys/reboot.h" +#include "sys/device.h" + +#include "machine/autoconf.h" +#include "machine/vmparam.h" +#include "machine/cpu.h" +#include "machine/pte.h" +#include "machine/isr.h" -#include "../include/vmparam.h" -#include "../include/cpu.h" -#include "pte.h" -#include "isr.h" +extern void mainbusattach __P((struct device *, struct device *, void *)); + +struct mainbus_softc { + struct device mainbus_dev; +}; +struct cfdriver mainbuscd = +{ NULL, "mainbus", always_match, mainbusattach, DV_DULL, + sizeof(struct mainbus_softc), 0}; -struct isr isrqueue[NISR]; +void mainbusattach(parent, self, args) + struct device *parent; + struct device *self; + void *args; +{ + struct cfdata *new_match; + + printf("\n"); + while (1) { + new_match = config_search(NULL, self, NULL); + if (!new_match) break; + config_attach(self, new_match, NULL, NULL); + } +} + +void configure() +{ + int root_found; + + isr_init(); + + root_found = config_rootfound("mainbus", NULL); + if (!root_found) + panic("configure: autoconfig failed, no device tree root found"); +} -void -configure() +int always_match(parent, cf, args) + struct device *parent; + struct cfdata *cf; + void *args; { - isrinit(); + return 1; } diff --git a/sys/arch/sun3/sun3/idprom.c b/sys/arch/sun3/sun3/idprom.c index f56d3d94369..96846c8c6e5 100644 --- a/sys/arch/sun3/sun3/idprom.c +++ b/sys/arch/sun3/sun3/idprom.c @@ -1,30 +1,71 @@ #include "systm.h" +#include "device.h" + +#include "machine/autoconf.h" +#include "machine/control.h" #include "machine/idprom.h" +#include "machine/obctl.h" + #include "idprom.h" -static int idprom_init = 0; +extern void idpromattach __P((struct device *, struct device *, void *)); + +struct idprom_softc { + struct device idprom_driver; + int idprom_init; + struct idprom idprom_copy; + char *idprom_addr; + int idprom_size; +}; + +struct cfdriver idpromcd = +{ NULL, "idprom", always_match, idpromattach, DV_DULL, + sizeof(struct idprom_softc), 0}; -static struct idprom idprom_copy; +#define IDPROM_CHECK(unit) \ + if (unit >= idpromcd.cd_ndevs || (idpromcd.cd_devs[unit] == NULL)) \ + return ENXIO +#define UNIT_TO_IDP(unit) idpromcd.cd_devs[unit] + + +void idpromattach(parent, self, args) + struct device *parent; + struct device *self; + void *args; +{ + struct idprom_softc *idp = (struct idprom_softc *) self; + struct obctl_cf_loc *obctl_loc = OBCTL_LOC(self); -static int idprom_ok = 0; + idp->idprom_init = 0; -int idprom_open(dev, oflags, devtype, p) + idp->idprom_addr = + OBCTL_DEFAULT_PARAM(char *, obctl_loc->obctl_addr, IDPROM_BASE); + idp->idprom_size = + OBCTL_DEFAULT_PARAM(int, obctl_loc->obctl_size, IDPROM_SIZE); + obctl_print(idp->idprom_addr, idp->idprom_size); + printf("\n"); +} + +int idpromopen(dev, oflags, devtype, p) dev_t dev; int oflags; int devtype; struct proc *p; { - int unit,s; + struct idprom_softc *idp; + int unit, idprom_ok; unit = minor(dev); - if (unit >= NIDPROM) - return ENXIO; - if (!idprom_init) idprom_ok = idprom_fetch(&idprom_copy, IDPROM_VERSION); + IDPROM_CHECK(unit); + idp = UNIT_TO_IDP(unit); + if (!idp->idprom_init) + idprom_ok = idprom_fetch(&idp->idprom_copy, IDPROM_VERSION); if (!idprom_ok) return EIO; + idp->idprom_init = 1; return 0; } -int idprom_close(dev, fflag, devtype, p) +int idpromclose(dev, fflag, devtype, p) dev_t dev; int fflag; int devtype; @@ -33,30 +74,27 @@ int idprom_close(dev, fflag, devtype, p) int unit; unit = minor(dev); - if (unit >= NIDPROM) - return ENXIO; + IDPROM_CHECK(unit); return 0; } -idprom_read(dev, uio, ioflag) +idpromread(dev, uio, ioflag) dev_t dev; struct uio *uio; int ioflag; { - int error, unit,length; - + int error, unit, length; + struct idprom_softc *idp; unit = minor(dev); - - if (unit >= NIDPROM) - return ENXIO; - + IDPROM_CHECK(unit); + idp = UNIT_TO_IDP(unit); + if (!idp->idprom_init) return EIO; error = 0; while (uio->uio_resid > 0) { - if (uio->uio_offset >= IDPROM_SIZE) break; /* past or at end */ - length = min(uio->uio_resid, (IDPROM_SIZE-uio->uio_offset)); - error = uiomove((caddr_t) &idprom_copy, length, uio); + if (uio->uio_offset >= idp->idprom_size) break; /* past or at end */ + length = min(uio->uio_resid, (idp->idprom_size - uio->uio_offset)); + error = uiomove((caddr_t) &idp->idprom_copy, length, uio); } return error; } - diff --git a/sys/arch/sun3/sun3/isr.c b/sys/arch/sun3/sun3/isr.c new file mode 100644 index 00000000000..6532c3079d3 --- /dev/null +++ b/sys/arch/sun3/sun3/isr.c @@ -0,0 +1,89 @@ +#include "param.h" +#include "systm.h" +#include "malloc.h" + +#include "net/netisr.h" +#include "machine/isr.h" + + +struct isr *isr_array[NISR]; + +void isr_init() +{ + int i; + + for (i = 0; i < NISR; i++) + isr_array[i] = NULL; +} + +void isr_add(level, handler, arg) + int level; + int (*handler)(); + int arg; +{ + struct isr *new_isr; + + if ((level < 0) || (level >= NISR)) + panic("isr_add: attempt to add handler for bad level"); + new_isr = (struct isr *) + malloc(sizeof(struct isr), M_DEVBUF, M_NOWAIT); + if (!new_isr) + panic("isr_add: allocation of new 'isr' failed"); + new_isr->isr_arg = arg; + new_isr->isr_ipl = level; + new_isr->isr_intr = handler; + new_isr->isr_back = NULL; + if (isr_array[level]) + new_isr->isr_forw = isr_array[level]; + isr_array[level] = new_isr; +} + +void intrhand(sr) + int sr; +{ + struct isr *isr; + int found; + int ipl; + + ipl = (sr >> 8) & 7; + + isr = isr_array[ipl]; + if (!isr) { + printf("intrhand: unexpected sr 0x%x\n", sr); + return; + } + if (!ipl) { + printf("intrhand: spurious interrupt\n"); + return; + } + found = 0; + for (; isr != NULL; isr = isr->isr_forw) + if (isr->isr_intr(isr->isr_arg)) { + found++; + break; + } + if (!found) + printf("intrhand: stray interrupt, sr 0x%x\n", sr); +} + +netintr() +{ +#ifdef INET + if (netisr & (1 << NETISR_IP)) { + netisr &= ~(1 << NETISR_IP); + ipintr(); + } +#endif +#ifdef NS + if (netisr & (1 << NETISR_NS)) { + netisr &= ~(1 << NETISR_NS); + nsintr(); + } +#endif +#ifdef ISO + if (netisr & (1 << NETISR_ISO)) { + netisr &= ~(1 << NETISR_ISO); + clnlintr(); + } +#endif +} diff --git a/sys/arch/sun3/sun3/locore2.c b/sys/arch/sun3/sun3/locore2.c index 3a5c8f4754b..11682ad6088 100644 --- a/sys/arch/sun3/sun3/locore2.c +++ b/sys/arch/sun3/sun3/locore2.c @@ -274,6 +274,17 @@ void sun3_vm_init() sun3_context_equiv(); } +void idprom_etheraddr(eaddrp) + u_char *eaddrp; +{ + eaddrp[0] = identity_prom.idp_etheraddr[0]; + eaddrp[1] = identity_prom.idp_etheraddr[1]; + eaddrp[2] = identity_prom.idp_etheraddr[2]; + eaddrp[3] = identity_prom.idp_etheraddr[3]; + eaddrp[4] = identity_prom.idp_etheraddr[4]; + eaddrp[5] = identity_prom.idp_etheraddr[5]; +} + void sun3_verify_hardware() { unsigned char arch; diff --git a/sys/arch/sun3/sun3/machdep.c b/sys/arch/sun3/sun3/machdep.c index 3a017394331..5aef37e8a62 100644 --- a/sys/arch/sun3/sun3/machdep.c +++ b/sys/arch/sun3/sun3/machdep.c @@ -134,14 +134,14 @@ void cpu_startup() size = (vm_size_t)(v - firstaddr); firstaddr = (caddr_t) kmem_alloc(kernel_map, round_page(size)); if (firstaddr == 0) - panic("startup: no room for tables"); + panic("cpu_startup: no room for tables"); goto again; } /* * End of second pass, addresses have been assigned */ if ((vm_size_t)(v - firstaddr) != size) - panic("startup: table size inconsistency"); + panic("cpu_startup: table size inconsistency"); /* buffer_map stuff but not used */ /* * Allocate a submap for exec arguments. This map effectively @@ -152,10 +152,11 @@ void cpu_startup() * NOT CURRENTLY USED -- cgd */ /* - * Allocate a submap for physio + * Allocate a map for physio and DVMA */ - phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, - VM_PHYS_SIZE, TRUE); + phys_map = vm_map_create(kernel_pmap, DVMA_SPACE_START, DVMA_SPACE_END, 0); + if (!phys_map) + panic("cpu_startup: unable to create physmap"); /* * Finally, allocate mbuf pool. Since mclrefcnt is an off-size @@ -183,7 +184,7 @@ void cpu_startup() * Configure the system. */ printf("about to call configure\n"); -/* configure();*/ + configure(); sun3_stop(); cold = 0; @@ -840,64 +841,3 @@ hexstr(val, len) return(nbuf); } -netintr() -{ -#ifdef INET - if (netisr & (1 << NETISR_IP)) { - netisr &= ~(1 << NETISR_IP); - ipintr(); - } -#endif -#ifdef NS - if (netisr & (1 << NETISR_NS)) { - netisr &= ~(1 << NETISR_NS); - nsintr(); - } -#endif -#ifdef ISO - if (netisr & (1 << NETISR_ISO)) { - netisr &= ~(1 << NETISR_ISO); - clnlintr(); - } -#endif -} - -intrhand(sr) - int sr; -{ -#if 0 - register struct isr *isr; - register int found = 0; - register int ipl; - extern struct isr isrqueue[]; - - ipl = (sr >> 8) & 7; - switch (ipl) { - - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - ipl = ISRIPL(ipl); - isr = isrqueue[ipl].isr_forw; - for (; isr != &isrqueue[ipl]; isr = isr->isr_forw) { - if ((isr->isr_intr)(isr->isr_arg)) { - found++; - break; - } - } - if (found == 0) - printf("stray interrupt, sr 0x%x\n", sr); - break; - - case 0: - default: - printf("intrhand: unexpected sr 0x%x\n", sr); - break; - } -#endif -} - diff --git a/sys/arch/sun3/sun3/obio.c b/sys/arch/sun3/sun3/obio.c index 944cdee02e4..2b139c9f786 100644 --- a/sys/arch/sun3/sun3/obio.c +++ b/sys/arch/sun3/sun3/obio.c @@ -1,18 +1,20 @@ -#include "systm.h" +#include "sys/systm.h" +#include "sys/device.h" +#include "machine/autoconf.h" #include "machine/obio.h" #include "machine/pte.h" #include "machine/param.h" #include "machine/mon.h" +#include "machine/isr.h" #define ALL 0xFF extern vm_offset_t intersil_va; - -char *interrupt_reg; -vm_offset_t eeprom_va; -vm_offset_t memerr_va; +char *interrupt_reg = NULL; +vm_offset_t eeprom_va = NULL; +vm_offset_t memerr_va = NULL; static struct obio_internal { vm_offset_t *obio_internal_va; @@ -29,6 +31,39 @@ static struct obio_internal { /* {&ecc_va, OBIO_MEMERR, ALL, OBIO_MEMERR_SIZE }, */ }; +extern void obioattach __P((struct device *, struct device *, void *)); + +struct obio_softc { + struct device obio_dev; +}; + +struct cfdriver obiocd = +{ NULL, "obio", always_match, obioattach, DV_DULL, + sizeof(struct obio_softc), 0}; + +void obio_print(addr, level) + caddr_t addr; + int level; +{ + printf(" addr 0x%x", addr); + if (level >=0) + printf(" level %d", level); +} + +void obioattach(parent, self, args) + struct device *parent; + struct device *self; + void *args; +{ + struct cfdata *new_match; + + printf("\n"); + while (1) { + new_match = config_search(NULL, self, NULL); + if (!new_match) break; + config_attach(self, new_match, NULL, NULL); + } +} /* * this routine "configures" any internal OBIO devices which must be @@ -48,7 +83,7 @@ void obio_internal_configure() for (oip = obio_internal_dev; oip->obio_internal_va; oip++) { if ((cpu_machine_id & oip->obio_cpu_mask) == 0) continue; - npages = (sun3_round_page(oip->obio_size)) >>PGSHIFT; + npages = PA_PGNUM(sun3_round_page(oip->obio_size)); va = high_segment_alloc(npages); if (!va) mon_panic("obio_internal_configure: short pages for internal devs"); @@ -58,6 +93,35 @@ void obio_internal_configure() pte_proto |= PG_WRITE; obio_pa = oip->obio_addr; for (; npages != 0; npages--, va += NBPG, obio_pa += NBPG) - set_pte(va, pte_proto | (obio_pa >> PGSHIFT)); + set_pte(va, pte_proto | PA_PGNUM(obio_pa)); } } + +caddr_t obio_alloc(obio_addr, obio_size, obio_flags) + caddr_t obio_addr; + caddr_t obio_size; + int obio_flags; +{ + int npages; + vm_offset_t va, high_segment_alloc(), obio_pa, obio_va, pte_proto; + + npages = PA_PGNUM(sun3_round_page(obio_size)); + if (!npages) + panic("obio_alloc: attempt to allocate 0 pages for obio"); + va = high_segment_alloc(npages); + if (!va) + va = (vm_offset_t) obio_vm_alloc(npages); + if (!va) + panic("obio_alloc: unable to allocate va for obio mapping"); + pte_proto = PG_VALID|PG_SYSTEM|PG_OBIO; + if ((obio_flags & OBIO_CACHE) == 0) + pte_proto |= PG_NC; + if (obio_flags & OBIO_WRITE) + pte_proto |= PG_WRITE; + obio_va = va; + obio_pa = (vm_offset_t) obio_addr; + for (; npages ; npages--, obio_va += NBPG, obio_pa += NBPG) + set_pte(obio_va, pte_proto | PA_PGNUM(obio_pa)); + return (caddr_t) va; +} + diff --git a/sys/arch/sun3/sun3/obio.h b/sys/arch/sun3/sun3/obio.h index eea575d230d..84d42087ede 100644 --- a/sys/arch/sun3/sun3/obio.h +++ b/sys/arch/sun3/sun3/obio.h @@ -39,6 +39,26 @@ #define OBIO_DES_SIZE 0x00004 #define OBIO_ECCREG_SIZE 0x00100 +/* flags to obio_alloc() */ +#define OBIO_CACHE 0x1 +#define OBIO_WRITE 0x2 + +struct obio_cf_loc { + int obio_addr; + int obio_level; +}; + +caddr_t obio_alloc __P((caddr_t, caddr_t, int)); +caddr_t obio_vm_alloc __P((int)); +void obio_print __P((caddr_t addr, int level)); +void obio_probe __P((caddr_t addr)); + + +#define OBIO_DEFAULT_PARAM(cast, arg, default) \ + (cast) (arg == -1 ? default : arg) + +#define OBIO_LOC(device) (struct obio_cf_loc *) device->dv_cfdata->cf_loc + #ifdef KERNEL extern char *interrupt_reg; diff --git a/sys/arch/sun3/sun3/obmem.c b/sys/arch/sun3/sun3/obmem.c new file mode 100644 index 00000000000..095cce6bfbd --- /dev/null +++ b/sys/arch/sun3/sun3/obmem.c @@ -0,0 +1,42 @@ +#include "sys/systm.h" +#include "sys/device.h" + +#include "machine/autoconf.h" +#include "machine/obmem.h" +#include "machine/param.h" + +extern void obmemattach __P((struct device *, struct device *, void *)); + +struct obmem_softc { + struct device obmem_dev; +}; + +struct cfdriver obmemcd = +{ NULL, "obmem", always_match, obmemattach, DV_DULL, + sizeof(struct obmem_softc), 0}; + +void obmem_print(addr, size, level) + caddr_t addr; + int size; + int level; +{ + printf(" addr 0x%x size 0x%x", addr, size); + if (level <0) + printf(" level %d\n", level); +} + +void obmemattach(parent, self, args) + struct device *parent; + struct device *self; + void *args; +{ + struct cfdata *new_match; + + printf("\n"); + while (1) { + new_match = config_search(NULL, self, NULL); + if (!new_match) break; + config_attach(self, new_match, NULL, NULL); + } + +} diff --git a/sys/arch/sun3/sun3/obmem.h b/sys/arch/sun3/sun3/obmem.h new file mode 100644 index 00000000000..026e84bdba5 --- /dev/null +++ b/sys/arch/sun3/sun3/obmem.h @@ -0,0 +1,9 @@ +/* put something in here about framebuffers... */ + +struct obmem_cf_loc { + int obmem_cf_addr; + int obmem_cf_size; + int obmem_cf_level; +}; + + diff --git a/sys/arch/sun3/sun3/pmap.c b/sys/arch/sun3/sun3/pmap.c index 4ccf066b50a..38cd0cd2cae 100644 --- a/sys/arch/sun3/sun3/pmap.c +++ b/sys/arch/sun3/sun3/pmap.c @@ -480,8 +480,6 @@ pmeg_t pmeg_allocate_invalid(pmap, va) pmegp->pmeg_reserved = 0; pmegp->pmeg_vpages = 0; enqueue_tail(&pmeg_active_queue, pmegp); - printf("pmeg_allocate_invalid: pmeg %d allocated to pmap %x\n", - pmegp->pmeg_index, pmap); return pmegp; } @@ -635,54 +633,39 @@ unsigned char pv_link(pmap, pa, va, flags) head = pv = pa_to_pvp(pa); PMAP_LOCK(); - printf("entering pv_link, pv == %x\n", pv); - printf("entering pv_link, pv_head_table == %x\n", pv_head_table); - printf("entering pv_link, pa == %x pgnum %x\n", pa, PA_PGNUM(pa)); if (pv->pv_pmap == NULL) { /* not currently "managed" */ pv->pv_va = va; pv->pv_pmap = pmap, pv->pv_next = NULL; pv->pv_flags = flags; - printf("pv_link: before force_cache_flags\n"); force_cache_flags(pa, flags); - printf("pv_link: not currently managed\n"); return flags & PV_NC; } - printf("entering pv_link loop\n"); for (npv = pv ; npv != NULL; last= npv, npv = npv->pv_next ) { if ((npv->pv_pmap != pmap) || (npv->pv_va != va)) continue; - printf("pv_link: found match\n"); if (flags == npv->pv_flags) /* no change */ return get_cache_flags(pa); npv->pv_flags = flags; goto recompute; } - printf("entering pv_link new entry\n"); /*zalloc(pv_zone);*/ pv = malloc(sizeof(struct pv_entry), M_VMPVENT, M_WAITOK); pv->pv_va = va; pv->pv_pmap = pmap, pv->pv_next = NULL; pv->pv_flags = flags; - printf("entering pv_link before last\n"); last->pv_next = pv; - printf("entering pv_link after last\n"); recompute: if (get_cache_flags(pa) & PG_NC) return flags & PV_NC; /* already NC */ if (flags & PV_NC) { /* being NCed, wasn't before */ force_cache_flags(pa, flags); - printf("pv_link: change pte 1\n"); pv_change_pte(head, MAKE_PV_REAL(PV_NC), 0); - printf("pv_link: change pte 1 end\n"); return flags & PV_NC; } - printf("pv_link: cache compute\n"); nflags = pv_compute_cache(head); force_cache_flags(pa, nflags); - printf("pv_link: change pte 2 \n"); pv_change_pte(head, MAKE_PV_REAL(nflags), 0); /* */ - printf("pv_link: change pte 2 after\n"); return nflags & PV_NC; } void pv_change_pte(pv_list, set_bits, clear_bits) @@ -798,10 +781,6 @@ void pv_init() mon_panic("pmap: kmem_alloc() of pv cache table failed"); bzero(pv_cache_table, sizeof(char)* PA_PGNUM(avail_end)); pv_initialized++; - printf("PV: head: %x\n modified: %x\n cache: %x\n", - pv_head_table, - pv_modified_table, - pv_cache_table); } void sun3_protection_init() @@ -1028,11 +1007,10 @@ void pmap_remove_range_mmu(pmap, sva, eva) pmeg_t pmegp; vm_offset_t va,pte; - printf("entering pmap_remove_range_mmu: %x -> %x\n", sva, eva); saved_context = get_context(); if (pmap != kernel_pmap) set_context(pmap->pm_context->context_num); - printf("pmap_remove_range_mmu: past stupid context thing\n"); + sme = get_segmap(sva); if (sme == SEGINV) { if (pmap == kernel_pmap) return; @@ -1044,28 +1022,19 @@ void pmap_remove_range_mmu(pmap, sva, eva) pmegp = pmeg_p(sme); /* have pmeg, will travel */ if (!pmegp->pmeg_vpages) goto outta_here; /* no valid pages anyway */ - printf("pmap_remove_range_mmu: starting removal"); + va = sva; while (va < eva) { pte = get_pte(va); if (pte & PG_VALID) { - printf("before save_modified_bits(): %x\n", pv_modified_table); - printf("before save_modified_bits(): PG_PGNUM(pte)== %x\n", - PG_PGNUM(pte)); - printf("before save_modified_bits(): pv_init %d\n", - pv_initialized); if (pv_initialized) save_modified_bits(pte); - printf("after save_modified_bits()\n"); pv_unlink(pmap, PG_PA(pte), va); - printf("after after pv_unlink()\n"); pmegp->pmeg_vpages--; - printf("after pmegp->pmeg_vpages--\n"); set_pte(va, PG_INVAL); } va+= NBPG; } - printf("pmap_remove_range_mmu: past removal"); if (pmegp->pmeg_vpages <= 0) { if (is_pmeg_wired(pmegp)) printf("pmap: removing wired pmeg\n"); @@ -1079,7 +1048,6 @@ void pmap_remove_range_mmu(pmap, sva, eva) else set_segmap(sva, SEGINV); } - printf("pmap_remove_range_mmu: past cleanup"); outta_here: set_context(saved_context); } @@ -1219,8 +1187,6 @@ void pmap_enter_kernel(va, pa, prot, wired, pte_proto, mem_type) */ if (va < VM_MIN_KERNEL_ADDRESS) printf("pmap: kernel trying to allocate virtual space below itself\n"); - if ((va+NBPG) >= VM_MAX_KERNEL_ADDRESS) - printf("pmap: kernel trying to allocate virtual space above itself\n"); s = splpmap(); sme = get_segmap(va); /* XXXX -- lots of non-defined routines, need to see if pmap has a @@ -1270,8 +1236,6 @@ add_pte: /* can be destructive */ else set_pte(va, pte_proto); } - printf("pmap_enter_kernel: va: %x pa: %x pte_proto: %x\n", va, pa, - pte_proto); pmegp->pmeg_vpages++; /* assumes pmap_enter can never insert a non-valid page*/ splx(s); diff --git a/sys/arch/sun3/sun3/sun3_startup.c b/sys/arch/sun3/sun3/sun3_startup.c index 3a5c8f4754b..11682ad6088 100644 --- a/sys/arch/sun3/sun3/sun3_startup.c +++ b/sys/arch/sun3/sun3/sun3_startup.c @@ -274,6 +274,17 @@ void sun3_vm_init() sun3_context_equiv(); } +void idprom_etheraddr(eaddrp) + u_char *eaddrp; +{ + eaddrp[0] = identity_prom.idp_etheraddr[0]; + eaddrp[1] = identity_prom.idp_etheraddr[1]; + eaddrp[2] = identity_prom.idp_etheraddr[2]; + eaddrp[3] = identity_prom.idp_etheraddr[3]; + eaddrp[4] = identity_prom.idp_etheraddr[4]; + eaddrp[5] = identity_prom.idp_etheraddr[5]; +} + void sun3_verify_hardware() { unsigned char arch; diff --git a/sys/arch/sun3/sun3/vm_machdep.c b/sys/arch/sun3/sun3/vm_machdep.c index bfdf4a5e6f8..c9d214d5cfb 100644 --- a/sys/arch/sun3/sun3/vm_machdep.c +++ b/sys/arch/sun3/sun3/vm_machdep.c @@ -7,6 +7,7 @@ #include "vm/vm.h" #include "vm/vm_kern.h" +#include "vm/vm_map.h" #include "machine/cpu.h" #include "machine/pte.h" @@ -153,3 +154,39 @@ vunmapbuf(bp) bp->b_un.b_addr = bp->b_saveaddr; bp->b_saveaddr = NULL; } + +/* idea for implementation borrowed from chris torek */ + +caddr_t dvma_malloc(size) + size_t size; +{ + caddr_t new_mem; + vm_size_t new_size; + + if (!size) + return NULL; + new_size = sun3_round_page(size); + new_mem = (caddr_t) kmem_alloc(phys_map, new_size); + if (!new_mem) + panic("dvma_malloc: no space in phys_map"); + /* uncache this piece of memory :) */ + return new_mem; +} + +caddr_t obio_vm_alloc(npages) + int npages; +{ + vm_size_t size; + vm_offset_t addr; + int result; + + if (npages == 0); + size = npages*NBPG; + addr = vm_map_min(phys_map); + result = vm_map_find(phys_map, NULL, (vm_offset_t) 0, &addr, size, TRUE); + if (result != KERN_SUCCESS) return NULL; + vm_map_lock(phys_map); + vm_map_delete(phys_map, addr, addr+size); + vm_map_unlock(phys_map); + return (caddr_t) addr; +} diff --git a/sys/conf/files.newconf b/sys/conf/files.newconf index 1b7bf7a044c..34e41c063d1 100644 --- a/sys/conf/files.newconf +++ b/sys/conf/files.newconf @@ -34,10 +34,6 @@ pseudo-device sl: ifnet pseudo-device tun: ifnet pseudo-device bpfilter: ifnet -pseudo-device devpager -pseudo-device swappager -pseudo-device vnodepager - # kernel sources file ddb/db_access.c ddb file ddb/db_aout.c ddb @@ -86,6 +82,7 @@ file kern/kern_time.c file kern/kern_xxx.c file kern/spec_vnops.c file kern/subr_acct.c accounting +file kern/subr_autoconf.c file kern/subr_log.c file kern/subr_mcount.c profiling-routine file kern/subr_prf.c @@ -236,9 +233,9 @@ file ufs/ufs_subr.c file ufs/ufs_tables.c file ufs/ufs_vfsops.c file ufs/ufs_vnops.c -file vm/device_pager.c devpager needs-count +file vm/device_pager.c devpager file vm/kern_lock.c -file vm/swap_pager.c swappager needs-count +file vm/swap_pager.c swappager file vm/vm_fault.c file vm/vm_glue.c file vm/vm_init.c @@ -253,4 +250,4 @@ file vm/vm_pager.c file vm/vm_swap.c file vm/vm_unix.c file vm/vm_user.c -file vm/vnode_pager.c vnodepager needs-count +file vm/vnode_pager.c vnodepager diff --git a/sys/kern/subr_autoconf.c b/sys/kern/subr_autoconf.c index d2e47c6218c..cd5d3a9dcb5 100644 --- a/sys/kern/subr_autoconf.c +++ b/sys/kern/subr_autoconf.c @@ -15,7 +15,7 @@ * * %W% (Berkeley) %G% * - * from: $Header: /cvsroot/src/sys/kern/subr_autoconf.c,v 1.2 1993/08/13 22:00:55 glass Exp $ (LBL) + * from: $Header: /cvsroot/src/sys/kern/subr_autoconf.c,v 1.3 1993/08/15 23:04:50 glass Exp $ (LBL) */ #include "param.h" @@ -56,8 +56,14 @@ mapply(m, cf) if (m->fn != NULL) pri = (*m->fn)(m->parent, cf, m->aux); - else + else { + if (!cf->cf_driver->cd_match) { + printf("mapply: no match function for '%s' device\n", + cf->cf_driver->cd_name); + panic("mapply: not match function\n"); + } pri = (*cf->cf_driver->cd_match)(m->parent, cf, m->aux); + } if (pri > m->pri) { m->match = cf; m->pri = pri; @@ -157,7 +163,8 @@ config_found(parent, aux, print) config_attach(parent, cf, aux, print); return (1); } - printf(msgs[(*print)(aux, parent->dv_xname)]); + if (print) + printf(msgs[(*print)(aux, parent->dv_xname)]); return (0); } @@ -230,8 +237,9 @@ config_attach(parent, cf, aux, print) panic("config_attach: device name too long"); /* get memory for all device vars */ - dev = (struct device *)malloc(cd->cd_devsize, M_DEVBUF, M_WAITOK); - /* XXX cannot wait! */ + dev = (struct device *)malloc(cd->cd_devsize, M_DEVBUF, M_NOWAIT); + if (!dev) + panic("config_attach: memory allocation for device softc failed"); bzero(dev, cd->cd_devsize); *nextp = dev; /* link up */ nextp = &dev->dv_next; @@ -245,7 +253,8 @@ config_attach(parent, cf, aux, print) printf("%s (root)", dev->dv_xname); else { printf("%s at %s", dev->dv_xname, parent->dv_xname); - (void) (*print)(aux, (char *)0); + if (print) + (void) (*print)(aux, (char *)0); } /* put this device in the devices array */ @@ -257,7 +266,9 @@ config_attach(parent, cf, aux, print) void **nsp; if (old == 0) { - nsp = malloc(MINALLOCSIZE, M_DEVBUF, M_WAITOK); /*XXX*/ + nsp = malloc(MINALLOCSIZE, M_DEVBUF, M_NOWAIT); + if (!nsp) + panic("config_attach: expanding dev array"); bzero(nsp, MINALLOCSIZE); cd->cd_ndevs = MINALLOCSIZE / sizeof(void *); } else { @@ -268,7 +279,9 @@ config_attach(parent, cf, aux, print) cd->cd_ndevs = new; oldbytes = old * sizeof(void *); newbytes = new * sizeof(void *); - nsp = malloc(newbytes, M_DEVBUF, M_WAITOK); /*XXX*/ + nsp = malloc(newbytes, M_DEVBUF, M_NOWAIT); + if (!nsp) + panic("config_attach: expanding dev array (2)"); bcopy(cd->cd_devs, nsp, oldbytes); bzero(&nsp[old], newbytes - oldbytes); free(cd->cd_devs, M_DEVBUF); |
