1#include <sys/cdefs.h>
2__FBSDID("$FreeBSD: releng/10.3/sys/dev/xen/console/xencons_ring.c 255040 2013-08-29 19:52:18Z gibbs $");
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 <sys/cons.h>
17
18#include <machine/stdarg.h>
19
20#include <xen/xen-os.h>
21#include <xen/hypervisor.h>
22#include <xen/xen_intr.h>
23#include <sys/cons.h>
24
25#include <xen/xen_intr.h>
26#include <xen/evtchn.h>
27#include <xen/interface/io/console.h>
28
29#include <dev/xen/console/xencons_ring.h>
30#include <xen/evtchn.h>
31#include <xen/interface/io/console.h>
32
33#define console_evtchn	console.domU.evtchn
34xen_intr_handle_t console_handle;
35extern char *console_page;
36extern struct mtx              cn_mtx;
37extern device_t xencons_dev;
38
39static inline struct xencons_interface *
40xencons_interface(void)
41{
42	return (struct xencons_interface *)console_page;
43}
44
45
46int
47xencons_has_input(void)
48{
49	struct xencons_interface *intf;
50
51	intf = xencons_interface();
52
53	return (intf->in_cons != intf->in_prod);
54}
55
56
57int
58xencons_ring_send(const char *data, unsigned len)
59{
60	struct xencons_interface *intf;
61	XENCONS_RING_IDX cons, prod;
62	int sent;
63
64	intf = xencons_interface();
65	cons = intf->out_cons;
66	prod = intf->out_prod;
67	sent = 0;
68
69	mb();
70	KASSERT((prod - cons) <= sizeof(intf->out),
71		("console send ring inconsistent"));
72
73	while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
74		intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
75
76	wmb();
77	intf->out_prod = prod;
78
79	xen_intr_signal(console_handle);
80
81	return sent;
82
83}
84
85
86static xencons_receiver_func *xencons_receiver;
87
88void
89xencons_handle_input(void *unused)
90{
91	struct xencons_interface *intf;
92	XENCONS_RING_IDX cons, prod;
93
94	CN_LOCK(cn_mtx);
95	intf = xencons_interface();
96
97	cons = intf->in_cons;
98	prod = intf->in_prod;
99	CN_UNLOCK(cn_mtx);
100
101	/* XXX needs locking */
102	while (cons != prod) {
103		xencons_rx(intf->in + MASK_XENCONS_IDX(cons, intf->in), 1);
104		cons++;
105	}
106
107	mb();
108	intf->in_cons = cons;
109
110	CN_LOCK(cn_mtx);
111	xen_intr_signal(console_handle);
112
113	xencons_tx();
114	CN_UNLOCK(cn_mtx);
115}
116
117void
118xencons_ring_register_receiver(xencons_receiver_func *f)
119{
120	xencons_receiver = f;
121}
122
123int
124xencons_ring_init(void)
125{
126	int err;
127
128	if (!xen_start_info->console_evtchn)
129		return 0;
130
131	err = xen_intr_bind_local_port(xencons_dev,
132	    xen_start_info->console_evtchn, NULL, xencons_handle_input, NULL,
133	    INTR_TYPE_MISC | INTR_MPSAFE, &console_handle);
134	if (err) {
135		return err;
136	}
137
138	return 0;
139}
140
141extern void xencons_suspend(void);
142extern void xencons_resume(void);
143
144void
145xencons_suspend(void)
146{
147
148	if (!xen_start_info->console_evtchn)
149		return;
150
151	xen_intr_unbind(&console_handle);
152}
153
154void
155xencons_resume(void)
156{
157
158	(void)xencons_ring_init();
159}
160
161/*
162 * Local variables:
163 * mode: C
164 * c-set-style: "BSD"
165 * c-basic-offset: 8
166 * tab-width: 4
167 * indent-tabs-mode: t
168 * End:
169 */
170