11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
263920f4717924206c3fa23d42645d4f8965de4cdJeff Dike * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Licensed under the GPL
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
663920f4717924206c3fa23d42645d4f8965de4cdJeff Dike#include <linux/slab.h>
763920f4717924206c3fa23d42645d4f8965de4cdJeff Dike#include <linux/completion.h>
863920f4717924206c3fa23d42645d4f8965de4cdJeff Dike#include <linux/irqreturn.h>
963920f4717924206c3fa23d42645d4f8965de4cdJeff Dike#include <asm/irq.h>
1037185b33240870719b6b5913a46e6a441f1ae96fAl Viro#include <irq_kern.h>
1137185b33240870719b6b5913a46e6a441f1ae96fAl Viro#include <os.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct xterm_wait {
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct completion ready;
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int fd;
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int pid;
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int new_fd;
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
207bea96fd22a8fd19f90817405b4abe032317a0e3Al Virostatic irqreturn_t xterm_interrupt(int irq, void *data)
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct xterm_wait *xterm = data;
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int fd;
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fd = os_rcv_fd(xterm->fd, &xterm->pid);
2663920f4717924206c3fa23d42645d4f8965de4cdJeff Dike	if (fd == -EAGAIN)
2763920f4717924206c3fa23d42645d4f8965de4cdJeff Dike		return IRQ_NONE;
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	xterm->new_fd = fd;
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	complete(&xterm->ready);
3163920f4717924206c3fa23d42645d4f8965de4cdJeff Dike
3263920f4717924206c3fa23d42645d4f8965de4cdJeff Dike	return IRQ_HANDLED;
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint xterm_fd(int socket, int *pid_out)
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct xterm_wait *data;
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err, ret;
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data = kmalloc(sizeof(*data), GFP_KERNEL);
4163920f4717924206c3fa23d42645d4f8965de4cdJeff Dike	if (data == NULL) {
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "xterm_fd : failed to allocate xterm_wait\n");
4363920f4717924206c3fa23d42645d4f8965de4cdJeff Dike		return -ENOMEM;
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* This is a locked semaphore... */
4763920f4717924206c3fa23d42645d4f8965de4cdJeff Dike	*data = ((struct xterm_wait) { .fd 		= socket,
4863920f4717924206c3fa23d42645d4f8965de4cdJeff Dike				       .pid 		= -1,
4963920f4717924206c3fa23d42645d4f8965de4cdJeff Dike				       .new_fd	 	= -1 });
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_completion(&data->ready);
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5263920f4717924206c3fa23d42645d4f8965de4cdJeff Dike	err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt,
53aab944606f9490f158d3b28f6c44a33c4701a5b3Theodore Ts'o			     IRQF_SHARED, "xterm", data);
5463920f4717924206c3fa23d42645d4f8965de4cdJeff Dike	if (err) {
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, "
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       "err = %d\n",  err);
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = err;
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* ... so here we wait for an xterm interrupt.
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * XXX Note, if the xterm doesn't work for some reason (eg. DISPLAY
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * isn't set) this will hang... */
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wait_for_completion(&data->ready);
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
67fa7a0449e0ea6588f64c06a045ea8728280f3457Richard Weinberger	um_free_irq(XTERM_IRQ, data);
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = data->new_fd;
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*pid_out = data->pid;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out:
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(data);
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7463920f4717924206c3fa23d42645d4f8965de4cdJeff Dike	return ret;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
76