ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c @ 7158:78e1e94e4088

xencons must notify via evtchn. It can't use the irq as the
notification handle because console is used early, before the
irq is set up.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Sep 30 17:34:01 2005 +0100 (2005-09-30)
parents 8c23b56f3954
children 4e0c94871be2 2d2414d6f938
line source
1 #include <linux/version.h>
2 #include <linux/module.h>
3 #include <linux/errno.h>
4 #include <linux/signal.h>
5 #include <linux/sched.h>
6 #include <linux/interrupt.h>
7 #include <linux/tty.h>
8 #include <linux/tty_flip.h>
9 #include <linux/serial.h>
10 #include <linux/major.h>
11 #include <linux/ptrace.h>
12 #include <linux/ioport.h>
13 #include <linux/mm.h>
14 #include <linux/slab.h>
16 #include <asm/hypervisor.h>
17 #include <asm-xen/evtchn.h>
18 #include <linux/wait.h>
19 #include <linux/interrupt.h>
20 #include <linux/sched.h>
21 #include <linux/err.h>
22 #include "xencons_ring.h"
24 struct ring_head
25 {
26 u32 cons;
27 u32 prod;
28 char buf[0];
29 } __attribute__((packed));
31 static int xencons_irq;
33 #define XENCONS_RING_SIZE (PAGE_SIZE/2 - sizeof (struct ring_head))
34 #define XENCONS_IDX(cnt) ((cnt) % XENCONS_RING_SIZE)
35 #define XENCONS_FULL(ring) (((ring)->prod - (ring)->cons) == XENCONS_RING_SIZE)
37 static inline struct ring_head *outring(void)
38 {
39 return mfn_to_virt(xen_start_info->console_mfn);
40 }
42 static inline struct ring_head *inring(void)
43 {
44 return mfn_to_virt(xen_start_info->console_mfn) + PAGE_SIZE/2;
45 }
48 /* don't block - write as much as possible and return */
49 static int __xencons_ring_send(
50 struct ring_head *ring, const char *data, unsigned len)
51 {
52 int copied = 0;
54 mb();
55 while (copied < len && !XENCONS_FULL(ring)) {
56 ring->buf[XENCONS_IDX(ring->prod)] = data[copied];
57 ring->prod++;
58 copied++;
59 }
60 mb();
62 return copied;
63 }
65 int xencons_ring_send(const char *data, unsigned len)
66 {
67 int sent = __xencons_ring_send(outring(), data, len);
68 /* Use evtchn: this is called early, before irq is set up. */
69 notify_remote_via_evtchn(xen_start_info->console_evtchn);
70 return sent;
71 }
74 static xencons_receiver_func *xencons_receiver;
76 static irqreturn_t handle_input(int irq, void *unused, struct pt_regs *regs)
77 {
78 struct ring_head *ring = inring();
79 while (ring->cons < ring->prod) {
80 if (xencons_receiver != NULL) {
81 xencons_receiver(ring->buf + XENCONS_IDX(ring->cons),
82 1, regs);
83 }
84 ring->cons++;
85 }
86 return IRQ_HANDLED;
87 }
89 void xencons_ring_register_receiver(xencons_receiver_func *f)
90 {
91 xencons_receiver = f;
92 }
94 int xencons_ring_init(void)
95 {
96 int err;
98 if (xencons_irq)
99 unbind_evtchn_from_irqhandler(xencons_irq, inring());
100 xencons_irq = 0;
102 if (!xen_start_info->console_evtchn)
103 return 0;
105 err = bind_evtchn_to_irqhandler(
106 xen_start_info->console_evtchn,
107 handle_input, 0, "xencons", inring());
108 if (err <= 0) {
109 xprintk("XEN console request irq failed %i\n", err);
110 return err;
111 }
113 xencons_irq = err;
115 return 0;
116 }
118 void xencons_resume(void)
119 {
120 (void)xencons_ring_init();
121 }
123 /*
124 * Local variables:
125 * c-file-style: "linux"
126 * indent-tabs-mode: t
127 * c-indent-level: 8
128 * c-basic-offset: 8
129 * tab-width: 8
130 * End:
131 */