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
					
				| @ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Kees Jongenburger
						Kees Jongenburger