console.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. * Copyright (C) 2006-2011 Free Software Foundation
  3. *
  4. * This program is free software ; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation ; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY ; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with the program ; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. #include <sys/types.h>
  19. #include <device/tty.h>
  20. #include <device/cons.h>
  21. #include <machine/pmap.h>
  22. #include <machine/machspl.h>
  23. #include <xen/public/io/console.h>
  24. #include "console.h"
  25. #include "ring.h"
  26. #include "evt.h"
  27. /* Hypervisor part */
  28. decl_simple_lock_data(static, outlock);
  29. decl_simple_lock_data(static, inlock);
  30. static struct xencons_interface *console;
  31. static int kd_pollc;
  32. int kb_mode; /* XXX: actually don't care. */
  33. #undef hyp_console_write
  34. void hyp_console_write(const char *str, int len)
  35. {
  36. hyp_console_io (CONSOLEIO_write, len, kvtolin(str));
  37. }
  38. int hypputc(int c)
  39. {
  40. if (!console) {
  41. char d = c;
  42. hyp_console_io(CONSOLEIO_write, 1, kvtolin(&d));
  43. } else {
  44. spl_t spl = splhigh();
  45. static int complain;
  46. simple_lock(&outlock);
  47. while (hyp_ring_smash(console->out, console->out_prod, console->out_cons)) {
  48. if (!complain) {
  49. complain = 1;
  50. hyp_console_put("ring smash\n");
  51. }
  52. /* TODO: are we allowed to sleep in putc? */
  53. hyp_yield();
  54. }
  55. hyp_ring_cell(console->out, console->out_prod) = c;
  56. wmb();
  57. console->out_prod++;
  58. hyp_event_channel_send(boot_info.console_evtchn);
  59. simple_unlock(&outlock);
  60. splx(spl);
  61. }
  62. return 0;
  63. }
  64. int hypcnputc(dev_t dev, int c)
  65. {
  66. return hypputc(c);
  67. }
  68. /* get char by polling, used by debugger */
  69. int hypcngetc(dev_t dev, int wait)
  70. {
  71. int ret;
  72. if (wait)
  73. while (console->in_prod == console->in_cons)
  74. hyp_yield();
  75. else
  76. if (console->in_prod == console->in_cons)
  77. return -1;
  78. ret = hyp_ring_cell(console->in, console->in_cons);
  79. mb();
  80. console->in_cons++;
  81. hyp_event_channel_send(boot_info.console_evtchn);
  82. return ret;
  83. }
  84. void cnpollc(boolean_t on) {
  85. if (on) {
  86. kd_pollc++;
  87. } else {
  88. --kd_pollc;
  89. }
  90. }
  91. void kd_setleds1(u_char val)
  92. {
  93. /* Can't do this. */
  94. }
  95. /* Mach part */
  96. struct tty hypcn_tty;
  97. static void hypcnintr(int unit, spl_t spl, void *ret_addr, void *regs) {
  98. struct tty *tp = &hypcn_tty;
  99. if (kd_pollc)
  100. return;
  101. simple_lock(&inlock);
  102. while (console->in_prod != console->in_cons) {
  103. int c = hyp_ring_cell(console->in, console->in_cons);
  104. mb();
  105. console->in_cons++;
  106. #if MACH_KDB
  107. if (c == (char)0xA3) {
  108. printf("pound pressed\n");
  109. kdb_kintr();
  110. continue;
  111. }
  112. #endif /* MACH_KDB */
  113. if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)))
  114. (*linesw[tp->t_line].l_rint)(c, tp);
  115. }
  116. hyp_event_channel_send(boot_info.console_evtchn);
  117. simple_unlock(&inlock);
  118. }
  119. int hypcnread(dev_t dev, io_req_t ior)
  120. {
  121. struct tty *tp = &hypcn_tty;
  122. tp->t_state |= TS_CARR_ON;
  123. return char_read(tp, ior);
  124. }
  125. int hypcnwrite(dev_t dev, io_req_t ior)
  126. {
  127. return char_write(&hypcn_tty, ior);
  128. }
  129. void hypcnstart(struct tty *tp)
  130. {
  131. spl_t o_pri;
  132. int ch;
  133. unsigned char c;
  134. if (tp->t_state & TS_TTSTOP)
  135. return;
  136. while (1) {
  137. tp->t_state &= ~TS_BUSY;
  138. if (tp->t_state & TS_TTSTOP)
  139. break;
  140. if ((tp->t_outq.c_cc <= 0) || (ch = getc(&tp->t_outq)) == -1)
  141. break;
  142. c = ch;
  143. o_pri = splsoftclock();
  144. hypputc(c);
  145. splx(o_pri);
  146. }
  147. if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
  148. tt_write_wakeup(tp);
  149. }
  150. }
  151. void hypcnstop()
  152. {
  153. }
  154. io_return_t hypcngetstat(dev_t dev, int flavor, int *data, unsigned int *count)
  155. {
  156. return tty_get_status(&hypcn_tty, flavor, data, count);
  157. }
  158. io_return_t hypcnsetstat(dev_t dev, int flavor, int *data, unsigned int count)
  159. {
  160. return tty_set_status(&hypcn_tty, flavor, data, count);
  161. }
  162. int hypcnportdeath(dev_t dev, mach_port_t port)
  163. {
  164. return tty_portdeath(&hypcn_tty, (ipc_port_t) port);
  165. }
  166. int hypcnopen(dev_t dev, int flag, io_req_t ior)
  167. {
  168. struct tty *tp = &hypcn_tty;
  169. spl_t o_pri;
  170. o_pri = spltty();
  171. simple_lock(&tp->t_lock);
  172. if (!(tp->t_state & (TS_ISOPEN|TS_WOPEN))) {
  173. /* XXX ttychars allocates memory */
  174. simple_unlock(&tp->t_lock);
  175. ttychars(tp);
  176. simple_lock(&tp->t_lock);
  177. tp->t_oproc = hypcnstart;
  178. tp->t_stop = hypcnstop;
  179. tp->t_ospeed = tp->t_ispeed = B9600;
  180. tp->t_flags = ODDP|EVENP|ECHO|CRMOD|XTABS;
  181. }
  182. tp->t_state |= TS_CARR_ON;
  183. simple_unlock(&tp->t_lock);
  184. splx(o_pri);
  185. return (char_open(dev, tp, flag, ior));
  186. }
  187. void hypcnclose(dev_t dev, int flag)
  188. {
  189. struct tty *tp = &hypcn_tty;
  190. spl_t s = spltty();
  191. simple_lock(&tp->t_lock);
  192. ttyclose(tp);
  193. simple_unlock(&tp->t_lock);
  194. splx(s);
  195. }
  196. int hypcnprobe(struct consdev *cp)
  197. {
  198. cp->cn_dev = makedev(0, 0);
  199. cp->cn_pri = CN_INTERNAL;
  200. return 0;
  201. }
  202. int hypcninit(struct consdev *cp)
  203. {
  204. if (console)
  205. return 0;
  206. simple_lock_init(&outlock);
  207. simple_lock_init(&inlock);
  208. console = (void*) mfn_to_kv(boot_info.console_mfn);
  209. #ifdef MACH_PV_PAGETABLES
  210. pmap_set_page_readwrite(console);
  211. #endif /* MACH_PV_PAGETABLES */
  212. hyp_evt_handler(boot_info.console_evtchn, hypcnintr, 0, SPL6);
  213. return 0;
  214. }