import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.git] / drivers / sbus / char / sunserial.c
1 /* $Id: sunserial.c,v 1.1.1.1 2005/04/11 02:50:34 jack 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 #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
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
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 }