From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LwGWI-000403-ME for qemu-devel@nongnu.org; Tue, 21 Apr 2009 10:00:18 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LwGWD-0003zT-Tx for qemu-devel@nongnu.org; Tue, 21 Apr 2009 10:00:18 -0400 Received: from [199.232.76.173] (port=57890 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LwGWD-0003zQ-Qr for qemu-devel@nongnu.org; Tue, 21 Apr 2009 10:00:13 -0400 Received: from li2-213.members.linode.com ([69.56.173.213]:41764 helo=mail.zilogic.com) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LwGWB-0001Vj-7n for qemu-devel@nongnu.org; Tue, 21 Apr 2009 10:00:12 -0400 Received: from [172.16.0.223] (unknown [122.174.75.87]) by mail.zilogic.com (Postfix) with ESMTP id 3C4811055F for ; Tue, 21 Apr 2009 10:00:04 -0400 (EDT) Message-ID: <49EDD4FC.9090408@bravegnu.org> Date: Tue, 21 Apr 2009 19:45:24 +0530 From: Vijay Kumar MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PATCH] Add support for parallel port interrupts List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Implement the interrupt chain for parallel ports. Receive interrupts from /dev/parportX by registering read handlers. Convert parallel port interrupts to char events (PPINT). Handle the event in the simulated parallel port and raise the interrupt to the guest. Signed-off-by: Vijay Kumar B. Index: qemu/hw/parallel.c =================================================================== --- qemu.orig/hw/parallel.c 2009-04-21 19:14:34.000000000 +0530 +++ qemu/hw/parallel.c 2009-04-21 19:19:50.000000000 +0530 @@ -86,6 +86,22 @@ qemu_irq_lower(s->irq); } +static void parallel_event(void *opaque, int event) +{ + int i; + int irqc; + ParallelState *s = opaque; + + pdebug("event %x\n", event); + + if (event == CHR_EVENT_PPINT) { + /* Generate a pulse for each interrupt received. */ + qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_CLEAR_INT, &irqc); + for (i = 0; i < irqc; i++) + qemu_irq_pulse(s->irq); + } +} + static void parallel_ioport_write_sw(void *opaque, uint32_t addr, uint32_t val) { @@ -165,6 +181,14 @@ parm &= ~PARA_CTR_DIR; } + if ((val & PARA_CTR_INTEN) != (s->control & PARA_CTR_INTEN)) { + if (val & PARA_CTR_INTEN) { + qemu_chr_add_handlers(s->chr, NULL, NULL, parallel_event, s); + } else { + qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL); + } + } + qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_CONTROL, &parm); s->control = val; break; Index: qemu/qemu-char.h =================================================================== --- qemu.orig/qemu-char.h 2009-04-21 19:14:34.000000000 +0530 +++ qemu/qemu-char.h 2009-04-21 19:14:41.000000000 +0530 @@ -11,6 +11,7 @@ #define CHR_EVENT_RESET 2 /* new connection established */ #define CHR_EVENT_MUX_IN 3 /* mux-focus was set to this terminal */ #define CHR_EVENT_MUX_OUT 4 /* mux-focus will move on */ +#define CHR_EVENT_PPINT 5 /* parallel port interrupt occured */ #define CHR_IOCTL_SERIAL_SET_PARAMS 1 @@ -37,6 +38,8 @@ #define CHR_IOCTL_SERIAL_SET_TIOCM 13 #define CHR_IOCTL_SERIAL_GET_TIOCM 14 +#define CHR_IOCTL_PP_CLEAR_INT 15 + #define CHR_TIOCM_CTS 0x020 #define CHR_TIOCM_CAR 0x040 #define CHR_TIOCM_DSR 0x100 Index: qemu/qemu-char.c =================================================================== --- qemu.orig/qemu-char.c 2009-04-21 19:14:34.000000000 +0530 +++ qemu/qemu-char.c 2009-04-21 19:17:00.000000000 +0530 @@ -1202,6 +1202,10 @@ if (ioctl(fd, PPDATADIR, (int *)arg) < 0) return -ENOTSUP; break; + case CHR_IOCTL_PP_CLEAR_INT: + if (ioctl(fd, PPCLRIRQ, (int *)arg) < 0) + return -ENOTSUP; + break; case CHR_IOCTL_PP_EPP_READ_ADDR: if (pp_hw_mode(drv, IEEE1284_MODE_EPP|IEEE1284_ADDR)) { struct ParallelIOArg *parg = arg; @@ -1244,11 +1248,34 @@ return 0; } +/* When poll()ed, /dev/parportX reports a read event when an interrupt + * occurs. We register a handler pp_int_notify() to receive interrupt + * notifications. The character event mechanism is then used for + * reporting interrupts to the hw peripherals. + */ + +static void pp_int_notify(void *opaque) +{ + CharDriverState *chr = opaque; + qemu_chr_event(chr, CHR_EVENT_PPINT); +} + +static void pp_chr_update_read_handler(CharDriverState *chr) +{ + ParallelCharDriver *s = chr->opaque; + + if (chr->chr_event == NULL) + qemu_set_fd_handler(s->fd, NULL, NULL, NULL); + else + qemu_set_fd_handler(s->fd, pp_int_notify, NULL, chr); +} + static void pp_close(CharDriverState *chr) { ParallelCharDriver *drv = chr->opaque; int fd = drv->fd; + qemu_set_fd_handler(fd, NULL, NULL, NULL); pp_hw_mode(drv, IEEE1284_MODE_COMPAT); ioctl(fd, PPRELEASE); close(fd); @@ -1278,6 +1305,7 @@ chr->chr_write = null_chr_write; chr->chr_ioctl = pp_ioctl; chr->chr_close = pp_close; + chr->chr_update_read_handler = pp_chr_update_read_handler; chr->opaque = drv; qemu_chr_reset(chr);