diff options
Diffstat (limited to 'arch/um/drivers/xterm_kern.c')
-rw-r--r-- | arch/um/drivers/xterm_kern.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c new file mode 100644 index 000000000000..7917b9d1cec8 --- /dev/null +++ b/arch/um/drivers/xterm_kern.c | |||
@@ -0,0 +1,93 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/errno.h" | ||
7 | #include "linux/slab.h" | ||
8 | #include "linux/signal.h" | ||
9 | #include "linux/interrupt.h" | ||
10 | #include "asm/semaphore.h" | ||
11 | #include "asm/irq.h" | ||
12 | #include "irq_user.h" | ||
13 | #include "irq_kern.h" | ||
14 | #include "kern_util.h" | ||
15 | #include "os.h" | ||
16 | #include "xterm.h" | ||
17 | |||
18 | struct xterm_wait { | ||
19 | struct completion ready; | ||
20 | int fd; | ||
21 | int pid; | ||
22 | int new_fd; | ||
23 | }; | ||
24 | |||
25 | static irqreturn_t xterm_interrupt(int irq, void *data, struct pt_regs *regs) | ||
26 | { | ||
27 | struct xterm_wait *xterm = data; | ||
28 | int fd; | ||
29 | |||
30 | fd = os_rcv_fd(xterm->fd, &xterm->pid); | ||
31 | if(fd == -EAGAIN) | ||
32 | return(IRQ_NONE); | ||
33 | |||
34 | xterm->new_fd = fd; | ||
35 | complete(&xterm->ready); | ||
36 | return(IRQ_HANDLED); | ||
37 | } | ||
38 | |||
39 | int xterm_fd(int socket, int *pid_out) | ||
40 | { | ||
41 | struct xterm_wait *data; | ||
42 | int err, ret; | ||
43 | |||
44 | data = kmalloc(sizeof(*data), GFP_KERNEL); | ||
45 | if(data == NULL){ | ||
46 | printk(KERN_ERR "xterm_fd : failed to allocate xterm_wait\n"); | ||
47 | return(-ENOMEM); | ||
48 | } | ||
49 | |||
50 | /* This is a locked semaphore... */ | ||
51 | *data = ((struct xterm_wait) | ||
52 | { .fd = socket, | ||
53 | .pid = -1, | ||
54 | .new_fd = -1 }); | ||
55 | init_completion(&data->ready); | ||
56 | |||
57 | err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt, | ||
58 | SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, | ||
59 | "xterm", data); | ||
60 | if (err){ | ||
61 | printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, " | ||
62 | "err = %d\n", err); | ||
63 | ret = err; | ||
64 | goto out; | ||
65 | } | ||
66 | |||
67 | /* ... so here we wait for an xterm interrupt. | ||
68 | * | ||
69 | * XXX Note, if the xterm doesn't work for some reason (eg. DISPLAY | ||
70 | * isn't set) this will hang... */ | ||
71 | wait_for_completion(&data->ready); | ||
72 | |||
73 | free_irq_by_irq_and_dev(XTERM_IRQ, data); | ||
74 | free_irq(XTERM_IRQ, data); | ||
75 | |||
76 | ret = data->new_fd; | ||
77 | *pid_out = data->pid; | ||
78 | out: | ||
79 | kfree(data); | ||
80 | |||
81 | return(ret); | ||
82 | } | ||
83 | |||
84 | /* | ||
85 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
86 | * Emacs will notice this stuff at the end of the file and automatically | ||
87 | * adjust the settings for this buffer only. This must remain at the end | ||
88 | * of the file. | ||
89 | * --------------------------------------------------------------------------- | ||
90 | * Local variables: | ||
91 | * c-file-style: "linux" | ||
92 | * End: | ||
93 | */ | ||