Home | History | Annotate | Line # | Download | only in common
promdev.c revision 1.10
      1 /*	$NetBSD: promdev.c,v 1.10 2001/04/04 15:41:46 pk 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 <sys/systm.h>
     41 #include <machine/idprom.h>
     42 #include <machine/oldmon.h>
     43 #include <machine/promlib.h>
     44 #include <machine/ctlreg.h>
     45 #include <sparc/sparc/asm.h>
     46 #include <machine/pte.h>
     47 
     48 #include <lib/libsa/stand.h>
     49 
     50 #include <sparc/stand/common/promdev.h>
     51 
     52 /* OBP V0-3 PROM vector */
     53 #define obpvec	((struct promvec *)romp)
     54 
     55 int	obp_close __P((struct open_file *));
     56 int	obp_strategy __P((void *, int, daddr_t, size_t, void *, size_t *));
     57 int	obp_v0_strategy __P((void *, int, daddr_t, size_t, void *, size_t *));
     58 ssize_t	obp_v0_xmit __P((struct promdata *, void *, size_t));
     59 ssize_t	obp_v0_recv __P((struct promdata *, void *, size_t));
     60 int	obp_v2_strategy __P((void *, int, daddr_t, size_t, void *, size_t *));
     61 ssize_t	obp_v2_xmit __P((struct promdata *, void *, size_t));
     62 ssize_t	obp_v2_recv __P((struct promdata *, void *, size_t));
     63 int	oldmon_close __P((struct open_file *));
     64 int	oldmon_strategy __P((void *, int, daddr_t, size_t, void *, size_t *));
     65 void	oldmon_iclose __P((struct saioreq *));
     66 int	oldmon_iopen __P((struct promdata *));
     67 ssize_t	oldmon_xmit __P((struct promdata *, void *, size_t));
     68 ssize_t	oldmon_recv __P((struct promdata *, void *, size_t));
     69 
     70 static char	*oldmon_mapin __P((u_long, int, int));
     71 #ifndef BOOTXX
     72 static char	*mygetpropstring __P((int, char *));
     73 static int	getdevtype __P((int, char *));
     74 #endif
     75 
     76 extern struct filesystem file_system_nfs[];
     77 extern struct filesystem file_system_ufs[];
     78 
     79 #define null_devopen	(void *)sparc_noop
     80 #define null_devioctl	(void *)sparc_noop
     81 
     82 #if 0
     83 struct devsw devsw[];
     84 int	ndevs = (sizeof(devsw)/sizeof(devsw[0]));
     85 #endif
     86 
     87 struct devsw oldmon_devsw =
     88 	{ "oldmon", oldmon_strategy, null_devopen, oldmon_close, null_devioctl };
     89 struct devsw obp_v0_devsw =
     90 	{ "obp v0", obp_v0_strategy, null_devopen, obp_close, null_devioctl };
     91 struct devsw obp_v2_devsw =
     92 	{ "obp v2", obp_v2_strategy, null_devopen, obp_close, null_devioctl };
     93 
     94 
     95 char	*prom_bootdevice;
     96 static int	saveecho;
     97 
     98 
     99 void
    100 putchar(c)
    101 	int c;
    102 {
    103 
    104 	if (c == '\n')
    105 		prom_putchar('\r');
    106 	prom_putchar(c);
    107 }
    108 
    109 void
    110 _rtt()
    111 {
    112 	prom_halt();
    113 }
    114 
    115 int
    116 devopen(f, fname, file)
    117 	struct open_file *f;
    118 	const char *fname;
    119 	char **file;
    120 {
    121 	int	error = 0, fd;
    122 	struct	promdata *pd;
    123 
    124 	pd = (struct promdata *)alloc(sizeof *pd);
    125 	f->f_devdata = (void *)pd;
    126 
    127 	switch (prom_version()) {
    128 	case PROM_OLDMON:
    129 		error = oldmon_iopen(pd);
    130 #ifndef BOOTXX
    131 		pd->xmit = oldmon_xmit;
    132 		pd->recv = oldmon_recv;
    133 #endif
    134 		f->f_dev = &oldmon_devsw;
    135 		saveecho = *romVectorPtr->echo;
    136 		*romVectorPtr->echo = 0;
    137 		break;
    138 
    139 	case PROM_OBP_V0:
    140 	case PROM_OBP_V2:
    141 	case PROM_OBP_V3:
    142 	case PROM_OPENFIRM:
    143 		if (prom_bootdevice == NULL) {
    144 			error = ENXIO;
    145 			break;
    146 		}
    147 		fd = prom_open(prom_bootdevice);
    148 		if (fd == 0) {
    149 			error = ENXIO;
    150 			break;
    151 		}
    152 		pd->fd = fd;
    153 		switch (prom_version()) {
    154 		case PROM_OBP_V0:
    155 #ifndef BOOTXX
    156 			pd->xmit = obp_v0_xmit;
    157 			pd->recv = obp_v0_recv;
    158 #endif
    159 			f->f_dev = &obp_v0_devsw;
    160 			break;
    161 		case PROM_OBP_V2:
    162 		case PROM_OBP_V3:
    163 		case PROM_OPENFIRM:
    164 #ifndef BOOTXX
    165 			pd->xmit = obp_v2_xmit;
    166 			pd->recv = obp_v2_recv;
    167 #endif
    168 			f->f_dev = &obp_v2_devsw;
    169 		}
    170 	}
    171 
    172 	if (error) {
    173 		printf("Can't open device `%s'\n", prom_bootdevice);
    174 		return (error);
    175 	}
    176 
    177 #ifdef BOOTXX
    178 	pd->devtype = DT_BLOCK;
    179 #else /* BOOTXX */
    180 	pd->devtype = getdevtype(fd, prom_bootdevice);
    181 	/* Assume type BYTE is a raw device */
    182 	if (pd->devtype != DT_BYTE)
    183 		*file = (char *)fname;
    184 
    185 	if (pd->devtype == DT_NET) {
    186 		bcopy(file_system_nfs, file_system, sizeof(struct fs_ops));
    187 		if ((error = net_open(pd)) != 0) {
    188 			printf("Can't open NFS network connection on `%s'\n",
    189 				prom_bootdevice);
    190 			return (error);
    191 		}
    192 	} else
    193 		bcopy(file_system_ufs, file_system, sizeof(struct fs_ops));
    194 #endif /* BOOTXX */
    195 	return (0);
    196 }
    197 
    198 
    199 int
    200 obp_v0_strategy(devdata, flag, dblk, size, buf, rsize)
    201 	void	*devdata;
    202 	int	flag;
    203 	daddr_t	dblk;
    204 	size_t	size;
    205 	void	*buf;
    206 	size_t	*rsize;
    207 {
    208 	int	n, error = 0;
    209 	struct	promdata *pd = (struct promdata *)devdata;
    210 	int	fd = pd->fd;
    211 
    212 #ifdef DEBUG_PROM
    213 	printf("promstrategy: size=%d dblk=%d\n", size, dblk);
    214 #endif
    215 
    216 #define prom_bread(fd, nblk, dblk, buf) \
    217 		(*obpvec->pv_v0devops.v0_rbdev)(fd, nblk, dblk, buf)
    218 #define prom_bwrite(fd, nblk, dblk, buf) \
    219 		(*obpvec->pv_v0devops.v0_wbdev)(fd, nblk, dblk, buf)
    220 
    221 #ifndef BOOTXX	/* We know it's a block device, so save some space */
    222 	if (pd->devtype != DT_BLOCK) {
    223 		printf("promstrategy: non-block device not supported\n");
    224 		error = EINVAL;
    225 	}
    226 #endif
    227 
    228 	n = (flag == F_READ)
    229 		? prom_bread(fd, btodb(size), dblk, buf)
    230 		: prom_bwrite(fd, btodb(size), dblk, buf);
    231 
    232 	*rsize = dbtob(n);
    233 
    234 #ifdef DEBUG_PROM
    235 	printf("rsize = %x\n", *rsize);
    236 #endif
    237 	return (error);
    238 }
    239 
    240 int
    241 obp_v2_strategy(devdata, flag, dblk, size, buf, rsize)
    242 	void	*devdata;
    243 	int	flag;
    244 	daddr_t	dblk;
    245 	size_t	size;
    246 	void	*buf;
    247 	size_t	*rsize;
    248 {
    249 	int	error = 0;
    250 	struct	promdata *pd = (struct promdata *)devdata;
    251 	int	fd = pd->fd;
    252 
    253 #ifdef DEBUG_PROM
    254 	printf("promstrategy: size=%d dblk=%d\n", size, dblk);
    255 #endif
    256 
    257 #ifndef BOOTXX	/* We know it's a block device, so save some space */
    258 	if (pd->devtype == DT_BLOCK)
    259 #endif
    260 		prom_seek(fd, dbtob(dblk));
    261 
    262 	*rsize = (flag == F_READ)
    263 		? prom_read(fd, buf, size)
    264 		: prom_write(fd, buf, size);
    265 
    266 #ifdef DEBUG_PROM
    267 	printf("rsize = %x\n", *rsize);
    268 #endif
    269 	return (error);
    270 }
    271 
    272 /*
    273  * On old-monitor machines, things work differently.
    274  */
    275 int
    276 oldmon_strategy(devdata, flag, dblk, size, buf, rsize)
    277 	void	*devdata;
    278 	int	flag;
    279 	daddr_t	dblk;
    280 	size_t	size;
    281 	void	*buf;
    282 	size_t	*rsize;
    283 {
    284 	struct promdata	*pd = devdata;
    285 	struct saioreq	*si;
    286 	struct om_boottable *ops;
    287 	char	*dmabuf;
    288 	int	si_flag;
    289 	size_t	xcnt;
    290 
    291 	si = pd->si;
    292 	ops = si->si_boottab;
    293 
    294 #ifdef DEBUG_PROM
    295 	printf("prom_strategy: size=%d dblk=%d\n", size, dblk);
    296 #endif
    297 
    298 	dmabuf = dvma_mapin(buf, size);
    299 
    300 	si->si_bn = dblk;
    301 	si->si_ma = dmabuf;
    302 	si->si_cc = size;
    303 
    304 	si_flag = (flag == F_READ) ? SAIO_F_READ : SAIO_F_WRITE;
    305 	xcnt = (*ops->b_strategy)(si, si_flag);
    306 	dvma_mapout(dmabuf, size);
    307 
    308 #ifdef DEBUG_PROM
    309 	printf("disk_strategy: xcnt = %x\n", xcnt);
    310 #endif
    311 
    312 	if (xcnt <= 0)
    313 		return (EIO);
    314 
    315 	*rsize = xcnt;
    316 	return (0);
    317 }
    318 
    319 int
    320 obp_close(f)
    321 	struct open_file *f;
    322 {
    323 	struct promdata *pd = f->f_devdata;
    324 	register int fd = pd->fd;
    325 
    326 #ifndef BOOTXX
    327 	if (pd->devtype == DT_NET)
    328 		net_close(pd);
    329 #endif
    330 	prom_close(fd);
    331 	return 0;
    332 }
    333 
    334 int
    335 oldmon_close(f)
    336 	struct open_file *f;
    337 {
    338 	struct promdata *pd = f->f_devdata;
    339 
    340 #ifndef BOOTXX
    341 	if (pd->devtype == DT_NET)
    342 		net_close(pd);
    343 #endif
    344 	oldmon_iclose(pd->si);
    345 	pd->si = NULL;
    346 	*romVectorPtr->echo = saveecho; /* Hmm, probably must go somewhere else */
    347 	return 0;
    348 }
    349 
    350 #ifndef BOOTXX
    351 ssize_t
    352 obp_v0_xmit(pd, buf, len)
    353 	struct	promdata *pd;
    354 	void	*buf;
    355 	size_t	len;
    356 {
    357 
    358 	return ((*obpvec->pv_v0devops.v0_wnet)(pd->fd, len, buf));
    359 }
    360 
    361 ssize_t
    362 obp_v2_xmit(pd, buf, len)
    363 	struct	promdata *pd;
    364 	void	*buf;
    365 	size_t	len;
    366 {
    367 
    368 	return (prom_write(pd->fd, buf, len));
    369 }
    370 
    371 ssize_t
    372 obp_v0_recv(pd, buf, len)
    373 	struct	promdata *pd;
    374 	void	*buf;
    375 	size_t	len;
    376 {
    377 
    378 	return ((*obpvec->pv_v0devops.v0_rnet)(pd->fd, len, buf));
    379 }
    380 
    381 ssize_t
    382 obp_v2_recv(pd, buf, len)
    383 	struct	promdata *pd;
    384 	void	*buf;
    385 	size_t	len;
    386 {
    387 	int	n;
    388 
    389 	n = prom_read(pd->fd, buf, len);
    390 
    391 	/* OBP V2 & V3 may return -2 */
    392 	return (n == -2 ? 0 : n);
    393 }
    394 
    395 ssize_t
    396 oldmon_xmit(pd, buf, len)
    397 	struct	promdata *pd;
    398 	void	*buf;
    399 	size_t	len;
    400 {
    401 	struct saioreq	*si;
    402 	struct saif	*sif;
    403 	char		*dmabuf;
    404 	int		rv;
    405 
    406 	si = pd->si;
    407 	sif = si->si_sif;
    408 	if (sif == NULL) {
    409 		printf("xmit: not a network device\n");
    410 		return (-1);
    411 	}
    412 	dmabuf = dvma_mapin(buf, len);
    413 	rv = sif->sif_xmit(si->si_devdata, dmabuf, len);
    414 	dvma_mapout(dmabuf, len);
    415 
    416 	return (ssize_t)(rv ? -1 : len);
    417 }
    418 
    419 ssize_t
    420 oldmon_recv(pd, buf, len)
    421 	struct	promdata *pd;
    422 	void	*buf;
    423 	size_t	len;
    424 {
    425 	struct saioreq	*si;
    426 	struct saif	*sif;
    427 	char		*dmabuf;
    428 	int		rv;
    429 
    430 	si = pd->si;
    431 	sif = si->si_sif;
    432 	dmabuf = dvma_mapin(buf, len);
    433 	rv = sif->sif_poll(si->si_devdata, dmabuf);
    434 	dvma_mapout(dmabuf, len);
    435 
    436 	return (ssize_t)rv;
    437 }
    438 
    439 int
    440 getchar()
    441 {
    442 	return (prom_getchar());
    443 }
    444 
    445 time_t
    446 getsecs()
    447 {
    448 	(void)prom_peekchar();
    449 	return (prom_ticks() / 1000);
    450 }
    451 
    452 
    453 
    454 void
    455 prom_getether(fd, ea)
    456 	int fd;
    457 	u_char *ea;
    458 {
    459 static	struct idprom idprom;
    460 
    461 	switch (prom_version()) {
    462 	case PROM_OLDMON:
    463 		if (idprom.id_format == 0) {
    464 			int len = sizeof(struct idprom);
    465 			u_char *src = (char *)AC_IDPROM;
    466 			u_char *dst = (char *)&idprom;
    467 			do {
    468 				*dst++ = lduba(src++, ASI_CONTROL);
    469 			} while (--len > 0);
    470 		}
    471 		bcopy(idprom.id_ether, ea, 6);
    472 		break;
    473 
    474 	/*
    475 	 * XXX - maybe we should simply always look at the `idprom' property
    476 	 *	 and not bother with `pv_enaddr' or `prom_interpret()' at all.
    477 	 */
    478 	case PROM_OBP_V0:
    479 		if (idprom.id_format == 0) {
    480 			void *buf = &idprom;
    481 			int len = sizeof(struct idprom);
    482 			int node = prom_findroot();
    483 			if (getprop(node, "idprom", 1, &len, &buf) != 0) {
    484 				printf("`idprom' property cannot be read: "
    485 					"cannot get ethernet address");
    486 				/*
    487 				 * Copy ethernet address into `ea' anyway,
    488 				 * so that it will be zeroed.
    489 				 */
    490 			}
    491 		}
    492 		bcopy(idprom.id_ether, ea, 6);
    493 		break;
    494 
    495 	case PROM_OBP_V2:
    496 		(void)(*obpvec->pv_enaddr)(fd, (char *)ea);
    497 		break;
    498 
    499 	case PROM_OPENFIRM:
    500 	case PROM_OBP_V3:
    501 		{
    502 		char buf[64];
    503 		sprintf(buf, "%lx mac-address drop swap 6 cmove", (u_long)ea);
    504 		prom_interpret(buf);
    505 		}
    506 		break;
    507 	}
    508 }
    509 
    510 
    511 /*
    512  * A number of well-known devices on sun4s.
    513  */
    514 static struct dtab {
    515 	char	*name;
    516 	int	type;
    517 } dtab[] = {
    518 	{ "sd",	DT_BLOCK },
    519 	{ "st",	DT_BLOCK },
    520 	{ "xd",	DT_BLOCK },
    521 	{ "xy",	DT_BLOCK },
    522 	{ "fd",	DT_BLOCK },
    523 	{ "le",	DT_NET },
    524 	{ "ie",	DT_NET },
    525 	{ NULL, 0 }
    526 };
    527 
    528 int
    529 getdevtype(fd, name)
    530 	int	fd;
    531 	char	*name;
    532 {
    533 	struct dtab *dp;
    534 	int node;
    535 	char *cp;
    536 
    537 	switch (prom_version()) {
    538 	case PROM_OLDMON:
    539 	case PROM_OBP_V0:
    540 		for (dp = dtab; dp->name; dp++) {
    541 			if (name[0] == dp->name[0] &&
    542 			    name[1] == dp->name[1])
    543 				return (dp->type);
    544 		}
    545 		break;
    546 
    547 	case PROM_OBP_V2:
    548 	case PROM_OBP_V3:
    549 	case PROM_OPENFIRM:
    550 		node = prom_instance_to_package(fd);
    551 		cp = mygetpropstring(node, "device_type");
    552 		if (strcmp(cp, "block") == 0)
    553 			return (DT_BLOCK);
    554 		else if (strcmp(cp, "network") == 0)
    555 			return (DT_NET);
    556 		else if (strcmp(cp, "byte") == 0)
    557 			return (DT_BYTE);
    558 		break;
    559 	}
    560 	return (0);
    561 }
    562 
    563 /*
    564  * Return a string property.  There is a (small) limit on the length;
    565  * the string is fetched into a static buffer which is overwritten on
    566  * subsequent calls.
    567  */
    568 char *
    569 mygetpropstring(node, name)
    570 	int node;
    571 	char *name;
    572 {
    573 	int len;
    574 static	char buf[64];
    575 
    576 	len = prom_proplen(node, name);
    577 	if (len > 0)
    578 		_prom_getprop(node, name, buf, len);
    579 	else
    580 		len = 0;
    581 
    582 	buf[len] = '\0';	/* usually unnecessary */
    583 	return (buf);
    584 }
    585 #endif /* BOOTXX */
    586 
    587 /*
    588  * Old monitor routines
    589  */
    590 
    591 struct saioreq prom_si;
    592 static int promdev_inuse;
    593 
    594 int
    595 oldmon_iopen(pd)
    596 	struct promdata	*pd;
    597 {
    598 	struct om_bootparam *bp;
    599 	struct om_boottable *ops;
    600 	struct devinfo *dip;
    601 	struct saioreq *si;
    602 	int	error;
    603 
    604 	if (promdev_inuse)
    605 		return (EMFILE);
    606 
    607 	bp = *romVectorPtr->bootParam;
    608 	ops = bp->bootTable;
    609 	dip = ops->b_devinfo;
    610 
    611 #ifdef DEBUG_PROM
    612 	printf("Boot device type: %s\n", ops->b_desc);
    613 	printf("d_devbytes=%d\n", dip->d_devbytes);
    614 	printf("d_dmabytes=%d\n", dip->d_dmabytes);
    615 	printf("d_localbytes=%d\n", dip->d_localbytes);
    616 	printf("d_stdcount=%d\n", dip->d_stdcount);
    617 	printf("d_stdaddrs[%d]=%x\n", bp->ctlrNum, dip->d_stdaddrs[bp->ctlrNum]);
    618 	printf("d_devtype=%d\n", dip->d_devtype);
    619 	printf("d_maxiobytes=%d\n", dip->d_maxiobytes);
    620 #endif
    621 
    622 	dvma_init();
    623 
    624 	si = &prom_si;
    625 	memset(si, 0, sizeof(*si));
    626 	si->si_boottab = ops;
    627 	si->si_ctlr = bp->ctlrNum;
    628 	si->si_unit = bp->unitNum;
    629 	si->si_boff = bp->partNum;
    630 
    631 	if (si->si_ctlr > dip->d_stdcount)
    632 		return (ECTLR);
    633 
    634 	if (dip->d_devbytes) {
    635 		si->si_devaddr = oldmon_mapin(dip->d_stdaddrs[si->si_ctlr],
    636 			dip->d_devbytes, dip->d_devtype);
    637 #ifdef	DEBUG_PROM
    638 		printf("prom_iopen: devaddr=0x%x pte=0x%x\n",
    639 			si->si_devaddr,
    640 			getpte4((u_long)si->si_devaddr & ~PGOFSET));
    641 #endif
    642 	}
    643 
    644 	if (dip->d_dmabytes) {
    645 		si->si_dmaaddr = dvma_alloc(dip->d_dmabytes);
    646 #ifdef	DEBUG_PROM
    647 		printf("prom_iopen: dmaaddr=0x%x\n", si->si_dmaaddr);
    648 #endif
    649 	}
    650 
    651 	if (dip->d_localbytes) {
    652 		si->si_devdata = alloc(dip->d_localbytes);
    653 #ifdef	DEBUG_PROM
    654 		printf("prom_iopen: devdata=0x%x\n", si->si_devdata);
    655 #endif
    656 	}
    657 
    658 	/* OK, call the PROM device open routine. */
    659 	error = (*ops->b_open)(si);
    660 	if (error != 0) {
    661 		printf("prom_iopen: \"%s\" error=%d\n", ops->b_desc, error);
    662 		return (ENXIO);
    663 	}
    664 #ifdef	DEBUG_PROM
    665 	printf("prom_iopen: succeeded, error=%d\n", error);
    666 #endif
    667 
    668 	pd->si = si;
    669 	promdev_inuse++;
    670 	return (0);
    671 }
    672 
    673 void
    674 oldmon_iclose(si)
    675 	struct saioreq *si;
    676 {
    677 	struct om_boottable *ops;
    678 	struct devinfo *dip;
    679 
    680 	if (promdev_inuse == 0)
    681 		return;
    682 
    683 	ops = si->si_boottab;
    684 	dip = ops->b_devinfo;
    685 
    686 	(*ops->b_close)(si);
    687 
    688 	if (si->si_dmaaddr) {
    689 		dvma_free(si->si_dmaaddr, dip->d_dmabytes);
    690 		si->si_dmaaddr = NULL;
    691 	}
    692 
    693 	promdev_inuse = 0;
    694 }
    695 
    696 static struct mapinfo {
    697 	int maptype;
    698 	int pgtype;
    699 	int base;
    700 } oldmon_mapinfo[] = {
    701 #define PG_COMMON	(PG_V|PG_W|PG_S|PG_NC)
    702 	{ MAP_MAINMEM,   PG_OBMEM | PG_COMMON, 0 },
    703 	{ MAP_OBIO,      PG_OBIO  | PG_COMMON, 0 },
    704 	{ MAP_MBMEM,     PG_VME16 | PG_COMMON, 0xFF000000 },
    705 	{ MAP_MBIO,      PG_VME16 | PG_COMMON, 0xFFFF0000 },
    706 	{ MAP_VME16A16D, PG_VME16 | PG_COMMON, 0xFFFF0000 },
    707 	{ MAP_VME16A32D, PG_VME32 | PG_COMMON, 0xFFFF0000 },
    708 	{ MAP_VME24A16D, PG_VME16 | PG_COMMON, 0xFF000000 },
    709 	{ MAP_VME24A32D, PG_VME32 | PG_COMMON, 0xFF000000 },
    710 	{ MAP_VME32A16D, PG_VME16 | PG_COMMON, 0 },
    711 	{ MAP_VME32A32D, PG_VME32 | PG_COMMON, 0 },
    712 };
    713 static int oldmon_mapinfo_cnt =
    714 	sizeof(oldmon_mapinfo) / sizeof(oldmon_mapinfo[0]);
    715 
    716 /* The virtual address we will use for PROM device mappings. */
    717 static u_long prom_devmap = MONSHORTSEG;
    718 
    719 static char *
    720 oldmon_mapin(physaddr, length, maptype)
    721 	u_long physaddr;
    722 	int length, maptype;
    723 {
    724 	int i, pa, pte, va;
    725 
    726 	if (length > (4*NBPG))
    727 		panic("oldmon_mapin: length=%d\n", length);
    728 
    729 	for (i = 0; i < oldmon_mapinfo_cnt; i++)
    730 		if (oldmon_mapinfo[i].maptype == maptype)
    731 			goto found;
    732 	panic("oldmon_mapin: invalid maptype %d\n", maptype);
    733 
    734 found:
    735 	pte = oldmon_mapinfo[i].pgtype;
    736 	pa = oldmon_mapinfo[i].base;
    737 	pa += physaddr;
    738 	pte |= ((pa >> SUN4_PGSHIFT) & PG_PFNUM);
    739 
    740 	va = prom_devmap;
    741 	do {
    742 		setpte4(va, pte);
    743 		va += NBPG;
    744 		pte += 1;
    745 		length -= NBPG;
    746 	} while (length > 0);
    747 	return ((char*)(prom_devmap | (pa & PGOFSET)));
    748 }
    749