sunserial.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:9k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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