summary refs log tree commit diff
path: root/arch/um/os-Linux/irq.c
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2006-03-29 13:24:50 +1100
committerPaul Mackerras <paulus@samba.org>2006-03-29 13:24:50 +1100
commitbac30d1a78d0f11c613968fc8b351a91ed465386 (patch)
treee52f3c876522a2f6047a6ec1c27df2e8a79486b8 /arch/um/os-Linux/irq.c
parente8222502ee6157e2713da9e0792c21f4ad458d50 (diff)
parentca9ba4471c1203bb6e759b76e83167fec54fe590 (diff)
downloadlinux-bac30d1a78d0f11c613968fc8b351a91ed465386.tar.gz
Merge ../linux-2.6
Diffstat (limited to 'arch/um/os-Linux/irq.c')
-rw-r--r--arch/um/os-Linux/irq.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
new file mode 100644
index 000000000000..e599be423da1
--- /dev/null
+++ b/arch/um/os-Linux/irq.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/poll.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include "user_util.h"
+#include "kern_util.h"
+#include "user.h"
+#include "process.h"
+#include "sigio.h"
+#include "irq_user.h"
+#include "os.h"
+
+static struct pollfd *pollfds = NULL;
+static int pollfds_num = 0;
+static int pollfds_size = 0;
+
+int os_waiting_for_events(struct irq_fd *active_fds)
+{
+	struct irq_fd *irq_fd;
+	int i, n, err;
+
+	n = poll(pollfds, pollfds_num, 0);
+	if(n < 0){
+		err = -errno;
+		if(errno != EINTR)
+			printk("sigio_handler: os_waiting_for_events:"
+			       " poll returned %d, errno = %d\n", n, errno);
+		return err;
+	}
+
+	if(n == 0)
+		return 0;
+
+	irq_fd = active_fds;
+
+	for(i = 0; i < pollfds_num; i++){
+		if(pollfds[i].revents != 0){
+			irq_fd->current_events = pollfds[i].revents;
+			pollfds[i].fd = -1;
+		}
+		irq_fd = irq_fd->next;
+	}
+	return n;
+}
+
+int os_isatty(int fd)
+{
+	return(isatty(fd));
+}
+
+int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds)
+{
+	if (pollfds_num == pollfds_size) {
+		if (size_tmpfds <= pollfds_size * sizeof(pollfds[0])) {
+			/* return min size needed for new pollfds area */
+			return((pollfds_size + 1) * sizeof(pollfds[0]));
+		}
+
+		if(pollfds != NULL){
+			memcpy(tmp_pfd, pollfds,
+			       sizeof(pollfds[0]) * pollfds_size);
+			/* remove old pollfds */
+			kfree(pollfds);
+		}
+		pollfds = tmp_pfd;
+		pollfds_size++;
+	} else {
+		/* remove not used tmp_pfd */
+		if (tmp_pfd != NULL)
+			kfree(tmp_pfd);
+	}
+
+	pollfds[pollfds_num] = ((struct pollfd) { .fd 	= fd,
+						  .events 	= events,
+						  .revents 	= 0 });
+	pollfds_num++;
+
+	return(0);
+}
+
+void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg,
+		struct irq_fd *active_fds, struct irq_fd ***last_irq_ptr2)
+{
+	struct irq_fd **prev;
+	int i = 0;
+
+	prev = &active_fds;
+	while(*prev != NULL){
+		if((*test)(*prev, arg)){
+			struct irq_fd *old_fd = *prev;
+			if((pollfds[i].fd != -1) &&
+			   (pollfds[i].fd != (*prev)->fd)){
+				printk("os_free_irq_by_cb - mismatch between "
+				       "active_fds and pollfds, fd %d vs %d\n",
+				       (*prev)->fd, pollfds[i].fd);
+				goto out;
+			}
+
+			pollfds_num--;
+
+			/* This moves the *whole* array after pollfds[i]
+			 * (though it doesn't spot as such)!
+			 */
+
+			memmove(&pollfds[i], &pollfds[i + 1],
+			       (pollfds_num - i) * sizeof(pollfds[0]));
+			if(*last_irq_ptr2 == &old_fd->next)
+				*last_irq_ptr2 = prev;
+
+			*prev = (*prev)->next;
+			if(old_fd->type == IRQ_WRITE)
+				ignore_sigio_fd(old_fd->fd);
+			kfree(old_fd);
+			continue;
+		}
+		prev = &(*prev)->next;
+		i++;
+	}
+ out:
+	return;
+}
+
+
+int os_get_pollfd(int i)
+{
+	return(pollfds[i].fd);
+}
+
+void os_set_pollfd(int i, int fd)
+{
+	pollfds[i].fd = fd;
+}
+
+void os_set_ioignore(void)
+{
+	set_handler(SIGIO, SIG_IGN, 0, -1);
+}
+
+void init_irq_signals(int on_sigstack)
+{
+	__sighandler_t h;
+	int flags;
+
+	flags = on_sigstack ? SA_ONSTACK : 0;
+	if(timer_irq_inited) h = (__sighandler_t) alarm_handler;
+	else h = boot_timer_handler;
+
+	set_handler(SIGVTALRM, h, flags | SA_RESTART,
+		    SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
+	set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART,
+		    SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
+	signal(SIGWINCH, SIG_IGN);
+}