console.c 7.1 KB

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