xencons_ring.c revision 181643
1#include <sys/cdefs.h>
2__FBSDID("$FreeBSD: head/sys/dev/xen/console/xencons_ring.c 181643 2008-08-12 20:01:57Z kmacy $");
3
4#include <sys/param.h>
5#include <sys/module.h>
6#include <sys/systm.h>
7#include <sys/consio.h>
8#include <sys/proc.h>
9#include <sys/uio.h>
10#include <sys/tty.h>
11#include <sys/systm.h>
12#include <sys/taskqueue.h>
13#include <sys/conf.h>
14#include <sys/kernel.h>
15#include <sys/bus.h>
16#include <machine/stdarg.h>
17#include <machine/xen/xen-os.h>
18#include <machine/xen/hypervisor.h>
19#include <machine/xen/xen_intr.h>
20#include <sys/cons.h>
21
22
23#include <dev/xen/console/xencons_ring.h>
24#include <machine/xen/evtchn.h>
25#include <xen/interface/io/console.h>
26
27
28#define console_evtchn	console.domU.evtchn
29extern char *console_page;
30
31static inline struct xencons_interface *
32xencons_interface(void)
33{
34	return (struct xencons_interface *)console_page;
35}
36
37
38int
39xencons_has_input(void)
40{
41	struct xencons_interface *intf;
42
43	intf = xencons_interface();
44
45	return (intf->in_cons != intf->in_prod);
46}
47
48
49int
50xencons_ring_send(const char *data, unsigned len)
51{
52	struct xencons_interface *intf;
53	XENCONS_RING_IDX cons, prod;
54	int sent;
55
56	intf = xencons_interface();
57	cons = intf->out_cons;
58	prod = intf->out_prod;
59	sent = 0;
60
61	mb();
62	PANIC_IF((prod - cons) > sizeof(intf->out));
63
64	while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
65		intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
66
67	wmb();
68	intf->out_prod = prod;
69
70	notify_remote_via_evtchn(xen_start_info->console_evtchn);
71
72	return sent;
73
74}
75
76
77static xencons_receiver_func *xencons_receiver;
78
79void
80xencons_handle_input(void *unused)
81{
82	struct xencons_interface *intf;
83	XENCONS_RING_IDX cons, prod;
84
85	intf = xencons_interface();
86
87	cons = intf->in_cons;
88	prod = intf->in_prod;
89
90	/* XXX needs locking */
91	while (cons != prod) {
92		xencons_rx(intf->in + MASK_XENCONS_IDX(cons, intf->in), 1);
93		cons++;
94	}
95
96	mb();
97	intf->in_cons = cons;
98
99	notify_remote_via_evtchn(xen_start_info->console_evtchn);
100
101	xencons_tx();
102}
103
104void
105xencons_ring_register_receiver(xencons_receiver_func *f)
106{
107	xencons_receiver = f;
108}
109
110int
111xencons_ring_init(void)
112{
113	int err;
114
115	if (!xen_start_info->console_evtchn)
116		return 0;
117
118	err = bind_caller_port_to_irqhandler(xen_start_info->console_evtchn,
119					"xencons", xencons_handle_input, NULL,
120					INTR_TYPE_MISC | INTR_MPSAFE, NULL);
121	if (err) {
122		XENPRINTF("XEN console request irq failed %i\n", err);
123		return err;
124	}
125
126	return 0;
127}
128#ifdef notyet
129void
130xencons_suspend(void)
131{
132
133	if (!xen_start_info->console_evtchn)
134		return;
135
136	unbind_evtchn_from_irqhandler(xen_start_info->console_evtchn, NULL);
137}
138
139void
140xencons_resume(void)
141{
142
143	(void)xencons_ring_init();
144}
145#endif
146/*
147 * Local variables:
148 * mode: C
149 * c-set-style: "BSD"
150 * c-basic-offset: 8
151 * tab-width: 4
152 * indent-tabs-mode: t
153 * End:
154 */
155