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 /* 22*12564SGongtian.Zhao@Sun.COM * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 230Sstevel@tonic-gate */ 240Sstevel@tonic-gate 250Sstevel@tonic-gate #ifndef _SYS_DDI_INTR_H 260Sstevel@tonic-gate #define _SYS_DDI_INTR_H 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * Sun DDI interrupt support definitions 300Sstevel@tonic-gate */ 310Sstevel@tonic-gate 320Sstevel@tonic-gate #include <sys/ddipropdefs.h> 330Sstevel@tonic-gate #include <sys/rwlock.h> 3410053SEvan.Yan@Sun.COM #include <sys/processor.h> 350Sstevel@tonic-gate 360Sstevel@tonic-gate #ifdef __cplusplus 370Sstevel@tonic-gate extern "C" { 380Sstevel@tonic-gate #endif 390Sstevel@tonic-gate 400Sstevel@tonic-gate #ifdef _KERNEL 410Sstevel@tonic-gate 420Sstevel@tonic-gate /* 430Sstevel@tonic-gate * Interrupt related definitions. 440Sstevel@tonic-gate */ 450Sstevel@tonic-gate 460Sstevel@tonic-gate /* 470Sstevel@tonic-gate * Returned by ddi_add_intr or ddi_add_fastintr in order to signal 480Sstevel@tonic-gate * the the caller requested interrupt number to be added does not 490Sstevel@tonic-gate * exist. 500Sstevel@tonic-gate */ 510Sstevel@tonic-gate #define DDI_INTR_NOTFOUND 1 /* interrupt not found error */ 520Sstevel@tonic-gate 530Sstevel@tonic-gate /* 540Sstevel@tonic-gate * For use by driver interrupt service routines to return to the 550Sstevel@tonic-gate * system whether an interrupt was for the driver or not. 560Sstevel@tonic-gate */ 570Sstevel@tonic-gate #define DDI_INTR_CLAIMED 1 /* returned when driver claims intr */ 580Sstevel@tonic-gate #define DDI_INTR_UNCLAIMED 0 /* returned when driver does not */ 590Sstevel@tonic-gate 600Sstevel@tonic-gate /* Hardware interrupt types */ 610Sstevel@tonic-gate #define DDI_INTR_TYPE_FIXED 0x1 620Sstevel@tonic-gate #define DDI_INTR_TYPE_MSI 0x2 630Sstevel@tonic-gate #define DDI_INTR_TYPE_MSIX 0x4 640Sstevel@tonic-gate 650Sstevel@tonic-gate /* Hardware interrupt priority must be a number within these min/max values */ 660Sstevel@tonic-gate #define DDI_INTR_PRI_MIN 1 670Sstevel@tonic-gate #define DDI_INTR_PRI_MAX 12 680Sstevel@tonic-gate 690Sstevel@tonic-gate /* Soft priority must be a number within these min/max values */ 700Sstevel@tonic-gate #define DDI_INTR_SOFTPRI_MIN 1 710Sstevel@tonic-gate #define DDI_INTR_SOFTPRI_MAX 9 720Sstevel@tonic-gate 730Sstevel@tonic-gate /* Used in calls to allocate soft interrupt priority. */ 740Sstevel@tonic-gate #define DDI_INTR_SOFTPRI_DEFAULT DDI_INTR_SOFTPRI_MIN 750Sstevel@tonic-gate 760Sstevel@tonic-gate /* 770Sstevel@tonic-gate * Interrupt flags specify certain capabilities for a given 780Sstevel@tonic-gate * interrupt (by type and inum). 790Sstevel@tonic-gate * RO/RW refer to use by ddi_intr_set_cap(9f) 800Sstevel@tonic-gate * 810Sstevel@tonic-gate * DDI_INTR_FLAG_MSI64 is an internal flag not exposed to leaf drivers. 820Sstevel@tonic-gate */ 830Sstevel@tonic-gate #define DDI_INTR_FLAG_LEVEL 0x0001 /* (RW) level trigger */ 840Sstevel@tonic-gate #define DDI_INTR_FLAG_EDGE 0x0002 /* (RW) edge triggered */ 850Sstevel@tonic-gate #define DDI_INTR_FLAG_MASKABLE 0x0010 /* (RO) maskable */ 860Sstevel@tonic-gate #define DDI_INTR_FLAG_PENDING 0x0020 /* (RO) int pending supported */ 870Sstevel@tonic-gate #define DDI_INTR_FLAG_BLOCK 0x0100 /* (RO) requires block enable */ 8810053SEvan.Yan@Sun.COM #define DDI_INTR_FLAG_MSI64 0x0200 /* (RO) MSI/X supports 64 bit addr */ 890Sstevel@tonic-gate 900Sstevel@tonic-gate /* 91693Sgovinda * Macro to be used while passing interrupt priority 92693Sgovinda * for lock initialization. 93693Sgovinda */ 94693Sgovinda #define DDI_INTR_PRI(pri) (void *)((uintptr_t)(pri)) 95693Sgovinda 96693Sgovinda /* 970Sstevel@tonic-gate * Typedef for interrupt handles 980Sstevel@tonic-gate */ 990Sstevel@tonic-gate typedef struct __ddi_intr_handle *ddi_intr_handle_t; 1000Sstevel@tonic-gate typedef struct __ddi_softint_handle *ddi_softint_handle_t; 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate /* 1030Sstevel@tonic-gate * Definition for behavior flag which is used with ddi_intr_alloc(9f). 1040Sstevel@tonic-gate */ 1050Sstevel@tonic-gate #define DDI_INTR_ALLOC_NORMAL 0 /* Non-strict alloc */ 1060Sstevel@tonic-gate #define DDI_INTR_ALLOC_STRICT 1 /* Strict allocation */ 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate /* 1090Sstevel@tonic-gate * Typedef for driver's interrupt handler 1100Sstevel@tonic-gate */ 1110Sstevel@tonic-gate typedef uint_t (ddi_intr_handler_t)(caddr_t arg1, caddr_t arg2); 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate #endif /* _KERNEL */ 1140Sstevel@tonic-gate #include <sys/ddi_intr_impl.h> 1150Sstevel@tonic-gate #ifdef _KERNEL 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate /* 1180Sstevel@tonic-gate * DDI interrupt function prototypes. 1190Sstevel@tonic-gate * 1200Sstevel@tonic-gate * New DDI interrupt interfaces. 1210Sstevel@tonic-gate */ 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate /* 1240Sstevel@tonic-gate * ddi_intr_get_supported_types: 1250Sstevel@tonic-gate * 1260Sstevel@tonic-gate * Return, as a bit mask, the hardware interrupt types supported by 1270Sstevel@tonic-gate * both the device and by the host in the integer pointed 1280Sstevel@tonic-gate * to be the 'typesp' argument. 1290Sstevel@tonic-gate */ 1300Sstevel@tonic-gate int ddi_intr_get_supported_types(dev_info_t *dip, int *typesp); 1310Sstevel@tonic-gate 1320Sstevel@tonic-gate /* 1330Sstevel@tonic-gate * ddi_intr_get_nintrs: 1340Sstevel@tonic-gate * 1350Sstevel@tonic-gate * Return as an integer in the integer pointed to by the argument 1360Sstevel@tonic-gate * *nintrsp*, the number of interrupts the device supports for the 1370Sstevel@tonic-gate * given interrupt type. 1380Sstevel@tonic-gate */ 1390Sstevel@tonic-gate int ddi_intr_get_nintrs(dev_info_t *dip, int type, int *nintrsp); 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate /* 1420Sstevel@tonic-gate * ddi_intr_get_navail: 1430Sstevel@tonic-gate * 1440Sstevel@tonic-gate * Return as an integer in the integer pointed to by the argument 1450Sstevel@tonic-gate * *navailp*, the number of interrupts currently available for the 1460Sstevel@tonic-gate * given interrupt type. 1470Sstevel@tonic-gate */ 1480Sstevel@tonic-gate int ddi_intr_get_navail(dev_info_t *dip, int type, int *navailp); 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate /* 1510Sstevel@tonic-gate * Interrupt resource allocate/free functions 1520Sstevel@tonic-gate */ 1530Sstevel@tonic-gate int ddi_intr_alloc(dev_info_t *dip, ddi_intr_handle_t *h_array, 1540Sstevel@tonic-gate int type, int inum, int count, int *actualp, int behavior); 1550Sstevel@tonic-gate int ddi_intr_free(ddi_intr_handle_t h); 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate /* 1580Sstevel@tonic-gate * Interrupt get/set capacity functions 1590Sstevel@tonic-gate */ 1600Sstevel@tonic-gate int ddi_intr_get_cap(ddi_intr_handle_t h, int *flagsp); 1610Sstevel@tonic-gate int ddi_intr_set_cap(ddi_intr_handle_t h, int flags); 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate /* 1640Sstevel@tonic-gate * Interrupt priority management functions 1650Sstevel@tonic-gate */ 1660Sstevel@tonic-gate uint_t ddi_intr_get_hilevel_pri(void); 1670Sstevel@tonic-gate int ddi_intr_get_pri(ddi_intr_handle_t h, uint_t *prip); 1680Sstevel@tonic-gate int ddi_intr_set_pri(ddi_intr_handle_t h, uint_t pri); 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate /* 1710Sstevel@tonic-gate * Interrupt add/duplicate/remove functions 1720Sstevel@tonic-gate */ 1730Sstevel@tonic-gate int ddi_intr_add_handler(ddi_intr_handle_t h, 1740Sstevel@tonic-gate ddi_intr_handler_t inthandler, void *arg1, void *arg2); 1750Sstevel@tonic-gate int ddi_intr_dup_handler(ddi_intr_handle_t org, int vector, 1760Sstevel@tonic-gate ddi_intr_handle_t *dup); 1770Sstevel@tonic-gate int ddi_intr_remove_handler(ddi_intr_handle_t h); 1780Sstevel@tonic-gate 17910053SEvan.Yan@Sun.COM 18010053SEvan.Yan@Sun.COM /* 1810Sstevel@tonic-gate * Interrupt enable/disable/block_enable/block_disable functions 1820Sstevel@tonic-gate */ 1830Sstevel@tonic-gate int ddi_intr_enable(ddi_intr_handle_t h); 1840Sstevel@tonic-gate int ddi_intr_disable(ddi_intr_handle_t h); 1850Sstevel@tonic-gate int ddi_intr_block_enable(ddi_intr_handle_t *h_array, int count); 1860Sstevel@tonic-gate int ddi_intr_block_disable(ddi_intr_handle_t *h_array, int count); 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate /* 1890Sstevel@tonic-gate * Interrupt set/clr mask functions 1900Sstevel@tonic-gate */ 1910Sstevel@tonic-gate int ddi_intr_set_mask(ddi_intr_handle_t h); 1920Sstevel@tonic-gate int ddi_intr_clr_mask(ddi_intr_handle_t h); 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate /* 1950Sstevel@tonic-gate * Interrupt get pending function 1960Sstevel@tonic-gate */ 1970Sstevel@tonic-gate int ddi_intr_get_pending(ddi_intr_handle_t h, int *pendingp); 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate /* 20010053SEvan.Yan@Sun.COM * Interrupt resource management function 20110053SEvan.Yan@Sun.COM */ 20210053SEvan.Yan@Sun.COM int ddi_intr_set_nreq(dev_info_t *dip, int nreq); 20310053SEvan.Yan@Sun.COM 20410053SEvan.Yan@Sun.COM /* 2050Sstevel@tonic-gate * Soft interrupt functions 2060Sstevel@tonic-gate */ 2070Sstevel@tonic-gate int ddi_intr_add_softint(dev_info_t *dip, ddi_softint_handle_t *h, 2080Sstevel@tonic-gate int soft_pri, ddi_intr_handler_t handler, void *arg1); 2090Sstevel@tonic-gate int ddi_intr_remove_softint(ddi_softint_handle_t h); 2100Sstevel@tonic-gate int ddi_intr_trigger_softint(ddi_softint_handle_t h, void *arg2); 2110Sstevel@tonic-gate int ddi_intr_get_softint_pri(ddi_softint_handle_t h, uint_t *soft_prip); 2120Sstevel@tonic-gate int ddi_intr_set_softint_pri(ddi_softint_handle_t h, uint_t soft_pri); 2130Sstevel@tonic-gate 2148561SScott.Carter@Sun.COM /* 2150Sstevel@tonic-gate * Old DDI interrupt interfaces. 216693Sgovinda * 217693Sgovinda * The following DDI interrupt interfaces are obsolete. 218693Sgovinda * Use the above new DDI interrupt interfaces instead. 2190Sstevel@tonic-gate */ 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate /* 2220Sstevel@tonic-gate * Return non-zero if the specified interrupt exists and the handler 2230Sstevel@tonic-gate * will be restricted to using only certain functions because the 2240Sstevel@tonic-gate * interrupt level is not blocked by the scheduler. I.e., it cannot 2250Sstevel@tonic-gate * signal other threads. 2260Sstevel@tonic-gate */ 2270Sstevel@tonic-gate int ddi_intr_hilevel(dev_info_t *dip, uint_t inumber); 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate int ddi_get_iblock_cookie(dev_info_t *dip, uint_t inumber, 2300Sstevel@tonic-gate ddi_iblock_cookie_t *iblock_cookiep); 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate /* 2330Sstevel@tonic-gate * ddi_dev_nintrs 2340Sstevel@tonic-gate * 2350Sstevel@tonic-gate * If the device has h/w interrupt(s), report 2360Sstevel@tonic-gate * how many of them that there are into resultp. 2370Sstevel@tonic-gate * Return DDI_FAILURE if the device has no interrupts. 2380Sstevel@tonic-gate */ 2390Sstevel@tonic-gate int ddi_dev_nintrs(dev_info_t *dev, int *resultp); 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate /* 2420Sstevel@tonic-gate * ddi_add_intr: Add an interrupt to the system. 2430Sstevel@tonic-gate * 2440Sstevel@tonic-gate * The interrupt number "inumber" determines which interrupt will 2450Sstevel@tonic-gate * be added. The interrupt number is associated with interrupt 2460Sstevel@tonic-gate * information provided from self identifying devices or configuration 2470Sstevel@tonic-gate * information for non-self identifying devices. If only one interrupt 2480Sstevel@tonic-gate * is associated with the device then the interrupt number should be 0. 2490Sstevel@tonic-gate * 2500Sstevel@tonic-gate * If successful, "*iblock_cookiep" will contain information necessary 2510Sstevel@tonic-gate * for initializing locks (mutex_init, cv_init, etc.) as well as for 2520Sstevel@tonic-gate * possible later removal of the interrupt from the system. 2530Sstevel@tonic-gate * 2540Sstevel@tonic-gate * If successful, "*idevice_cookiep" will contain the correct programmable 2550Sstevel@tonic-gate * device interrupt value (see <sys/dditypes.h> in the form of the 2560Sstevel@tonic-gate * type ddi_idevice_cookie_t). 2570Sstevel@tonic-gate * 2580Sstevel@tonic-gate * Either cookie pointer may be specified as a NULL pointer 2590Sstevel@tonic-gate * in which case no value will be returned. 2600Sstevel@tonic-gate * 2610Sstevel@tonic-gate * The interrupt handler "int_handler" is the address of the routine 2620Sstevel@tonic-gate * to be called upon receipt of an appropriate interrupt. The 2630Sstevel@tonic-gate * interrupt handler should return DDI_INTR_CLAIMED if the 2640Sstevel@tonic-gate * interrupt was claimed, else DDI_INTR_UNCLAIMED. The argument 2650Sstevel@tonic-gate * "int_handler_arg" will be passed to the "int_handler" 2660Sstevel@tonic-gate * upon receipt of an appropriate interrupt. 2670Sstevel@tonic-gate * 2680Sstevel@tonic-gate * If successful ddi_add_intr will return DDI_SUCCESS. 2690Sstevel@tonic-gate * If the interrupt information cannot be found it will 2700Sstevel@tonic-gate * return DDI_INTR_NOTFOUND. 2710Sstevel@tonic-gate * 2720Sstevel@tonic-gate */ 2730Sstevel@tonic-gate int ddi_add_intr(dev_info_t *dip, uint_t inumber, 2740Sstevel@tonic-gate ddi_iblock_cookie_t *iblock_cookiep, 2750Sstevel@tonic-gate ddi_idevice_cookie_t *idevice_cookiep, 2760Sstevel@tonic-gate uint_t (*int_handler)(caddr_t int_handler_arg), 2770Sstevel@tonic-gate caddr_t int_handler_arg); 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate /* 2800Sstevel@tonic-gate * The following function is for Sun's internal use only at present 2810Sstevel@tonic-gate */ 2820Sstevel@tonic-gate int ddi_add_fastintr(dev_info_t *dip, uint_t inumber, 2830Sstevel@tonic-gate ddi_iblock_cookie_t *iblock_cookiep, 2840Sstevel@tonic-gate ddi_idevice_cookie_t *idevice_cookiep, 2850Sstevel@tonic-gate uint_t (*hi_int_handler)(void)); 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate /* 2880Sstevel@tonic-gate * ddi_remove_intr: Remove interrupt set up by ddi_add_intr. 2890Sstevel@tonic-gate * 2900Sstevel@tonic-gate * This routine is intended to be used by drivers that are 2910Sstevel@tonic-gate * preparing to unload themselves "detach" from the system. 2920Sstevel@tonic-gate */ 2930Sstevel@tonic-gate void ddi_remove_intr(dev_info_t *dip, uint_t inum, 2940Sstevel@tonic-gate ddi_iblock_cookie_t iblock_cookie); 2950Sstevel@tonic-gate 2960Sstevel@tonic-gate /* 2970Sstevel@tonic-gate * For use by ddi_add_softintr in order to specify a priority preference. 2980Sstevel@tonic-gate */ 2990Sstevel@tonic-gate #define DDI_SOFTINT_FIXED 0 /* Fixed priority soft interrupt */ 3000Sstevel@tonic-gate #define DDI_SOFTINT_LOW 8 /* Low priority soft interrupt */ 3010Sstevel@tonic-gate #define DDI_SOFTINT_MED 128 /* Medium priority soft interrupt */ 3020Sstevel@tonic-gate #define DDI_SOFTINT_HIGH 256 /* High priority soft interrupt */ 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate int ddi_get_soft_iblock_cookie(dev_info_t *dip, int preference, 3060Sstevel@tonic-gate ddi_iblock_cookie_t *iblock_cookiep); 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate /* 3090Sstevel@tonic-gate * ddi_add_softintr: Add a "soft" interrupt to the system. 3100Sstevel@tonic-gate * 3110Sstevel@tonic-gate * Like ddi_add_intr, only for system interrupts that you can trigger 3120Sstevel@tonic-gate * yourself. You specify a preference (see above) for the level you 3130Sstevel@tonic-gate * want. You get an identifier back which you can use to either trigger 3140Sstevel@tonic-gate * a soft interrupt or, later, remove it. 3150Sstevel@tonic-gate */ 3160Sstevel@tonic-gate int ddi_add_softintr(dev_info_t *dip, int preference, ddi_softintr_t *idp, 3170Sstevel@tonic-gate ddi_iblock_cookie_t *iblock_cookiep, 3180Sstevel@tonic-gate ddi_idevice_cookie_t *idevice_cookiep, 3190Sstevel@tonic-gate uint_t (*int_handler)(caddr_t int_handler_arg), 3200Sstevel@tonic-gate caddr_t int_handler_arg); 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate void ddi_remove_softintr(ddi_softintr_t id); 3230Sstevel@tonic-gate 3240Sstevel@tonic-gate void ddi_trigger_softintr(ddi_softintr_t id); 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate #endif /* _KERNEL */ 3270Sstevel@tonic-gate 3280Sstevel@tonic-gate #ifdef __cplusplus 3290Sstevel@tonic-gate } 3300Sstevel@tonic-gate #endif 3310Sstevel@tonic-gate 3320Sstevel@tonic-gate #endif /* _SYS_DDI_INTR_H */ 333