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