Writing Device Drivers

Interrupt Handling

These interfaces manage device interrupts and software interrupts. The basic model is to register with the system an interrupt-handling function to be called when a device interrupts or a software interrupt is triggered.

int ddi_get_iblock_cookie(dev_info_t *dip, u_int inumber, ddi_iblock_cooki
e_t *iblock_cookiep);

ddi_get_iblock_cookie retrieves the interrupt block cookie associated with a particular interrupt specification. This routine should be called before ddi_add_intr to retrieve the interrupt block cookie needed to initialize lock (mutex(9F), rwlock(9F)) used by the interrupt routine. The interrupt number inumber determines which interrupt specification to retrieve the cookie for. inumber is associated with information provided either by the device (see sbus(4)) or the hardware configuration file (see vme(4), sysbus(4), isa(4), eisa(4), mca(4), and driver.conf(4)). If only one interrupt is associated with the device, inumber should be 0.

On a successful return, *iblock_cookiep contains information needed for initializing locks associated with the interrupt specification corresponding to inumber (see mutex_init(9F) and rw_init(9F)). The driver can then initialize locks acquired by the interrupt routine before calling ddi_add_intr which prevents a possible race condition where the driver's interrupt handler is called immediately after the driver has called ddi_add_intr but before the driver has initialized the locks. This may happen when an interrupt for a different device occurs on the same interrupt level. If the interrupt routine acquires the lock before the lock has been initialized, undefined behavior may result.

int ddi_add_intr(dev_info_t *dip, u_int inumber,  	
			ddi_iblock_cookie_t *iblock_cookiep, ddi_idevice_cookie_t *idevice_cookiep,  
				u_int (*int_handler)(caddr_t), caddr_t int_handler_arg);

ddi_add_intr(9F) tells the system to call the function pointed to by int_handler when the device specified by dip issues the interrupt identified by inumber. ddi_add_intr(9F) passes back an interrupt block cookie in the location pointed to by iblock_cookiep, and an interrupt device cookie in the location pointed to by idevice_cookiep. The interrupt block cookie is used to initialize mutual exclusion locks (mutexes) and other synchronization variables. The device interrupt cookie is used to program the level at which the device interrupts, for those devices that support such programming.

void ddi_remove_intr(dev_info_t *dip, u_int inumber,  	
			ddi_iblock_cookie_t iblock_cookie);

ddi_remove_intr(9F) tells the system to stop calling the interrupt handler registered for the interrupt inumber on the device identified by dip. iblock_cookie is the interrupt block cookie that was returned by ddi_add_intr(9F) when the interrupt handler was set up. Device interrupts must be disabled before calling ddi_remove_intr(9F), and always call ddi_remove_intr(9F) in the detach(9E) entry point before returning successfully (if any interrupts handlers were added).

int ddi_add_softintr(dev_info_t *dip, int preference,  	
			ddi_softintr_t *idp, ddi_iblock_cookie_t *ibcp,  	
			ddi_idevice_cookie_t *idcp, u_int (*int_handler)(caddr_t),  	
			caddr_t int_handler_arg);

ddi_add_softintr(9F) tells the system to call the function pointed to by int_handler when a certain software interrupt is triggered. ddi_add_softintr(9F) returns a software interrupt ID in the location pointed to by idp. This ID is later used by ddi_trigger_softintr(9F) to trigger the software interrupt.

void ddi_trigger_softintr(ddi_softintr_t id);

ddi_trigger_softintr(9F) triggers the software interrupt identified by id. The interrupt handling function that was set up for this software interrupt by ddi_add_softintr(9F) is then called.

void ddi_remove_softintr(ddi_softintr_t id);

ddi_remove_softintr(9F) tells the system to stop calling the software-interrupt handler for the software interrupt identified by id. If the driver has soft interrupts registered, it must call ddi_remove_softintr(9F) in the detach(9E) entry point before returning successfully.

int ddi_dev_nintrs(dev_info_t *dip, int *result);

ddi_dev_nintrs(9F) passes back in the location pointed to by result the number of different interrupt specifications that the device indicated by dip can generate. This is useful when dealing with a device that can interrupt at more than one level.

int ddi_intr_hilevel(dev_info_t *dip, u_int inumber);

ddi_intr_hilevel(9F) returns nonzero if the system considers the interrupt specified by inumber on the device identified by dip to be high level. Otherwise, it returns zero.