promdev.c revision 1.2 1 /* $NetBSD: promdev.c,v 1.2 1998/05/27 10:29: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 <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 static char storage[1024];
91 char *ap, *cp, *dp;
92
93 if (cputyp == CPU_SUN4)
94 prom0_fake();
95
96 if (promvec->pv_romvec_vers >= 2) {
97 char *ep = storage + sizeof(storage) - 1;
98
99 prom_bootdevice = *promvec->pv_v2bootargs.v2_bootpath;
100
101 #ifndef BOOTXX
102 cp = *promvec->pv_v2bootargs.v2_bootargs;
103 dp = prom_bootfile = storage;
104 /* Copy kernel name */
105 while (*cp != 0 && *cp != ' ' && *cp != '\t') {
106 if (dp >= ep) {
107 printf("v2_bootargs too long\n");
108 _rtt();
109 }
110 *dp++ = *cp++;
111 }
112 *dp = '\0';
113 /* Skip whitespace */
114 while (*cp != 0 && (*cp == ' ' || *cp == '\t'))
115 cp++;
116
117 ap = cp;
118 #endif
119 } else {
120 dp = prom_bootdevice = storage;
121 cp = (*promvec->pv_v0bootargs)->ba_argv[0];
122 while (*cp) {
123 *dp++ = *cp;
124 if (*cp++ == ')')
125 break;
126 }
127 *dp = '\0';
128 #ifndef BOOTXX
129 prom_bootfile = (*promvec->pv_v0bootargs)->ba_kernel;
130 ap = (*promvec->pv_v0bootargs)->ba_argv[1];
131 #endif
132 }
133
134 #ifndef BOOTXX
135 if (ap == NULL || *ap != '-')
136 return;
137
138 while (*ap) {
139 switch (*ap++) {
140 case 'a':
141 prom_boothow |= RB_ASKNAME;
142 break;
143 case 's':
144 prom_boothow |= RB_SINGLE;
145 break;
146 case 'd':
147 prom_boothow |= RB_KDB;
148 debug = 1;
149 break;
150 }
151 }
152 #endif
153 }
154
155 int
156 devopen(f, fname, file)
157 struct open_file *f;
158 const char *fname;
159 char **file;
160 {
161 int error = 0, fd;
162 struct promdata *pd;
163
164 pd = (struct promdata *)alloc(sizeof *pd);
165
166 if (cputyp == CPU_SUN4) {
167 error = prom0_iopen(pd);
168 #ifndef BOOTXX
169 pd->xmit = prom0_xmit;
170 pd->recv = prom0_recv;
171 #endif
172 } else {
173 fd = (promvec->pv_romvec_vers >= 2)
174 ? (*promvec->pv_v2devops.v2_open)(prom_bootdevice)
175 : (*promvec->pv_v0devops.v0_open)(prom_bootdevice);
176 if (fd == 0) {
177 error = ENXIO;
178 } else {
179 pd->fd = fd;
180 #ifndef BOOTXX
181 pd->xmit = obp_xmit;
182 pd->recv = obp_recv;
183 #endif
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 bcopy(file_system_nfs, file_system, sizeof(struct fs_ops));
202 if ((error = net_open(pd)) != 0) {
203 printf("Can't open network device `%s'\n",
204 prom_bootdevice);
205 return error;
206 }
207 } else
208 bcopy(file_system_ufs, file_system, sizeof(struct fs_ops));
209 #endif /* BOOTXX */
210
211 f->f_dev = &devsw[cputyp == CPU_SUN4 ? 0 : 1];
212 f->f_devdata = (void *)pd;
213 return 0;
214 }
215
216 int
217 obp_strategy(devdata, flag, dblk, size, buf, rsize)
218 void *devdata;
219 int flag;
220 daddr_t dblk;
221 size_t size;
222 void *buf;
223 size_t *rsize;
224 {
225 int error = 0;
226 struct promdata *pd = (struct promdata *)devdata;
227 int fd = pd->fd;
228
229 #ifdef DEBUG_PROM
230 printf("promstrategy: size=%d dblk=%d\n", size, dblk);
231 #endif
232
233 if (promvec->pv_romvec_vers >= 2) {
234 if (pd->devtype == DT_BLOCK)
235 (*promvec->pv_v2devops.v2_seek)(fd, 0, dbtob(dblk));
236
237 *rsize = (*((flag == F_READ)
238 ? (u_int (*)())promvec->pv_v2devops.v2_read
239 : (u_int (*)())promvec->pv_v2devops.v2_write
240 ))(fd, buf, size);
241 } else {
242 int n = (*((flag == F_READ)
243 ? (u_int (*)())promvec->pv_v0devops.v0_rbdev
244 : (u_int (*)())promvec->pv_v0devops.v0_wbdev
245 ))(fd, btodb(size), dblk, buf);
246 *rsize = dbtob(n);
247 }
248
249 #ifdef DEBUG_PROM
250 printf("rsize = %x\n", *rsize);
251 #endif
252 return error;
253 }
254
255 /*
256 * On old-monitor machines, things work differently.
257 */
258 int
259 prom0_strategy(devdata, flag, dblk, size, buf, rsize)
260 void *devdata;
261 int flag;
262 daddr_t dblk;
263 size_t size;
264 void *buf;
265 size_t *rsize;
266 {
267 struct promdata *pd = devdata;
268 struct saioreq *si;
269 struct om_boottable *ops;
270 char *dmabuf;
271 int si_flag;
272 size_t xcnt;
273
274 si = pd->si;
275 ops = si->si_boottab;
276
277 #ifdef DEBUG_PROM
278 printf("prom_strategy: size=%d dblk=%d\n", size, dblk);
279 #endif
280
281 dmabuf = dvma_mapin(buf, size);
282
283 si->si_bn = dblk;
284 si->si_ma = dmabuf;
285 si->si_cc = size;
286
287 si_flag = (flag == F_READ) ? SAIO_F_READ : SAIO_F_WRITE;
288 xcnt = (*ops->b_strategy)(si, si_flag);
289 dvma_mapout(dmabuf, size);
290
291 #ifdef DEBUG_PROM
292 printf("disk_strategy: xcnt = %x\n", xcnt);
293 #endif
294
295 if (xcnt <= 0)
296 return (EIO);
297
298 *rsize = xcnt;
299 return (0);
300 }
301
302 int
303 obp_close(f)
304 struct open_file *f;
305 {
306 struct promdata *pd = f->f_devdata;
307 register int fd = pd->fd;
308
309 #ifndef BOOTXX
310 if (pd->devtype == DT_NET)
311 net_close(pd);
312 #endif
313 if (promvec->pv_romvec_vers >= 2)
314 (void)(*promvec->pv_v2devops.v2_close)(fd);
315 else
316 (void)(*promvec->pv_v0devops.v0_close)(fd);
317 return 0;
318 }
319
320 int
321 prom0_close(f)
322 struct open_file *f;
323 {
324 struct promdata *pd = f->f_devdata;
325
326 #ifndef BOOTXX
327 if (pd->devtype == DT_NET)
328 net_close(pd);
329 #endif
330 prom0_iclose(pd->si);
331 pd->si = NULL;
332 *romp->echo = saveecho; /* Hmm, probably must go somewhere else */
333 return 0;
334 }
335
336 #ifndef BOOTXX
337 ssize_t
338 obp_xmit(pd, buf, len)
339 struct promdata *pd;
340 void *buf;
341 size_t len;
342 {
343 return (promvec->pv_romvec_vers >= 2
344 ? (*promvec->pv_v2devops.v2_write)(pd->fd, buf, len)
345 : (*promvec->pv_v0devops.v0_wnet)(pd->fd, len, buf));
346 }
347
348 ssize_t
349 obp_recv(pd, buf, len)
350 struct promdata *pd;
351 void *buf;
352 size_t len;
353 {
354 int n;
355
356 n = (promvec->pv_romvec_vers >= 2
357 ? (*promvec->pv_v2devops.v2_read)(pd->fd, buf, len)
358 : (*promvec->pv_v0devops.v0_rnet)(pd->fd, len, buf));
359 return (n == -2 ? 0 : n);
360 }
361
362 ssize_t
363 prom0_xmit(pd, buf, len)
364 struct promdata *pd;
365 void *buf;
366 size_t len;
367 {
368 struct saioreq *si;
369 struct saif *sif;
370 char *dmabuf;
371 int rv;
372
373 si = pd->si;
374 sif = si->si_sif;
375 if (sif == NULL) {
376 printf("xmit: not a network device\n");
377 return (-1);
378 }
379 dmabuf = dvma_mapin(buf, len);
380 rv = sif->sif_xmit(si->si_devdata, dmabuf, len);
381 dvma_mapout(dmabuf, len);
382
383 return (ssize_t)(rv ? -1 : len);
384 }
385
386 ssize_t
387 prom0_recv(pd, buf, len)
388 struct promdata *pd;
389 void *buf;
390 size_t len;
391 {
392 struct saioreq *si;
393 struct saif *sif;
394 char *dmabuf;
395 int rv;
396
397 si = pd->si;
398 sif = si->si_sif;
399 dmabuf = dvma_mapin(buf, len);
400 rv = sif->sif_poll(si->si_devdata, dmabuf);
401 dvma_mapout(dmabuf, len);
402
403 return (ssize_t)rv;
404 }
405
406 int
407 getchar()
408 {
409 char c;
410 register int n;
411
412 if (promvec->pv_romvec_vers > 2)
413 while ((n = (*promvec->pv_v2devops.v2_read)
414 (*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 1)) != 1);
415 else
416 c = (*promvec->pv_getchar)();
417
418 if (c == '\r')
419 c = '\n';
420 return (c);
421 }
422
423 int
424 peekchar()
425 {
426 char c;
427 register int n;
428
429 if (promvec->pv_romvec_vers > 2) {
430 n = (*promvec->pv_v2devops.v2_read)
431 (*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 1);
432 if (n < 0)
433 return -1;
434 } else
435 c = (*promvec->pv_nbgetchar)();
436
437 if (c == '\r')
438 c = '\n';
439 return (c);
440 }
441 #endif
442
443 static void
444 pv_putchar(c)
445 int c;
446 {
447 char c0 = c;
448
449 if (promvec->pv_romvec_vers > 2)
450 (*promvec->pv_v2devops.v2_write)
451 (*promvec->pv_v2bootargs.v2_fd1, &c0, 1);
452 else
453 (*promvec->pv_putchar)(c);
454 }
455
456 void
457 putchar(c)
458 int c;
459 {
460
461 if (c == '\n')
462 pv_putchar('\r');
463 pv_putchar(c);
464 }
465
466 void
467 _rtt()
468 {
469 promvec->pv_halt();
470 }
471
472 #ifndef BOOTXX
473 int hz = 1000;
474
475 time_t
476 getsecs()
477 {
478 register int ticks = getticks();
479 return ((time_t)(ticks / hz));
480 }
481
482 int
483 getticks()
484 {
485 if (promvec->pv_romvec_vers >= 2) {
486 char c;
487 (void)(*promvec->pv_v2devops.v2_read)
488 (*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 0);
489 } else {
490 (void)(*promvec->pv_nbgetchar)();
491 }
492 return *(promvec->pv_ticks);
493 }
494
495 void
496 prom_getether(fd, ea)
497 u_char *ea;
498 {
499 if (cputyp == CPU_SUN4) {
500 static struct idprom sun4_idprom;
501 u_char *src, *dst;
502 int len, x;
503
504 if (sun4_idprom.id_format == 0) {
505 dst = (char*)&sun4_idprom;
506 src = (char*)AC_IDPROM;
507 len = sizeof(struct idprom);
508 do {
509 x = lduba(src++, ASI_CONTROL);
510 *dst++ = x;
511 } while (--len > 0);
512 }
513 bcopy(sun4_idprom.id_ether, ea, 6);
514 } else if (promvec->pv_romvec_vers <= 2) {
515 (void)(*promvec->pv_enaddr)(fd, (char *)ea);
516 } else {
517 char buf[64];
518 sprintf(buf, "%x mac-address drop swap 6 cmove", ea);
519 promvec->pv_fortheval.v2_eval(buf);
520 }
521 }
522
523
524 /*
525 * A number of well-known devices on sun4s.
526 */
527 static struct dtab {
528 char *name;
529 int type;
530 } dtab[] = {
531 { "sd", DT_BLOCK },
532 { "st", DT_BLOCK },
533 { "xd", DT_BLOCK },
534 { "xy", DT_BLOCK },
535 { "fd", DT_BLOCK },
536 { "le", DT_NET },
537 { "ie", DT_NET },
538 { NULL, 0 }
539 };
540
541 int
542 getdevtype(fd, name)
543 int fd;
544 char *name;
545 {
546 if (promvec->pv_romvec_vers >= 2) {
547 int node = (*promvec->pv_v2devops.v2_fd_phandle)(fd);
548 char *cp = getpropstring(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 } else {
556 struct dtab *dp;
557 for (dp = dtab; dp->name; dp++) {
558 if (name[0] == dp->name[0] &&
559 name[1] == dp->name[1])
560 return dp->type;
561 }
562 }
563 return 0;
564 }
565
566 /*
567 * OpenPROM nodes & property routines (from <sparc/autoconf.c>).
568 */
569 int
570 getprop(node, name, buf, bufsiz)
571 int node;
572 char *name;
573 void *buf;
574 register int bufsiz;
575 {
576 register struct nodeops *no;
577 register int len;
578
579 no = promvec->pv_nodeops;
580 len = no->no_proplen(node, name);
581 if (len > bufsiz) {
582 printf("node %x property %s length %d > %d\n",
583 node, name, len, bufsiz);
584 return (0);
585 }
586 no->no_getprop(node, name, buf);
587 return (len);
588 }
589
590 /*
591 * Return a string property. There is a (small) limit on the length;
592 * the string is fetched into a static buffer which is overwritten on
593 * subsequent calls.
594 */
595 char *
596 getpropstring(node, name)
597 int node;
598 char *name;
599 {
600 register int len;
601 static char stringbuf[64];
602
603 len = getprop(node, name, (void *)stringbuf, sizeof stringbuf - 1);
604 if (len == -1)
605 len = 0;
606 stringbuf[len] = '\0'; /* usually unnecessary */
607 return (stringbuf);
608 }
609 #endif /* BOOTXX */
610
611 /*
612 * Old monitor routines
613 */
614
615 #include <machine/pte.h>
616
617 struct saioreq prom_si;
618 static int promdev_inuse;
619
620 int
621 prom0_iopen(pd)
622 struct promdata *pd;
623 {
624 struct om_bootparam *bp;
625 struct om_boottable *ops;
626 struct devinfo *dip;
627 struct saioreq *si;
628 int error;
629
630 if (promdev_inuse)
631 return(EMFILE);
632
633 bp = *romp->bootParam;
634 ops = bp->bootTable;
635 dip = ops->b_devinfo;
636
637 #ifdef DEBUG_PROM
638 printf("Boot device type: %s\n", ops->b_desc);
639 printf("d_devbytes=%d\n", dip->d_devbytes);
640 printf("d_dmabytes=%d\n", dip->d_dmabytes);
641 printf("d_localbytes=%d\n", dip->d_localbytes);
642 printf("d_stdcount=%d\n", dip->d_stdcount);
643 printf("d_stdaddrs[%d]=%x\n", bp->ctlrNum, dip->d_stdaddrs[bp->ctlrNum]);
644 printf("d_devtype=%d\n", dip->d_devtype);
645 printf("d_maxiobytes=%d\n", dip->d_maxiobytes);
646 #endif
647
648 dvma_init();
649
650 si = &prom_si;
651 bzero((caddr_t)si, sizeof(*si));
652 si->si_boottab = ops;
653 si->si_ctlr = bp->ctlrNum;
654 si->si_unit = bp->unitNum;
655 si->si_boff = bp->partNum;
656
657 if (si->si_ctlr > dip->d_stdcount) {
658 printf("Invalid controller number\n");
659 return(ENXIO);
660 }
661
662 if (dip->d_devbytes) {
663 si->si_devaddr = prom_mapin(dip->d_stdaddrs[si->si_ctlr],
664 dip->d_devbytes, dip->d_devtype);
665 #ifdef DEBUG_PROM
666 printf("prom_iopen: devaddr=0x%x pte=0x%x\n",
667 si->si_devaddr,
668 getpte((u_long)si->si_devaddr & ~PGOFSET));
669 #endif
670 }
671
672 if (dip->d_dmabytes) {
673 si->si_dmaaddr = dvma_alloc(dip->d_dmabytes);
674 #ifdef DEBUG_PROM
675 printf("prom_iopen: dmaaddr=0x%x\n", si->si_dmaaddr);
676 #endif
677 }
678
679 if (dip->d_localbytes) {
680 si->si_devdata = alloc(dip->d_localbytes);
681 #ifdef DEBUG_PROM
682 printf("prom_iopen: devdata=0x%x\n", si->si_devdata);
683 #endif
684 }
685
686 /* OK, call the PROM device open routine. */
687 error = (*ops->b_open)(si);
688 if (error != 0) {
689 printf("prom_iopen: \"%s\" error=%d\n",
690 ops->b_desc, error);
691 return (ENXIO);
692 }
693 #ifdef DEBUG_PROM
694 printf("prom_iopen: succeeded, error=%d\n", error);
695 #endif
696
697 pd->si = si;
698 promdev_inuse++;
699 return (0);
700 }
701
702 void
703 prom0_iclose(si)
704 struct saioreq *si;
705 {
706 struct om_boottable *ops;
707 struct devinfo *dip;
708
709 if (promdev_inuse == 0)
710 return;
711
712 ops = si->si_boottab;
713 dip = ops->b_devinfo;
714
715 (*ops->b_close)(si);
716
717 if (si->si_dmaaddr) {
718 dvma_free(si->si_dmaaddr, dip->d_dmabytes);
719 si->si_dmaaddr = NULL;
720 }
721
722 promdev_inuse = 0;
723 }
724
725 static struct mapinfo {
726 int maptype;
727 int pgtype;
728 int base;
729 } prom_mapinfo[] = {
730 { MAP_MAINMEM, PG_OBMEM, 0 },
731 { MAP_OBIO, PG_OBIO, 0 },
732 { MAP_MBMEM, PG_VME16, 0xFF000000 },
733 { MAP_MBIO, PG_VME16, 0xFFFF0000 },
734 { MAP_VME16A16D, PG_VME16, 0xFFFF0000 },
735 { MAP_VME16A32D, PG_VME32, 0xFFFF0000 },
736 { MAP_VME24A16D, PG_VME16, 0xFF000000 },
737 { MAP_VME24A32D, PG_VME32, 0xFF000000 },
738 { MAP_VME32A16D, PG_VME16, 0 },
739 { MAP_VME32A32D, PG_VME32, 0 },
740 };
741 static prom_mapinfo_cnt = sizeof(prom_mapinfo) / sizeof(prom_mapinfo[0]);
742
743 /* The virtual address we will use for PROM device mappings. */
744 static u_long prom_devmap = MONSHORTSEG;
745
746 static char *
747 prom_mapin(physaddr, length, maptype)
748 u_long physaddr;
749 int length, maptype;
750 {
751 int i, pa, pte, va;
752
753 if (length > (4*NBPG))
754 panic("prom_mapin: length=%d\n", length);
755
756 for (i = 0; i < prom_mapinfo_cnt; i++)
757 if (prom_mapinfo[i].maptype == maptype)
758 goto found;
759 panic("prom_mapin: invalid maptype %d\n", maptype);
760 found:
761
762 pte = prom_mapinfo[i].pgtype;
763 pte |= (PG_V|PG_W|PG_S|PG_NC);
764 pa = prom_mapinfo[i].base;
765 pa += physaddr;
766 pte |= ((pa >> PGSHIFT) & PG_PFNUM);
767
768 va = prom_devmap;
769 do {
770 setpte(va, pte);
771 va += NBPG;
772 pte += 1;
773 length -= NBPG;
774 } while (length > 0);
775 return ((char*)(prom_devmap | (pa & PGOFSET)));
776 }
777
778 void
779 prom0_fake()
780 {
781 static struct promvec promvecstore;
782
783 promvec = &promvecstore;
784
785 promvec->pv_stdin = romp->inSource;
786 promvec->pv_stdout = romp->outSink;
787 promvec->pv_putchar = romp->putChar;
788 promvec->pv_putstr = romp->fbWriteStr;
789 promvec->pv_nbgetchar = romp->mayGet;
790 promvec->pv_getchar = romp->getChar;
791 promvec->pv_romvec_vers = 0; /* eek! */
792 promvec->pv_reboot = romp->reBoot;
793 promvec->pv_abort = romp->abortEntry;
794 promvec->pv_setctxt = romp->setcxsegmap;
795 promvec->pv_v0bootargs = (struct v0bootargs **)(romp->bootParam);
796 promvec->pv_halt = romp->exitToMon;
797 promvec->pv_ticks = romp->nmiClock;
798 saveecho = *romp->echo;
799 *romp->echo = 0;
800 }
801