|
|
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();
1.1.1.2 root 50: static int complain;
1.1 root 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:
1.1.1.3 ! root 132: int hypcnread(dev_t dev, io_req_t ior)
1.1 root 133: {
134: struct tty *tp = &hypcn_tty;
135: tp->t_state |= TS_CARR_ON;
136: return char_read(tp, ior);
137: }
138:
1.1.1.3 ! root 139: int hypcnwrite(dev_t dev, io_req_t ior)
1.1 root 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:
1.1.1.3 ! root 210: void hypcnclose(dev_t dev, int flag)
1.1 root 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: }
219:
220: int hypcnprobe(struct consdev *cp)
221: {
222: cp->cn_dev = makedev(0, 0);
223: cp->cn_pri = CN_INTERNAL;
224: return 0;
225: }
226:
227: int hypcninit(struct consdev *cp)
228: {
229: if (console)
230: return 0;
231: simple_lock_init(&outlock);
232: simple_lock_init(&inlock);
233: console = (void*) mfn_to_kv(boot_info.console_mfn);
234: #ifdef MACH_PV_PAGETABLES
235: pmap_set_page_readwrite(console);
236: #endif /* MACH_PV_PAGETABLES */
237: hyp_evt_handler(boot_info.console_evtchn, hypcnintr, 0, SPL6);
238: return 0;
239: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.