1/* $NetBSD: prom.c,v 1.16 2018/09/03 16:29:22 riastradh 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 38int console; 39 40#if !defined(NO_GETCHAR) || !defined(NO_PUTCHAR_HALT) 41static int test_getchar(int *); 42#endif 43static void putonechar(int c); 44 45void 46init_prom_calls(void) 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, sizeof(buf)); 61 console = buf[0] - '0'; 62} 63 64#if !defined(NO_GETCHAR) || !defined(NO_PUTCHAR_HALT) 65static int 66test_getchar(int *xc) 67{ 68 prom_return_t ret; 69 70 ret.bits = prom_dispatch(PROM_R_GETC, console); 71 *xc = ret.u.retval; 72 return ret.u.status == 0 || ret.u.status == 1; 73} 74#endif 75 76#if !defined(NO_GETCHAR) 77int 78getchar(void) 79{ 80 int c; 81 82 for (;;) { 83 if (test_getchar(&c)) { 84 if (c == 3) 85 halt(); 86 return c; 87 } 88 } 89} 90#endif 91 92static void 93putonechar(int c) 94{ 95 prom_return_t ret; 96 char cbuf = c; 97 98 do { 99 ret.bits = prom_dispatch(PROM_R_PUTS, console, &cbuf, 1); 100 } while ((ret.u.retval & 1) == 0); 101} 102 103void 104putchar(int c) 105{ 106#if !defined(NO_PUTCHAR_HALT) 107 int typed_c; 108#endif 109 110 if (c == '\r' || c == '\n') { 111 putonechar('\r'); 112 c = '\n'; 113 } 114 putonechar(c); 115#if !defined(NO_PUTCHAR_HALT) 116 if (test_getchar(&typed_c)) 117 if (typed_c == 3) 118 halt(); 119#endif 120} 121 122int 123prom_getenv(int id, char *buf, int len) 124{ 125 /* 126 * On at least some systems, the GETENV call requires a 127 * 8-byte-aligned buffer, or it bails out with a "kernel stack 128 * not valid halt". Provide a local, aligned buffer here and 129 * then copy to the caller's buffer. 130 */ 131 static char abuf[128] __attribute__((aligned (8))); 132 prom_return_t ret; 133 134 ret.bits = prom_dispatch(PROM_R_GETENV, id, abuf, 128); 135 if (ret.u.status & 0x4) 136 ret.u.retval = 0; 137 len = uimin(len - 1, ret.u.retval); 138 memcpy(buf, abuf, len); 139 buf[len] = '\0'; 140 141 return (len); 142} 143