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