summaryrefslogtreecommitdiff
path: root/sys/arch/sparc/stand/common/promdev.c
diff options
context:
space:
mode:
authorJason Downs <downsj@cvs.openbsd.org>1997-09-17 10:46:26 +0000
committerJason Downs <downsj@cvs.openbsd.org>1997-09-17 10:46:26 +0000
commit6476cf829b28337c9b81bab966bbc4a4abe37982 (patch)
tree4c6323f69275a5aaa2d1e0a467f4f907e2f47314 /sys/arch/sparc/stand/common/promdev.c
parent3e5a5259f8fb1b6393dd2cf83fb2c3eeda0ea959 (diff)
Reorganizaed bootblocks. Builds like hp300 now.
Diffstat (limited to 'sys/arch/sparc/stand/common/promdev.c')
-rw-r--r--sys/arch/sparc/stand/common/promdev.c805
1 files changed, 805 insertions, 0 deletions
diff --git a/sys/arch/sparc/stand/common/promdev.c b/sys/arch/sparc/stand/common/promdev.c
new file mode 100644
index 00000000000..25057863046
--- /dev/null
+++ b/sys/arch/sparc/stand/common/promdev.c
@@ -0,0 +1,805 @@
+/* $OpenBSD: promdev.c,v 1.1 1997/09/17 10:46:19 downsj Exp $ */
+/* $NetBSD: promdev.c,v 1.16 1995/11/14 15:04:01 pk Exp $ */
+
+/*
+ * Copyright (c) 1993 Paul Kranenburg
+ * Copyright (c) 1995 Gordon W. Ross
+ * 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 Paul Kranenburg.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Note: the `#ifndef BOOTXX' in here serve to queeze the code size
+ * of the 1st-stage boot program.
+ */
+#include <sys/param.h>
+#include <sys/reboot.h>
+#include <machine/idprom.h>
+#include <machine/oldmon.h>
+#include <machine/ctlreg.h>
+
+#include <lib/libsa/stand.h>
+
+#include <sparc/stand/common/promdev.h>
+
+/* u_long _randseed = 1; */
+
+
+int obp_close __P((struct open_file *));
+int obp_strategy __P((void *, int, daddr_t, size_t, void *, size_t *));
+ssize_t obp_xmit __P((struct promdata *, void *, size_t));
+ssize_t obp_recv __P((struct promdata *, void *, size_t));
+int prom0_close __P((struct open_file *));
+int prom0_strategy __P((void *, int, daddr_t, size_t, void *, size_t *));
+void prom0_iclose __P((struct saioreq *));
+int prom0_iopen __P((struct promdata *));
+ssize_t prom0_xmit __P((struct promdata *, void *, size_t));
+ssize_t prom0_recv __P((struct promdata *, void *, size_t));
+
+static char *prom_mapin __P((u_long, int, int));
+
+int getdevtype __P((int, char *));
+int getprop __P((int, char *, void *, int));
+char *getpropstring __P((int, char *));
+
+static void prom0_fake __P((void));
+
+extern struct filesystem file_system_nfs[];
+extern struct filesystem file_system_cd9660[];
+extern struct filesystem file_system_ufs[];
+
+int prom_open __P((struct open_file *f, ...)) { return 0; }
+int prom_ioctl __P((struct open_file *f, u_long c, void *d)) { return EIO; }
+
+struct devsw devsw[] = {
+ { "prom0", prom0_strategy, prom_open, prom0_close, prom_ioctl },
+ { "prom", obp_strategy, prom_open, obp_close, prom_ioctl }
+};
+
+int ndevs = (sizeof(devsw)/sizeof(devsw[0]));
+
+char *prom_bootdevice;
+char *prom_bootfile;
+int prom_boothow;
+
+struct promvec *promvec;
+static int saveecho;
+
+void
+prom_init()
+{
+ register char *ap, *cp, *dp;
+
+ if (cputyp == CPU_SUN4)
+ prom0_fake();
+
+ if (promvec->pv_romvec_vers >= 2) {
+ static char filestore[16];
+
+ prom_bootdevice = *promvec->pv_v2bootargs.v2_bootpath;
+
+#ifndef BOOTXX
+ cp = *promvec->pv_v2bootargs.v2_bootargs;
+ dp = prom_bootfile = filestore;
+ while (*cp && *cp != '-')
+ *dp++ = *cp++;
+ while (dp > prom_bootfile && *--dp == ' ');
+ *++dp = '\0';
+ ap = cp;
+#endif
+ } else {
+ static char bootstore[16];
+ dp = prom_bootdevice = bootstore;
+ cp = (*promvec->pv_v0bootargs)->ba_argv[0];
+ while (*cp) {
+ *dp++ = *cp;
+ if (*cp++ == ')')
+ break;
+ }
+ *dp = '\0';
+#ifndef BOOTXX
+ prom_bootfile = (*promvec->pv_v0bootargs)->ba_kernel;
+ ap = (*promvec->pv_v0bootargs)->ba_argv[1];
+#endif
+ }
+
+#ifndef BOOTXX
+ if (ap == NULL || *ap != '-')
+ return;
+
+ while (*ap) {
+ switch (*ap++) {
+ case 'a':
+ prom_boothow |= RB_ASKNAME;
+ break;
+ case 's':
+ prom_boothow |= RB_SINGLE;
+ break;
+ case 'd':
+ prom_boothow |= RB_KDB;
+ debug = 1;
+ break;
+ }
+ }
+#endif
+}
+
+int
+devopen(f, fname, file)
+ struct open_file *f;
+ const char *fname;
+ char **file;
+{
+ int error = 0, fd;
+ struct promdata *pd;
+
+ pd = (struct promdata *)alloc(sizeof *pd);
+
+ if (cputyp == CPU_SUN4) {
+ error = prom0_iopen(pd);
+#ifndef BOOTXX
+ pd->xmit = prom0_xmit;
+ pd->recv = prom0_recv;
+#endif
+ } else {
+ fd = (promvec->pv_romvec_vers >= 2)
+ ? (*promvec->pv_v2devops.v2_open)(prom_bootdevice)
+ : (*promvec->pv_v0devops.v0_open)(prom_bootdevice);
+ if (fd == 0) {
+ error = ENXIO;
+ } else {
+ pd->fd = fd;
+#ifndef BOOTXX
+ pd->xmit = obp_xmit;
+ pd->recv = obp_recv;
+#endif
+ }
+ }
+
+ if (error) {
+ printf("Can't open device `%s'\n", prom_bootdevice);
+ return (error);
+ }
+
+#ifdef BOOTXX
+ pd->devtype = DT_BLOCK;
+#else /* BOOTXX */
+ pd->devtype = getdevtype(fd, prom_bootdevice);
+ /* Assume type BYTE is a raw device */
+ if (pd->devtype != DT_BYTE)
+ *file = (char *)fname;
+
+ if (pd->devtype == DT_NET) {
+ bcopy(file_system_nfs, file_system, sizeof(struct fs_ops));
+ if ((error = net_open(pd)) != 0) {
+ printf("Can't open network device `%s'\n",
+ prom_bootdevice);
+ return error;
+ }
+ } else {
+ bcopy(file_system_ufs, file_system, sizeof(struct fs_ops));
+ bcopy(&file_system_cd9660, file_system + 1, sizeof file_system[0]);
+ nfsys = 2;
+ }
+#endif /* BOOTXX */
+
+ f->f_dev = &devsw[cputyp == CPU_SUN4 ? 0 : 1];
+ f->f_devdata = (void *)pd;
+ return 0;
+}
+
+int
+obp_strategy(devdata, flag, dblk, size, buf, rsize)
+ void *devdata;
+ int flag;
+ daddr_t dblk;
+ size_t size;
+ void *buf;
+ size_t *rsize;
+{
+ int error = 0;
+ struct promdata *pd = (struct promdata *)devdata;
+ int fd = pd->fd;
+
+#ifdef DEBUG_PROM
+ printf("promstrategy: size=%d dblk=%d\n", size, dblk);
+#endif
+
+ if (promvec->pv_romvec_vers >= 2) {
+ if (pd->devtype == DT_BLOCK)
+ (*promvec->pv_v2devops.v2_seek)(fd, 0, dbtob(dblk));
+
+ *rsize = (*((flag == F_READ)
+ ? (u_int (*)())promvec->pv_v2devops.v2_read
+ : (u_int (*)())promvec->pv_v2devops.v2_write
+ ))(fd, buf, size);
+ } else {
+ int n = (*((flag == F_READ)
+ ? (u_int (*)())promvec->pv_v0devops.v0_rbdev
+ : (u_int (*)())promvec->pv_v0devops.v0_wbdev
+ ))(fd, btodb(size), dblk, buf);
+ *rsize = dbtob(n);
+ }
+
+#ifdef DEBUG_PROM
+ printf("rsize = %x\n", *rsize);
+#endif
+ return error;
+}
+
+/*
+ * On old-monitor machines, things work differently.
+ */
+int
+prom0_strategy(devdata, flag, dblk, size, buf, rsize)
+ void *devdata;
+ int flag;
+ daddr_t dblk;
+ size_t size;
+ void *buf;
+ size_t *rsize;
+{
+ struct promdata *pd = devdata;
+ struct saioreq *si;
+ struct om_boottable *ops;
+ char *dmabuf;
+ int si_flag;
+ size_t xcnt;
+
+ si = pd->si;
+ ops = si->si_boottab;
+
+#ifdef DEBUG_PROM
+ printf("prom_strategy: size=%d dblk=%d\n", size, dblk);
+#endif
+
+ dmabuf = dvma_mapin(buf, size);
+
+ si->si_bn = dblk;
+ si->si_ma = dmabuf;
+ si->si_cc = size;
+
+ si_flag = (flag == F_READ) ? SAIO_F_READ : SAIO_F_WRITE;
+ xcnt = (*ops->b_strategy)(si, si_flag);
+ dvma_mapout(dmabuf, size);
+
+#ifdef DEBUG_PROM
+ printf("disk_strategy: xcnt = %x\n", xcnt);
+#endif
+
+ if (xcnt <= 0)
+ return (EIO);
+
+ *rsize = xcnt;
+ return (0);
+}
+
+int
+obp_close(f)
+ struct open_file *f;
+{
+ struct promdata *pd = f->f_devdata;
+ register int fd = pd->fd;
+
+#ifndef BOOTXX
+ if (pd->devtype == DT_NET)
+ net_close(pd);
+#endif
+ if (promvec->pv_romvec_vers >= 2)
+ (void)(*promvec->pv_v2devops.v2_close)(fd);
+ else
+ (void)(*promvec->pv_v0devops.v0_close)(fd);
+ return 0;
+}
+
+int
+prom0_close(f)
+ struct open_file *f;
+{
+ struct promdata *pd = f->f_devdata;
+
+#ifndef BOOTXX
+ if (pd->devtype == DT_NET)
+ net_close(pd);
+#endif
+ prom0_iclose(pd->si);
+ pd->si = NULL;
+ *romp->echo = saveecho; /* Hmm, probably must go somewhere else */
+ return 0;
+}
+
+#ifndef BOOTXX
+ssize_t
+obp_xmit(pd, buf, len)
+ struct promdata *pd;
+ void *buf;
+ size_t len;
+{
+ return (promvec->pv_romvec_vers >= 2
+ ? (*promvec->pv_v2devops.v2_write)(pd->fd, buf, len)
+ : (*promvec->pv_v0devops.v0_wnet)(pd->fd, len, buf));
+}
+
+ssize_t
+obp_recv(pd, buf, len)
+ struct promdata *pd;
+ void *buf;
+ size_t len;
+{
+ int n;
+
+ n = (promvec->pv_romvec_vers >= 2
+ ? (*promvec->pv_v2devops.v2_read)(pd->fd, buf, len)
+ : (*promvec->pv_v0devops.v0_rnet)(pd->fd, len, buf));
+ return (n == -2 ? 0 : n);
+}
+
+ssize_t
+prom0_xmit(pd, buf, len)
+ struct promdata *pd;
+ void *buf;
+ size_t len;
+{
+ struct saioreq *si;
+ struct saif *sif;
+ char *dmabuf;
+ int rv;
+
+ si = pd->si;
+ sif = si->si_sif;
+ if (sif == NULL) {
+ printf("xmit: not a network device\n");
+ return (-1);
+ }
+ dmabuf = dvma_mapin(buf, len);
+ rv = sif->sif_xmit(si->si_devdata, dmabuf, len);
+ dvma_mapout(dmabuf, len);
+
+ return (ssize_t)(rv ? -1 : len);
+}
+
+ssize_t
+prom0_recv(pd, buf, len)
+ struct promdata *pd;
+ void *buf;
+ size_t len;
+{
+ struct saioreq *si;
+ struct saif *sif;
+ char *dmabuf;
+ int rv;
+
+ si = pd->si;
+ sif = si->si_sif;
+ dmabuf = dvma_mapin(buf, len);
+ rv = sif->sif_poll(si->si_devdata, dmabuf);
+ dvma_mapout(dmabuf, len);
+
+ return (ssize_t)rv;
+}
+
+int
+getchar()
+{
+ char c;
+ register int n;
+
+ if (promvec->pv_romvec_vers > 2)
+ while ((n = (*promvec->pv_v2devops.v2_read)
+ (*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 1)) != 1);
+ else
+ c = (*promvec->pv_getchar)();
+
+ if (c == '\r')
+ c = '\n';
+ return (c);
+}
+
+int
+cngetc()
+{
+ return getchar();
+}
+
+int
+peekchar()
+{
+ char c;
+ register int n;
+
+ if (promvec->pv_romvec_vers > 2) {
+ n = (*promvec->pv_v2devops.v2_read)
+ (*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 1);
+ if (n < 0)
+ return -1;
+ } else
+ c = (*promvec->pv_nbgetchar)();
+
+ if (c == '\r')
+ c = '\n';
+ return (c);
+}
+#endif
+
+static void
+pv_putchar(c)
+ int c;
+{
+ char c0 = c;
+
+ if (promvec->pv_romvec_vers > 2)
+ (*promvec->pv_v2devops.v2_write)
+ (*promvec->pv_v2bootargs.v2_fd1, &c0, 1);
+ else
+ (*promvec->pv_putchar)(c);
+}
+
+void
+putchar(c)
+ int c;
+{
+
+ if (c == '\n')
+ pv_putchar('\r');
+ pv_putchar(c);
+}
+
+void
+_rtt()
+{
+ promvec->pv_halt();
+}
+
+#ifndef BOOTXX
+int hz = 1000;
+
+time_t
+getsecs()
+{
+ register int ticks = getticks();
+ return ((time_t)(ticks / hz));
+}
+
+int
+getticks()
+{
+ if (promvec->pv_romvec_vers >= 2) {
+ char c;
+ (void)(*promvec->pv_v2devops.v2_read)
+ (*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 0);
+ } else {
+ (void)(*promvec->pv_nbgetchar)();
+ }
+ return *(promvec->pv_ticks);
+}
+
+void
+prom_getether(fd, ea)
+ u_char *ea;
+{
+ if (cputyp == CPU_SUN4) {
+ static struct idprom sun4_idprom;
+ u_char *src, *dst;
+ int len, x;
+
+ if (sun4_idprom.id_format == 0) {
+ dst = (char*)&sun4_idprom;
+ src = (char*)AC_IDPROM;
+ len = sizeof(struct idprom);
+ do {
+ x = lduba(src++, ASI_CONTROL);
+ *dst++ = x;
+ } while (--len > 0);
+ }
+ bcopy(sun4_idprom.id_ether, ea, 6);
+ } else if (promvec->pv_romvec_vers <= 2) {
+ (void)(*promvec->pv_enaddr)(fd, (char *)ea);
+ } else {
+ char buf[64];
+ sprintf(buf, "%x mac-address drop swap 6 cmove", ea);
+ promvec->pv_fortheval.v2_eval(buf);
+ }
+}
+
+
+/*
+ * A number of well-known devices on sun4s.
+ */
+static struct dtab {
+ char *name;
+ int type;
+} dtab[] = {
+ { "sd", DT_BLOCK },
+ { "st", DT_BLOCK },
+ { "xd", DT_BLOCK },
+ { "xy", DT_BLOCK },
+ { "fd", DT_BLOCK },
+ { "le", DT_NET },
+ { "ie", DT_NET },
+ { NULL, 0 }
+};
+
+int
+getdevtype(fd, name)
+ int fd;
+ char *name;
+{
+ if (promvec->pv_romvec_vers >= 2) {
+ int node = (*promvec->pv_v2devops.v2_fd_phandle)(fd);
+ char *cp = getpropstring(node, "device_type");
+ if (strcmp(cp, "block") == 0)
+ return DT_BLOCK;
+ else if (strcmp(cp, "network") == 0)
+ return DT_NET;
+ else if (strcmp(cp, "byte") == 0)
+ return DT_BYTE;
+ } else {
+ struct dtab *dp;
+ for (dp = dtab; dp->name; dp++) {
+ if (name[0] == dp->name[0] &&
+ name[1] == dp->name[1])
+ return dp->type;
+ }
+ }
+ return 0;
+}
+
+/*
+ * OpenPROM nodes & property routines (from <sparc/autoconf.c>).
+ */
+int
+getprop(node, name, buf, bufsiz)
+ int node;
+ char *name;
+ void *buf;
+ register int bufsiz;
+{
+ register struct nodeops *no;
+ register int len;
+
+ no = promvec->pv_nodeops;
+ len = no->no_proplen(node, name);
+ if (len > bufsiz) {
+ printf("node %x property %s length %d > %d\n",
+ node, name, len, bufsiz);
+ return (0);
+ }
+ no->no_getprop(node, name, buf);
+ return (len);
+}
+
+/*
+ * Return a string property. There is a (small) limit on the length;
+ * the string is fetched into a static buffer which is overwritten on
+ * subsequent calls.
+ */
+char *
+getpropstring(node, name)
+ int node;
+ char *name;
+{
+ register int len;
+ static char stringbuf[64];
+
+ len = getprop(node, name, (void *)stringbuf, sizeof stringbuf - 1);
+ if (len == -1)
+ len = 0;
+ stringbuf[len] = '\0'; /* usually unnecessary */
+ return (stringbuf);
+}
+#endif /* BOOTXX */
+
+/*
+ * Old monitor routines
+ */
+
+#include <machine/pte.h>
+
+struct saioreq prom_si;
+static int promdev_inuse;
+
+int
+prom0_iopen(pd)
+ struct promdata *pd;
+{
+ struct om_bootparam *bp;
+ struct om_boottable *ops;
+ struct devinfo *dip;
+ struct saioreq *si;
+ int error;
+
+ if (promdev_inuse)
+ return(EMFILE);
+
+ bp = *romp->bootParam;
+ ops = bp->bootTable;
+ dip = ops->b_devinfo;
+
+#ifdef DEBUG_PROM
+ printf("Boot device type: %s\n", ops->b_desc);
+ printf("d_devbytes=%d\n", dip->d_devbytes);
+ printf("d_dmabytes=%d\n", dip->d_dmabytes);
+ printf("d_localbytes=%d\n", dip->d_localbytes);
+ printf("d_stdcount=%d\n", dip->d_stdcount);
+ printf("d_stdaddrs[%d]=%x\n", bp->ctlrNum, dip->d_stdaddrs[bp->ctlrNum]);
+ printf("d_devtype=%d\n", dip->d_devtype);
+ printf("d_maxiobytes=%d\n", dip->d_maxiobytes);
+#endif
+
+ dvma_init();
+
+ si = &prom_si;
+ bzero((caddr_t)si, sizeof(*si));
+ si->si_boottab = ops;
+ si->si_ctlr = bp->ctlrNum;
+ si->si_unit = bp->unitNum;
+ si->si_boff = bp->partNum;
+
+ if (si->si_ctlr > dip->d_stdcount) {
+ printf("Invalid controller number\n");
+ return(ENXIO);
+ }
+
+ if (dip->d_devbytes) {
+ si->si_devaddr = prom_mapin(dip->d_stdaddrs[si->si_ctlr],
+ dip->d_devbytes, dip->d_devtype);
+#ifdef DEBUG_PROM
+ printf("prom_iopen: devaddr=0x%x pte=0x%x\n",
+ si->si_devaddr,
+ getpte((u_long)si->si_devaddr & ~PGOFSET));
+#endif
+ }
+
+ if (dip->d_dmabytes) {
+ si->si_dmaaddr = dvma_alloc(dip->d_dmabytes);
+#ifdef DEBUG_PROM
+ printf("prom_iopen: dmaaddr=0x%x\n", si->si_dmaaddr);
+#endif
+ }
+
+ if (dip->d_localbytes) {
+ si->si_devdata = alloc(dip->d_localbytes);
+#ifdef DEBUG_PROM
+ printf("prom_iopen: devdata=0x%x\n", si->si_devdata);
+#endif
+ }
+
+ /* OK, call the PROM device open routine. */
+ error = (*ops->b_open)(si);
+ if (error != 0) {
+ printf("prom_iopen: \"%s\" error=%d\n",
+ ops->b_desc, error);
+ return (ENXIO);
+ }
+#ifdef DEBUG_PROM
+ printf("prom_iopen: succeeded, error=%d\n", error);
+#endif
+
+ pd->si = si;
+ promdev_inuse++;
+ return (0);
+}
+
+void
+prom0_iclose(si)
+ struct saioreq *si;
+{
+ struct om_boottable *ops;
+ struct devinfo *dip;
+
+ if (promdev_inuse == 0)
+ return;
+
+ ops = si->si_boottab;
+ dip = ops->b_devinfo;
+
+ (*ops->b_close)(si);
+
+ if (si->si_dmaaddr) {
+ dvma_free(si->si_dmaaddr, dip->d_dmabytes);
+ si->si_dmaaddr = NULL;
+ }
+
+ promdev_inuse = 0;
+}
+
+static struct mapinfo {
+ int maptype;
+ int pgtype;
+ int base;
+} prom_mapinfo[] = {
+ { MAP_MAINMEM, PG_OBMEM, 0 },
+ { MAP_OBIO, PG_OBIO, 0 },
+ { MAP_MBMEM, PG_VME16, 0xFF000000 },
+ { MAP_MBIO, PG_VME16, 0xFFFF0000 },
+ { MAP_VME16A16D, PG_VME16, 0xFFFF0000 },
+ { MAP_VME16A32D, PG_VME32, 0xFFFF0000 },
+ { MAP_VME24A16D, PG_VME16, 0xFF000000 },
+ { MAP_VME24A32D, PG_VME32, 0xFF000000 },
+ { MAP_VME32A16D, PG_VME16, 0 },
+ { MAP_VME32A32D, PG_VME32, 0 },
+};
+static prom_mapinfo_cnt = sizeof(prom_mapinfo) / sizeof(prom_mapinfo[0]);
+
+/* The virtual address we will use for PROM device mappings. */
+static u_long prom_devmap = MONSHORTSEG;
+
+static char *
+prom_mapin(physaddr, length, maptype)
+ u_long physaddr;
+ int length, maptype;
+{
+ int i, pa, pte, va;
+
+ if (length > (4*NBPG))
+ panic("prom_mapin: length=%d\n", length);
+
+ for (i = 0; i < prom_mapinfo_cnt; i++)
+ if (prom_mapinfo[i].maptype == maptype)
+ goto found;
+ panic("prom_mapin: invalid maptype %d\n", maptype);
+found:
+
+ pte = prom_mapinfo[i].pgtype;
+ pte |= (PG_V|PG_W|PG_S|PG_NC);
+ pa = prom_mapinfo[i].base;
+ pa += physaddr;
+ pte |= ((pa >> PGSHIFT) & PG_PFNUM);
+
+ va = prom_devmap;
+ do {
+ setpte(va, pte);
+ va += NBPG;
+ pte += 1;
+ length -= NBPG;
+ } while (length > 0);
+ return ((char*)(prom_devmap | (pa & PGOFSET)));
+}
+
+void
+prom0_fake()
+{
+static struct promvec promvecstore;
+
+ promvec = &promvecstore;
+
+ promvec->pv_stdin = romp->inSource;
+ promvec->pv_stdout = romp->outSink;
+ promvec->pv_putchar = romp->putChar;
+ promvec->pv_putstr = romp->fbWriteStr;
+ promvec->pv_nbgetchar = romp->mayGet;
+ promvec->pv_getchar = romp->getChar;
+ promvec->pv_romvec_vers = 0; /* eek! */
+ promvec->pv_reboot = romp->reBoot;
+ promvec->pv_abort = romp->abortEntry;
+ promvec->pv_setctxt = romp->setcxsegmap;
+ promvec->pv_v0bootargs = (struct v0bootargs **)(romp->bootParam);
+ promvec->pv_halt = romp->exitToMon;
+ promvec->pv_ticks = romp->nmiClock;
+ saveecho = *romp->echo;
+ *romp->echo = 0;
+}