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.
This commit is contained in:
parent
aa3db0e0e2
commit
037aeb5a13
1 changed files with 20 additions and 8 deletions
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue