]>
Commit | Line | Data |
---|---|---|
a6316ce4 MT |
1 | #include <stdio.h> |
2 | #include <stdlib.h> | |
3 | #include <string.h> | |
4 | #include <unistd.h> | |
5 | #include <fcntl.h> | |
6 | #include <errno.h> | |
7 | #include <termios.h> | |
8 | #include <sys/stat.h> | |
9 | #include <sys/types.h> | |
10 | #include <sys/time.h> | |
11 | #include <sys/ioctl.h> | |
12 | #include <linux/serial.h> | |
13 | ||
14 | #ifdef __sparc__ | |
15 | ||
16 | struct serial_struct { | |
17 | int type; | |
18 | int line; | |
19 | unsigned long port; | |
20 | int irq; | |
21 | int flags; | |
22 | int xmit_fifo_size; | |
23 | int custom_divisor; | |
24 | int baud_base; | |
25 | unsigned short close_delay; | |
26 | char io_type; | |
27 | char reserved_char[1]; | |
28 | int hub6; | |
29 | unsigned short closing_wait; /* time to wait before closing */ | |
30 | unsigned short closing_wait2; /* no longer used... */ | |
31 | unsigned char *iomem_base; | |
32 | unsigned short iomem_reg_shift; | |
33 | int reserved[2]; | |
34 | }; | |
35 | ||
36 | #ifdef DIET | |
37 | typedef unsigned int u_int; | |
38 | #endif | |
39 | ||
40 | #include <asm/kbio.h> | |
41 | #include <asm/openpromio.h> | |
42 | #endif | |
43 | ||
44 | #include "hd.h" | |
45 | #include "hd_int.h" | |
46 | #include "kbd.h" | |
47 | ||
48 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
49 | * | |
50 | * Look for keyboards not covered by kernel input device driver, mainly | |
51 | * some sort of serial consoles. | |
52 | * | |
53 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
54 | */ | |
55 | ||
56 | #ifdef __sparc__ | |
57 | static void add_sun_console(hd_data_t *hd_data); | |
58 | #else | |
59 | static void add_serial_console(hd_data_t *hd_data); | |
60 | #endif | |
61 | ||
62 | ||
63 | void hd_scan_kbd(hd_data_t *hd_data) | |
64 | { | |
65 | hd_t *hd; | |
66 | ||
67 | if(!hd_probe_feature(hd_data, pr_kbd)) return; | |
68 | ||
69 | hd_data->module = mod_kbd; | |
70 | ||
71 | /* some clean-up */ | |
72 | remove_hd_entries(hd_data); | |
73 | ||
74 | PROGRESS(2, 0, "uml"); | |
75 | ||
76 | if(hd_is_uml(hd_data)) { | |
77 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
78 | hd->base_class.id = bc_keyboard; | |
79 | hd->sub_class.id = sc_keyboard_kbd; | |
80 | hd->bus.id = bus_none; | |
81 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0201); | |
82 | hd->device.id = MAKE_ID(TAG_SPECIAL, 2); | |
83 | } | |
84 | ||
85 | PROGRESS(3, 0, "serial console"); | |
86 | ||
87 | #ifdef __sparc__ | |
88 | add_sun_console(hd_data); | |
89 | #else | |
90 | add_serial_console(hd_data); | |
91 | #endif | |
92 | } | |
93 | ||
94 | ||
95 | #ifndef __sparc__ | |
96 | ||
97 | void add_serial_console(hd_data_t *hd_data) | |
98 | { | |
99 | hd_t *hd; | |
100 | hd_res_t *res = NULL; | |
101 | int fd, i; | |
102 | str_list_t *cmd, *cmd0, *sl; | |
103 | unsigned u, u1; | |
104 | struct serial_struct ser_info; | |
105 | unsigned tty_major = 0, tty_minor = 0; | |
106 | char c, *dev = NULL, *s; | |
107 | ||
108 | /* first, try console= option */ | |
109 | cmd = cmd0 = get_cmdline(hd_data, "console"); | |
110 | ||
111 | /* use last console entry */ | |
112 | if(cmd) while(cmd->next) cmd = cmd->next; | |
113 | ||
114 | if( | |
115 | cmd && | |
116 | ( | |
117 | /* everything != "ttyN" */ | |
118 | strncmp(cmd->str, "tty", 3) || | |
119 | !(cmd->str[3] == 0 || (cmd->str[3] >= '0' && cmd->str[3] <= '9')) | |
120 | ) | |
121 | ) { | |
122 | sl = hd_split(',', cmd->str); | |
123 | s = sl->str; | |
124 | if(!strncmp(s, "/dev/", sizeof "/dev/" - 1)) s += sizeof "/dev/" - 1; | |
125 | dev = new_str(s); | |
126 | if(sl->next && (i = sscanf(sl->next->str, "%u%c%u", &u, &c, &u1)) >= 1) { | |
127 | res = add_res_entry(&res, new_mem(sizeof *res)); | |
128 | res->baud.type = res_baud; | |
129 | res->baud.speed = u; | |
130 | if(i >= 2) res->baud.parity = c; | |
131 | if(i >= 3) res->baud.bits = u1; | |
132 | } | |
133 | free_str_list(sl); | |
134 | } | |
135 | ||
136 | #ifdef __UCLIBC__ | |
137 | if(!dev && (fd = open(DEV_CONSOLE, O_RDWR | O_NONBLOCK | O_NOCTTY)) >= 0) { | |
138 | /* | |
139 | if(ioctl(fd, TIOCGDEV, &u) != -1) { | |
140 | tty_major = (u >> 8) & 0xfff; | |
141 | tty_minor = (u & 0xff) | ((u >> 12) & 0xfff00); | |
142 | ADD2LOG(DEV_CONSOLE ": major %u, minor %u\n", tty_major, tty_minor); | |
143 | } | |
144 | */ | |
145 | ||
146 | if(tty_major == 229 /* iseries hvc */) { | |
147 | if (tty_minor >= 128) { | |
148 | str_printf(&dev, 0, "hvsi%u", tty_minor-128); | |
149 | } else { | |
150 | str_printf(&dev, 0, "hvc%u", tty_minor); | |
151 | } | |
152 | } | |
153 | else if(!ioctl(fd, TIOCGSERIAL, &ser_info)) { | |
154 | ADD2LOG("serial console at line %d\n", ser_info.line); | |
155 | str_printf(&dev, 0, "ttyS%d", ser_info.line); | |
156 | } | |
157 | close(fd); | |
158 | } | |
159 | #endif | |
160 | ||
161 | if(dev) { | |
162 | ||
163 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
164 | hd->base_class.id = bc_keyboard; | |
165 | hd->sub_class.id = sc_keyboard_console; | |
166 | hd->bus.id = bus_serial; | |
167 | hd->device.name = new_str("serial console"); | |
168 | ||
169 | if(*dev) str_printf(&hd->unix_dev_name, 0, "/dev/%s", dev); | |
170 | ||
171 | hd->res = res; | |
172 | ||
173 | free_mem(dev); | |
174 | } | |
175 | ||
176 | free_str_list(cmd0); | |
177 | } | |
178 | ||
179 | ||
180 | #else /* defined(__sparc__) */ | |
181 | ||
182 | ||
183 | void add_sun_console(hd_data_t *hd_data) | |
184 | { | |
185 | int fd, kid, kid2, klay, ser_cons, i; | |
186 | unsigned u, u1, u2; | |
187 | char c1, c2; | |
188 | struct serial_struct ser_info; | |
189 | unsigned char buf[OPROMMAXPARAM]; | |
190 | struct openpromio *opio = (struct openpromio *) buf; | |
191 | hd_t *hd; | |
192 | hd_res_t *res; | |
193 | ||
194 | if((fd = open(DEV_CONSOLE, O_RDWR | O_NONBLOCK | O_NOCTTY)) >= 0) | |
195 | { | |
196 | if(ioctl(fd, TIOCGSERIAL, &ser_info)) | |
197 | { | |
198 | ser_cons = -1; | |
199 | } | |
200 | else | |
201 | { | |
202 | ser_cons = ser_info.line; | |
203 | ADD2LOG("serial console at line %d\n", ser_cons); | |
204 | } | |
205 | close(fd); | |
206 | ||
207 | if(ser_cons >= 0 && (fd = open(DEV_OPENPROM, O_RDWR | O_NONBLOCK)) >= 0) | |
208 | { | |
209 | sprintf(opio->oprom_array, "tty%c-mode", (ser_cons & 1) + 'a'); | |
210 | opio->oprom_size = sizeof buf - 0x100; | |
211 | if(!ioctl(fd, OPROMGETOPT, opio)) | |
212 | { | |
213 | if(opio->oprom_size < 0x100) | |
214 | { | |
215 | opio->oprom_array[opio->oprom_size] = 0; | |
216 | ADD2LOG( | |
217 | "prom(tty%c-mode) = \"%s\" (%d bytes)\n", | |
218 | (ser_cons & 1) + 'a', opio->oprom_array, | |
219 | opio->oprom_size | |
220 | ); | |
221 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
222 | hd->base_class.id = bc_keyboard; | |
223 | hd->sub_class.id = sc_keyboard_console; | |
224 | hd->bus.id = bus_serial; | |
225 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0203); | |
226 | hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0000); | |
227 | str_printf(&hd->unix_dev_name, 0, "/dev/ttyS%d", ser_cons); | |
228 | if((i = sscanf(opio->oprom_array, "%u,%u,%c,%u,%c", | |
229 | &u, &u1, &c1, &u2, &c2)) >= 1) | |
230 | { | |
231 | res = add_res_entry(&hd->res, new_mem(sizeof *res)); | |
232 | res->baud.type = res_baud; | |
233 | res->baud.speed = u; | |
234 | if(i >= 2) res->baud.bits = u1; | |
235 | if(i >= 3) res->baud.parity = c1; | |
236 | if(i >= 4) res->baud.stopbits = u2; | |
237 | if(i >= 5) res->baud.handshake = c2; | |
238 | } | |
239 | } | |
240 | } | |
241 | close(fd); | |
242 | /* We have a serial console, so don't test for keyboard. Else | |
243 | we will always find a PS/2 keyboard */ | |
244 | return; | |
245 | } | |
246 | } | |
247 | ||
248 | PROGRESS(1, 0, "sun kbd"); | |
249 | ||
250 | if((fd = open(DEV_KBD, O_RDWR | O_NONBLOCK | O_NOCTTY)) >= 0) | |
251 | { | |
252 | if(ioctl(fd, KIOCTYPE, &kid)) kid = -1; | |
253 | if(ioctl(fd, KIOCLAYOUT, &klay)) klay = -1; | |
254 | close(fd); | |
255 | ||
256 | if(kid != -1) | |
257 | { | |
258 | ADD2LOG("sun keyboard: type %d, layout %d\n", kid, klay); | |
259 | ||
260 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
261 | hd->base_class.id = bc_keyboard; | |
262 | hd->sub_class.id = sc_keyboard_kbd; | |
263 | hd->bus.id = bus_serial; | |
264 | if(kid == 4 && klay >= 0) | |
265 | hd->prog_if.id = klay; | |
266 | ||
267 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0202); | |
268 | kid2 = kid; | |
269 | if(kid == 4 && klay > 0x20) | |
270 | kid2 = 5; | |
271 | hd->device.id = MAKE_ID(TAG_SPECIAL, kid2); | |
272 | if(kid2 == 5) { | |
273 | if(klay == 0x22 || klay == 0x51) | |
274 | { | |
275 | hd->sub_vendor.id = MAKE_ID(TAG_SPECIAL, 0x0202); | |
276 | hd->sub_device.id = MAKE_ID(TAG_SPECIAL, 0x0001); | |
277 | } | |
278 | else if(!( | |
279 | klay == 0x21 || (klay >= 0x2f && klay <= 0x31) || | |
280 | klay == 0x50 || (klay >= 0x5e && klay <= 0x60) | |
281 | )) | |
282 | { | |
283 | hd->sub_vendor.id = MAKE_ID(TAG_SPECIAL, 0x0202); | |
284 | hd->sub_device.id = MAKE_ID(TAG_SPECIAL, 0x0002); | |
285 | } | |
286 | } | |
287 | } | |
288 | } | |
289 | else | |
290 | { | |
291 | for(hd = hd_data->hd; hd; hd = hd->next) { | |
292 | if(hd->base_class.id == bc_keyboard) break; | |
293 | } | |
294 | if(!hd) { | |
295 | /* We must have a PS/2 Keyboard */ | |
296 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
297 | hd->base_class.id = bc_keyboard; | |
298 | hd->sub_class.id = sc_keyboard_kbd; | |
299 | hd->bus.id = bus_ps2; | |
300 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0201); | |
301 | hd->device.id = MAKE_ID(TAG_SPECIAL, 1); | |
302 | } | |
303 | } | |
304 | } | |
305 | ||
306 | #endif /* __sparc__ */ | |
307 | ||
308 |