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