10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 58561SScott.Carter@Sun.COM * Common Development and Distribution License (the "License"). 68561SScott.Carter@Sun.COM * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 228561SScott.Carter@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #ifndef _SYS_DDI_INTR_H 270Sstevel@tonic-gate #define _SYS_DDI_INTR_H 280Sstevel@tonic-gate 290Sstevel@tonic-gate /* 300Sstevel@tonic-gate * Sun DDI interrupt support definitions 310Sstevel@tonic-gate */ 320Sstevel@tonic-gate 330Sstevel@tonic-gate #include <sys/ddipropdefs.h> 340Sstevel@tonic-gate #include <sys/rwlock.h> 35*10053SEvan.Yan@Sun.COM #include <sys/processor.h> 360Sstevel@tonic-gate 370Sstevel@tonic-gate #ifdef __cplusplus 380Sstevel@tonic-gate extern "C" { 390Sstevel@tonic-gate #endif 400Sstevel@tonic-gate 410Sstevel@tonic-gate #ifdef _KERNEL 420Sstevel@tonic-gate 430Sstevel@tonic-gate /* 440Sstevel@tonic-gate * Interrupt related definitions. 450Sstevel@tonic-gate */ 460Sstevel@tonic-gate 470Sstevel@tonic-gate /* 480Sstevel@tonic-gate * Returned by ddi_add_intr or ddi_add_fastintr in order to signal 490Sstevel@tonic-gate * the the caller requested interrupt number to be added does not 500Sstevel@tonic-gate * exist. 510Sstevel@tonic-gate */ 520Sstevel@tonic-gate #define DDI_INTR_NOTFOUND 1 /* interrupt not found error */ 530Sstevel@tonic-gate 540Sstevel@tonic-gate /* 550Sstevel@tonic-gate * For use by driver interrupt service routines to return to the 560Sstevel@tonic-gate * system whether an interrupt was for the driver or not. 570Sstevel@tonic-gate */ 580Sstevel@tonic-gate #define DDI_INTR_CLAIMED 1 /* returned when driver claims intr */ 590Sstevel@tonic-gate #define DDI_INTR_UNCLAIMED 0 /* returned when driver does not */ 600Sstevel@tonic-gate 610Sstevel@tonic-gate /* Hardware interrupt types */ 620Sstevel@tonic-gate #define DDI_INTR_TYPE_FIXED 0x1 630Sstevel@tonic-gate #define DDI_INTR_TYPE_MSI 0x2 640Sstevel@tonic-gate #define DDI_INTR_TYPE_MSIX 0x4 650Sstevel@tonic-gate 660Sstevel@tonic-gate /* Hardware interrupt priority must be a number within these min/max values */ 670Sstevel@tonic-gate #define DDI_INTR_PRI_MIN 1 680Sstevel@tonic-gate #define DDI_INTR_PRI_MAX 12 690Sstevel@tonic-gate 700Sstevel@tonic-gate /* Soft priority must be a number within these min/max values */ 710Sstevel@tonic-gate #define DDI_INTR_SOFTPRI_MIN 1 720Sstevel@tonic-gate #define DDI_INTR_SOFTPRI_MAX 9 730Sstevel@tonic-gate 740Sstevel@tonic-gate /* Used in calls to allocate soft interrupt priority. */ 750Sstevel@tonic-gate #define DDI_INTR_SOFTPRI_DEFAULT DDI_INTR_SOFTPRI_MIN 760Sstevel@tonic-gate 770Sstevel@tonic-gate /* 780Sstevel@tonic-gate * Interrupt flags specify certain capabilities for a given 790Sstevel@tonic-gate * interrupt (by type and inum). 800Sstevel@tonic-gate * RO/RW refer to use by ddi_intr_set_cap(9f) 810Sstevel@tonic-gate * 820Sstevel@tonic-gate * DDI_INTR_FLAG_MSI64 is an internal flag not exposed to leaf drivers. 830Sstevel@tonic-gate */ 840Sstevel@tonic-gate #define DDI_INTR_FLAG_LEVEL 0x0001 /* (RW) level trigger */ 850Sstevel@tonic-gate #define DDI_INTR_FLAG_EDGE 0x0002 /* (RW) edge triggered */ 860Sstevel@tonic-gate #define DDI_INTR_FLAG_MASKABLE 0x0010 /* (RO) maskable */ 870Sstevel@tonic-gate #define DDI_INTR_FLAG_PENDING 0x0020 /* (RO) int pending supported */ 880Sstevel@tonic-gate #define DDI_INTR_FLAG_BLOCK 0x0100 /* (RO) requires block enable */ 89*10053SEvan.Yan@Sun.COM #define DDI_INTR_FLAG_MSI64 0x0200 /* (RO) MSI/X supports 64 bit addr */ 90*10053SEvan.Yan@Sun.COM #define DDI_INTR_FLAG_RETARGETABLE 0x0400 /* (RO) retargetable */ 910Sstevel@tonic-gate 920Sstevel@tonic-gate /* 93693Sgovinda * Macro to be used while passing interrupt priority 94693Sgovinda * for lock initialization. 95693Sgovinda */ 96693Sgovinda #define DDI_INTR_PRI(pri) (void *)((uintptr_t)(pri)) 97693Sgovinda 98693Sgovinda /* 990Sstevel@tonic-gate * Typedef for interrupt handles 1000Sstevel@tonic-gate */ 1010Sstevel@tonic-gate typedef struct __ddi_intr_handle *ddi_intr_handle_t; 1020Sstevel@tonic-gate typedef struct __ddi_softint_handle *ddi_softint_handle_t; 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate /* 105*10053SEvan.Yan@Sun.COM * Typedef for interrupt target 106*10053SEvan.Yan@Sun.COM */ 107*10053SEvan.Yan@Sun.COM typedef processorid_t ddi_intr_target_t; 108*10053SEvan.Yan@Sun.COM 109*10053SEvan.Yan@Sun.COM /* 1100Sstevel@tonic-gate * Definition for behavior flag which is used with ddi_intr_alloc(9f). 1110Sstevel@tonic-gate */ 1120Sstevel@tonic-gate #define DDI_INTR_ALLOC_NORMAL 0 /* Non-strict alloc */ 1130Sstevel@tonic-gate #define DDI_INTR_ALLOC_STRICT 1 /* Strict allocation */ 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate /* 1160Sstevel@tonic-gate * Typedef for driver's interrupt handler 1170Sstevel@tonic-gate */ 1180Sstevel@tonic-gate typedef uint_t (ddi_intr_handler_t)(caddr_t arg1, caddr_t arg2); 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate #endif /* _KERNEL */ 1210Sstevel@tonic-gate #include <sys/ddi_intr_impl.h> 1220Sstevel@tonic-gate #ifdef _KERNEL 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate /* 1250Sstevel@tonic-gate * DDI interrupt function prototypes. 1260Sstevel@tonic-gate * 1270Sstevel@tonic-gate * New DDI interrupt interfaces. 1280Sstevel@tonic-gate */ 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate /* 1310Sstevel@tonic-gate * ddi_intr_get_supported_types: 1320Sstevel@tonic-gate * 1330Sstevel@tonic-gate * Return, as a bit mask, the hardware interrupt types supported by 1340Sstevel@tonic-gate * both the device and by the host in the integer pointed 1350Sstevel@tonic-gate * to be the 'typesp' argument. 1360Sstevel@tonic-gate */ 1370Sstevel@tonic-gate int ddi_intr_get_supported_types(dev_info_t *dip, int *typesp); 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate /* 1400Sstevel@tonic-gate * ddi_intr_get_nintrs: 1410Sstevel@tonic-gate * 1420Sstevel@tonic-gate * Return as an integer in the integer pointed to by the argument 1430Sstevel@tonic-gate * *nintrsp*, the number of interrupts the device supports for the 1440Sstevel@tonic-gate * given interrupt type. 1450Sstevel@tonic-gate */ 1460Sstevel@tonic-gate int ddi_intr_get_nintrs(dev_info_t *dip, int type, int *nintrsp); 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate /* 1490Sstevel@tonic-gate * ddi_intr_get_navail: 1500Sstevel@tonic-gate * 1510Sstevel@tonic-gate * Return as an integer in the integer pointed to by the argument 1520Sstevel@tonic-gate * *navailp*, the number of interrupts currently available for the 1530Sstevel@tonic-gate * given interrupt type. 1540Sstevel@tonic-gate */ 1550Sstevel@tonic-gate int ddi_intr_get_navail(dev_info_t *dip, int type, int *navailp); 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate /* 1580Sstevel@tonic-gate * Interrupt resource allocate/free functions 1590Sstevel@tonic-gate */ 1600Sstevel@tonic-gate int ddi_intr_alloc(dev_info_t *dip, ddi_intr_handle_t *h_array, 1610Sstevel@tonic-gate int type, int inum, int count, int *actualp, int behavior); 1620Sstevel@tonic-gate int ddi_intr_free(ddi_intr_handle_t h); 1630Sstevel@tonic-gate 1640Sstevel@tonic-gate /* 1650Sstevel@tonic-gate * Interrupt get/set capacity functions 1660Sstevel@tonic-gate */ 1670Sstevel@tonic-gate int ddi_intr_get_cap(ddi_intr_handle_t h, int *flagsp); 1680Sstevel@tonic-gate int ddi_intr_set_cap(ddi_intr_handle_t h, int flags); 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate /* 1710Sstevel@tonic-gate * Interrupt priority management functions 1720Sstevel@tonic-gate */ 1730Sstevel@tonic-gate uint_t ddi_intr_get_hilevel_pri(void); 1740Sstevel@tonic-gate int ddi_intr_get_pri(ddi_intr_handle_t h, uint_t *prip); 1750Sstevel@tonic-gate int ddi_intr_set_pri(ddi_intr_handle_t h, uint_t pri); 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate /* 1780Sstevel@tonic-gate * Interrupt add/duplicate/remove functions 1790Sstevel@tonic-gate */ 1800Sstevel@tonic-gate int ddi_intr_add_handler(ddi_intr_handle_t h, 1810Sstevel@tonic-gate ddi_intr_handler_t inthandler, void *arg1, void *arg2); 1820Sstevel@tonic-gate int ddi_intr_dup_handler(ddi_intr_handle_t org, int vector, 1830Sstevel@tonic-gate ddi_intr_handle_t *dup); 1840Sstevel@tonic-gate int ddi_intr_remove_handler(ddi_intr_handle_t h); 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate /* 187*10053SEvan.Yan@Sun.COM * Interrupt get/set affinity functions 188*10053SEvan.Yan@Sun.COM */ 189*10053SEvan.Yan@Sun.COM int ddi_intr_get_affinity(ddi_intr_handle_t h, ddi_intr_target_t *tgt_p); 190*10053SEvan.Yan@Sun.COM int ddi_intr_set_affinity(ddi_intr_handle_t h, ddi_intr_target_t tgt); 191*10053SEvan.Yan@Sun.COM 192*10053SEvan.Yan@Sun.COM /* 1930Sstevel@tonic-gate * Interrupt enable/disable/block_enable/block_disable functions 1940Sstevel@tonic-gate */ 1950Sstevel@tonic-gate int ddi_intr_enable(ddi_intr_handle_t h); 1960Sstevel@tonic-gate int ddi_intr_disable(ddi_intr_handle_t h); 1970Sstevel@tonic-gate int ddi_intr_block_enable(ddi_intr_handle_t *h_array, int count); 1980Sstevel@tonic-gate int ddi_intr_block_disable(ddi_intr_handle_t *h_array, int count); 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate /* 2010Sstevel@tonic-gate * Interrupt set/clr mask functions 2020Sstevel@tonic-gate */ 2030Sstevel@tonic-gate int ddi_intr_set_mask(ddi_intr_handle_t h); 2040Sstevel@tonic-gate int ddi_intr_clr_mask(ddi_intr_handle_t h); 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate /* 2070Sstevel@tonic-gate * Interrupt get pending function 2080Sstevel@tonic-gate */ 2090Sstevel@tonic-gate int ddi_intr_get_pending(ddi_intr_handle_t h, int *pendingp); 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate /* 212*10053SEvan.Yan@Sun.COM * Interrupt resource management function 213*10053SEvan.Yan@Sun.COM */ 214*10053SEvan.Yan@Sun.COM int ddi_intr_set_nreq(dev_info_t *dip, int nreq); 215*10053SEvan.Yan@Sun.COM 216*10053SEvan.Yan@Sun.COM /* 2170Sstevel@tonic-gate * Soft interrupt functions 2180Sstevel@tonic-gate */ 2190Sstevel@tonic-gate int ddi_intr_add_softint(dev_info_t *dip, ddi_softint_handle_t *h, 2200Sstevel@tonic-gate int soft_pri, ddi_intr_handler_t handler, void *arg1); 2210Sstevel@tonic-gate int ddi_intr_remove_softint(ddi_softint_handle_t h); 2220Sstevel@tonic-gate int ddi_intr_trigger_softint(ddi_softint_handle_t h, void *arg2); 2230Sstevel@tonic-gate int ddi_intr_get_softint_pri(ddi_softint_handle_t h, uint_t *soft_prip); 2240Sstevel@tonic-gate int ddi_intr_set_softint_pri(ddi_softint_handle_t h, uint_t soft_pri); 2250Sstevel@tonic-gate 2268561SScott.Carter@Sun.COM /* 2270Sstevel@tonic-gate * Old DDI interrupt interfaces. 228693Sgovinda * 229693Sgovinda * The following DDI interrupt interfaces are obsolete. 230693Sgovinda * Use the above new DDI interrupt interfaces instead. 2310Sstevel@tonic-gate */ 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate /* 2340Sstevel@tonic-gate * Return non-zero if the specified interrupt exists and the handler 2350Sstevel@tonic-gate * will be restricted to using only certain functions because the 2360Sstevel@tonic-gate * interrupt level is not blocked by the scheduler. I.e., it cannot 2370Sstevel@tonic-gate * signal other threads. 2380Sstevel@tonic-gate */ 2390Sstevel@tonic-gate int ddi_intr_hilevel(dev_info_t *dip, uint_t inumber); 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate int ddi_get_iblock_cookie(dev_info_t *dip, uint_t inumber, 2420Sstevel@tonic-gate ddi_iblock_cookie_t *iblock_cookiep); 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate /* 2450Sstevel@tonic-gate * ddi_dev_nintrs 2460Sstevel@tonic-gate * 2470Sstevel@tonic-gate * If the device has h/w interrupt(s), report 2480Sstevel@tonic-gate * how many of them that there are into resultp. 2490Sstevel@tonic-gate * Return DDI_FAILURE if the device has no interrupts. 2500Sstevel@tonic-gate */ 2510Sstevel@tonic-gate int ddi_dev_nintrs(dev_info_t *dev, int *resultp); 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate /* 2540Sstevel@tonic-gate * ddi_add_intr: Add an interrupt to the system. 2550Sstevel@tonic-gate * 2560Sstevel@tonic-gate * The interrupt number "inumber" determines which interrupt will 2570Sstevel@tonic-gate * be added. The interrupt number is associated with interrupt 2580Sstevel@tonic-gate * information provided from self identifying devices or configuration 2590Sstevel@tonic-gate * information for non-self identifying devices. If only one interrupt 2600Sstevel@tonic-gate * is associated with the device then the interrupt number should be 0. 2610Sstevel@tonic-gate * 2620Sstevel@tonic-gate * If successful, "*iblock_cookiep" will contain information necessary 2630Sstevel@tonic-gate * for initializing locks (mutex_init, cv_init, etc.) as well as for 2640Sstevel@tonic-gate * possible later removal of the interrupt from the system. 2650Sstevel@tonic-gate * 2660Sstevel@tonic-gate * If successful, "*idevice_cookiep" will contain the correct programmable 2670Sstevel@tonic-gate * device interrupt value (see <sys/dditypes.h> in the form of the 2680Sstevel@tonic-gate * type ddi_idevice_cookie_t). 2690Sstevel@tonic-gate * 2700Sstevel@tonic-gate * Either cookie pointer may be specified as a NULL pointer 2710Sstevel@tonic-gate * in which case no value will be returned. 2720Sstevel@tonic-gate * 2730Sstevel@tonic-gate * The interrupt handler "int_handler" is the address of the routine 2740Sstevel@tonic-gate * to be called upon receipt of an appropriate interrupt. The 2750Sstevel@tonic-gate * interrupt handler should return DDI_INTR_CLAIMED if the 2760Sstevel@tonic-gate * interrupt was claimed, else DDI_INTR_UNCLAIMED. The argument 2770Sstevel@tonic-gate * "int_handler_arg" will be passed to the "int_handler" 2780Sstevel@tonic-gate * upon receipt of an appropriate interrupt. 2790Sstevel@tonic-gate * 2800Sstevel@tonic-gate * If successful ddi_add_intr will return DDI_SUCCESS. 2810Sstevel@tonic-gate * If the interrupt information cannot be found it will 2820Sstevel@tonic-gate * return DDI_INTR_NOTFOUND. 2830Sstevel@tonic-gate * 2840Sstevel@tonic-gate */ 2850Sstevel@tonic-gate int ddi_add_intr(dev_info_t *dip, uint_t inumber, 2860Sstevel@tonic-gate ddi_iblock_cookie_t *iblock_cookiep, 2870Sstevel@tonic-gate ddi_idevice_cookie_t *idevice_cookiep, 2880Sstevel@tonic-gate uint_t (*int_handler)(caddr_t int_handler_arg), 2890Sstevel@tonic-gate caddr_t int_handler_arg); 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate /* 2920Sstevel@tonic-gate * The following function is for Sun's internal use only at present 2930Sstevel@tonic-gate */ 2940Sstevel@tonic-gate int ddi_add_fastintr(dev_info_t *dip, uint_t inumber, 2950Sstevel@tonic-gate ddi_iblock_cookie_t *iblock_cookiep, 2960Sstevel@tonic-gate ddi_idevice_cookie_t *idevice_cookiep, 2970Sstevel@tonic-gate uint_t (*hi_int_handler)(void)); 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate /* 3000Sstevel@tonic-gate * ddi_remove_intr: Remove interrupt set up by ddi_add_intr. 3010Sstevel@tonic-gate * 3020Sstevel@tonic-gate * This routine is intended to be used by drivers that are 3030Sstevel@tonic-gate * preparing to unload themselves "detach" from the system. 3040Sstevel@tonic-gate */ 3050Sstevel@tonic-gate void ddi_remove_intr(dev_info_t *dip, uint_t inum, 3060Sstevel@tonic-gate ddi_iblock_cookie_t iblock_cookie); 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate /* 3090Sstevel@tonic-gate * For use by ddi_add_softintr in order to specify a priority preference. 3100Sstevel@tonic-gate */ 3110Sstevel@tonic-gate #define DDI_SOFTINT_FIXED 0 /* Fixed priority soft interrupt */ 3120Sstevel@tonic-gate #define DDI_SOFTINT_LOW 8 /* Low priority soft interrupt */ 3130Sstevel@tonic-gate #define DDI_SOFTINT_MED 128 /* Medium priority soft interrupt */ 3140Sstevel@tonic-gate #define DDI_SOFTINT_HIGH 256 /* High priority soft interrupt */ 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate int ddi_get_soft_iblock_cookie(dev_info_t *dip, int preference, 3180Sstevel@tonic-gate ddi_iblock_cookie_t *iblock_cookiep); 3190Sstevel@tonic-gate 3200Sstevel@tonic-gate /* 3210Sstevel@tonic-gate * ddi_add_softintr: Add a "soft" interrupt to the system. 3220Sstevel@tonic-gate * 3230Sstevel@tonic-gate * Like ddi_add_intr, only for system interrupts that you can trigger 3240Sstevel@tonic-gate * yourself. You specify a preference (see above) for the level you 3250Sstevel@tonic-gate * want. You get an identifier back which you can use to either trigger 3260Sstevel@tonic-gate * a soft interrupt or, later, remove it. 3270Sstevel@tonic-gate */ 3280Sstevel@tonic-gate int ddi_add_softintr(dev_info_t *dip, int preference, ddi_softintr_t *idp, 3290Sstevel@tonic-gate ddi_iblock_cookie_t *iblock_cookiep, 3300Sstevel@tonic-gate ddi_idevice_cookie_t *idevice_cookiep, 3310Sstevel@tonic-gate uint_t (*int_handler)(caddr_t int_handler_arg), 3320Sstevel@tonic-gate caddr_t int_handler_arg); 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate void ddi_remove_softintr(ddi_softintr_t id); 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate void ddi_trigger_softintr(ddi_softintr_t id); 3370Sstevel@tonic-gate 3380Sstevel@tonic-gate #endif /* _KERNEL */ 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate #ifdef __cplusplus 3410Sstevel@tonic-gate } 3420Sstevel@tonic-gate #endif 3430Sstevel@tonic-gate 3440Sstevel@tonic-gate #endif /* _SYS_DDI_INTR_H */ 345