console.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /*
  2. * File : console.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://openlab.rt-thread.com/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2006-09-15 QiuYi the first version
  13. */
  14. #include <rtthread.h>
  15. #include <rthw.h>
  16. #include <bsp.h>
  17. static unsigned addr_6845;
  18. static rt_uint16_t *crt_buf;
  19. static rt_int16_t crt_pos;
  20. extern void init_keyboard();
  21. extern void rt_keyboard_isr(void);
  22. extern rt_bool_t rt_keyboard_getc(char* c);
  23. static void rt_console_putc(int c);
  24. /**
  25. * @addtogroup QEMU
  26. */
  27. /*@{*/
  28. /**
  29. * This function initializes cga
  30. *
  31. */
  32. void rt_cga_init(void)
  33. {
  34. rt_uint16_t volatile *cp;
  35. rt_uint16_t was;
  36. rt_uint32_t pos;
  37. cp = (rt_uint16_t *) (CGA_BUF);
  38. was = *cp;
  39. *cp = (rt_uint16_t) 0xA55A;
  40. if (*cp != 0xA55A)
  41. {
  42. cp = (rt_uint16_t *) (MONO_BUF);
  43. addr_6845 = MONO_BASE;
  44. }
  45. else
  46. {
  47. *cp = was;
  48. addr_6845 = CGA_BASE;
  49. }
  50. /* Extract cursor location */
  51. outb(addr_6845, 14);
  52. pos = inb(addr_6845+1) << 8;
  53. outb(addr_6845, 15);
  54. pos |= inb(addr_6845+1);
  55. crt_buf = (rt_uint16_t *)cp;
  56. crt_pos = pos;
  57. }
  58. /**
  59. * This function will write a character to cga
  60. *
  61. * @param c the char to write
  62. */
  63. static void rt_cga_putc(int c)
  64. {
  65. /* if no attribute given, then use black on white */
  66. if (!(c & ~0xff)) c |= 0x0700;
  67. switch (c & 0xff)
  68. {
  69. case '\b':
  70. if (crt_pos > 0)
  71. {
  72. crt_pos--;
  73. crt_buf[crt_pos] = (c&~0xff) | ' ';
  74. }
  75. break;
  76. case '\n':
  77. crt_pos += CRT_COLS;
  78. /* cascade */
  79. case '\r':
  80. crt_pos -= (crt_pos % CRT_COLS);
  81. break;
  82. case '\t':
  83. rt_console_putc(' ');
  84. rt_console_putc(' ');
  85. rt_console_putc(' ');
  86. rt_console_putc(' ');
  87. rt_console_putc(' ');
  88. break;
  89. default:
  90. crt_buf[crt_pos++] = c; /* write the character */
  91. break;
  92. }
  93. if (crt_pos >= CRT_SIZE)
  94. {
  95. rt_int32_t i;
  96. rt_memcpy(crt_buf, crt_buf + CRT_COLS, (CRT_SIZE - CRT_COLS) << 1);
  97. for (i = CRT_SIZE - CRT_COLS; i < CRT_SIZE; i++)
  98. crt_buf[i] = 0x0700 | ' ';
  99. crt_pos -= CRT_COLS;
  100. }
  101. outb(addr_6845, 14);
  102. outb(addr_6845+1, crt_pos >> 8);
  103. outb(addr_6845, 15);
  104. outb(addr_6845+1, crt_pos);
  105. }
  106. /**
  107. * This function will write a character to serial an cga
  108. *
  109. * @param c the char to write
  110. */
  111. static void rt_console_putc(int c)
  112. {
  113. rt_cga_putc(c);
  114. // rt_serial_putc(c);
  115. }
  116. /* RT-Thread Device Interface */
  117. #define CONSOLE_RX_BUFFER_SIZE 64
  118. static struct rt_device console_device;
  119. static rt_uint8_t rx_buffer[CONSOLE_RX_BUFFER_SIZE];
  120. static rt_uint32_t read_index, save_index;
  121. static rt_err_t rt_console_init (rt_device_t dev)
  122. {
  123. return RT_EOK;
  124. }
  125. static rt_err_t rt_console_open(rt_device_t dev, rt_uint16_t oflag)
  126. {
  127. return RT_EOK;
  128. }
  129. static rt_err_t rt_console_close(rt_device_t dev)
  130. {
  131. return RT_EOK;
  132. }
  133. static rt_err_t rt_console_control(rt_device_t dev, rt_uint8_t cmd, void *args)
  134. {
  135. return RT_EOK;
  136. }
  137. static rt_size_t rt_console_write(rt_device_t dev, rt_off_t pos, const void * buffer, rt_size_t size)
  138. {
  139. rt_size_t i = size;
  140. const char* str = buffer;
  141. while(i--)
  142. {
  143. rt_console_putc(*str++);
  144. }
  145. return size;
  146. }
  147. static rt_size_t rt_console_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
  148. {
  149. rt_uint8_t* ptr = buffer;
  150. rt_err_t err_code = RT_EOK;
  151. /* interrupt mode Rx */
  152. while (size)
  153. {
  154. rt_base_t level;
  155. /* disable interrupt */
  156. level = rt_hw_interrupt_disable();
  157. if (read_index != save_index)
  158. {
  159. /* read a character */
  160. *ptr++ = rx_buffer[read_index];
  161. size--;
  162. /* move to next position */
  163. read_index ++;
  164. if (read_index >= CONSOLE_RX_BUFFER_SIZE)
  165. read_index = 0;
  166. }
  167. else
  168. {
  169. /* set error code */
  170. err_code = -RT_EEMPTY;
  171. /* enable interrupt */
  172. rt_hw_interrupt_enable(level);
  173. break;
  174. }
  175. /* enable interrupt */
  176. rt_hw_interrupt_enable(level);
  177. }
  178. /* set error code */
  179. rt_set_errno(err_code);
  180. return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
  181. }
  182. static void rt_console_isr(int vector, void* param)
  183. {
  184. char c;
  185. rt_bool_t ret;
  186. rt_base_t level;
  187. rt_keyboard_isr();
  188. ret = rt_keyboard_getc(&c);
  189. if(ret == RT_FALSE)
  190. {
  191. /* do nothing */
  192. }
  193. else
  194. {
  195. /* disable interrupt */
  196. level = rt_hw_interrupt_disable();
  197. /* save character */
  198. rx_buffer[save_index] = c;
  199. save_index ++;
  200. if (save_index >= CONSOLE_RX_BUFFER_SIZE)
  201. save_index = 0;
  202. /* if the next position is read index, discard this 'read char' */
  203. if (save_index == read_index)
  204. {
  205. read_index ++;
  206. if (read_index >= CONSOLE_RX_BUFFER_SIZE)
  207. read_index = 0;
  208. }
  209. /* enable interrupt */
  210. rt_hw_interrupt_enable(level);
  211. }
  212. /* invoke callback */
  213. if (console_device.rx_indicate != RT_NULL)
  214. {
  215. rt_size_t rx_length;
  216. /* get rx length */
  217. rx_length = read_index > save_index ?
  218. CONSOLE_RX_BUFFER_SIZE - read_index + save_index :
  219. save_index - read_index;
  220. if(rx_length > 0)
  221. {
  222. console_device.rx_indicate(&console_device, rx_length);
  223. }
  224. }
  225. else
  226. {
  227. }
  228. }
  229. /**
  230. * This function initializes console
  231. *
  232. */
  233. void rt_hw_console_init(void)
  234. {
  235. rt_cga_init();
  236. init_keyboard();
  237. /* install keyboard isr */
  238. rt_hw_interrupt_install(INTKEYBOARD, rt_console_isr, RT_NULL, "kbd");
  239. rt_hw_interrupt_umask(INTKEYBOARD);
  240. console_device.type = RT_Device_Class_Char;
  241. console_device.rx_indicate = RT_NULL;
  242. console_device.tx_complete = RT_NULL;
  243. console_device.init = rt_console_init;
  244. console_device.open = rt_console_open;
  245. console_device.close = rt_console_close;
  246. console_device.read = rt_console_read;
  247. console_device.write = rt_console_write;
  248. console_device.control = rt_console_control;
  249. console_device.user_data = RT_NULL;
  250. /* register a character device */
  251. rt_device_register(&console_device,
  252. "console",
  253. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM);
  254. }
  255. /**
  256. * This function is used to display a string on console, normally, it's
  257. * invoked by rt_kprintf
  258. *
  259. * @param str the displayed string
  260. *
  261. * Modified:
  262. * caoxl 2009-10-14
  263. * the name is change to rt_hw_console_output in the v0.3.0
  264. *
  265. */
  266. void rt_hw_console_output(const char* str)
  267. {
  268. while (*str)
  269. {
  270. rt_console_putc (*str++);
  271. }
  272. }
  273. /*@}*/