|
|
1.1 ! root 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: ! 19: #include <sys/types.h> ! 20: #include <device/tty.h> ! 21: #include <device/cons.h> ! 22: #include <machine/pmap.h> ! 23: #include <machine/machspl.h> ! 24: #include <xen/public/io/console.h> ! 25: #include "console.h" ! 26: #include "ring.h" ! 27: #include "evt.h" ! 28: ! 29: /* Hypervisor part */ ! 30: ! 31: decl_simple_lock_data(static, outlock); ! 32: decl_simple_lock_data(static, inlock); ! 33: static struct xencons_interface *console; ! 34: static int kd_pollc; ! 35: int kb_mode; /* XXX: actually don't care. */ ! 36: ! 37: #undef hyp_console_write ! 38: void hyp_console_write(const char *str, int len) ! 39: { ! 40: hyp_console_io (CONSOLEIO_write, len, kvtolin(str)); ! 41: } ! 42: ! 43: int hypputc(int c) ! 44: { ! 45: if (!console) { ! 46: char d = c; ! 47: hyp_console_io(CONSOLEIO_write, 1, kvtolin(&d)); ! 48: } else { ! 49: spl_t spl = splhigh(); ! 50: int complain; ! 51: simple_lock(&outlock); ! 52: while (hyp_ring_smash(console->out, console->out_prod, console->out_cons)) { ! 53: if (!complain) { ! 54: complain = 1; ! 55: hyp_console_put("ring smash\n"); ! 56: } ! 57: /* TODO: are we allowed to sleep in putc? */ ! 58: hyp_yield(); ! 59: } ! 60: hyp_ring_cell(console->out, console->out_prod) = c; ! 61: wmb(); ! 62: console->out_prod++; ! 63: hyp_event_channel_send(boot_info.console_evtchn); ! 64: simple_unlock(&outlock); ! 65: splx(spl); ! 66: } ! 67: return 0; ! 68: } ! 69: ! 70: int hypcnputc(dev_t dev, int c) ! 71: { ! 72: return hypputc(c); ! 73: } ! 74: ! 75: /* get char by polling, used by debugger */ ! 76: int hypcngetc(dev_t dev, int wait) ! 77: { ! 78: int ret; ! 79: if (wait) ! 80: while (console->in_prod == console->in_cons) ! 81: hyp_yield(); ! 82: else ! 83: if (console->in_prod == console->in_cons) ! 84: return -1; ! 85: ret = hyp_ring_cell(console->in, console->in_cons); ! 86: mb(); ! 87: console->in_cons++; ! 88: hyp_event_channel_send(boot_info.console_evtchn); ! 89: return ret; ! 90: } ! 91: ! 92: void cnpollc(boolean_t on) { ! 93: if (on) { ! 94: kd_pollc++; ! 95: } else { ! 96: --kd_pollc; ! 97: } ! 98: } ! 99: ! 100: void kd_setleds1(u_char val) ! 101: { ! 102: /* Can't do this. */ ! 103: } ! 104: ! 105: /* Mach part */ ! 106: ! 107: struct tty hypcn_tty; ! 108: ! 109: static void hypcnintr(int unit, spl_t spl, void *ret_addr, void *regs) { ! 110: struct tty *tp = &hypcn_tty; ! 111: if (kd_pollc) ! 112: return; ! 113: simple_lock(&inlock); ! 114: while (console->in_prod != console->in_cons) { ! 115: int c = hyp_ring_cell(console->in, console->in_cons); ! 116: mb(); ! 117: console->in_cons++; ! 118: #if MACH_KDB ! 119: if (c == (char)'�') { ! 120: printf("� pressed\n"); ! 121: kdb_kintr(); ! 122: continue; ! 123: } ! 124: #endif /* MACH_KDB */ ! 125: if ((tp->t_state & (TS_ISOPEN|TS_WOPEN))) ! 126: (*linesw[tp->t_line].l_rint)(c, tp); ! 127: } ! 128: hyp_event_channel_send(boot_info.console_evtchn); ! 129: simple_unlock(&inlock); ! 130: } ! 131: ! 132: int hypcnread(int dev, io_req_t ior) ! 133: { ! 134: struct tty *tp = &hypcn_tty; ! 135: tp->t_state |= TS_CARR_ON; ! 136: return char_read(tp, ior); ! 137: } ! 138: ! 139: int hypcnwrite(int dev, io_req_t ior) ! 140: { ! 141: return char_write(&hypcn_tty, ior); ! 142: } ! 143: ! 144: void hypcnstart(struct tty *tp) ! 145: { ! 146: spl_t o_pri; ! 147: int ch; ! 148: unsigned char c; ! 149: ! 150: if (tp->t_state & TS_TTSTOP) ! 151: return; ! 152: while (1) { ! 153: tp->t_state &= ~TS_BUSY; ! 154: if (tp->t_state & TS_TTSTOP) ! 155: break; ! 156: if ((tp->t_outq.c_cc <= 0) || (ch = getc(&tp->t_outq)) == -1) ! 157: break; ! 158: c = ch; ! 159: o_pri = splsoftclock(); ! 160: hypputc(c); ! 161: splx(o_pri); ! 162: } ! 163: if (tp->t_outq.c_cc <= TTLOWAT(tp)) { ! 164: tt_write_wakeup(tp); ! 165: } ! 166: } ! 167: ! 168: void hypcnstop() ! 169: { ! 170: } ! 171: ! 172: io_return_t hypcngetstat(dev_t dev, int flavor, int *data, unsigned int *count) ! 173: { ! 174: return tty_get_status(&hypcn_tty, flavor, data, count); ! 175: } ! 176: ! 177: io_return_t hypcnsetstat(dev_t dev, int flavor, int *data, unsigned int count) ! 178: { ! 179: return tty_set_status(&hypcn_tty, flavor, data, count); ! 180: } ! 181: ! 182: int hypcnportdeath(dev_t dev, mach_port_t port) ! 183: { ! 184: return tty_portdeath(&hypcn_tty, (ipc_port_t) port); ! 185: } ! 186: ! 187: int hypcnopen(dev_t dev, int flag, io_req_t ior) ! 188: { ! 189: struct tty *tp = &hypcn_tty; ! 190: spl_t o_pri; ! 191: ! 192: o_pri = spltty(); ! 193: simple_lock(&tp->t_lock); ! 194: if (!(tp->t_state & (TS_ISOPEN|TS_WOPEN))) { ! 195: /* XXX ttychars allocates memory */ ! 196: simple_unlock(&tp->t_lock); ! 197: ttychars(tp); ! 198: simple_lock(&tp->t_lock); ! 199: tp->t_oproc = hypcnstart; ! 200: tp->t_stop = hypcnstop; ! 201: tp->t_ospeed = tp->t_ispeed = B9600; ! 202: tp->t_flags = ODDP|EVENP|ECHO|CRMOD|XTABS; ! 203: } ! 204: tp->t_state |= TS_CARR_ON; ! 205: simple_unlock(&tp->t_lock); ! 206: splx(o_pri); ! 207: return (char_open(dev, tp, flag, ior)); ! 208: } ! 209: ! 210: int hypcnclose(int dev, int flag) ! 211: { ! 212: struct tty *tp = &hypcn_tty; ! 213: spl_t s = spltty(); ! 214: simple_lock(&tp->t_lock); ! 215: ttyclose(tp); ! 216: simple_unlock(&tp->t_lock); ! 217: splx(s); ! 218: return 0; ! 219: } ! 220: ! 221: int hypcnprobe(struct consdev *cp) ! 222: { ! 223: cp->cn_dev = makedev(0, 0); ! 224: cp->cn_pri = CN_INTERNAL; ! 225: return 0; ! 226: } ! 227: ! 228: int hypcninit(struct consdev *cp) ! 229: { ! 230: if (console) ! 231: return 0; ! 232: simple_lock_init(&outlock); ! 233: simple_lock_init(&inlock); ! 234: console = (void*) mfn_to_kv(boot_info.console_mfn); ! 235: #ifdef MACH_PV_PAGETABLES ! 236: pmap_set_page_readwrite(console); ! 237: #endif /* MACH_PV_PAGETABLES */ ! 238: hyp_evt_handler(boot_info.console_evtchn, hypcnintr, 0, SPL6); ! 239: return 0; ! 240: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.