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