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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  drivers/s390/char/hwc_tty.c
  3.  *    HWC line mode terminal driver.
  4.  *
  5.  *  S390 version
  6.  *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  7.  *    Author(s): Martin Peschke <mpeschke@de.ibm.com>
  8.  *
  9.  *  Thanks to Martin Schwidefsky.
  10.  */
  11. #include <linux/config.h>
  12. #include <linux/major.h>
  13. #include <linux/termios.h>
  14. #include <linux/tty.h>
  15. #include <linux/tty_driver.h>
  16. #include <linux/sched.h>
  17. #include <linux/mm.h>
  18. #include <linux/devfs_fs_kernel.h>
  19. #include <linux/init.h>
  20. #include <asm/uaccess.h>
  21. #include "hwc_rw.h"
  22. #include "ctrlchar.h"
  23. #define HWC_TTY_PRINT_HEADER "hwc tty driver: "
  24. #define HWC_TTY_BUF_SIZE 512
  25. typedef struct {
  26. struct tty_struct *tty;
  27. unsigned char buf[HWC_TTY_BUF_SIZE];
  28. unsigned short int buf_count;
  29. spinlock_t lock;
  30. hwc_high_level_calls_t calls;
  31. } hwc_tty_data_struct;
  32. static hwc_tty_data_struct hwc_tty_data =
  33. { /* NULL/0 */ };
  34. static struct tty_driver hwc_tty_driver;
  35. static struct tty_struct *hwc_tty_table[1];
  36. static struct termios *hwc_tty_termios[1];
  37. static struct termios *hwc_tty_termios_locked[1];
  38. static int hwc_tty_refcount = 0;
  39. extern struct termios tty_std_termios;
  40. void hwc_tty_wake_up (void);
  41. void hwc_tty_input (unsigned char *, unsigned int);
  42. static int 
  43. hwc_tty_open (struct tty_struct *tty,
  44.       struct file *filp)
  45. {
  46. if (MINOR (tty->device) - tty->driver.minor_start)
  47. return -ENODEV;
  48. tty->driver_data = &hwc_tty_data;
  49. hwc_tty_data.buf_count = 0;
  50. hwc_tty_data.tty = tty;
  51. tty->low_latency = 0;
  52. hwc_tty_data.calls.wake_up = hwc_tty_wake_up;
  53. hwc_tty_data.calls.move_input = hwc_tty_input;
  54. hwc_register_calls (&(hwc_tty_data.calls));
  55. return 0;
  56. }
  57. static void 
  58. hwc_tty_close (struct tty_struct *tty,
  59.        struct file *filp)
  60. {
  61. if (MINOR (tty->device) != tty->driver.minor_start) {
  62. printk (KERN_WARNING HWC_TTY_PRINT_HEADER
  63. "do not close hwc tty because of wrong device number");
  64. return;
  65. }
  66. if (tty->count > 1)
  67. return;
  68. hwc_tty_data.tty = NULL;
  69. hwc_unregister_calls (&(hwc_tty_data.calls));
  70. }
  71. static int 
  72. hwc_tty_write_room (struct tty_struct *tty)
  73. {
  74. int retval;
  75. retval = hwc_write_room (IN_BUFS_TOTAL);
  76. return retval;
  77. }
  78. static int 
  79. hwc_tty_write (struct tty_struct *tty,
  80.        int from_user,
  81.        const unsigned char *buf,
  82.        int count)
  83. {
  84. int retval;
  85. if (hwc_tty_data.buf_count > 0) {
  86. hwc_write (0, hwc_tty_data.buf, hwc_tty_data.buf_count);
  87. hwc_tty_data.buf_count = 0;
  88. }
  89. retval = hwc_write (from_user, buf, count);
  90. return retval;
  91. }
  92. static void 
  93. hwc_tty_put_char (struct tty_struct *tty,
  94.   unsigned char ch)
  95. {
  96. unsigned long flags;
  97. spin_lock_irqsave (&hwc_tty_data.lock, flags);
  98. if (hwc_tty_data.buf_count >= HWC_TTY_BUF_SIZE) {
  99. hwc_write (0, hwc_tty_data.buf, hwc_tty_data.buf_count);
  100. hwc_tty_data.buf_count = 0;
  101. }
  102. hwc_tty_data.buf[hwc_tty_data.buf_count] = ch;
  103. hwc_tty_data.buf_count++;
  104. spin_unlock_irqrestore (&hwc_tty_data.lock, flags);
  105. }
  106. static void 
  107. hwc_tty_flush_chars (struct tty_struct *tty)
  108. {
  109. unsigned long flags;
  110. spin_lock_irqsave (&hwc_tty_data.lock, flags);
  111. hwc_write (0, hwc_tty_data.buf, hwc_tty_data.buf_count);
  112. hwc_tty_data.buf_count = 0;
  113. spin_unlock_irqrestore (&hwc_tty_data.lock, flags);
  114. }
  115. static int 
  116. hwc_tty_chars_in_buffer (struct tty_struct *tty)
  117. {
  118. int retval;
  119. retval = hwc_chars_in_buffer (IN_BUFS_TOTAL);
  120. return retval;
  121. }
  122. static void 
  123. hwc_tty_flush_buffer (struct tty_struct *tty)
  124. {
  125. hwc_tty_wake_up ();
  126. }
  127. static int 
  128. hwc_tty_ioctl (
  129.       struct tty_struct *tty,
  130.       struct file *file,
  131.       unsigned int cmd,
  132.       unsigned long arg)
  133. {
  134. if (tty->flags & (1 << TTY_IO_ERROR))
  135. return -EIO;
  136. return hwc_ioctl (cmd, arg);
  137. }
  138. void 
  139. hwc_tty_wake_up (void)
  140. {
  141. if (hwc_tty_data.tty == NULL)
  142. return;
  143. if ((hwc_tty_data.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
  144.     hwc_tty_data.tty->ldisc.write_wakeup)
  145. (hwc_tty_data.tty->ldisc.write_wakeup) (hwc_tty_data.tty);
  146. wake_up_interruptible (&hwc_tty_data.tty->write_wait);
  147. }
  148. void 
  149. hwc_tty_input (unsigned char *buf, unsigned int count)
  150. {
  151. struct tty_struct *tty = hwc_tty_data.tty;
  152. if (tty != NULL) {
  153. char *cchar;
  154. if ((cchar = ctrlchar_handle (buf, count, tty))) {
  155. if (cchar == (char *) -1)
  156. return;
  157. tty->flip.count++;
  158. *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
  159. *tty->flip.char_buf_ptr++ = *cchar;
  160. } else {
  161. memcpy (tty->flip.char_buf_ptr, buf, count);
  162. if (count < 2 || (
  163.  strncmp (buf + count - 2, "^n", 2) ||
  164.     strncmp (buf + count - 2, "252n", 2))) {
  165. tty->flip.char_buf_ptr[count] = 'n';
  166. count++;
  167. } else
  168. count -= 2;
  169. memset (tty->flip.flag_buf_ptr, TTY_NORMAL, count);
  170. tty->flip.char_buf_ptr += count;
  171. tty->flip.flag_buf_ptr += count;
  172. tty->flip.count += count;
  173. }
  174. tty_flip_buffer_push (tty);
  175. hwc_tty_wake_up ();
  176. }
  177. }
  178. void 
  179. hwc_tty_init (void)
  180. {
  181. if (!CONSOLE_IS_HWC)
  182. return;
  183. ctrlchar_init ();
  184. memset (&hwc_tty_driver, 0, sizeof (struct tty_driver));
  185. memset (&hwc_tty_data, 0, sizeof (hwc_tty_data_struct));
  186. hwc_tty_driver.magic = TTY_DRIVER_MAGIC;
  187. hwc_tty_driver.driver_name = "tty_hwc";
  188. hwc_tty_driver.name = "ttyS";
  189. hwc_tty_driver.name_base = 0;
  190. hwc_tty_driver.major = TTY_MAJOR;
  191. hwc_tty_driver.minor_start = 64;
  192. hwc_tty_driver.num = 1;
  193. hwc_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM;
  194. hwc_tty_driver.subtype = SYSTEM_TYPE_TTY;
  195. hwc_tty_driver.init_termios = tty_std_termios;
  196. hwc_tty_driver.init_termios.c_iflag = IGNBRK | IGNPAR;
  197. hwc_tty_driver.init_termios.c_oflag = ONLCR;
  198. hwc_tty_driver.init_termios.c_lflag = ISIG | ECHO;
  199. hwc_tty_driver.flags = TTY_DRIVER_REAL_RAW;
  200. hwc_tty_driver.refcount = &hwc_tty_refcount;
  201. hwc_tty_driver.table = hwc_tty_table;
  202. hwc_tty_driver.termios = hwc_tty_termios;
  203. hwc_tty_driver.termios_locked = hwc_tty_termios_locked;
  204. hwc_tty_driver.open = hwc_tty_open;
  205. hwc_tty_driver.close = hwc_tty_close;
  206. hwc_tty_driver.write = hwc_tty_write;
  207. hwc_tty_driver.put_char = hwc_tty_put_char;
  208. hwc_tty_driver.flush_chars = hwc_tty_flush_chars;
  209. hwc_tty_driver.write_room = hwc_tty_write_room;
  210. hwc_tty_driver.chars_in_buffer = hwc_tty_chars_in_buffer;
  211. hwc_tty_driver.flush_buffer = hwc_tty_flush_buffer;
  212. hwc_tty_driver.ioctl = hwc_tty_ioctl;
  213. hwc_tty_driver.throttle = NULL;
  214. hwc_tty_driver.unthrottle = NULL;
  215. hwc_tty_driver.send_xchar = NULL;
  216. hwc_tty_driver.set_termios = NULL;
  217. hwc_tty_driver.set_ldisc = NULL;
  218. hwc_tty_driver.stop = NULL;
  219. hwc_tty_driver.start = NULL;
  220. hwc_tty_driver.hangup = NULL;
  221. hwc_tty_driver.break_ctl = NULL;
  222. hwc_tty_driver.wait_until_sent = NULL;
  223. hwc_tty_driver.read_proc = NULL;
  224. hwc_tty_driver.write_proc = NULL;
  225. if (tty_register_driver (&hwc_tty_driver))
  226. panic ("Couldn't register hwc_tty drivern");
  227. }