1/* $Id: console.c,v 1.1.1.1 2007/08/03 18:52:18 Exp $ 2 * console.c: Routines that deal with sending and receiving IO 3 * to/from the current console device using the PROM. 4 * 5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 6 * Copyright (C) 1998 Pete Zaitcev <zaitcev@yahoo.com> 7 */ 8 9#include <linux/types.h> 10#include <linux/kernel.h> 11#include <linux/sched.h> 12#include <asm/openprom.h> 13#include <asm/sun4prom.h> 14#include <asm/oplib.h> 15#include <asm/system.h> 16#include <linux/string.h> 17 18extern void restore_current(void); 19 20static char con_name_jmc[] = "/obio/su@"; /* "/obio/su@0,3002f8"; */ 21#define CON_SIZE_JMC (sizeof(con_name_jmc)) 22 23/* Non blocking get character from console input device, returns -1 24 * if no input was taken. This can be used for polling. 25 */ 26int 27prom_nbgetchar(void) 28{ 29 static char inc; 30 int i = -1; 31 unsigned long flags; 32 33 spin_lock_irqsave(&prom_lock, flags); 34 switch(prom_vers) { 35 case PROM_V0: 36 case PROM_SUN4: 37 i = (*(romvec->pv_nbgetchar))(); 38 break; 39 case PROM_V2: 40 case PROM_V3: 41 if( (*(romvec->pv_v2devops).v2_dev_read)(*romvec->pv_v2bootargs.fd_stdin , &inc, 0x1) == 1) { 42 i = inc; 43 } else { 44 i = -1; 45 } 46 break; 47 default: 48 i = -1; 49 break; 50 }; 51 restore_current(); 52 spin_unlock_irqrestore(&prom_lock, flags); 53 return i; /* Ugh, we could spin forever on unsupported proms ;( */ 54} 55 56/* Non blocking put character to console device, returns -1 if 57 * unsuccessful. 58 */ 59int 60prom_nbputchar(char c) 61{ 62 static char outc; 63 unsigned long flags; 64 int i = -1; 65 66 spin_lock_irqsave(&prom_lock, flags); 67 switch(prom_vers) { 68 case PROM_V0: 69 case PROM_SUN4: 70 i = (*(romvec->pv_nbputchar))(c); 71 break; 72 case PROM_V2: 73 case PROM_V3: 74 outc = c; 75 if( (*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout, &outc, 0x1) == 1) 76 i = 0; 77 else 78 i = -1; 79 break; 80 default: 81 i = -1; 82 break; 83 }; 84 restore_current(); 85 spin_unlock_irqrestore(&prom_lock, flags); 86 return i; /* Ugh, we could spin forever on unsupported proms ;( */ 87} 88 89/* Blocking version of get character routine above. */ 90char 91prom_getchar(void) 92{ 93 int character; 94 while((character = prom_nbgetchar()) == -1) ; 95 return (char) character; 96} 97 98/* Blocking version of put character routine above. */ 99void 100prom_putchar(char c) 101{ 102 while(prom_nbputchar(c) == -1) ; 103 return; 104} 105 106/* Query for input device type */ 107enum prom_input_device 108prom_query_input_device(void) 109{ 110 unsigned long flags; 111 int st_p; 112 char propb[64]; 113 char *p; 114 int propl; 115 116 switch(prom_vers) { 117 case PROM_V0: 118 case PROM_V2: 119 case PROM_SUN4: 120 default: 121 switch(*romvec->pv_stdin) { 122 case PROMDEV_KBD: return PROMDEV_IKBD; 123 case PROMDEV_TTYA: return PROMDEV_ITTYA; 124 case PROMDEV_TTYB: return PROMDEV_ITTYB; 125 default: 126 return PROMDEV_I_UNK; 127 }; 128 case PROM_V3: 129 spin_lock_irqsave(&prom_lock, flags); 130 st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin); 131 restore_current(); 132 spin_unlock_irqrestore(&prom_lock, flags); 133 if(prom_node_has_property(st_p, "keyboard")) 134 return PROMDEV_IKBD; 135 if (prom_getproperty(st_p, "name", propb, sizeof(propb)) != -1) { 136 if(strncmp(propb, "keyboard", sizeof("serial")) == 0) 137 return PROMDEV_IKBD; 138 } 139 if (prom_getproperty(st_p, "device_type", propb, sizeof(propb)) != -1) { 140 if(strncmp(propb, "serial", sizeof("serial"))) 141 return PROMDEV_I_UNK; 142 } 143 propl = prom_getproperty(prom_root_node, "stdin-path", propb, sizeof(propb)); 144 if(propl > 2) { 145 p = propb; 146 while(*p) p++; p -= 2; 147 if(p[0] == ':') { 148 if(p[1] == 'a') 149 return PROMDEV_ITTYA; 150 else if(p[1] == 'b') 151 return PROMDEV_ITTYB; 152 } 153 } 154 return PROMDEV_I_UNK; 155 } 156} 157 158/* Query for output device type */ 159 160enum prom_output_device 161prom_query_output_device(void) 162{ 163 unsigned long flags; 164 int st_p; 165 char propb[64]; 166 char *p; 167 int propl; 168 169 switch(prom_vers) { 170 case PROM_V0: 171 case PROM_SUN4: 172 switch(*romvec->pv_stdin) { 173 case PROMDEV_SCREEN: return PROMDEV_OSCREEN; 174 case PROMDEV_TTYA: return PROMDEV_OTTYA; 175 case PROMDEV_TTYB: return PROMDEV_OTTYB; 176 }; 177 break; 178 case PROM_V2: 179 case PROM_V3: 180 spin_lock_irqsave(&prom_lock, flags); 181 st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout); 182 restore_current(); 183 spin_unlock_irqrestore(&prom_lock, flags); 184 propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb)); 185 if (propl == sizeof("display") && 186 strncmp("display", propb, sizeof("display")) == 0) 187 { 188 return PROMDEV_OSCREEN; 189 } 190 if(prom_vers == PROM_V3) { 191 if(propl >= 0 && 192 strncmp("serial", propb, sizeof("serial")) != 0) 193 return PROMDEV_O_UNK; 194 propl = prom_getproperty(prom_root_node, "stdout-path", 195 propb, sizeof(propb)); 196 if(propl == CON_SIZE_JMC && 197 strncmp(propb, con_name_jmc, CON_SIZE_JMC) == 0) 198 return PROMDEV_OTTYA; 199 if(propl > 2) { 200 p = propb; 201 while(*p) p++; p-= 2; 202 if(p[0]==':') { 203 if(p[1] == 'a') 204 return PROMDEV_OTTYA; 205 else if(p[1] == 'b') 206 return PROMDEV_OTTYB; 207 } 208 } 209 } else { 210 switch(*romvec->pv_stdin) { 211 case PROMDEV_TTYA: return PROMDEV_OTTYA; 212 case PROMDEV_TTYB: return PROMDEV_OTTYB; 213 }; 214 } 215 break; 216 default: 217 ; 218 }; 219 return PROMDEV_O_UNK; 220} 221