From: Kees Jongenburger Date: Wed, 10 Apr 2013 13:00:42 +0000 (+0200) Subject: arm:rs232 fix. X-Git-Tag: v3.3.0~1035 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zlib_tech.html?a=commitdiff_plain;h=037aeb5a13262c8d0434a82586547f993a30ed38;p=minix.git arm:rs232 fix. The kernel API for requesting interrupts and the associated callback have a somewhat strange behaviour. Requesting an interrupts is done by calling sys_irqsetpolicy using an interrupt and a given id. This id can be modified by the sys_irqsetpolicy and must be used for subsequent calls to sys_irqenable/sys_irqdisable. However upon an incoming call from the kernel NOTIFY_ARG contains the original value encoded in a set e.g. if 1 << id == true the interrupt was raised. --- diff --git a/drivers/tty/arch/earm/rs232.c b/drivers/tty/arch/earm/rs232.c index 3a3b256bd..fc3a9734c 100644 --- a/drivers/tty/arch/earm/rs232.c +++ b/drivers/tty/arch/earm/rs232.c @@ -108,6 +108,7 @@ typedef struct rs232 { int irq; /* irq for this line */ int irq_hook_id; /* interrupt hook */ + int irq_hook_kernel_id; /* id as returned from sys_irqsetpolicy */ char ibuf[RS_IBUFSIZE]; /* input buffer */ char obuf[RS_OBUFSIZE]; /* output buffer */ @@ -428,7 +429,7 @@ static void rs_config(rs232_t *rs) * avoid looping forever. */ - if (sys_irqdisable(&rs->irq_hook_id) != OK) + if (sys_irqdisable(&rs->irq_hook_kernel_id) != OK) panic("unable to disable interrupts"); /* Select the baud rate divisor registers and change the rate. */ @@ -456,7 +457,7 @@ static void rs_config(rs232_t *rs) if ((tp->tty_termios.c_lflag & IXON) && rs->oxoff != _POSIX_VDISABLE) rs->ostate &= ~ORAW; (void) serial_in(rs, OMAP3_IIR); - if (sys_irqenable(&rs->irq_hook_id) != OK) + if (sys_irqenable(&rs->irq_hook_kernel_id) != OK) panic("unable to enable interrupts"); } @@ -519,16 +520,27 @@ rs_init(tty_t *tp) /* Configure IRQ */ rs->irq = this_omap3.irq; - rs->irq_hook_id = 1 << line; /* call back with irq line number */ - if (sys_irqsetpolicy(rs->irq, 0, &rs->irq_hook_id) != OK) { + + /* callback with irq line number + 1 because using line number 0 + fails eslewhere */ + rs->irq_hook_kernel_id = rs->irq_hook_id = line + 1; + + /* sys_irqsetpolicy modifies irq_hook_kernel_id. this modified id + * needs to be used in sys_irqenable and similar calls. + */ + if (sys_irqsetpolicy(rs->irq, 0, &rs->irq_hook_kernel_id) != OK) { printf("RS232: Couldn't obtain hook for irq %d\n", rs->irq); } else { - if (sys_irqenable(&rs->irq_hook_id) != OK) { + if (sys_irqenable(&rs->irq_hook_kernel_id) != OK) { printf("RS232: Couldn't enable irq %d (hooked)\n", rs->irq); } } - rs_irq_set |= (1 << (rs->irq_hook_id + 1)); + + /* When we get called back we get called back using the original + * hook_id bit set. e.g. if we register with hook_id 5 the callback + * calls us with the 5 th bit set */ + rs_irq_set |= (1 << (rs->irq_hook_id )); /* Enable interrupts */ rs_reset(rs); @@ -559,9 +571,9 @@ rs_interrupt(message *m) irq_set = m->NOTIFY_ARG; for (line = 0, rs = rs_lines; line < NR_RS_LINES; line++, rs++) { - if (irq_set & (1 << (rs->irq_hook_id+1))) { + if (irq_set & (1 << rs->irq_hook_id)) { rs232_handler(rs); - if (sys_irqenable(&rs->irq_hook_id) != OK) + if (sys_irqenable(&rs->irq_hook_kernel_id) != OK) panic("unable to enable interrupts"); } }