Home | History | Annotate | Line # | Download | only in common
promdev.c revision 1.1
      1 /*	$NetBSD: promdev.c,v 1.1 1997/06/01 03:39:38 mrg Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1993 Paul Kranenburg
      5  * Copyright (c) 1995 Gordon W. Ross
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *      This product includes software developed by Paul Kranenburg.
     19  * 4. The name of the author may not be used to endorse or promote products
     20  *    derived from this software without specific prior written permission
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 /*
     35  * Note: the `#ifndef BOOTXX' in here serve to queeze the code size
     36  * of the 1st-stage boot program.
     37  */
     38 #include <sys/param.h>
     39 #include <sys/reboot.h>
     40 #include <machine/idprom.h>
     41 #include <machine/oldmon.h>
     42 #include <machine/ctlreg.h>
     43 
     44 #include <lib/libsa/stand.h>
     45 
     46 #include <sparc/stand/common/promdev.h>
     47 
     48 int	obp_close __P((struct open_file *));
     49 int	obp_strategy __P((void *, int, daddr_t, size_t, void *, size_t *));
     50 ssize_t	obp_xmit __P((struct promdata *, void *, size_t));
     51 ssize_t	obp_recv __P((struct promdata *, void *, size_t));
     52 int	prom0_close __P((struct open_file *));
     53 int	prom0_strategy __P((void *, int, daddr_t, size_t, void *, size_t *));
     54 void	prom0_iclose __P((struct saioreq *));
     55 int	prom0_iopen __P((struct promdata *));
     56 ssize_t	prom0_xmit __P((struct promdata *, void *, size_t));
     57 ssize_t	prom0_recv __P((struct promdata *, void *, size_t));
     58 
     59 static char	*prom_mapin __P((u_long, int, int));
     60 
     61 int	getdevtype __P((int, char *));
     62 int	getprop __P((int, char *, void *, int));
     63 char	*getpropstring __P((int, char *));
     64 
     65 static void	prom0_fake __P((void));
     66 
     67 extern struct filesystem file_system_nfs[];
     68 extern struct filesystem file_system_ufs[];
     69 
     70 int prom_open __P((struct open_file *f, ...)) { return 0; }
     71 int prom_ioctl __P((struct open_file *f, u_long c, void *d)) { return EIO; }
     72 
     73 struct devsw devsw[] = {
     74 	{ "prom0", prom0_strategy, prom_open, prom0_close, prom_ioctl },
     75 	{ "prom", obp_strategy, prom_open, obp_close, prom_ioctl }
     76 };
     77 
     78 int	ndevs = (sizeof(devsw)/sizeof(devsw[0]));
     79 
     80 char	*prom_bootdevice;
     81 char	*prom_bootfile;
     82 int	prom_boothow;
     83 
     84 struct	promvec	*promvec;
     85 static int	saveecho;
     86 
     87 void
     88 prom_init()
     89 {
     90 	register char	*ap, *cp, *dp;
     91 
     92 	if (cputyp == CPU_SUN4)
     93 		prom0_fake();
     94 
     95 	if (promvec->pv_romvec_vers >= 2) {
     96 		static char filestore[16];
     97 
     98 		prom_bootdevice = *promvec->pv_v2bootargs.v2_bootpath;
     99 
    100 #ifndef BOOTXX
    101 		cp = *promvec->pv_v2bootargs.v2_bootargs;
    102 		dp = prom_bootfile = filestore;
    103 		while (*cp && *cp != '-')
    104 			*dp++ = *cp++;
    105 		while (dp > prom_bootfile && *--dp == ' ');
    106 		*++dp = '\0';
    107 		ap = cp;
    108 #endif
    109 	} else {
    110 		static char bootstore[16];
    111 		dp = prom_bootdevice = bootstore;
    112 		cp = (*promvec->pv_v0bootargs)->ba_argv[0];
    113 		while (*cp) {
    114 			*dp++ = *cp;
    115 			if (*cp++ == ')')
    116 				break;
    117 		}
    118 		*dp = '\0';
    119 #ifndef BOOTXX
    120 		prom_bootfile = (*promvec->pv_v0bootargs)->ba_kernel;
    121 		ap = (*promvec->pv_v0bootargs)->ba_argv[1];
    122 #endif
    123 	}
    124 
    125 #ifndef BOOTXX
    126 	if (ap == NULL || *ap != '-')
    127 		return;
    128 
    129 	while (*ap) {
    130 		switch (*ap++) {
    131 		case 'a':
    132 			prom_boothow |= RB_ASKNAME;
    133 			break;
    134 		case 's':
    135 			prom_boothow |= RB_SINGLE;
    136 			break;
    137 		case 'd':
    138 			prom_boothow |= RB_KDB;
    139 			debug = 1;
    140 			break;
    141 		}
    142 	}
    143 #endif
    144 }
    145 
    146 int
    147 devopen(f, fname, file)
    148 	struct open_file *f;
    149 	const char *fname;
    150 	char **file;
    151 {
    152 	int	error = 0, fd;
    153 	struct	promdata *pd;
    154 
    155 	pd = (struct promdata *)alloc(sizeof *pd);
    156 
    157 	if (cputyp == CPU_SUN4) {
    158 		error = prom0_iopen(pd);
    159 #ifndef BOOTXX
    160 		pd->xmit = prom0_xmit;
    161 		pd->recv = prom0_recv;
    162 #endif
    163 	} else {
    164 		fd = (promvec->pv_romvec_vers >= 2)
    165 			? (*promvec->pv_v2devops.v2_open)(prom_bootdevice)
    166 			: (*promvec->pv_v0devops.v0_open)(prom_bootdevice);
    167 		if (fd == 0) {
    168 			error = ENXIO;
    169 		} else {
    170 			pd->fd = fd;
    171 #ifndef BOOTXX
    172 			pd->xmit = obp_xmit;
    173 			pd->recv = obp_recv;
    174 #endif
    175 		}
    176 	}
    177 
    178 	if (error) {
    179 		printf("Can't open device `%s'\n", prom_bootdevice);
    180 		return (error);
    181 	}
    182 
    183 #ifdef BOOTXX
    184 	pd->devtype = DT_BLOCK;
    185 #else /* BOOTXX */
    186 	pd->devtype = getdevtype(fd, prom_bootdevice);
    187 	/* Assume type BYTE is a raw device */
    188 	if (pd->devtype != DT_BYTE)
    189 		*file = (char *)fname;
    190 
    191 	if (pd->devtype == DT_NET) {
    192 		bcopy(file_system_nfs, file_system, sizeof(struct fs_ops));
    193 		if ((error = net_open(pd)) != 0) {
    194 			printf("Can't open network device `%s'\n",
    195 				prom_bootdevice);
    196 			return error;
    197 		}
    198 	} else
    199 		bcopy(file_system_ufs, file_system, sizeof(struct fs_ops));
    200 #endif /* BOOTXX */
    201 
    202 	f->f_dev = &devsw[cputyp == CPU_SUN4 ? 0 : 1];
    203 	f->f_devdata = (void *)pd;
    204 	return 0;
    205 }
    206 
    207 int
    208 obp_strategy(devdata, flag, dblk, size, buf, rsize)
    209 	void	*devdata;
    210 	int	flag;
    211 	daddr_t	dblk;
    212 	size_t	size;
    213 	void	*buf;
    214 	size_t	*rsize;
    215 {
    216 	int	error = 0;
    217 	struct	promdata *pd = (struct promdata *)devdata;
    218 	int	fd = pd->fd;
    219 
    220 #ifdef DEBUG_PROM
    221 	printf("promstrategy: size=%d dblk=%d\n", size, dblk);
    222 #endif
    223 
    224 	if (promvec->pv_romvec_vers >= 2) {
    225 		if (pd->devtype == DT_BLOCK)
    226 			(*promvec->pv_v2devops.v2_seek)(fd, 0, dbtob(dblk));
    227 
    228 		*rsize = (*((flag == F_READ)
    229 				? (u_int (*)())promvec->pv_v2devops.v2_read
    230 				: (u_int (*)())promvec->pv_v2devops.v2_write
    231 			 ))(fd, buf, size);
    232 	} else {
    233 		int n = (*((flag == F_READ)
    234 				? (u_int (*)())promvec->pv_v0devops.v0_rbdev
    235 				: (u_int (*)())promvec->pv_v0devops.v0_wbdev
    236 			))(fd, btodb(size), dblk, buf);
    237 		*rsize = dbtob(n);
    238 	}
    239 
    240 #ifdef DEBUG_PROM
    241 	printf("rsize = %x\n", *rsize);
    242 #endif
    243 	return error;
    244 }
    245 
    246 /*
    247  * On old-monitor machines, things work differently.
    248  */
    249 int
    250 prom0_strategy(devdata, flag, dblk, size, buf, rsize)
    251 	void	*devdata;
    252 	int	flag;
    253 	daddr_t	dblk;
    254 	size_t	size;
    255 	void	*buf;
    256 	size_t	*rsize;
    257 {
    258 	struct promdata	*pd = devdata;
    259 	struct saioreq	*si;
    260 	struct om_boottable *ops;
    261 	char	*dmabuf;
    262 	int	si_flag;
    263 	size_t	xcnt;
    264 
    265 	si = pd->si;
    266 	ops = si->si_boottab;
    267 
    268 #ifdef DEBUG_PROM
    269 	printf("prom_strategy: size=%d dblk=%d\n", size, dblk);
    270 #endif
    271 
    272 	dmabuf = dvma_mapin(buf, size);
    273 
    274 	si->si_bn = dblk;
    275 	si->si_ma = dmabuf;
    276 	si->si_cc = size;
    277 
    278 	si_flag = (flag == F_READ) ? SAIO_F_READ : SAIO_F_WRITE;
    279 	xcnt = (*ops->b_strategy)(si, si_flag);
    280 	dvma_mapout(dmabuf, size);
    281 
    282 #ifdef DEBUG_PROM
    283 	printf("disk_strategy: xcnt = %x\n", xcnt);
    284 #endif
    285 
    286 	if (xcnt <= 0)
    287 		return (EIO);
    288 
    289 	*rsize = xcnt;
    290 	return (0);
    291 }
    292 
    293 int
    294 obp_close(f)
    295 	struct open_file *f;
    296 {
    297 	struct promdata *pd = f->f_devdata;
    298 	register int fd = pd->fd;
    299 
    300 #ifndef BOOTXX
    301 	if (pd->devtype == DT_NET)
    302 		net_close(pd);
    303 #endif
    304 	if (promvec->pv_romvec_vers >= 2)
    305 		(void)(*promvec->pv_v2devops.v2_close)(fd);
    306 	else
    307 		(void)(*promvec->pv_v0devops.v0_close)(fd);
    308 	return 0;
    309 }
    310 
    311 int
    312 prom0_close(f)
    313 	struct open_file *f;
    314 {
    315 	struct promdata *pd = f->f_devdata;
    316 
    317 #ifndef BOOTXX
    318 	if (pd->devtype == DT_NET)
    319 		net_close(pd);
    320 #endif
    321 	prom0_iclose(pd->si);
    322 	pd->si = NULL;
    323 	*romp->echo = saveecho; /* Hmm, probably must go somewhere else */
    324 	return 0;
    325 }
    326 
    327 #ifndef BOOTXX
    328 ssize_t
    329 obp_xmit(pd, buf, len)
    330 	struct	promdata *pd;
    331 	void	*buf;
    332 	size_t	len;
    333 {
    334 	return (promvec->pv_romvec_vers >= 2
    335 		? (*promvec->pv_v2devops.v2_write)(pd->fd, buf, len)
    336 		: (*promvec->pv_v0devops.v0_wnet)(pd->fd, len, buf));
    337 }
    338 
    339 ssize_t
    340 obp_recv(pd, buf, len)
    341 	struct	promdata *pd;
    342 	void	*buf;
    343 	size_t	len;
    344 {
    345 	int n;
    346 
    347 	n = (promvec->pv_romvec_vers >= 2
    348 		? (*promvec->pv_v2devops.v2_read)(pd->fd, buf, len)
    349 		: (*promvec->pv_v0devops.v0_rnet)(pd->fd, len, buf));
    350 	return (n == -2 ? 0 : n);
    351 }
    352 
    353 ssize_t
    354 prom0_xmit(pd, buf, len)
    355 	struct	promdata *pd;
    356 	void	*buf;
    357 	size_t	len;
    358 {
    359 	struct saioreq	*si;
    360 	struct saif	*sif;
    361 	char		*dmabuf;
    362 	int		rv;
    363 
    364 	si = pd->si;
    365 	sif = si->si_sif;
    366 	if (sif == NULL) {
    367 		printf("xmit: not a network device\n");
    368 		return (-1);
    369 	}
    370 	dmabuf = dvma_mapin(buf, len);
    371 	rv = sif->sif_xmit(si->si_devdata, dmabuf, len);
    372 	dvma_mapout(dmabuf, len);
    373 
    374 	return (ssize_t)(rv ? -1 : len);
    375 }
    376 
    377 ssize_t
    378 prom0_recv(pd, buf, len)
    379 	struct	promdata *pd;
    380 	void	*buf;
    381 	size_t	len;
    382 {
    383 	struct saioreq	*si;
    384 	struct saif	*sif;
    385 	char		*dmabuf;
    386 	int		rv;
    387 
    388 	si = pd->si;
    389 	sif = si->si_sif;
    390 	dmabuf = dvma_mapin(buf, len);
    391 	rv = sif->sif_poll(si->si_devdata, dmabuf);
    392 	dvma_mapout(dmabuf, len);
    393 
    394 	return (ssize_t)rv;
    395 }
    396 
    397 int
    398 getchar()
    399 {
    400 	char c;
    401 	register int n;
    402 
    403 	if (promvec->pv_romvec_vers > 2)
    404 		while ((n = (*promvec->pv_v2devops.v2_read)
    405 			(*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 1)) != 1);
    406 	else
    407 		c = (*promvec->pv_getchar)();
    408 
    409 	if (c == '\r')
    410 		c = '\n';
    411 	return (c);
    412 }
    413 
    414 int
    415 peekchar()
    416 {
    417 	char c;
    418 	register int n;
    419 
    420 	if (promvec->pv_romvec_vers > 2) {
    421 		n = (*promvec->pv_v2devops.v2_read)
    422 			(*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 1);
    423 		if (n < 0)
    424 			return -1;
    425 	} else
    426 		c = (*promvec->pv_nbgetchar)();
    427 
    428 	if (c == '\r')
    429 		c = '\n';
    430 	return (c);
    431 }
    432 #endif
    433 
    434 static void
    435 pv_putchar(c)
    436 	int c;
    437 {
    438 	char c0 = c;
    439 
    440 	if (promvec->pv_romvec_vers > 2)
    441 		(*promvec->pv_v2devops.v2_write)
    442 			(*promvec->pv_v2bootargs.v2_fd1, &c0, 1);
    443 	else
    444 		(*promvec->pv_putchar)(c);
    445 }
    446 
    447 void
    448 putchar(c)
    449 	int c;
    450 {
    451 
    452 	if (c == '\n')
    453 		pv_putchar('\r');
    454 	pv_putchar(c);
    455 }
    456 
    457 void
    458 _rtt()
    459 {
    460 	promvec->pv_halt();
    461 }
    462 
    463 #ifndef BOOTXX
    464 int hz = 1000;
    465 
    466 time_t
    467 getsecs()
    468 {
    469 	register int ticks = getticks();
    470 	return ((time_t)(ticks / hz));
    471 }
    472 
    473 int
    474 getticks()
    475 {
    476 	if (promvec->pv_romvec_vers >= 2) {
    477 		char c;
    478 		(void)(*promvec->pv_v2devops.v2_read)
    479 			(*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 0);
    480 	} else {
    481 		(void)(*promvec->pv_nbgetchar)();
    482 	}
    483 	return *(promvec->pv_ticks);
    484 }
    485 
    486 void
    487 prom_getether(fd, ea)
    488 	u_char *ea;
    489 {
    490 	if (cputyp == CPU_SUN4) {
    491 		static struct idprom sun4_idprom;
    492 		u_char *src, *dst;
    493 		int len, x;
    494 
    495 		if (sun4_idprom.id_format == 0) {
    496 			dst = (char*)&sun4_idprom;
    497 			src = (char*)AC_IDPROM;
    498 			len = sizeof(struct idprom);
    499 			do {
    500 				x = lduba(src++, ASI_CONTROL);
    501 				*dst++ = x;
    502 			} while (--len > 0);
    503 		}
    504 		bcopy(sun4_idprom.id_ether, ea, 6);
    505 	} else if (promvec->pv_romvec_vers <= 2) {
    506 		(void)(*promvec->pv_enaddr)(fd, (char *)ea);
    507 	} else {
    508 		char buf[64];
    509 		sprintf(buf, "%x mac-address drop swap 6 cmove", ea);
    510 		promvec->pv_fortheval.v2_eval(buf);
    511 	}
    512 }
    513 
    514 
    515 /*
    516  * A number of well-known devices on sun4s.
    517  */
    518 static struct dtab {
    519 	char	*name;
    520 	int	type;
    521 } dtab[] = {
    522 	{ "sd",	DT_BLOCK },
    523 	{ "st",	DT_BLOCK },
    524 	{ "xd",	DT_BLOCK },
    525 	{ "xy",	DT_BLOCK },
    526 	{ "fd",	DT_BLOCK },
    527 	{ "le",	DT_NET },
    528 	{ "ie",	DT_NET },
    529 	{ NULL, 0 }
    530 };
    531 
    532 int
    533 getdevtype(fd, name)
    534 	int	fd;
    535 	char	*name;
    536 {
    537 	if (promvec->pv_romvec_vers >= 2) {
    538 		int node = (*promvec->pv_v2devops.v2_fd_phandle)(fd);
    539 		char *cp = getpropstring(node, "device_type");
    540 		if (strcmp(cp, "block") == 0)
    541 			return DT_BLOCK;
    542 		else if (strcmp(cp, "network") == 0)
    543 			return DT_NET;
    544 		else if (strcmp(cp, "byte") == 0)
    545 			return DT_BYTE;
    546 	} else {
    547 		struct dtab *dp;
    548 		for (dp = dtab; dp->name; dp++) {
    549 			if (name[0] == dp->name[0] &&
    550 			    name[1] == dp->name[1])
    551 				return dp->type;
    552 		}
    553 	}
    554 	return 0;
    555 }
    556 
    557 /*
    558  * OpenPROM nodes & property routines (from <sparc/autoconf.c>).
    559  */
    560 int
    561 getprop(node, name, buf, bufsiz)
    562 	int node;
    563 	char *name;
    564 	void *buf;
    565 	register int bufsiz;
    566 {
    567 	register struct nodeops *no;
    568 	register int len;
    569 
    570 	no = promvec->pv_nodeops;
    571 	len = no->no_proplen(node, name);
    572 	if (len > bufsiz) {
    573 		printf("node %x property %s length %d > %d\n",
    574 		    node, name, len, bufsiz);
    575 		return (0);
    576 	}
    577 	no->no_getprop(node, name, buf);
    578 	return (len);
    579 }
    580 
    581 /*
    582  * Return a string property.  There is a (small) limit on the length;
    583  * the string is fetched into a static buffer which is overwritten on
    584  * subsequent calls.
    585  */
    586 char *
    587 getpropstring(node, name)
    588 	int node;
    589 	char *name;
    590 {
    591 	register int len;
    592 	static char stringbuf[64];
    593 
    594 	len = getprop(node, name, (void *)stringbuf, sizeof stringbuf - 1);
    595 	if (len == -1)
    596 		len = 0;
    597 	stringbuf[len] = '\0';	/* usually unnecessary */
    598 	return (stringbuf);
    599 }
    600 #endif /* BOOTXX */
    601 
    602 /*
    603  * Old monitor routines
    604  */
    605 
    606 #include <machine/pte.h>
    607 
    608 struct saioreq prom_si;
    609 static int promdev_inuse;
    610 
    611 int
    612 prom0_iopen(pd)
    613 	struct promdata	*pd;
    614 {
    615 	struct om_bootparam *bp;
    616 	struct om_boottable *ops;
    617 	struct devinfo *dip;
    618 	struct saioreq *si;
    619 	int	error;
    620 
    621 	if (promdev_inuse)
    622 		return(EMFILE);
    623 
    624 	bp = *romp->bootParam;
    625 	ops = bp->bootTable;
    626 	dip = ops->b_devinfo;
    627 
    628 #ifdef DEBUG_PROM
    629 	printf("Boot device type: %s\n", ops->b_desc);
    630 	printf("d_devbytes=%d\n", dip->d_devbytes);
    631 	printf("d_dmabytes=%d\n", dip->d_dmabytes);
    632 	printf("d_localbytes=%d\n", dip->d_localbytes);
    633 	printf("d_stdcount=%d\n", dip->d_stdcount);
    634 	printf("d_stdaddrs[%d]=%x\n", bp->ctlrNum, dip->d_stdaddrs[bp->ctlrNum]);
    635 	printf("d_devtype=%d\n", dip->d_devtype);
    636 	printf("d_maxiobytes=%d\n", dip->d_maxiobytes);
    637 #endif
    638 
    639 	dvma_init();
    640 
    641 	si = &prom_si;
    642 	bzero((caddr_t)si, sizeof(*si));
    643 	si->si_boottab = ops;
    644 	si->si_ctlr = bp->ctlrNum;
    645 	si->si_unit = bp->unitNum;
    646 	si->si_boff = bp->partNum;
    647 
    648 	if (si->si_ctlr > dip->d_stdcount) {
    649 		printf("Invalid controller number\n");
    650 		return(ENXIO);
    651 	}
    652 
    653 	if (dip->d_devbytes) {
    654 		si->si_devaddr = prom_mapin(dip->d_stdaddrs[si->si_ctlr],
    655 			dip->d_devbytes, dip->d_devtype);
    656 #ifdef	DEBUG_PROM
    657 		printf("prom_iopen: devaddr=0x%x pte=0x%x\n",
    658 			si->si_devaddr,
    659 			getpte((u_long)si->si_devaddr & ~PGOFSET));
    660 #endif
    661 	}
    662 
    663 	if (dip->d_dmabytes) {
    664 		si->si_dmaaddr = dvma_alloc(dip->d_dmabytes);
    665 #ifdef	DEBUG_PROM
    666 		printf("prom_iopen: dmaaddr=0x%x\n", si->si_dmaaddr);
    667 #endif
    668 	}
    669 
    670 	if (dip->d_localbytes) {
    671 		si->si_devdata = alloc(dip->d_localbytes);
    672 #ifdef	DEBUG_PROM
    673 		printf("prom_iopen: devdata=0x%x\n", si->si_devdata);
    674 #endif
    675 	}
    676 
    677 	/* OK, call the PROM device open routine. */
    678 	error = (*ops->b_open)(si);
    679 	if (error != 0) {
    680 		printf("prom_iopen: \"%s\" error=%d\n",
    681 			   ops->b_desc, error);
    682 		return (ENXIO);
    683 	}
    684 #ifdef	DEBUG_PROM
    685 	printf("prom_iopen: succeeded, error=%d\n", error);
    686 #endif
    687 
    688 	pd->si = si;
    689 	promdev_inuse++;
    690 	return (0);
    691 }
    692 
    693 void
    694 prom0_iclose(si)
    695 	struct saioreq *si;
    696 {
    697 	struct om_boottable *ops;
    698 	struct devinfo *dip;
    699 
    700 	if (promdev_inuse == 0)
    701 		return;
    702 
    703 	ops = si->si_boottab;
    704 	dip = ops->b_devinfo;
    705 
    706 	(*ops->b_close)(si);
    707 
    708 	if (si->si_dmaaddr) {
    709 		dvma_free(si->si_dmaaddr, dip->d_dmabytes);
    710 		si->si_dmaaddr = NULL;
    711 	}
    712 
    713 	promdev_inuse = 0;
    714 }
    715 
    716 static struct mapinfo {
    717 	int maptype;
    718 	int pgtype;
    719 	int base;
    720 } prom_mapinfo[] = {
    721 	{ MAP_MAINMEM,   PG_OBMEM, 0 },
    722 	{ MAP_OBIO,      PG_OBIO,  0 },
    723 	{ MAP_MBMEM,     PG_VME16, 0xFF000000 },
    724 	{ MAP_MBIO,      PG_VME16, 0xFFFF0000 },
    725 	{ MAP_VME16A16D, PG_VME16, 0xFFFF0000 },
    726 	{ MAP_VME16A32D, PG_VME32, 0xFFFF0000 },
    727 	{ MAP_VME24A16D, PG_VME16, 0xFF000000 },
    728 	{ MAP_VME24A32D, PG_VME32, 0xFF000000 },
    729 	{ MAP_VME32A16D, PG_VME16, 0 },
    730 	{ MAP_VME32A32D, PG_VME32, 0 },
    731 };
    732 static prom_mapinfo_cnt = sizeof(prom_mapinfo) / sizeof(prom_mapinfo[0]);
    733 
    734 /* The virtual address we will use for PROM device mappings. */
    735 static u_long prom_devmap = MONSHORTSEG;
    736 
    737 static char *
    738 prom_mapin(physaddr, length, maptype)
    739 	u_long physaddr;
    740 	int length, maptype;
    741 {
    742 	int i, pa, pte, va;
    743 
    744 	if (length > (4*NBPG))
    745 		panic("prom_mapin: length=%d\n", length);
    746 
    747 	for (i = 0; i < prom_mapinfo_cnt; i++)
    748 		if (prom_mapinfo[i].maptype == maptype)
    749 			goto found;
    750 	panic("prom_mapin: invalid maptype %d\n", maptype);
    751 found:
    752 
    753 	pte = prom_mapinfo[i].pgtype;
    754 	pte |= (PG_V|PG_W|PG_S|PG_NC);
    755 	pa = prom_mapinfo[i].base;
    756 	pa += physaddr;
    757 	pte |= ((pa >> PGSHIFT) & PG_PFNUM);
    758 
    759 	va = prom_devmap;
    760 	do {
    761 		setpte(va, pte);
    762 		va += NBPG;
    763 		pte += 1;
    764 		length -= NBPG;
    765 	} while (length > 0);
    766 	return ((char*)(prom_devmap | (pa & PGOFSET)));
    767 }
    768 
    769 void
    770 prom0_fake()
    771 {
    772 static	struct promvec promvecstore;
    773 
    774 	promvec = &promvecstore;
    775 
    776 	promvec->pv_stdin = romp->inSource;
    777 	promvec->pv_stdout = romp->outSink;
    778 	promvec->pv_putchar = romp->putChar;
    779 	promvec->pv_putstr = romp->fbWriteStr;
    780 	promvec->pv_nbgetchar = romp->mayGet;
    781 	promvec->pv_getchar = romp->getChar;
    782 	promvec->pv_romvec_vers = 0;            /* eek! */
    783 	promvec->pv_reboot = romp->reBoot;
    784 	promvec->pv_abort = romp->abortEntry;
    785 	promvec->pv_setctxt = romp->setcxsegmap;
    786 	promvec->pv_v0bootargs = (struct v0bootargs **)(romp->bootParam);
    787 	promvec->pv_halt = romp->exitToMon;
    788 	promvec->pv_ticks = romp->nmiClock;
    789 	saveecho = *romp->echo;
    790 	*romp->echo = 0;
    791 }
    792