File: /usr/src/linux/drivers/sbus/char/sunserial.c

1     /* $Id: sunserial.c,v 1.79 2001/04/18 21:06:17 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     
28     int __init con_is_present(void)
29     {
30     	return serial_console ? 0 : 1;
31     }
32     
33     static void __init nop_rs_kgdb_hook(int channel)
34     {
35     	printk("Oops: %s called\n", __FUNCTION__);
36     }
37     
38     static void nop_rs_change_mouse_baud(int baud)
39     {
40     	printk("Oops: %s called\n", __FUNCTION__);
41     }
42     
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     
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     
74     void __init rs_kgdb_hook(int channel)
75     {
76     	rs_ops.rs_kgdb_hook(channel);
77     }
78     
79     void __init serial_console_init(void)
80     {
81     	return;
82     }
83     
84     void rs_change_mouse_baud(int baud)
85     {
86     	rs_ops.rs_change_mouse_baud(baud);
87     }
88     
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     
95     int register_serial(struct serial_struct *req)
96     {
97     	return -1;
98     }
99     
100     void unregister_serial(int line)
101     {
102     }
103     
104     
105     static void nop_compute_shiftstate (void)
106     {
107     	printk("Oops: %s called\n", __FUNCTION__);
108     }
109     
110     static void nop_setledstate (struct kbd_struct *kbd, unsigned int ledstate)
111     {
112     	printk("Oops: %s called\n", __FUNCTION__);
113     }
114     
115     static unsigned char nop_getledstate (void)
116     {
117     	printk("Oops: %s called\n", __FUNCTION__);
118     	return 0;
119     }
120     
121     static int nop_setkeycode (unsigned int scancode, unsigned int keycode)
122     {
123     	printk("Oops: %s called\n", __FUNCTION__);
124     	return -EINVAL;
125     }
126     
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     #ifdef CONFIG_USB
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     
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     #ifdef CONFIG_USB
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     
176     void compute_shiftstate (void)
177     {
178     	kbd_ops.compute_shiftstate();
179     }
180     
181     void setledstate (struct kbd_struct *kbd, unsigned int ledstate)
182     {
183     	kbd_ops.setledstate(kbd, ledstate);
184     }
185     
186     unsigned char getledstate (void)
187     {
188     	return kbd_ops.getledstate();
189     }
190     
191     int setkeycode (unsigned int scancode, unsigned int keycode)
192     {
193     	return kbd_ops.setkeycode(scancode, keycode);
194     }
195     
196     int getkeycode (unsigned int scancode)
197     {
198     	return kbd_ops.getkeycode(scancode);
199     }
200     
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
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
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
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
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     
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