1181643Skmacy#include <sys/cdefs.h>
2181643Skmacy__FBSDID("$FreeBSD: releng/10.3/sys/dev/xen/console/xencons_ring.c 255040 2013-08-29 19:52:18Z gibbs $");
3181643Skmacy
4181643Skmacy#include <sys/param.h>
5181643Skmacy#include <sys/module.h>
6181643Skmacy#include <sys/systm.h>
7181643Skmacy#include <sys/consio.h>
8181643Skmacy#include <sys/proc.h>
9181643Skmacy#include <sys/uio.h>
10181643Skmacy#include <sys/tty.h>
11181643Skmacy#include <sys/systm.h>
12181643Skmacy#include <sys/taskqueue.h>
13181643Skmacy#include <sys/conf.h>
14181643Skmacy#include <sys/kernel.h>
15181643Skmacy#include <sys/bus.h>
16189699Sdfr#include <sys/cons.h>
17189699Sdfr
18181643Skmacy#include <machine/stdarg.h>
19255040Sgibbs
20255040Sgibbs#include <xen/xen-os.h>
21186557Skmacy#include <xen/hypervisor.h>
22186557Skmacy#include <xen/xen_intr.h>
23181643Skmacy#include <sys/cons.h>
24181643Skmacy
25189699Sdfr#include <xen/xen_intr.h>
26189699Sdfr#include <xen/evtchn.h>
27189699Sdfr#include <xen/interface/io/console.h>
28181643Skmacy
29181643Skmacy#include <dev/xen/console/xencons_ring.h>
30186557Skmacy#include <xen/evtchn.h>
31181643Skmacy#include <xen/interface/io/console.h>
32181643Skmacy
33181643Skmacy#define console_evtchn	console.domU.evtchn
34255040Sgibbsxen_intr_handle_t console_handle;
35181643Skmacyextern char *console_page;
36186557Skmacyextern struct mtx              cn_mtx;
37255040Sgibbsextern device_t xencons_dev;
38186557Skmacy
39181643Skmacystatic inline struct xencons_interface *
40181643Skmacyxencons_interface(void)
41181643Skmacy{
42181643Skmacy	return (struct xencons_interface *)console_page;
43181643Skmacy}
44181643Skmacy
45181643Skmacy
46181643Skmacyint
47181643Skmacyxencons_has_input(void)
48181643Skmacy{
49181643Skmacy	struct xencons_interface *intf;
50181643Skmacy
51181643Skmacy	intf = xencons_interface();
52181643Skmacy
53181643Skmacy	return (intf->in_cons != intf->in_prod);
54181643Skmacy}
55181643Skmacy
56181643Skmacy
57181643Skmacyint
58181643Skmacyxencons_ring_send(const char *data, unsigned len)
59181643Skmacy{
60181643Skmacy	struct xencons_interface *intf;
61181643Skmacy	XENCONS_RING_IDX cons, prod;
62181643Skmacy	int sent;
63181643Skmacy
64181643Skmacy	intf = xencons_interface();
65181643Skmacy	cons = intf->out_cons;
66181643Skmacy	prod = intf->out_prod;
67181643Skmacy	sent = 0;
68181643Skmacy
69181643Skmacy	mb();
70189699Sdfr	KASSERT((prod - cons) <= sizeof(intf->out),
71189699Sdfr		("console send ring inconsistent"));
72181643Skmacy
73181643Skmacy	while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
74181643Skmacy		intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
75181643Skmacy
76181643Skmacy	wmb();
77181643Skmacy	intf->out_prod = prod;
78181643Skmacy
79255040Sgibbs	xen_intr_signal(console_handle);
80181643Skmacy
81181643Skmacy	return sent;
82181643Skmacy
83181643Skmacy}
84181643Skmacy
85181643Skmacy
86181643Skmacystatic xencons_receiver_func *xencons_receiver;
87181643Skmacy
88181643Skmacyvoid
89181643Skmacyxencons_handle_input(void *unused)
90181643Skmacy{
91181643Skmacy	struct xencons_interface *intf;
92181643Skmacy	XENCONS_RING_IDX cons, prod;
93181643Skmacy
94192003Skmacy	CN_LOCK(cn_mtx);
95181643Skmacy	intf = xencons_interface();
96181643Skmacy
97181643Skmacy	cons = intf->in_cons;
98181643Skmacy	prod = intf->in_prod;
99192004Skmacy	CN_UNLOCK(cn_mtx);
100192004Skmacy
101181643Skmacy	/* XXX needs locking */
102181643Skmacy	while (cons != prod) {
103181643Skmacy		xencons_rx(intf->in + MASK_XENCONS_IDX(cons, intf->in), 1);
104181643Skmacy		cons++;
105181643Skmacy	}
106181643Skmacy
107181643Skmacy	mb();
108181643Skmacy	intf->in_cons = cons;
109181643Skmacy
110192004Skmacy	CN_LOCK(cn_mtx);
111255040Sgibbs	xen_intr_signal(console_handle);
112181643Skmacy
113181643Skmacy	xencons_tx();
114192003Skmacy	CN_UNLOCK(cn_mtx);
115181643Skmacy}
116181643Skmacy
117181643Skmacyvoid
118181643Skmacyxencons_ring_register_receiver(xencons_receiver_func *f)
119181643Skmacy{
120181643Skmacy	xencons_receiver = f;
121181643Skmacy}
122181643Skmacy
123181643Skmacyint
124181643Skmacyxencons_ring_init(void)
125181643Skmacy{
126181643Skmacy	int err;
127181643Skmacy
128181643Skmacy	if (!xen_start_info->console_evtchn)
129181643Skmacy		return 0;
130181643Skmacy
131255040Sgibbs	err = xen_intr_bind_local_port(xencons_dev,
132255040Sgibbs	    xen_start_info->console_evtchn, NULL, xencons_handle_input, NULL,
133255040Sgibbs	    INTR_TYPE_MISC | INTR_MPSAFE, &console_handle);
134181643Skmacy	if (err) {
135181643Skmacy		return err;
136181643Skmacy	}
137181643Skmacy
138181643Skmacy	return 0;
139181643Skmacy}
140189699Sdfr
141189699Sdfrextern void xencons_suspend(void);
142189699Sdfrextern void xencons_resume(void);
143189699Sdfr
144181643Skmacyvoid
145181643Skmacyxencons_suspend(void)
146181643Skmacy{
147181643Skmacy
148181643Skmacy	if (!xen_start_info->console_evtchn)
149181643Skmacy		return;
150181643Skmacy
151255040Sgibbs	xen_intr_unbind(&console_handle);
152181643Skmacy}
153181643Skmacy
154181643Skmacyvoid
155181643Skmacyxencons_resume(void)
156181643Skmacy{
157181643Skmacy
158181643Skmacy	(void)xencons_ring_init();
159181643Skmacy}
160189699Sdfr
161181643Skmacy/*
162181643Skmacy * Local variables:
163181643Skmacy * mode: C
164181643Skmacy * c-set-style: "BSD"
165181643Skmacy * c-basic-offset: 8
166181643Skmacy * tab-width: 4
167181643Skmacy * indent-tabs-mode: t
168181643Skmacy * End:
169181643Skmacy */
170