1 /* $Id: sunserial.c,v 1.79.2.2 2002/01/05 01:12:31 davem Exp $
2  * serial.c: Serial port driver infrastructure for the Sparc.
3  *
4  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
5  */
6 
7 #include <linux/config.h>
8 #include <linux/kernel.h>
9 #include <linux/sched.h>
10 #include <linux/module.h>
11 #include <linux/errno.h>
12 #include <linux/tty.h>
13 #include <linux/serial.h>
14 #include <linux/serialP.h>
15 #include <linux/string.h>
16 #include <linux/kbd_diacr.h>
17 #include <linux/version.h>
18 #include <linux/init.h>
19 #include <linux/bootmem.h>
20 
21 #include <asm/oplib.h>
22 
23 #include "sunserial.h"
24 
25 int serial_console;
26 int stop_a_enabled = 1;
27 
con_is_present(void)28 int __init con_is_present(void)
29 {
30 	return serial_console ? 0 : 1;
31 }
32 
nop_rs_kgdb_hook(int channel)33 static void __init nop_rs_kgdb_hook(int channel)
34 {
35 	printk("Oops: %s called\n", __FUNCTION__);
36 }
37 
nop_rs_change_mouse_baud(int baud)38 static void nop_rs_change_mouse_baud(int baud)
39 {
40 	printk("Oops: %s called\n", __FUNCTION__);
41 }
42 
nop_rs_read_proc(char * page,char ** start,off_t off,int count,int * eof,void * data)43 static int nop_rs_read_proc(char *page, char **start, off_t off, int count,
44 			    int *eof, void *data)
45 {
46 	printk("Oops: %s called\n", __FUNCTION__);
47 	return 0;
48 }
49 
50 struct sunserial_operations rs_ops = {
51 	0,
52 	nop_rs_kgdb_hook,
53 	nop_rs_change_mouse_baud,
54 	nop_rs_read_proc
55 };
56 
rs_init(void)57 void rs_init(void)
58 {
59 	static int invoked = 0;
60 
61 	if (!invoked) {
62 		struct initfunc *init;
63 
64 		invoked = 1;
65 
66 		init = rs_ops.rs_init;
67 		while (init) {
68 			(void) init->init();
69 			init = init->next;
70 		}
71 	}
72 }
73 
rs_kgdb_hook(int channel)74 void __init rs_kgdb_hook(int channel)
75 {
76 	rs_ops.rs_kgdb_hook(channel);
77 }
78 
serial_console_init(void)79 void __init serial_console_init(void)
80 {
81 	return;
82 }
83 
rs_change_mouse_baud(int baud)84 void rs_change_mouse_baud(int baud)
85 {
86 	rs_ops.rs_change_mouse_baud(baud);
87 }
88 
rs_read_proc(char * page,char ** start,off_t off,int count,int * eof,void * data)89 int rs_read_proc(char *page, char **start, off_t off, int count,
90 		 int *eof, void *data)
91 {
92 	return rs_ops.rs_read_proc(page, start, off, count, eof, data);
93 }
94 
register_serial(struct serial_struct * req)95 int register_serial(struct serial_struct *req)
96 {
97 	return -1;
98 }
99 
unregister_serial(int line)100 void unregister_serial(int line)
101 {
102 }
103 
104 
nop_compute_shiftstate(void)105 static void nop_compute_shiftstate (void)
106 {
107 	printk("Oops: %s called\n", __FUNCTION__);
108 }
109 
nop_setledstate(struct kbd_struct * kbd,unsigned int ledstate)110 static void nop_setledstate (struct kbd_struct *kbd, unsigned int ledstate)
111 {
112 	printk("Oops: %s called\n", __FUNCTION__);
113 }
114 
nop_getledstate(void)115 static unsigned char nop_getledstate (void)
116 {
117 	printk("Oops: %s called\n", __FUNCTION__);
118 	return 0;
119 }
120 
nop_setkeycode(unsigned int scancode,unsigned int keycode)121 static int nop_setkeycode (unsigned int scancode, unsigned int keycode)
122 {
123 	printk("Oops: %s called\n", __FUNCTION__);
124 	return -EINVAL;
125 }
126 
nop_getkeycode(unsigned int scancode)127 static int nop_getkeycode (unsigned int scancode)
128 {
129 	printk("Oops: %s called\n", __FUNCTION__);
130 	return -EINVAL;
131 }
132 
133 struct sunkbd_operations kbd_ops = {
134 	0,
135 	nop_compute_shiftstate,
136 	nop_setledstate,
137 	nop_getledstate,
138 	nop_setkeycode,
139 	nop_getkeycode
140 };
141 
142 #if defined(CONFIG_USB) || defined(CONFIG_USB_MODULE)
143 extern void pci_compute_shiftstate(void);
144 extern int pci_setkeycode(unsigned int, unsigned int);
145 extern int pci_getkeycode(unsigned int);
146 extern void pci_setledstate(struct kbd_struct *, unsigned int);
147 extern unsigned char pci_getledstate(void);
148 extern int pcikbd_init(void);
149 #endif
150 
kbd_init(void)151 int kbd_init(void)
152 {
153 	struct initfunc *init;
154 	int err = -ENODEV;
155 
156 	init = kbd_ops.kbd_init;
157 	while (init) {
158 		err = init->init();
159 		init = init->next;
160 	}
161 #if defined(CONFIG_USB) || defined(CONFIG_USB_MODULE)
162 	if (!serial_console &&
163 	    kbd_ops.compute_shiftstate == nop_compute_shiftstate) {
164 		printk("kbd_init: Assuming USB keyboard.\n");
165 		kbd_ops.compute_shiftstate = pci_compute_shiftstate;
166 		kbd_ops.setledstate = pci_setledstate;
167 		kbd_ops.getledstate = pci_getledstate;
168 		kbd_ops.setkeycode = pci_setkeycode;
169 		kbd_ops.getkeycode = pci_getkeycode;
170 		pcikbd_init();
171 	}
172 #endif
173 	return err;
174 }
175 
compute_shiftstate(void)176 void compute_shiftstate (void)
177 {
178 	kbd_ops.compute_shiftstate();
179 }
180 
setledstate(struct kbd_struct * kbd,unsigned int ledstate)181 void setledstate (struct kbd_struct *kbd, unsigned int ledstate)
182 {
183 	kbd_ops.setledstate(kbd, ledstate);
184 }
185 
getledstate(void)186 unsigned char getledstate (void)
187 {
188 	return kbd_ops.getledstate();
189 }
190 
setkeycode(unsigned int scancode,unsigned int keycode)191 int setkeycode (unsigned int scancode, unsigned int keycode)
192 {
193 	return kbd_ops.setkeycode(scancode, keycode);
194 }
195 
getkeycode(unsigned int scancode)196 int getkeycode (unsigned int scancode)
197 {
198 	return kbd_ops.getkeycode(scancode);
199 }
200 
sunserial_alloc_bootmem(unsigned long size)201 void * __init sunserial_alloc_bootmem(unsigned long size)
202 {
203 	void *ret;
204 
205 	ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
206 	if (ret != NULL)
207 		memset(ret, 0, size);
208 
209 	return ret;
210 }
211 
212 void
sunserial_setinitfunc(int (* init)(void))213 sunserial_setinitfunc(int (*init) (void))
214 {
215 	struct initfunc *rs_init;
216 
217 	rs_init = sunserial_alloc_bootmem(sizeof(struct initfunc));
218 	if (rs_init == NULL) {
219 		prom_printf("sunserial_setinitfunc: Cannot alloc initfunc.\n");
220 		prom_halt();
221 	}
222 
223 	rs_init->init = init;
224 	rs_init->next = rs_ops.rs_init;
225 	rs_ops.rs_init = rs_init;
226 }
227 
228 void
sunserial_console_termios(struct console * con)229 sunserial_console_termios(struct console *con)
230 {
231 	char mode[16], buf[16], *s;
232 	char *mode_prop = "ttyX-mode";
233 	char *cd_prop = "ttyX-ignore-cd";
234 	char *dtr_prop = "ttyX-rts-dtr-off";
235 	int baud, bits, stop, cflag;
236 	char parity;
237 	int carrier = 0;
238 	int rtsdtr = 1;
239 	int topnd, nd;
240 
241 	if (!serial_console)
242 		return;
243 
244 	if (serial_console == 1) {
245 		mode_prop[3] = 'a';
246 		cd_prop[3] = 'a';
247 		dtr_prop[3] = 'a';
248 	} else {
249 		mode_prop[3] = 'b';
250 		cd_prop[3] = 'b';
251 		dtr_prop[3] = 'b';
252 	}
253 
254 	topnd = prom_getchild(prom_root_node);
255 	nd = prom_searchsiblings(topnd, "options");
256 	if (!nd) {
257 		strcpy(mode, "9600,8,n,1,-");
258 		goto no_options;
259 	}
260 
261 	if (!prom_node_has_property(nd, mode_prop)) {
262 		strcpy(mode, "9600,8,n,1,-");
263 		goto no_options;
264 	}
265 
266 	memset(mode, 0, sizeof(mode));
267 	prom_getstring(nd, mode_prop, mode, sizeof(mode));
268 
269 	if (prom_node_has_property(nd, cd_prop)) {
270 		memset(buf, 0, sizeof(buf));
271 		prom_getstring(nd, cd_prop, buf, sizeof(buf));
272 		if (!strcmp(buf, "false"))
273 			carrier = 1;
274 
275 		/* XXX: this is unused below. */
276 	}
277 
278 	if (prom_node_has_property(nd, cd_prop)) {
279 		memset(buf, 0, sizeof(buf));
280 		prom_getstring(nd, cd_prop, buf, sizeof(buf));
281 		if (!strcmp(buf, "false"))
282 			rtsdtr = 0;
283 
284 		/* XXX: this is unused below. */
285 	}
286 
287 no_options:
288 	cflag = CREAD | HUPCL | CLOCAL;
289 
290 	s = mode;
291 	baud = simple_strtoul(s, 0, 0);
292 	s = strchr(s, ',');
293 	bits = simple_strtoul(++s, 0, 0);
294 	s = strchr(s, ',');
295 	parity = *(++s);
296 	s = strchr(s, ',');
297 	stop = simple_strtoul(++s, 0, 0);
298 	s = strchr(s, ',');
299 	/* XXX handshake is not handled here. */
300 
301 	switch (baud) {
302 		case 150: cflag |= B150; break;
303 		case 300: cflag |= B300; break;
304 		case 600: cflag |= B600; break;
305 		case 1200: cflag |= B1200; break;
306 		case 2400: cflag |= B2400; break;
307 		case 4800: cflag |= B4800; break;
308 		case 9600: cflag |= B9600; break;
309 		case 19200: cflag |= B19200; break;
310 		case 38400: cflag |= B38400; break;
311 		default: baud = 9600; cflag |= B9600; break;
312 	}
313 
314 	switch (bits) {
315 		case 5: cflag |= CS5; break;
316 		case 6: cflag |= CS6; break;
317 		case 7: cflag |= CS7; break;
318 		case 8: cflag |= CS8; break;
319 		default: cflag |= CS8; break;
320 	}
321 
322 	switch (parity) {
323 		case 'o': cflag |= (PARENB | PARODD); break;
324 		case 'e': cflag |= PARENB; break;
325 		case 'n': default: break;
326 	}
327 
328 	switch (stop) {
329 		case 2: cflag |= CSTOPB; break;
330 		case 1: default: break;
331 	}
332 
333 	con->cflag = cflag;
334 }
335 
336 void
sunkbd_setinitfunc(int (* init)(void))337 sunkbd_setinitfunc(int (*init) (void))
338 {
339 	struct initfunc *kbd_init;
340 
341 	kbd_init = sunserial_alloc_bootmem(sizeof(struct initfunc));
342 	if (kbd_init == NULL) {
343 		prom_printf("sunkbd_setinitfunc: Cannot alloc initfunc.\n");
344 		prom_halt();
345 	}
346 
347 	kbd_init->init = init;
348 	kbd_init->next = kbd_ops.kbd_init;
349 	kbd_ops.kbd_init = kbd_init;
350 }
351 
352 #ifdef CONFIG_PCI
353 void
sunkbd_install_keymaps(ushort ** src_key_maps,unsigned int src_keymap_count,char * src_func_buf,char ** src_func_table,int src_funcbufsize,int src_funcbufleft,struct kbdiacr * src_accent_table,unsigned int src_accent_table_size)354 sunkbd_install_keymaps(ushort **src_key_maps, unsigned int src_keymap_count,
355 		       char *src_func_buf, char **src_func_table,
356 		       int src_funcbufsize, int src_funcbufleft,
357 		       struct kbdiacr *src_accent_table,
358 		       unsigned int src_accent_table_size)
359 {
360 	extern unsigned int keymap_count;
361 	int i, j;
362 
363 	for (i = 0; i < MAX_NR_KEYMAPS; i++) {
364 		if (src_key_maps[i]) {
365 			if (!key_maps[i]) {
366 				key_maps[i] = (ushort *)
367 					sunserial_alloc_bootmem(NR_KEYS * sizeof(ushort));
368 				if (key_maps[i] == NULL) {
369 					prom_printf("sunkbd_install_keymaps: "
370 						    "Cannot alloc key_map(%d).\n", i);
371 					prom_halt();
372 				}
373 			}
374 			for (j = 0; j < NR_KEYS; j++)
375 				key_maps[i][j] = src_key_maps[i][j];
376 		}
377 		key_maps[i] = src_key_maps[i];
378 	}
379 	keymap_count = src_keymap_count;
380 
381 	for (i = 0; i < MAX_NR_FUNC; i++)
382 		func_table[i] = src_func_table[i];
383 	funcbufptr = src_func_buf;
384 	funcbufsize = src_funcbufsize;
385 	funcbufleft = src_funcbufleft;
386 
387 	for (i = 0; i < MAX_DIACR; i++)
388 		accent_table[i] = src_accent_table[i];
389 	accent_table_size = src_accent_table_size;
390 }
391 #endif
392 
393 extern int su_probe(void);
394 extern int zs_probe(void);
395 #ifdef CONFIG_SAB82532
396 extern int sab82532_probe(void);
397 #endif
398 #ifdef CONFIG_PCI
399 extern int ps2kbd_probe(void);
400 #endif
401 
sun_serial_setup(void)402 void __init sun_serial_setup(void)
403 {
404 	int ret = 1;
405 
406 #if defined(CONFIG_PCI) && !defined(__sparc_v9__)
407 	/*
408 	 * Probing sequence on sparc differs from sparc64.
409 	 * Keyboard is probed ahead of su because we want su function
410 	 * when keyboard is active. su is probed ahead of zs in order to
411 	 * get console on MrCoffee with fine but disconnected zs.
412 	 */
413 	if (!serial_console)
414 		ps2kbd_probe();
415 	if (su_probe() == 0)
416 		return;
417 #endif
418 
419 	if (zs_probe() == 0)
420 		return;
421 
422 #ifdef CONFIG_SAB82532
423 	ret = sab82532_probe();
424 #endif
425 
426 #if defined(CONFIG_PCI) && defined(__sparc_v9__)
427 	/*
428 	 * Keyboard serial devices.
429 	 *
430 	 * Well done, Sun, prom_devopen("/pci@1f,4000/ebus@1/su@14,3083f8")
431 	 * hangs the machine if no keyboard is connected to the device...
432 	 * All PCI PROMs seem to do this, I have seen this on the Ultra 450
433 	 * with version 3.5 PROM, and on the Ultra/AX with 3.1.5 PROM.
434 	 *
435 	 * So be very careful not to probe for keyboards if we are on a
436 	 * serial console.
437 	 */
438 	if (!serial_console)
439 		ps2kbd_probe();
440 	if (su_probe() == 0)
441 		return;
442 #endif
443 
444 	if (!ret)
445 		return;
446 
447 #ifdef __sparc_v9__
448 	{	extern int this_is_starfire;
449 		/* Hello, Starfire. Pleased to meet you :) */
450 		if(this_is_starfire != 0)
451 			return;
452 	}
453 #endif
454 
455 	prom_printf("No serial devices found, bailing out.\n");
456 	prom_halt();
457 }
458