1 /* $NetBSD: prom.c,v 1.11 2002/07/30 20:36:42 nathanw Exp $ */ 2 3 /* 4 * Mach Operating System 5 * Copyright (c) 1992 Carnegie Mellon University 6 * All Rights Reserved. 7 * 8 * Permission to use, copy, modify and distribute this software and its 9 * documentation is hereby granted, provided that both the copyright 10 * notice and this permission notice appear in all copies of the 11 * software, derivative works or modified versions, and any portions 12 * thereof, and that both notices appear in supporting documentation. 13 * 14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 17 * 18 * Carnegie Mellon requests users of this software to return to 19 * 20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 21 * School of Computer Science 22 * Carnegie Mellon University 23 * Pittsburgh PA 15213-3890 24 * 25 * any improvements or extensions that they make and grant Carnegie Mellon 26 * the rights to redistribute these changes. 27 */ 28 29 #include <lib/libkern/libkern.h> 30 31 #include <sys/types.h> 32 33 #include <machine/prom.h> 34 #include <machine/rpb.h> 35 36 #include "common.h" 37 38 int console; 39 40 #if !defined(NO_GETCHAR) || !defined(NO_PUTCHAR_HALT) 41 static int test_getchar(int *); 42 #endif 43 static void putonechar(int c); 44 45 void 46 init_prom_calls() 47 { 48 extern struct prom_vec prom_dispatch_v; 49 struct rpb *r; 50 struct crb *c; 51 char buf[4]; 52 53 r = (struct rpb *)HWRPB_ADDR; 54 c = (struct crb *)((u_int8_t *)r + r->rpb_crb_off); 55 56 prom_dispatch_v.routine_arg = c->crb_v_dispatch; 57 prom_dispatch_v.routine = c->crb_v_dispatch->entry_va; 58 59 /* Look for console tty. */ 60 prom_getenv(PROM_E_TTY_DEV, buf, 4); 61 console = buf[0] - '0'; 62 } 63 64 #if !defined(NO_GETCHAR) || !defined(NO_PUTCHAR_HALT) 65 static int 66 test_getchar(xc) 67 int *xc; 68 { 69 prom_return_t ret; 70 71 ret.bits = prom_dispatch(PROM_R_GETC, console); 72 *xc = ret.u.retval; 73 return ret.u.status == 0 || ret.u.status == 1; 74 } 75 #endif 76 77 #if !defined(NO_GETCHAR) 78 int 79 getchar() 80 { 81 int c; 82 83 for (;;) { 84 if (test_getchar(&c)) { 85 if (c == 3) 86 halt(); 87 return c; 88 } 89 } 90 } 91 #endif 92 93 static void 94 putonechar(c) 95 int c; 96 { 97 prom_return_t ret; 98 char cbuf = c; 99 100 do { 101 ret.bits = prom_dispatch(PROM_R_PUTS, console, &cbuf, 1); 102 } while ((ret.u.retval & 1) == 0); 103 } 104 105 void 106 putchar(c) 107 int c; 108 { 109 #if !defined(NO_PUTCHAR_HALT) 110 int typed_c; 111 #endif 112 113 if (c == '\r' || c == '\n') { 114 putonechar('\r'); 115 c = '\n'; 116 } 117 putonechar(c); 118 #if !defined(NO_PUTCHAR_HALT) 119 if (test_getchar(&typed_c)) 120 if (typed_c == 3) 121 halt(); 122 #endif 123 } 124 125 int 126 prom_getenv(id, buf, len) 127 int id, len; 128 char *buf; 129 { 130 /* 131 * On at least some systems, the GETENV call requires a 132 * 8-byte-aligned buffer, or it bails out with a "kernel stack 133 * not valid halt". Provide a local, aligned buffer here and 134 * then copy to the caller's buffer. 135 */ 136 static char abuf[128] __attribute__((aligned (8))); 137 prom_return_t ret; 138 139 ret.bits = prom_dispatch(PROM_R_GETENV, id, abuf, 128); 140 if (ret.u.status & 0x4) 141 ret.u.retval = 0; 142 len = min(len - 1, ret.u.retval); 143 memcpy(buf, abuf, len); 144 buf[len] = '\0'; 145 146 return (len); 147 } 148