Home | History | Annotate | Line # | Download | only in common
promdev.c revision 1.9
      1 /*	$NetBSD: promdev.c,v 1.9 2001/01/18 12:50:10 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_OBP_V3: {
    500 		char buf[64];
    501 		sprintf(buf, "%lx mac-address drop swap 6 cmove", (u_long)ea);
    502 		prom_interpret(buf);
    503 		}
    504 		break;
    505 	}
    506 }
    507 
    508 
    509 /*
    510  * A number of well-known devices on sun4s.
    511  */
    512 static struct dtab {
    513 	char	*name;
    514 	int	type;
    515 } dtab[] = {
    516 	{ "sd",	DT_BLOCK },
    517 	{ "st",	DT_BLOCK },
    518 	{ "xd",	DT_BLOCK },
    519 	{ "xy",	DT_BLOCK },
    520 	{ "fd",	DT_BLOCK },
    521 	{ "le",	DT_NET },
    522 	{ "ie",	DT_NET },
    523 	{ NULL, 0 }
    524 };
    525 
    526 int
    527 getdevtype(fd, name)
    528 	int	fd;
    529 	char	*name;
    530 {
    531 	struct dtab *dp;
    532 	int node;
    533 	char *cp;
    534 
    535 	switch (prom_version()) {
    536 	case PROM_OLDMON:
    537 	case PROM_OBP_V0:
    538 		for (dp = dtab; dp->name; dp++) {
    539 			if (name[0] == dp->name[0] &&
    540 			    name[1] == dp->name[1])
    541 				return (dp->type);
    542 		}
    543 		break;
    544 
    545 	case PROM_OBP_V2:
    546 	case PROM_OBP_V3:
    547 		node = (*obpvec->pv_v2devops.v2_fd_phandle)(fd);
    548 		cp = mygetpropstring(node, "device_type");
    549 		if (strcmp(cp, "block") == 0)
    550 			return (DT_BLOCK);
    551 		else if (strcmp(cp, "network") == 0)
    552 			return (DT_NET);
    553 		else if (strcmp(cp, "byte") == 0)
    554 			return (DT_BYTE);
    555 		break;
    556 	}
    557 	return (0);
    558 }
    559 
    560 /*
    561  * Return a string property.  There is a (small) limit on the length;
    562  * the string is fetched into a static buffer which is overwritten on
    563  * subsequent calls.
    564  */
    565 char *
    566 mygetpropstring(node, name)
    567 	int node;
    568 	char *name;
    569 {
    570 	int len;
    571 static	char buf[64];
    572 
    573 	len = prom_proplen(node, name);
    574 	if (len > 0)
    575 		_prom_getprop(node, name, buf, len);
    576 	else
    577 		len = 0;
    578 
    579 	buf[len] = '\0';	/* usually unnecessary */
    580 	return (buf);
    581 }
    582 #endif /* BOOTXX */
    583 
    584 /*
    585  * Old monitor routines
    586  */
    587 
    588 struct saioreq prom_si;
    589 static int promdev_inuse;
    590 
    591 int
    592 oldmon_iopen(pd)
    593 	struct promdata	*pd;
    594 {
    595 	struct om_bootparam *bp;
    596 	struct om_boottable *ops;
    597 	struct devinfo *dip;
    598 	struct saioreq *si;
    599 	int	error;
    600 
    601 	if (promdev_inuse)
    602 		return (EMFILE);
    603 
    604 	bp = *romVectorPtr->bootParam;
    605 	ops = bp->bootTable;
    606 	dip = ops->b_devinfo;
    607 
    608 #ifdef DEBUG_PROM
    609 	printf("Boot device type: %s\n", ops->b_desc);
    610 	printf("d_devbytes=%d\n", dip->d_devbytes);
    611 	printf("d_dmabytes=%d\n", dip->d_dmabytes);
    612 	printf("d_localbytes=%d\n", dip->d_localbytes);
    613 	printf("d_stdcount=%d\n", dip->d_stdcount);
    614 	printf("d_stdaddrs[%d]=%x\n", bp->ctlrNum, dip->d_stdaddrs[bp->ctlrNum]);
    615 	printf("d_devtype=%d\n", dip->d_devtype);
    616 	printf("d_maxiobytes=%d\n", dip->d_maxiobytes);
    617 #endif
    618 
    619 	dvma_init();
    620 
    621 	si = &prom_si;
    622 	memset(si, 0, sizeof(*si));
    623 	si->si_boottab = ops;
    624 	si->si_ctlr = bp->ctlrNum;
    625 	si->si_unit = bp->unitNum;
    626 	si->si_boff = bp->partNum;
    627 
    628 	if (si->si_ctlr > dip->d_stdcount)
    629 		return (ECTLR);
    630 
    631 	if (dip->d_devbytes) {
    632 		si->si_devaddr = oldmon_mapin(dip->d_stdaddrs[si->si_ctlr],
    633 			dip->d_devbytes, dip->d_devtype);
    634 #ifdef	DEBUG_PROM
    635 		printf("prom_iopen: devaddr=0x%x pte=0x%x\n",
    636 			si->si_devaddr,
    637 			getpte4((u_long)si->si_devaddr & ~PGOFSET));
    638 #endif
    639 	}
    640 
    641 	if (dip->d_dmabytes) {
    642 		si->si_dmaaddr = dvma_alloc(dip->d_dmabytes);
    643 #ifdef	DEBUG_PROM
    644 		printf("prom_iopen: dmaaddr=0x%x\n", si->si_dmaaddr);
    645 #endif
    646 	}
    647 
    648 	if (dip->d_localbytes) {
    649 		si->si_devdata = alloc(dip->d_localbytes);
    650 #ifdef	DEBUG_PROM
    651 		printf("prom_iopen: devdata=0x%x\n", si->si_devdata);
    652 #endif
    653 	}
    654 
    655 	/* OK, call the PROM device open routine. */
    656 	error = (*ops->b_open)(si);
    657 	if (error != 0) {
    658 		printf("prom_iopen: \"%s\" error=%d\n", ops->b_desc, error);
    659 		return (ENXIO);
    660 	}
    661 #ifdef	DEBUG_PROM
    662 	printf("prom_iopen: succeeded, error=%d\n", error);
    663 #endif
    664 
    665 	pd->si = si;
    666 	promdev_inuse++;
    667 	return (0);
    668 }
    669 
    670 void
    671 oldmon_iclose(si)
    672 	struct saioreq *si;
    673 {
    674 	struct om_boottable *ops;
    675 	struct devinfo *dip;
    676 
    677 	if (promdev_inuse == 0)
    678 		return;
    679 
    680 	ops = si->si_boottab;
    681 	dip = ops->b_devinfo;
    682 
    683 	(*ops->b_close)(si);
    684 
    685 	if (si->si_dmaaddr) {
    686 		dvma_free(si->si_dmaaddr, dip->d_dmabytes);
    687 		si->si_dmaaddr = NULL;
    688 	}
    689 
    690 	promdev_inuse = 0;
    691 }
    692 
    693 static struct mapinfo {
    694 	int maptype;
    695 	int pgtype;
    696 	int base;
    697 } oldmon_mapinfo[] = {
    698 #define PG_COMMON	(PG_V|PG_W|PG_S|PG_NC)
    699 	{ MAP_MAINMEM,   PG_OBMEM | PG_COMMON, 0 },
    700 	{ MAP_OBIO,      PG_OBIO  | PG_COMMON, 0 },
    701 	{ MAP_MBMEM,     PG_VME16 | PG_COMMON, 0xFF000000 },
    702 	{ MAP_MBIO,      PG_VME16 | PG_COMMON, 0xFFFF0000 },
    703 	{ MAP_VME16A16D, PG_VME16 | PG_COMMON, 0xFFFF0000 },
    704 	{ MAP_VME16A32D, PG_VME32 | PG_COMMON, 0xFFFF0000 },
    705 	{ MAP_VME24A16D, PG_VME16 | PG_COMMON, 0xFF000000 },
    706 	{ MAP_VME24A32D, PG_VME32 | PG_COMMON, 0xFF000000 },
    707 	{ MAP_VME32A16D, PG_VME16 | PG_COMMON, 0 },
    708 	{ MAP_VME32A32D, PG_VME32 | PG_COMMON, 0 },
    709 };
    710 static int oldmon_mapinfo_cnt =
    711 	sizeof(oldmon_mapinfo) / sizeof(oldmon_mapinfo[0]);
    712 
    713 /* The virtual address we will use for PROM device mappings. */
    714 static u_long prom_devmap = MONSHORTSEG;
    715 
    716 static char *
    717 oldmon_mapin(physaddr, length, maptype)
    718 	u_long physaddr;
    719 	int length, maptype;
    720 {
    721 	int i, pa, pte, va;
    722 
    723 	if (length > (4*NBPG))
    724 		panic("oldmon_mapin: length=%d\n", length);
    725 
    726 	for (i = 0; i < oldmon_mapinfo_cnt; i++)
    727 		if (oldmon_mapinfo[i].maptype == maptype)
    728 			goto found;
    729 	panic("oldmon_mapin: invalid maptype %d\n", maptype);
    730 
    731 found:
    732 	pte = oldmon_mapinfo[i].pgtype;
    733 	pa = oldmon_mapinfo[i].base;
    734 	pa += physaddr;
    735 	pte |= ((pa >> SUN4_PGSHIFT) & PG_PFNUM);
    736 
    737 	va = prom_devmap;
    738 	do {
    739 		setpte4(va, pte);
    740 		va += NBPG;
    741 		pte += 1;
    742 		length -= NBPG;
    743 	} while (length > 0);
    744 	return ((char*)(prom_devmap | (pa & PGOFSET)));
    745 }
    746