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