1 /* $Id: console.c,v 1.25 2001/10/30 04:54:22 davem 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
18 extern void restore_current(void);
19
20 static 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 */
26 int
prom_nbgetchar(void)27 prom_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 */
59 int
prom_nbputchar(char c)60 prom_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. */
90 char
prom_getchar(void)91 prom_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. */
99 void
prom_putchar(char c)100 prom_putchar(char c)
101 {
102 while(prom_nbputchar(c) == -1) ;
103 return;
104 }
105
106 /* Query for input device type */
107 enum prom_input_device
prom_query_input_device()108 prom_query_input_device()
109 {
110 unsigned long flags;
111 int st_p;
112 char propb[64];
113 char *p;
114
115 switch(prom_vers) {
116 case PROM_V0:
117 case PROM_V2:
118 case PROM_SUN4:
119 default:
120 switch(*romvec->pv_stdin) {
121 case PROMDEV_KBD: return PROMDEV_IKBD;
122 case PROMDEV_TTYA: return PROMDEV_ITTYA;
123 case PROMDEV_TTYB: return PROMDEV_ITTYB;
124 default:
125 return PROMDEV_I_UNK;
126 };
127 case PROM_V3:
128 spin_lock_irqsave(&prom_lock, flags);
129 st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin);
130 restore_current();
131 spin_unlock_irqrestore(&prom_lock, flags);
132 if(prom_node_has_property(st_p, "keyboard"))
133 return PROMDEV_IKBD;
134 if (prom_getproperty(st_p, "name", propb, sizeof(propb)) != -1) {
135 if(strncmp(propb, "keyboard", sizeof("serial")) == 0)
136 return PROMDEV_IKBD;
137 }
138 if (prom_getproperty(st_p, "device_type", propb, sizeof(propb)) != -1) {
139 if(strncmp(propb, "serial", sizeof("serial")))
140 return PROMDEV_I_UNK;
141 }
142 prom_getproperty(prom_root_node, "stdin-path", propb, sizeof(propb));
143 p = propb;
144 while(*p) p++; p -= 2;
145 if(p[0] == ':') {
146 if(p[1] == 'a')
147 return PROMDEV_ITTYA;
148 else if(p[1] == 'b')
149 return PROMDEV_ITTYB;
150 }
151 return PROMDEV_I_UNK;
152 }
153 }
154
155 /* Query for output device type */
156
157 enum prom_output_device
prom_query_output_device()158 prom_query_output_device()
159 {
160 unsigned long flags;
161 int st_p;
162 char propb[64];
163 char *p;
164 int propl;
165
166 switch(prom_vers) {
167 case PROM_V0:
168 case PROM_SUN4:
169 switch(*romvec->pv_stdin) {
170 case PROMDEV_SCREEN: return PROMDEV_OSCREEN;
171 case PROMDEV_TTYA: return PROMDEV_OTTYA;
172 case PROMDEV_TTYB: return PROMDEV_OTTYB;
173 };
174 break;
175 case PROM_V2:
176 case PROM_V3:
177 spin_lock_irqsave(&prom_lock, flags);
178 st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout);
179 restore_current();
180 spin_unlock_irqrestore(&prom_lock, flags);
181 propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb));
182 if (propl >= 0 && propl == sizeof("display") &&
183 strncmp("display", propb, sizeof("display")) == 0)
184 {
185 return PROMDEV_OSCREEN;
186 }
187 if(prom_vers == PROM_V3) {
188 if(propl >= 0 &&
189 strncmp("serial", propb, sizeof("serial")) != 0)
190 return PROMDEV_O_UNK;
191 prom_getproperty(prom_root_node, "stdout-path", propb, sizeof(propb));
192 if(strncmp(propb, con_name_jmc, CON_SIZE_JMC) == 0)
193 return PROMDEV_OTTYA;
194 p = propb;
195 while(*p) p++; p -= 2;
196 if(p[0]==':') {
197 if(p[1] == 'a')
198 return PROMDEV_OTTYA;
199 else if(p[1] == 'b')
200 return PROMDEV_OTTYB;
201 }
202 } else {
203 switch(*romvec->pv_stdin) {
204 case PROMDEV_TTYA: return PROMDEV_OTTYA;
205 case PROMDEV_TTYB: return PROMDEV_OTTYB;
206 };
207 }
208 break;
209 default:
210 ;
211 };
212 return PROMDEV_O_UNK;
213 }
214