17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5102cb92eSjohnny * Common Development and Distribution License (the "License"). 6102cb92eSjohnny * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22a120541cSScott M. Carter * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate #include <sys/note.h> 267c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 277c478bd9Sstevel@tonic-gate #include <sys/types.h> 287c478bd9Sstevel@tonic-gate #include <sys/param.h> 297c478bd9Sstevel@tonic-gate #include <sys/systm.h> 307c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 317c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 327c478bd9Sstevel@tonic-gate #include <sys/debug.h> 337c478bd9Sstevel@tonic-gate #include <sys/avintr.h> 347c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 357c478bd9Sstevel@tonic-gate #include <sys/sunndi.h> 367c478bd9Sstevel@tonic-gate #include <sys/ndi_impldefs.h> /* include prototypes */ 3720036fe5Segillett #include <sys/atomic.h> 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate /* 407c478bd9Sstevel@tonic-gate * New DDI interrupt framework 417c478bd9Sstevel@tonic-gate */ 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate /* 447c478bd9Sstevel@tonic-gate * ddi_intr_get_supported_types: 457c478bd9Sstevel@tonic-gate * Return, as a bit mask, the hardware interrupt types supported by 467c478bd9Sstevel@tonic-gate * both the device and by the host in the integer pointed 477c478bd9Sstevel@tonic-gate * to be the 'typesp' argument. 487c478bd9Sstevel@tonic-gate */ 497c478bd9Sstevel@tonic-gate int 507c478bd9Sstevel@tonic-gate ddi_intr_get_supported_types(dev_info_t *dip, int *typesp) 517c478bd9Sstevel@tonic-gate { 527c478bd9Sstevel@tonic-gate int ret; 537c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t hdl; 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate if (dip == NULL) 567c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_get_supported_types: dip %p\n", 597c478bd9Sstevel@tonic-gate (void *)dip)); 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate if (*typesp = i_ddi_intr_get_supported_types(dip)) 627c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate bzero(&hdl, sizeof (ddi_intr_handle_impl_t)); 657c478bd9Sstevel@tonic-gate hdl.ih_dip = dip; 667c478bd9Sstevel@tonic-gate 67a195726fSgovinda ret = i_ddi_intr_ops(dip, dip, DDI_INTROP_SUPPORTED_TYPES, &hdl, 687c478bd9Sstevel@tonic-gate (void *)typesp); 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) 717c478bd9Sstevel@tonic-gate return (DDI_INTR_NOTFOUND); 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_get_supported_types: types %x\n", 747c478bd9Sstevel@tonic-gate *typesp)); 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate return (ret); 777c478bd9Sstevel@tonic-gate } 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate /* 807c478bd9Sstevel@tonic-gate * ddi_intr_get_nintrs: 817c478bd9Sstevel@tonic-gate * Return as an integer in the integer pointed to by the argument 827c478bd9Sstevel@tonic-gate * *nintrsp*, the number of interrupts the device supports for the 837c478bd9Sstevel@tonic-gate * given interrupt type. 847c478bd9Sstevel@tonic-gate */ 857c478bd9Sstevel@tonic-gate int 867c478bd9Sstevel@tonic-gate ddi_intr_get_nintrs(dev_info_t *dip, int type, int *nintrsp) 877c478bd9Sstevel@tonic-gate { 887c478bd9Sstevel@tonic-gate int ret; 897c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t hdl; 907c478bd9Sstevel@tonic-gate 91a195726fSgovinda DDI_INTR_APIDBG((CE_CONT, "ddi_intr_get_nintrs: dip %p, type: %d\n", 92a195726fSgovinda (void *)dip, type)); 937c478bd9Sstevel@tonic-gate 945febcb4aSScott Carter, SD IOSW if ((dip == NULL) || (nintrsp == NULL) || 955febcb4aSScott Carter, SD IOSW !DDI_INTR_TYPE_FLAG_VALID(type) || 96d626b9f5Sanish !(i_ddi_intr_get_supported_types(dip) & type)) { 975febcb4aSScott Carter, SD IOSW DDI_INTR_APIDBG((CE_CONT, "ddi_intr_get_nintrs: " 985febcb4aSScott Carter, SD IOSW "Invalid input args\n")); 99a195726fSgovinda return (DDI_EINVAL); 100a195726fSgovinda } 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate if (*nintrsp = i_ddi_intr_get_supported_nintrs(dip, type)) 1037c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate bzero(&hdl, sizeof (ddi_intr_handle_impl_t)); 1067c478bd9Sstevel@tonic-gate hdl.ih_dip = dip; 1077c478bd9Sstevel@tonic-gate hdl.ih_type = type; 1087c478bd9Sstevel@tonic-gate 109a195726fSgovinda ret = i_ddi_intr_ops(dip, dip, DDI_INTROP_NINTRS, &hdl, 1107c478bd9Sstevel@tonic-gate (void *)nintrsp); 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_get_nintrs:: nintrs %x\n", 1137c478bd9Sstevel@tonic-gate *nintrsp)); 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate return (ret); 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * ddi_intr_get_navail: 1207c478bd9Sstevel@tonic-gate * Bus nexus driver will return availble interrupt count value for 1217c478bd9Sstevel@tonic-gate * a given interrupt type. 1227c478bd9Sstevel@tonic-gate * 1237c478bd9Sstevel@tonic-gate * Return as an integer in the integer pointed to by the argument 1247c478bd9Sstevel@tonic-gate * *navailp*, the number of interrupts currently available for the 1257c478bd9Sstevel@tonic-gate * given interrupt type. 1267c478bd9Sstevel@tonic-gate */ 1277c478bd9Sstevel@tonic-gate int 1287c478bd9Sstevel@tonic-gate ddi_intr_get_navail(dev_info_t *dip, int type, int *navailp) 1297c478bd9Sstevel@tonic-gate { 130a195726fSgovinda DDI_INTR_APIDBG((CE_CONT, "ddi_intr_get_navail: dip %p, type: %d\n", 131a195726fSgovinda (void *)dip, type)); 1327c478bd9Sstevel@tonic-gate 1335febcb4aSScott Carter, SD IOSW if ((dip == NULL) || (navailp == NULL) || 1345febcb4aSScott Carter, SD IOSW !DDI_INTR_TYPE_FLAG_VALID(type) || 135d626b9f5Sanish !(i_ddi_intr_get_supported_types(dip) & type)) { 1365febcb4aSScott Carter, SD IOSW DDI_INTR_APIDBG((CE_CONT, "ddi_intr_get_navail: " 1375febcb4aSScott Carter, SD IOSW "Invalid input args\n")); 1387c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 139a195726fSgovinda } 1407c478bd9Sstevel@tonic-gate 1415febcb4aSScott Carter, SD IOSW if ((*navailp = i_ddi_intr_get_current_navail(dip, type)) == 0) 1425febcb4aSScott Carter, SD IOSW return (DDI_INTR_NOTFOUND); 1437c478bd9Sstevel@tonic-gate 1445febcb4aSScott Carter, SD IOSW return (DDI_SUCCESS); 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate /* 1487c478bd9Sstevel@tonic-gate * Interrupt allocate/free functions 1497c478bd9Sstevel@tonic-gate */ 1507c478bd9Sstevel@tonic-gate int 1517c478bd9Sstevel@tonic-gate ddi_intr_alloc(dev_info_t *dip, ddi_intr_handle_t *h_array, int type, int inum, 1527c478bd9Sstevel@tonic-gate int count, int *actualp, int behavior) 1537c478bd9Sstevel@tonic-gate { 1547c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp, tmp_hdl; 1555febcb4aSScott Carter, SD IOSW int i, ret, cap = 0, curr_type, nintrs; 1565febcb4aSScott Carter, SD IOSW uint_t pri, navail, curr_nintrs = 0; 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: name %s dip 0x%p " 1597c478bd9Sstevel@tonic-gate "type %x inum %x count %x behavior %x\n", ddi_driver_name(dip), 1607c478bd9Sstevel@tonic-gate (void *)dip, type, inum, count, behavior)); 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate /* Validate parameters */ 1635febcb4aSScott Carter, SD IOSW if ((dip == NULL) || (h_array == NULL) || (inum < 0) || (count < 1) || 1645febcb4aSScott Carter, SD IOSW (actualp == NULL) || !DDI_INTR_BEHAVIOR_FLAG_VALID(behavior)) { 1655febcb4aSScott Carter, SD IOSW DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: " 1665febcb4aSScott Carter, SD IOSW "Invalid input args\n")); 1677c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate /* Validate interrupt type */ 171d626b9f5Sanish if (!DDI_INTR_TYPE_FLAG_VALID(type) || 172d626b9f5Sanish !(i_ddi_intr_get_supported_types(dip) & type)) { 1737c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: type %x not " 1747c478bd9Sstevel@tonic-gate "supported\n", type)); 1757c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 1767c478bd9Sstevel@tonic-gate } 1777c478bd9Sstevel@tonic-gate 1785febcb4aSScott Carter, SD IOSW /* Validate inum not previously allocated */ 179d626b9f5Sanish if ((type == DDI_INTR_TYPE_FIXED) && 180d626b9f5Sanish (i_ddi_get_intr_handle(dip, inum) != NULL)) { 181d626b9f5Sanish DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: inum %d is already " 182d626b9f5Sanish "in use, cannot allocate again!!\n", inum)); 183d626b9f5Sanish return (DDI_EINVAL); 184d626b9f5Sanish } 185d626b9f5Sanish 1865febcb4aSScott Carter, SD IOSW /* Get how many interrupts the device supports */ 1875febcb4aSScott Carter, SD IOSW if ((nintrs = i_ddi_intr_get_supported_nintrs(dip, type)) == 0) { 1887c478bd9Sstevel@tonic-gate if (ddi_intr_get_nintrs(dip, type, &nintrs) != DDI_SUCCESS) { 1897c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: no " 1907c478bd9Sstevel@tonic-gate "interrupts found of type %d\n", type)); 1917c478bd9Sstevel@tonic-gate return (DDI_INTR_NOTFOUND); 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate 1955febcb4aSScott Carter, SD IOSW /* Get how many interrupts the device is already using */ 1965febcb4aSScott Carter, SD IOSW if ((curr_type = i_ddi_intr_get_current_type(dip)) != 0) { 1975febcb4aSScott Carter, SD IOSW DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: type %x " 1985febcb4aSScott Carter, SD IOSW "is already being used\n", curr_type)); 1995febcb4aSScott Carter, SD IOSW curr_nintrs = i_ddi_intr_get_current_nintrs(dip); 2005febcb4aSScott Carter, SD IOSW } 2015febcb4aSScott Carter, SD IOSW 2025febcb4aSScott Carter, SD IOSW /* Validate interrupt type consistency */ 2035febcb4aSScott Carter, SD IOSW if ((curr_type != 0) && (type != curr_type)) { 2045febcb4aSScott Carter, SD IOSW DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: Requested " 2055febcb4aSScott Carter, SD IOSW "interrupt type %x is different from interrupt type %x" 2065febcb4aSScott Carter, SD IOSW "already in use\n", type, curr_type)); 2075febcb4aSScott Carter, SD IOSW return (DDI_EINVAL); 2085febcb4aSScott Carter, SD IOSW } 2095febcb4aSScott Carter, SD IOSW 2105febcb4aSScott Carter, SD IOSW /* Validate count does not exceed what device supports */ 2117c478bd9Sstevel@tonic-gate if (count > nintrs) { 2127c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: no of interrupts " 2137c478bd9Sstevel@tonic-gate "requested %d is more than supported %d\n", count, nintrs)); 2147c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 2155febcb4aSScott Carter, SD IOSW } else if ((count + curr_nintrs) > nintrs) { 2167c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: count %d " 2177c478bd9Sstevel@tonic-gate "+ intrs in use %d exceeds supported %d intrs\n", 218d84bdf75Segillett count, curr_nintrs, nintrs)); 2197c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate 2225febcb4aSScott Carter, SD IOSW /* Validate power of 2 requirements for MSI */ 2235febcb4aSScott Carter, SD IOSW if ((type == DDI_INTR_TYPE_MSI) && !ISP2(curr_nintrs + count)) { 2247c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: " 2257c478bd9Sstevel@tonic-gate "MSI count %d is not a power of two\n", count)); 2267c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate /* 2305febcb4aSScott Carter, SD IOSW * Initialize the device's interrupt information structure, 2315febcb4aSScott Carter, SD IOSW * and establish an association with IRM if it is supported. 232ef643aefSegillett * 2335febcb4aSScott Carter, SD IOSW * NOTE: IRM checks minimum support, and can return DDI_EAGAIN. 2347c478bd9Sstevel@tonic-gate */ 2355febcb4aSScott Carter, SD IOSW if (curr_nintrs == 0) { 2365febcb4aSScott Carter, SD IOSW i_ddi_intr_devi_init(dip); 2375febcb4aSScott Carter, SD IOSW if (i_ddi_irm_insert(dip, type, count) == DDI_EAGAIN) { 2385febcb4aSScott Carter, SD IOSW cmn_err(CE_WARN, "ddi_intr_alloc: " 2395febcb4aSScott Carter, SD IOSW "cannot fit into interrupt pool\n"); 2405febcb4aSScott Carter, SD IOSW return (DDI_EAGAIN); 241d84bdf75Segillett } 2425febcb4aSScott Carter, SD IOSW } 2437c478bd9Sstevel@tonic-gate 244a120541cSScott M. Carter /* Synchronously adjust IRM associations for non-IRM aware drivers */ 245a120541cSScott M. Carter if (curr_nintrs && (i_ddi_irm_supported(dip, type) != DDI_SUCCESS)) 246a120541cSScott M. Carter (void) i_ddi_irm_modify(dip, count + curr_nintrs); 247a120541cSScott M. Carter 2485febcb4aSScott Carter, SD IOSW /* Get how many interrupts are currently available */ 2495febcb4aSScott Carter, SD IOSW navail = i_ddi_intr_get_current_navail(dip, type); 2505febcb4aSScott Carter, SD IOSW 2515febcb4aSScott Carter, SD IOSW /* Validate that requested number of interrupts are available */ 2525febcb4aSScott Carter, SD IOSW if (curr_nintrs == navail) { 2535febcb4aSScott Carter, SD IOSW DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: max # of intrs %d " 2545febcb4aSScott Carter, SD IOSW "already allocated\n", navail)); 2555febcb4aSScott Carter, SD IOSW return (DDI_EAGAIN); 2565febcb4aSScott Carter, SD IOSW } 2575febcb4aSScott Carter, SD IOSW if ((count + curr_nintrs) > navail) { 2585febcb4aSScott Carter, SD IOSW DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: requested # of " 2595febcb4aSScott Carter, SD IOSW "intrs %d exceeds # of available intrs %d\n", count, 2605febcb4aSScott Carter, SD IOSW navail - curr_nintrs)); 2617c478bd9Sstevel@tonic-gate if (behavior == DDI_INTR_ALLOC_STRICT) { 2627c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: " 2637c478bd9Sstevel@tonic-gate "DDI_INTR_ALLOC_STRICT flag is passed, " 2647c478bd9Sstevel@tonic-gate "return failure\n")); 265a120541cSScott M. Carter if (curr_nintrs == 0) 2665febcb4aSScott Carter, SD IOSW i_ddi_intr_devi_fini(dip); 267a120541cSScott M. Carter else if (i_ddi_irm_supported(dip, type) != DDI_SUCCESS) 268a120541cSScott M. Carter (void) i_ddi_irm_modify(dip, curr_nintrs); 2697c478bd9Sstevel@tonic-gate return (DDI_EAGAIN); 2707c478bd9Sstevel@tonic-gate } 2715febcb4aSScott Carter, SD IOSW count = navail - curr_nintrs; 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate /* Now allocate required number of interrupts */ 2757c478bd9Sstevel@tonic-gate bzero(&tmp_hdl, sizeof (ddi_intr_handle_impl_t)); 2767c478bd9Sstevel@tonic-gate tmp_hdl.ih_type = type; 2777c478bd9Sstevel@tonic-gate tmp_hdl.ih_inum = inum; 2787c478bd9Sstevel@tonic-gate tmp_hdl.ih_scratch1 = count; 27980ab886dSwesolows tmp_hdl.ih_scratch2 = (void *)(uintptr_t)behavior; 2807c478bd9Sstevel@tonic-gate tmp_hdl.ih_dip = dip; 2817c478bd9Sstevel@tonic-gate 282a195726fSgovinda if (i_ddi_intr_ops(dip, dip, DDI_INTROP_ALLOC, 2837c478bd9Sstevel@tonic-gate &tmp_hdl, (void *)actualp) != DDI_SUCCESS) { 2847c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: allocation " 2857c478bd9Sstevel@tonic-gate "failed\n")); 28620036fe5Segillett i_ddi_intr_devi_fini(dip); 2877c478bd9Sstevel@tonic-gate return (*actualp ? DDI_EAGAIN : DDI_INTR_NOTFOUND); 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate 290a195726fSgovinda if ((ret = i_ddi_intr_ops(dip, dip, DDI_INTROP_GETPRI, 2917c478bd9Sstevel@tonic-gate &tmp_hdl, (void *)&pri)) != DDI_SUCCESS) { 2927c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: get priority " 2937c478bd9Sstevel@tonic-gate "failed\n")); 29420036fe5Segillett goto fail; 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: getting capability\n")); 2987c478bd9Sstevel@tonic-gate 299a195726fSgovinda if ((ret = i_ddi_intr_ops(dip, dip, DDI_INTROP_GETCAP, 3007c478bd9Sstevel@tonic-gate &tmp_hdl, (void *)&cap)) != DDI_SUCCESS) { 3017c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: get capability " 3027c478bd9Sstevel@tonic-gate "failed\n")); 30320036fe5Segillett goto fail; 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate 30620036fe5Segillett /* 30720036fe5Segillett * Save current interrupt type, supported and current intr count. 30820036fe5Segillett */ 3097c478bd9Sstevel@tonic-gate i_ddi_intr_set_current_type(dip, type); 3107c478bd9Sstevel@tonic-gate i_ddi_intr_set_supported_nintrs(dip, nintrs); 3117c478bd9Sstevel@tonic-gate i_ddi_intr_set_current_nintrs(dip, 3127c478bd9Sstevel@tonic-gate i_ddi_intr_get_current_nintrs(dip) + *actualp); 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate /* Now, go and handle each "handle" */ 3155febcb4aSScott Carter, SD IOSW for (i = inum; i < (inum + *actualp); i++) { 3167c478bd9Sstevel@tonic-gate hdlp = (ddi_intr_handle_impl_t *)kmem_zalloc( 3177c478bd9Sstevel@tonic-gate (sizeof (ddi_intr_handle_impl_t)), KM_SLEEP); 3187c478bd9Sstevel@tonic-gate rw_init(&hdlp->ih_rwlock, NULL, RW_DRIVER, NULL); 3197c478bd9Sstevel@tonic-gate h_array[i] = (struct __ddi_intr_handle *)hdlp; 3207c478bd9Sstevel@tonic-gate hdlp->ih_type = type; 3217c478bd9Sstevel@tonic-gate hdlp->ih_pri = pri; 3227c478bd9Sstevel@tonic-gate hdlp->ih_cap = cap; 3237c478bd9Sstevel@tonic-gate hdlp->ih_ver = DDI_INTR_VERSION; 3247c478bd9Sstevel@tonic-gate hdlp->ih_state = DDI_IHDL_STATE_ALLOC; 3257c478bd9Sstevel@tonic-gate hdlp->ih_dip = dip; 3265febcb4aSScott Carter, SD IOSW hdlp->ih_inum = i; 3277a364d25Sschwartz i_ddi_alloc_intr_phdl(hdlp); 3287c478bd9Sstevel@tonic-gate if (type & DDI_INTR_TYPE_FIXED) 3295febcb4aSScott Carter, SD IOSW i_ddi_set_intr_handle(dip, hdlp->ih_inum, 3305febcb4aSScott Carter, SD IOSW (ddi_intr_handle_t)hdlp); 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: hdlp = 0x%p\n", 3337c478bd9Sstevel@tonic-gate (void *)h_array[i])); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 33720036fe5Segillett 33820036fe5Segillett fail: 33920036fe5Segillett (void) i_ddi_intr_ops(tmp_hdl.ih_dip, tmp_hdl.ih_dip, 34020036fe5Segillett DDI_INTROP_FREE, &tmp_hdl, NULL); 34120036fe5Segillett i_ddi_intr_devi_fini(dip); 34220036fe5Segillett 34320036fe5Segillett return (ret); 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate int 3477c478bd9Sstevel@tonic-gate ddi_intr_free(ddi_intr_handle_t h) 3487c478bd9Sstevel@tonic-gate { 3497c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp = (ddi_intr_handle_impl_t *)h; 3507c478bd9Sstevel@tonic-gate int ret; 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_free: hdlp = %p\n", (void *)hdlp)); 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate if (hdlp == NULL) 3557c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_WRITER); 35820036fe5Segillett if (((hdlp->ih_flags & DDI_INTR_MSIX_DUP) && 35920036fe5Segillett (hdlp->ih_state != DDI_IHDL_STATE_ADDED)) || 36020036fe5Segillett ((hdlp->ih_state != DDI_IHDL_STATE_ALLOC) && 36120036fe5Segillett (!(hdlp->ih_flags & DDI_INTR_MSIX_DUP)))) { 3627c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 3637c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate 366023ccc1eSegillett /* Set the number of interrupts to free */ 367023ccc1eSegillett hdlp->ih_scratch1 = 1; 368023ccc1eSegillett 369a195726fSgovinda ret = i_ddi_intr_ops(hdlp->ih_dip, hdlp->ih_dip, 3707c478bd9Sstevel@tonic-gate DDI_INTROP_FREE, hdlp, NULL); 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 3737c478bd9Sstevel@tonic-gate if (ret == DDI_SUCCESS) { 37420036fe5Segillett /* This would be the dup vector */ 37520036fe5Segillett if (hdlp->ih_flags & DDI_INTR_MSIX_DUP) 37620036fe5Segillett atomic_dec_32(&hdlp->ih_main->ih_dup_cnt); 37720036fe5Segillett else { 378a120541cSScott M. Carter int n, curr_type; 379a120541cSScott M. Carter 380a120541cSScott M. Carter n = i_ddi_intr_get_current_nintrs(hdlp->ih_dip) - 1; 381a120541cSScott M. Carter curr_type = i_ddi_intr_get_current_type(hdlp->ih_dip); 382a120541cSScott M. Carter 383a120541cSScott M. Carter i_ddi_intr_set_current_nintrs(hdlp->ih_dip, n); 384a120541cSScott M. Carter 385a120541cSScott M. Carter if ((i_ddi_irm_supported(hdlp->ih_dip, curr_type) 386a120541cSScott M. Carter != DDI_SUCCESS) && (n > 0)) 387a120541cSScott M. Carter (void) i_ddi_irm_modify(hdlp->ih_dip, n); 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate if (hdlp->ih_type & DDI_INTR_TYPE_FIXED) 3907c478bd9Sstevel@tonic-gate i_ddi_set_intr_handle(hdlp->ih_dip, 3917c478bd9Sstevel@tonic-gate hdlp->ih_inum, NULL); 3927c478bd9Sstevel@tonic-gate 393023ccc1eSegillett i_ddi_intr_devi_fini(hdlp->ih_dip); 3947a364d25Sschwartz i_ddi_free_intr_phdl(hdlp); 39520036fe5Segillett } 3967c478bd9Sstevel@tonic-gate rw_destroy(&hdlp->ih_rwlock); 3977c478bd9Sstevel@tonic-gate kmem_free(hdlp, sizeof (ddi_intr_handle_impl_t)); 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate return (ret); 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate /* 4047c478bd9Sstevel@tonic-gate * Interrupt get/set capacity functions 4057c478bd9Sstevel@tonic-gate * 4067c478bd9Sstevel@tonic-gate * The logic used to figure this out is shown here: 4077c478bd9Sstevel@tonic-gate * 4087c478bd9Sstevel@tonic-gate * Device level Platform level Intr source 4097c478bd9Sstevel@tonic-gate * 1. Fixed interrupts 4107c478bd9Sstevel@tonic-gate * (non-PCI) 4117c478bd9Sstevel@tonic-gate * o Flags supported N/A Maskable/Pending/ rootnex 4127c478bd9Sstevel@tonic-gate * No Block Enable 4137c478bd9Sstevel@tonic-gate * o navail 1 4147c478bd9Sstevel@tonic-gate * 4157c478bd9Sstevel@tonic-gate * 2. PCI Fixed interrupts 4167c478bd9Sstevel@tonic-gate * o Flags supported pending/Maskable Maskable/pending/ pci 4177c478bd9Sstevel@tonic-gate * No Block enable 4187c478bd9Sstevel@tonic-gate * o navail N/A 1 4197c478bd9Sstevel@tonic-gate * 4207c478bd9Sstevel@tonic-gate * 3. PCI MSI 4217c478bd9Sstevel@tonic-gate * o Flags supported Maskable/Pending Maskable/Pending pci 4227c478bd9Sstevel@tonic-gate * Block Enable (if drvr doesn't) Block Enable 4237c478bd9Sstevel@tonic-gate * o navail N/A #vectors - #used N/A 4247c478bd9Sstevel@tonic-gate * 4257c478bd9Sstevel@tonic-gate * 4. PCI MSI-X 4267c478bd9Sstevel@tonic-gate * o Flags supported Maskable/Pending Maskable/Pending pci 4277c478bd9Sstevel@tonic-gate * Block Enable Block Enable 4287c478bd9Sstevel@tonic-gate * o navail N/A #vectors - #used N/A 4297c478bd9Sstevel@tonic-gate * 4307c478bd9Sstevel@tonic-gate * where: 4317c478bd9Sstevel@tonic-gate * #vectors - Total numbers of vectors available 4327c478bd9Sstevel@tonic-gate * #used - Total numbers of vectors currently being used 4337c478bd9Sstevel@tonic-gate * 4347c478bd9Sstevel@tonic-gate * For devices complying to PCI2.3 or greater, see bit10 of Command Register 4357c478bd9Sstevel@tonic-gate * 0 - enables assertion of INTx 4367c478bd9Sstevel@tonic-gate * 1 - disables assertion of INTx 4377c478bd9Sstevel@tonic-gate * 4387c478bd9Sstevel@tonic-gate * For non MSI/X interrupts; if the IRQ is shared then all ddi_intr_set_*() 4397c478bd9Sstevel@tonic-gate * operations return failure. 4407c478bd9Sstevel@tonic-gate */ 4417c478bd9Sstevel@tonic-gate int 4427c478bd9Sstevel@tonic-gate ddi_intr_get_cap(ddi_intr_handle_t h, int *flagsp) 4437c478bd9Sstevel@tonic-gate { 4447c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp = (ddi_intr_handle_impl_t *)h; 4457c478bd9Sstevel@tonic-gate int ret; 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_get_cap: hdlp = %p\n", 4487c478bd9Sstevel@tonic-gate (void *)hdlp)); 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate *flagsp = 0; 4517c478bd9Sstevel@tonic-gate if (hdlp == NULL) 4527c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_READER); 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate if (hdlp->ih_cap) { 4577c478bd9Sstevel@tonic-gate *flagsp = hdlp->ih_cap & ~DDI_INTR_FLAG_MSI64; 4587c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 4597c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate 462a195726fSgovinda ret = i_ddi_intr_ops(hdlp->ih_dip, hdlp->ih_dip, 4637c478bd9Sstevel@tonic-gate DDI_INTROP_GETCAP, hdlp, (void *)flagsp); 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate if (ret == DDI_SUCCESS) { 4667c478bd9Sstevel@tonic-gate hdlp->ih_cap = *flagsp; 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate /* Mask out MSI/X 64-bit support to the consumer */ 4697c478bd9Sstevel@tonic-gate *flagsp &= ~DDI_INTR_FLAG_MSI64; 4707c478bd9Sstevel@tonic-gate } 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 4737c478bd9Sstevel@tonic-gate return (ret); 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate int 4777c478bd9Sstevel@tonic-gate ddi_intr_set_cap(ddi_intr_handle_t h, int flags) 4787c478bd9Sstevel@tonic-gate { 4797c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp = (ddi_intr_handle_impl_t *)h; 4807c478bd9Sstevel@tonic-gate int ret; 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_set_cap: hdlp = %p", (void *)hdlp)); 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate if (hdlp == NULL) 4857c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_WRITER); 4887c478bd9Sstevel@tonic-gate if (hdlp->ih_state != DDI_IHDL_STATE_ALLOC) { 4897c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 4907c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate /* Only DDI_INTR_FLAG_LEVEL or DDI_INTR_FLAG_EDGE are allowed */ 4947c478bd9Sstevel@tonic-gate if (!(flags & (DDI_INTR_FLAG_EDGE | DDI_INTR_FLAG_LEVEL))) { 4957c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "%s%d: only LEVEL or EDGE capability " 4967c478bd9Sstevel@tonic-gate "can be set\n", ddi_driver_name(hdlp->ih_dip), 4977c478bd9Sstevel@tonic-gate ddi_get_instance(hdlp->ih_dip))); 4987c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 4997c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate /* Both level/edge flags must be currently supported */ 5037c478bd9Sstevel@tonic-gate if (!(hdlp->ih_cap & (DDI_INTR_FLAG_EDGE | DDI_INTR_FLAG_LEVEL))) { 5047c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "%s%d: Both LEVEL and EDGE capability" 5057c478bd9Sstevel@tonic-gate " must be supported\n", ddi_driver_name(hdlp->ih_dip), 5067c478bd9Sstevel@tonic-gate ddi_get_instance(hdlp->ih_dip))); 5077c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 5087c478bd9Sstevel@tonic-gate return (DDI_ENOTSUP); 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate 511a195726fSgovinda ret = i_ddi_intr_ops(hdlp->ih_dip, hdlp->ih_dip, 5127c478bd9Sstevel@tonic-gate DDI_INTROP_SETCAP, hdlp, &flags); 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 5157c478bd9Sstevel@tonic-gate return (ret); 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate /* 5197c478bd9Sstevel@tonic-gate * Priority related functions 5207c478bd9Sstevel@tonic-gate */ 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate /* 5237c478bd9Sstevel@tonic-gate * ddi_intr_get_hilevel_pri: 5247c478bd9Sstevel@tonic-gate * Returns the minimum priority level for a 5257c478bd9Sstevel@tonic-gate * high-level interrupt on a platform. 5267c478bd9Sstevel@tonic-gate */ 5277c478bd9Sstevel@tonic-gate uint_t 5287c478bd9Sstevel@tonic-gate ddi_intr_get_hilevel_pri(void) 5297c478bd9Sstevel@tonic-gate { 5307c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_get_hilevel_pri:\n")); 5317c478bd9Sstevel@tonic-gate return (LOCK_LEVEL + 1); 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate int 5357c478bd9Sstevel@tonic-gate ddi_intr_get_pri(ddi_intr_handle_t h, uint_t *prip) 5367c478bd9Sstevel@tonic-gate { 5377c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp = (ddi_intr_handle_impl_t *)h; 5387c478bd9Sstevel@tonic-gate int ret; 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_get_pri: hdlp = %p\n", 5417c478bd9Sstevel@tonic-gate (void *)hdlp)); 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate *prip = 0; 5447c478bd9Sstevel@tonic-gate if (hdlp == NULL) 5457c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_READER); 5487c478bd9Sstevel@tonic-gate /* Already initialized, just return that */ 5497c478bd9Sstevel@tonic-gate if (hdlp->ih_pri) { 5507c478bd9Sstevel@tonic-gate *prip = hdlp->ih_pri; 5517c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 5527c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate 555a195726fSgovinda ret = i_ddi_intr_ops(hdlp->ih_dip, hdlp->ih_dip, 5567c478bd9Sstevel@tonic-gate DDI_INTROP_GETPRI, hdlp, (void *)prip); 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate if (ret == DDI_SUCCESS) 5597c478bd9Sstevel@tonic-gate hdlp->ih_pri = *prip; 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 5627c478bd9Sstevel@tonic-gate return (ret); 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate int 5667c478bd9Sstevel@tonic-gate ddi_intr_set_pri(ddi_intr_handle_t h, uint_t pri) 5677c478bd9Sstevel@tonic-gate { 5687c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp = (ddi_intr_handle_impl_t *)h; 5697c478bd9Sstevel@tonic-gate int ret; 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_set_pri: hdlp = %p", (void *)hdlp)); 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate if (hdlp == NULL) 5747c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate /* Validate priority argument */ 5777c478bd9Sstevel@tonic-gate if (pri < DDI_INTR_PRI_MIN || pri > DDI_INTR_PRI_MAX) { 5787c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_set_pri: invalid priority " 5797c478bd9Sstevel@tonic-gate "specified = %x\n", pri)); 5807c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_WRITER); 5847c478bd9Sstevel@tonic-gate if (hdlp->ih_state != DDI_IHDL_STATE_ALLOC) { 5857c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 5867c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate /* If the passed priority is same as existing priority; do nothing */ 5907c478bd9Sstevel@tonic-gate if (pri == hdlp->ih_pri) { 5917c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 5927c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate 595a195726fSgovinda ret = i_ddi_intr_ops(hdlp->ih_dip, hdlp->ih_dip, 5967c478bd9Sstevel@tonic-gate DDI_INTROP_SETPRI, hdlp, &pri); 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate if (ret == DDI_SUCCESS) 5997c478bd9Sstevel@tonic-gate hdlp->ih_pri = pri; 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 6027c478bd9Sstevel@tonic-gate return (ret); 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate /* 6067c478bd9Sstevel@tonic-gate * Interrupt add/duplicate/remove handlers 6077c478bd9Sstevel@tonic-gate */ 6087c478bd9Sstevel@tonic-gate int 6097c478bd9Sstevel@tonic-gate ddi_intr_add_handler(ddi_intr_handle_t h, ddi_intr_handler_t inthandler, 6107c478bd9Sstevel@tonic-gate void *arg1, void *arg2) 6117c478bd9Sstevel@tonic-gate { 6127c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp = (ddi_intr_handle_impl_t *)h; 6137c478bd9Sstevel@tonic-gate int ret; 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_add_handler: hdlp = 0x%p\n", 6167c478bd9Sstevel@tonic-gate (void *)hdlp)); 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate if ((hdlp == NULL) || (inthandler == NULL)) 6197c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_WRITER); 6227c478bd9Sstevel@tonic-gate if (hdlp->ih_state != DDI_IHDL_STATE_ALLOC) { 6237c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 6247c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate hdlp->ih_cb_func = inthandler; 6287c478bd9Sstevel@tonic-gate hdlp->ih_cb_arg1 = arg1; 6297c478bd9Sstevel@tonic-gate hdlp->ih_cb_arg2 = arg2; 6307c478bd9Sstevel@tonic-gate 631a195726fSgovinda ret = i_ddi_intr_ops(hdlp->ih_dip, hdlp->ih_dip, 6327c478bd9Sstevel@tonic-gate DDI_INTROP_ADDISR, hdlp, NULL); 6337c478bd9Sstevel@tonic-gate 6347c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 6357c478bd9Sstevel@tonic-gate hdlp->ih_cb_func = NULL; 6367c478bd9Sstevel@tonic-gate hdlp->ih_cb_arg1 = NULL; 6377c478bd9Sstevel@tonic-gate hdlp->ih_cb_arg2 = NULL; 6387c478bd9Sstevel@tonic-gate } else 6397c478bd9Sstevel@tonic-gate hdlp->ih_state = DDI_IHDL_STATE_ADDED; 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 6427c478bd9Sstevel@tonic-gate return (ret); 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate int 64620036fe5Segillett ddi_intr_dup_handler(ddi_intr_handle_t org, int dup_inum, 64720036fe5Segillett ddi_intr_handle_t *dup) 6487c478bd9Sstevel@tonic-gate { 6497c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp = (ddi_intr_handle_impl_t *)org; 6507c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *dup_hdlp; 6517c478bd9Sstevel@tonic-gate int ret; 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_dup_handler: hdlp = 0x%p\n", 6547c478bd9Sstevel@tonic-gate (void *)hdlp)); 6557c478bd9Sstevel@tonic-gate 65620036fe5Segillett /* Do some input argument checking ("dup" handle is not allocated) */ 657d626b9f5Sanish if ((hdlp == NULL) || (*dup != NULL) || (dup_inum < 0)) { 658d626b9f5Sanish DDI_INTR_APIDBG((CE_CONT, "ddi_intr_dup_handler: Invalid " 659d626b9f5Sanish "input args\n")); 6607c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 661d626b9f5Sanish } 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_READER); 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate /* Do some input argument checking */ 6667c478bd9Sstevel@tonic-gate if ((hdlp->ih_state == DDI_IHDL_STATE_ALLOC) || /* intr handle alloc? */ 66720036fe5Segillett (hdlp->ih_type != DDI_INTR_TYPE_MSIX) || /* only MSI-X allowed */ 66820036fe5Segillett (hdlp->ih_flags & DDI_INTR_MSIX_DUP)) { /* only dup original */ 6697c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 6707c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate 67320036fe5Segillett hdlp->ih_scratch1 = dup_inum; 674a195726fSgovinda ret = i_ddi_intr_ops(hdlp->ih_dip, hdlp->ih_dip, 67520036fe5Segillett DDI_INTROP_DUPVEC, hdlp, NULL); 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate if (ret == DDI_SUCCESS) { 6787c478bd9Sstevel@tonic-gate dup_hdlp = (ddi_intr_handle_impl_t *) 67920036fe5Segillett kmem_alloc(sizeof (ddi_intr_handle_impl_t), KM_SLEEP); 6807c478bd9Sstevel@tonic-gate 681*1a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&hdlp->ih_dup_cnt); 68220036fe5Segillett 68320036fe5Segillett *dup = (ddi_intr_handle_t)dup_hdlp; 68420036fe5Segillett bcopy(hdlp, dup_hdlp, sizeof (ddi_intr_handle_impl_t)); 68520036fe5Segillett 68620036fe5Segillett /* These fields are unique to each dupped msi-x vector */ 6877c478bd9Sstevel@tonic-gate rw_init(&dup_hdlp->ih_rwlock, NULL, RW_DRIVER, NULL); 6887c478bd9Sstevel@tonic-gate dup_hdlp->ih_state = DDI_IHDL_STATE_ADDED; 68920036fe5Segillett dup_hdlp->ih_inum = dup_inum; 69020036fe5Segillett dup_hdlp->ih_flags |= DDI_INTR_MSIX_DUP; 69120036fe5Segillett dup_hdlp->ih_dup_cnt = 0; 6927c478bd9Sstevel@tonic-gate 69320036fe5Segillett /* Point back to original vector */ 69420036fe5Segillett dup_hdlp->ih_main = hdlp; 6957c478bd9Sstevel@tonic-gate } 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 6987c478bd9Sstevel@tonic-gate return (ret); 6997c478bd9Sstevel@tonic-gate } 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate int 7027c478bd9Sstevel@tonic-gate ddi_intr_remove_handler(ddi_intr_handle_t h) 7037c478bd9Sstevel@tonic-gate { 7047c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp = (ddi_intr_handle_impl_t *)h; 70520036fe5Segillett int ret = DDI_SUCCESS; 7067c478bd9Sstevel@tonic-gate 7077c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_remove_handler: hdlp = %p\n", 7087c478bd9Sstevel@tonic-gate (void *)hdlp)); 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate if (hdlp == NULL) 7117c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_WRITER); 71420036fe5Segillett 7157c478bd9Sstevel@tonic-gate if (hdlp->ih_state != DDI_IHDL_STATE_ADDED) { 71620036fe5Segillett ret = DDI_EINVAL; 71720036fe5Segillett goto done; 71820036fe5Segillett } else if (hdlp->ih_flags & DDI_INTR_MSIX_DUP) 71920036fe5Segillett goto done; 72020036fe5Segillett 72120036fe5Segillett ASSERT(hdlp->ih_dup_cnt == 0); 72220036fe5Segillett if (hdlp->ih_dup_cnt > 0) { 72320036fe5Segillett DDI_INTR_APIDBG((CE_CONT, "ddi_intr_remove_handler: MSI-X " 72420036fe5Segillett "dup_cnt %d is not 0\n", hdlp->ih_dup_cnt)); 72520036fe5Segillett ret = DDI_FAILURE; 72620036fe5Segillett goto done; 7277c478bd9Sstevel@tonic-gate } 7287c478bd9Sstevel@tonic-gate 729a195726fSgovinda ret = i_ddi_intr_ops(hdlp->ih_dip, hdlp->ih_dip, 7307c478bd9Sstevel@tonic-gate DDI_INTROP_REMISR, hdlp, NULL); 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate if (ret == DDI_SUCCESS) { 7337c478bd9Sstevel@tonic-gate hdlp->ih_state = DDI_IHDL_STATE_ALLOC; 7347c478bd9Sstevel@tonic-gate hdlp->ih_cb_func = NULL; 7357c478bd9Sstevel@tonic-gate hdlp->ih_cb_arg1 = NULL; 7367c478bd9Sstevel@tonic-gate hdlp->ih_cb_arg2 = NULL; 7377c478bd9Sstevel@tonic-gate } 7387c478bd9Sstevel@tonic-gate 73920036fe5Segillett done: 7407c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 7417c478bd9Sstevel@tonic-gate return (ret); 7427c478bd9Sstevel@tonic-gate } 7437c478bd9Sstevel@tonic-gate 74409b1eac2SEvan Yan 74509b1eac2SEvan Yan /* 7467c478bd9Sstevel@tonic-gate * Interrupt enable/disable/block_enable/block_disable handlers 7477c478bd9Sstevel@tonic-gate */ 7487c478bd9Sstevel@tonic-gate int 7497c478bd9Sstevel@tonic-gate ddi_intr_enable(ddi_intr_handle_t h) 7507c478bd9Sstevel@tonic-gate { 7517c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp = (ddi_intr_handle_impl_t *)h; 7527c478bd9Sstevel@tonic-gate int ret; 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_enable: hdlp = %p\n", 7557c478bd9Sstevel@tonic-gate (void *)hdlp)); 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate if (hdlp == NULL) 7587c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_WRITER); 7617c478bd9Sstevel@tonic-gate if ((hdlp->ih_state != DDI_IHDL_STATE_ADDED) || 7627c478bd9Sstevel@tonic-gate ((hdlp->ih_type == DDI_INTR_TYPE_MSI) && 7637c478bd9Sstevel@tonic-gate (hdlp->ih_cap & DDI_INTR_FLAG_BLOCK))) { 7647c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 7657c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 7667c478bd9Sstevel@tonic-gate } 7677c478bd9Sstevel@tonic-gate 76820036fe5Segillett I_DDI_VERIFY_MSIX_HANDLE(hdlp); 76920036fe5Segillett 770a195726fSgovinda ret = i_ddi_intr_ops(hdlp->ih_dip, hdlp->ih_dip, 7717c478bd9Sstevel@tonic-gate DDI_INTROP_ENABLE, hdlp, NULL); 7727c478bd9Sstevel@tonic-gate 7732145b8d4SGuoli Shu if (ret == DDI_SUCCESS) { 7747c478bd9Sstevel@tonic-gate hdlp->ih_state = DDI_IHDL_STATE_ENABLE; 7752145b8d4SGuoli Shu i_ddi_intr_set_current_nenables(hdlp->ih_dip, 7762145b8d4SGuoli Shu i_ddi_intr_get_current_nenables(hdlp->ih_dip) + 1); 7772145b8d4SGuoli Shu } 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 7807c478bd9Sstevel@tonic-gate return (ret); 7817c478bd9Sstevel@tonic-gate } 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate int 7847c478bd9Sstevel@tonic-gate ddi_intr_disable(ddi_intr_handle_t h) 7857c478bd9Sstevel@tonic-gate { 7867c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp = (ddi_intr_handle_impl_t *)h; 7877c478bd9Sstevel@tonic-gate int ret; 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_disable: hdlp = %p\n", 7907c478bd9Sstevel@tonic-gate (void *)hdlp)); 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate if (hdlp == NULL) 7937c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_WRITER); 7967c478bd9Sstevel@tonic-gate if ((hdlp->ih_state != DDI_IHDL_STATE_ENABLE) || 7977c478bd9Sstevel@tonic-gate ((hdlp->ih_type == DDI_INTR_TYPE_MSI) && 7987c478bd9Sstevel@tonic-gate (hdlp->ih_cap & DDI_INTR_FLAG_BLOCK))) { 7997c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 8007c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate 80320036fe5Segillett I_DDI_VERIFY_MSIX_HANDLE(hdlp); 80420036fe5Segillett 805a195726fSgovinda ret = i_ddi_intr_ops(hdlp->ih_dip, hdlp->ih_dip, 8067c478bd9Sstevel@tonic-gate DDI_INTROP_DISABLE, hdlp, NULL); 8077c478bd9Sstevel@tonic-gate 8082145b8d4SGuoli Shu if (ret == DDI_SUCCESS) { 8097c478bd9Sstevel@tonic-gate hdlp->ih_state = DDI_IHDL_STATE_ADDED; 8102145b8d4SGuoli Shu i_ddi_intr_set_current_nenables(hdlp->ih_dip, 8112145b8d4SGuoli Shu i_ddi_intr_get_current_nenables(hdlp->ih_dip) - 1); 8122145b8d4SGuoli Shu } 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 8157c478bd9Sstevel@tonic-gate return (ret); 8167c478bd9Sstevel@tonic-gate } 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate int 8197c478bd9Sstevel@tonic-gate ddi_intr_block_enable(ddi_intr_handle_t *h_array, int count) 8207c478bd9Sstevel@tonic-gate { 8217c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp; 8227c478bd9Sstevel@tonic-gate int i, ret; 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_block_enable: h_array = %p\n", 8257c478bd9Sstevel@tonic-gate (void *)h_array)); 8267c478bd9Sstevel@tonic-gate 8277c478bd9Sstevel@tonic-gate if (h_array == NULL) 8287c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 8317c478bd9Sstevel@tonic-gate hdlp = (ddi_intr_handle_impl_t *)h_array[i]; 8327c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_READER); 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate if (hdlp->ih_state != DDI_IHDL_STATE_ADDED || 8357c478bd9Sstevel@tonic-gate hdlp->ih_type != DDI_INTR_TYPE_MSI || 8367c478bd9Sstevel@tonic-gate !(hdlp->ih_cap & DDI_INTR_FLAG_BLOCK)) { 8377c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 8387c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 8397c478bd9Sstevel@tonic-gate } 8407c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 8417c478bd9Sstevel@tonic-gate } 8427c478bd9Sstevel@tonic-gate 8437c478bd9Sstevel@tonic-gate hdlp = (ddi_intr_handle_impl_t *)h_array[0]; 8447c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_WRITER); 8457c478bd9Sstevel@tonic-gate hdlp->ih_scratch1 = count; 846102cb92eSjohnny hdlp->ih_scratch2 = (void *)h_array; 8477c478bd9Sstevel@tonic-gate 848a195726fSgovinda ret = i_ddi_intr_ops(hdlp->ih_dip, hdlp->ih_dip, 8497c478bd9Sstevel@tonic-gate DDI_INTROP_BLOCKENABLE, hdlp, NULL); 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 8527c478bd9Sstevel@tonic-gate 8537c478bd9Sstevel@tonic-gate if (ret == DDI_SUCCESS) { 8547c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 8557c478bd9Sstevel@tonic-gate hdlp = (ddi_intr_handle_impl_t *)h_array[i]; 8567c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_WRITER); 8577c478bd9Sstevel@tonic-gate hdlp->ih_state = DDI_IHDL_STATE_ENABLE; 8587c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 8597c478bd9Sstevel@tonic-gate } 8602145b8d4SGuoli Shu i_ddi_intr_set_current_nenables(hdlp->ih_dip, 1); 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate return (ret); 8647c478bd9Sstevel@tonic-gate } 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate int 8677c478bd9Sstevel@tonic-gate ddi_intr_block_disable(ddi_intr_handle_t *h_array, int count) 8687c478bd9Sstevel@tonic-gate { 8697c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp; 8707c478bd9Sstevel@tonic-gate int i, ret; 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_block_disable: h_array = %p\n", 8737c478bd9Sstevel@tonic-gate (void *)h_array)); 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate if (h_array == NULL) 8767c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 8777c478bd9Sstevel@tonic-gate 8787c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 8797c478bd9Sstevel@tonic-gate hdlp = (ddi_intr_handle_impl_t *)h_array[i]; 8807c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_READER); 8817c478bd9Sstevel@tonic-gate if (hdlp->ih_state != DDI_IHDL_STATE_ENABLE || 8827c478bd9Sstevel@tonic-gate hdlp->ih_type != DDI_INTR_TYPE_MSI || 8837c478bd9Sstevel@tonic-gate !(hdlp->ih_cap & DDI_INTR_FLAG_BLOCK)) { 8847c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 8857c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 8867c478bd9Sstevel@tonic-gate } 8877c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate hdlp = (ddi_intr_handle_impl_t *)h_array[0]; 8917c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_WRITER); 8927c478bd9Sstevel@tonic-gate hdlp->ih_scratch1 = count; 893102cb92eSjohnny hdlp->ih_scratch2 = (void *)h_array; 8947c478bd9Sstevel@tonic-gate 895a195726fSgovinda ret = i_ddi_intr_ops(hdlp->ih_dip, hdlp->ih_dip, 8967c478bd9Sstevel@tonic-gate DDI_INTROP_BLOCKDISABLE, hdlp, NULL); 8977c478bd9Sstevel@tonic-gate 8987c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate if (ret == DDI_SUCCESS) { 9017c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 9027c478bd9Sstevel@tonic-gate hdlp = (ddi_intr_handle_impl_t *)h_array[i]; 9037c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_WRITER); 9047c478bd9Sstevel@tonic-gate hdlp->ih_state = DDI_IHDL_STATE_ADDED; 9057c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 9067c478bd9Sstevel@tonic-gate } 9072145b8d4SGuoli Shu i_ddi_intr_set_current_nenables(hdlp->ih_dip, 0); 9087c478bd9Sstevel@tonic-gate } 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate return (ret); 9117c478bd9Sstevel@tonic-gate } 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate /* 9147c478bd9Sstevel@tonic-gate * Interrupt set/clr mask handlers 9157c478bd9Sstevel@tonic-gate */ 9167c478bd9Sstevel@tonic-gate int 9177c478bd9Sstevel@tonic-gate ddi_intr_set_mask(ddi_intr_handle_t h) 9187c478bd9Sstevel@tonic-gate { 9197c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp = (ddi_intr_handle_impl_t *)h; 9207c478bd9Sstevel@tonic-gate int ret; 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_set_mask: hdlp = %p\n", 9237c478bd9Sstevel@tonic-gate (void *)hdlp)); 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate if (hdlp == NULL) 9267c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_WRITER); 92907f14c08Sgovinda if ((hdlp->ih_state != DDI_IHDL_STATE_ENABLE) || 93007f14c08Sgovinda (!(hdlp->ih_cap & DDI_INTR_FLAG_MASKABLE))) { 9317c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 9327c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 9337c478bd9Sstevel@tonic-gate } 9347c478bd9Sstevel@tonic-gate 935a195726fSgovinda ret = i_ddi_intr_ops(hdlp->ih_dip, hdlp->ih_dip, 9367c478bd9Sstevel@tonic-gate DDI_INTROP_SETMASK, hdlp, NULL); 9377c478bd9Sstevel@tonic-gate 9387c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 9397c478bd9Sstevel@tonic-gate return (ret); 9407c478bd9Sstevel@tonic-gate } 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate int 9437c478bd9Sstevel@tonic-gate ddi_intr_clr_mask(ddi_intr_handle_t h) 9447c478bd9Sstevel@tonic-gate { 9457c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp = (ddi_intr_handle_impl_t *)h; 9467c478bd9Sstevel@tonic-gate int ret; 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_clr_mask: hdlp = %p\n", 9497c478bd9Sstevel@tonic-gate (void *)hdlp)); 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate if (hdlp == NULL) 9527c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_WRITER); 95507f14c08Sgovinda if ((hdlp->ih_state != DDI_IHDL_STATE_ENABLE) || 95607f14c08Sgovinda (!(hdlp->ih_cap & DDI_INTR_FLAG_MASKABLE))) { 9577c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 9587c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 9597c478bd9Sstevel@tonic-gate } 9607c478bd9Sstevel@tonic-gate 961a195726fSgovinda ret = i_ddi_intr_ops(hdlp->ih_dip, hdlp->ih_dip, 9627c478bd9Sstevel@tonic-gate DDI_INTROP_CLRMASK, hdlp, NULL); 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 9657c478bd9Sstevel@tonic-gate return (ret); 9667c478bd9Sstevel@tonic-gate } 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate /* 9697c478bd9Sstevel@tonic-gate * Interrupt get_pending handler 9707c478bd9Sstevel@tonic-gate */ 9717c478bd9Sstevel@tonic-gate int 9727c478bd9Sstevel@tonic-gate ddi_intr_get_pending(ddi_intr_handle_t h, int *pendingp) 9737c478bd9Sstevel@tonic-gate { 9747c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp = (ddi_intr_handle_impl_t *)h; 9757c478bd9Sstevel@tonic-gate int ret; 9767c478bd9Sstevel@tonic-gate 9777c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_get_pending: hdlp = %p\n", 9787c478bd9Sstevel@tonic-gate (void *)hdlp)); 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate if (hdlp == NULL) 9817c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_READER); 9847c478bd9Sstevel@tonic-gate if (!(hdlp->ih_cap & DDI_INTR_FLAG_PENDING)) { 9857c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 9867c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 9877c478bd9Sstevel@tonic-gate } 9887c478bd9Sstevel@tonic-gate 989a195726fSgovinda ret = i_ddi_intr_ops(hdlp->ih_dip, hdlp->ih_dip, 9907c478bd9Sstevel@tonic-gate DDI_INTROP_GETPENDING, hdlp, (void *)pendingp); 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 9937c478bd9Sstevel@tonic-gate return (ret); 9947c478bd9Sstevel@tonic-gate } 9957c478bd9Sstevel@tonic-gate 9967c478bd9Sstevel@tonic-gate /* 99709b1eac2SEvan Yan * Set the number of interrupts requested from IRM 99809b1eac2SEvan Yan */ 99909b1eac2SEvan Yan int 100009b1eac2SEvan Yan ddi_intr_set_nreq(dev_info_t *dip, int nreq) 100109b1eac2SEvan Yan { 1002a120541cSScott M. Carter int curr_type, nintrs; 1003a120541cSScott M. Carter 100409b1eac2SEvan Yan DDI_INTR_APIDBG((CE_CONT, "ddi_intr_set_nreq: dip %p, nreq %d\n", 100509b1eac2SEvan Yan (void *)dip, nreq)); 100609b1eac2SEvan Yan 1007a120541cSScott M. Carter ASSERT(dip != NULL); 1008a120541cSScott M. Carter ASSERT(nreq > 0); 1009a120541cSScott M. Carter 1010a120541cSScott M. Carter /* Sanity check inputs */ 1011a120541cSScott M. Carter if ((dip == NULL) || (nreq < 1)) 1012a120541cSScott M. Carter return (DDI_EINVAL); 1013a120541cSScott M. Carter 1014a120541cSScott M. Carter curr_type = i_ddi_intr_get_current_type(dip); 1015a120541cSScott M. Carter 1016a120541cSScott M. Carter /* Only valid for IRM drivers actively using interrupts */ 1017a120541cSScott M. Carter if ((curr_type == 0) || 1018a120541cSScott M. Carter (i_ddi_irm_supported(dip, curr_type) != DDI_SUCCESS)) 1019a120541cSScott M. Carter return (DDI_ENOTSUP); 1020a120541cSScott M. Carter 1021a120541cSScott M. Carter /* Range check */ 1022a120541cSScott M. Carter if (ddi_intr_get_nintrs(dip, curr_type, &nintrs) != DDI_SUCCESS) 1023a120541cSScott M. Carter return (DDI_FAILURE); 1024a120541cSScott M. Carter if (nreq > nintrs) 102509b1eac2SEvan Yan return (DDI_EINVAL); 102609b1eac2SEvan Yan 102709b1eac2SEvan Yan return (i_ddi_irm_modify(dip, nreq)); 102809b1eac2SEvan Yan } 102909b1eac2SEvan Yan 103009b1eac2SEvan Yan /* 10317c478bd9Sstevel@tonic-gate * Soft interrupt handlers 10327c478bd9Sstevel@tonic-gate */ 10337c478bd9Sstevel@tonic-gate /* 10347c478bd9Sstevel@tonic-gate * Add a soft interrupt and register its handler 10357c478bd9Sstevel@tonic-gate */ 10367c478bd9Sstevel@tonic-gate /* ARGSUSED */ 10377c478bd9Sstevel@tonic-gate int 10387c478bd9Sstevel@tonic-gate ddi_intr_add_softint(dev_info_t *dip, ddi_softint_handle_t *h_p, int soft_pri, 10397c478bd9Sstevel@tonic-gate ddi_intr_handler_t handler, void *arg1) 10407c478bd9Sstevel@tonic-gate { 10417c478bd9Sstevel@tonic-gate ddi_softint_hdl_impl_t *hdlp; 10427c478bd9Sstevel@tonic-gate int ret; 10437c478bd9Sstevel@tonic-gate 10447c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_add_softint: dip = %p, " 10457c478bd9Sstevel@tonic-gate "softpri = 0x%x\n", (void *)dip, soft_pri)); 10467c478bd9Sstevel@tonic-gate 10477c478bd9Sstevel@tonic-gate if ((dip == NULL) || (h_p == NULL) || (handler == NULL)) { 10487c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_add_softint: " 10497c478bd9Sstevel@tonic-gate "invalid arguments")); 10507c478bd9Sstevel@tonic-gate 10517c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 10527c478bd9Sstevel@tonic-gate } 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate /* Validate input arguments */ 10557c478bd9Sstevel@tonic-gate if (soft_pri < DDI_INTR_SOFTPRI_MIN || 10567c478bd9Sstevel@tonic-gate soft_pri > DDI_INTR_SOFTPRI_MAX) { 10577c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_add_softint: invalid " 10587c478bd9Sstevel@tonic-gate "soft_pri input given = %x\n", soft_pri)); 10597c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 10607c478bd9Sstevel@tonic-gate } 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate hdlp = (ddi_softint_hdl_impl_t *)kmem_zalloc( 10637c478bd9Sstevel@tonic-gate sizeof (ddi_softint_hdl_impl_t), KM_SLEEP); 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate /* fill up internally */ 10667c478bd9Sstevel@tonic-gate rw_init(&hdlp->ih_rwlock, NULL, RW_DRIVER, NULL); 10677c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_WRITER); 10687c478bd9Sstevel@tonic-gate hdlp->ih_pri = soft_pri; 10697c478bd9Sstevel@tonic-gate hdlp->ih_dip = dip; 10707c478bd9Sstevel@tonic-gate hdlp->ih_cb_func = handler; 10717c478bd9Sstevel@tonic-gate hdlp->ih_cb_arg1 = arg1; 10727c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_add_softint: hdlp = %p\n", 10737c478bd9Sstevel@tonic-gate (void *)hdlp)); 10747c478bd9Sstevel@tonic-gate 10757c478bd9Sstevel@tonic-gate /* do the platform specific calls */ 10767c478bd9Sstevel@tonic-gate if ((ret = i_ddi_add_softint(hdlp)) != DDI_SUCCESS) { 10777c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 10787c478bd9Sstevel@tonic-gate rw_destroy(&hdlp->ih_rwlock); 10797c478bd9Sstevel@tonic-gate kmem_free(hdlp, sizeof (ddi_softint_hdl_impl_t)); 10807c478bd9Sstevel@tonic-gate return (ret); 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate *h_p = (ddi_softint_handle_t)hdlp; 10847c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 10857c478bd9Sstevel@tonic-gate return (ret); 10867c478bd9Sstevel@tonic-gate } 10877c478bd9Sstevel@tonic-gate 10887c478bd9Sstevel@tonic-gate /* 10897c478bd9Sstevel@tonic-gate * Remove the soft interrupt 10907c478bd9Sstevel@tonic-gate */ 10917c478bd9Sstevel@tonic-gate int 10927c478bd9Sstevel@tonic-gate ddi_intr_remove_softint(ddi_softint_handle_t h) 10937c478bd9Sstevel@tonic-gate { 10947c478bd9Sstevel@tonic-gate ddi_softint_hdl_impl_t *hdlp = (ddi_softint_hdl_impl_t *)h; 10957c478bd9Sstevel@tonic-gate 10967c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_remove_softint: hdlp = %p\n", 10977c478bd9Sstevel@tonic-gate (void *)hdlp)); 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate if (hdlp == NULL) 11007c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 11017c478bd9Sstevel@tonic-gate 11027c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_WRITER); 11037c478bd9Sstevel@tonic-gate i_ddi_remove_softint(hdlp); 11047c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 11057c478bd9Sstevel@tonic-gate rw_destroy(&hdlp->ih_rwlock); 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate /* kmem_free the hdl impl_t structure allocated earlier */ 11087c478bd9Sstevel@tonic-gate kmem_free(hdlp, sizeof (ddi_softint_hdl_impl_t)); 11097c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 11107c478bd9Sstevel@tonic-gate } 11117c478bd9Sstevel@tonic-gate 11127c478bd9Sstevel@tonic-gate /* 11137c478bd9Sstevel@tonic-gate * Trigger a soft interrupt 11147c478bd9Sstevel@tonic-gate */ 11157c478bd9Sstevel@tonic-gate int 11167c478bd9Sstevel@tonic-gate ddi_intr_trigger_softint(ddi_softint_handle_t h, void *arg2) 11177c478bd9Sstevel@tonic-gate { 11187c478bd9Sstevel@tonic-gate ddi_softint_hdl_impl_t *hdlp = (ddi_softint_hdl_impl_t *)h; 11197c478bd9Sstevel@tonic-gate int ret; 11207c478bd9Sstevel@tonic-gate 11217c478bd9Sstevel@tonic-gate if (hdlp == NULL) 11227c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 11237c478bd9Sstevel@tonic-gate 1124b08160e2Sgovinda if ((ret = i_ddi_trigger_softint(hdlp, arg2)) != DDI_SUCCESS) { 11257c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_trigger_softint: failed, " 11267c478bd9Sstevel@tonic-gate " ret 0%x\n", ret)); 1127b08160e2Sgovinda 1128b08160e2Sgovinda return (ret); 11297c478bd9Sstevel@tonic-gate } 11307c478bd9Sstevel@tonic-gate 1131b08160e2Sgovinda hdlp->ih_cb_arg2 = arg2; 1132b08160e2Sgovinda return (DDI_SUCCESS); 11337c478bd9Sstevel@tonic-gate } 11347c478bd9Sstevel@tonic-gate 11357c478bd9Sstevel@tonic-gate /* 11367c478bd9Sstevel@tonic-gate * Get the soft interrupt priority 11377c478bd9Sstevel@tonic-gate */ 11387c478bd9Sstevel@tonic-gate int 11397c478bd9Sstevel@tonic-gate ddi_intr_get_softint_pri(ddi_softint_handle_t h, uint_t *soft_prip) 11407c478bd9Sstevel@tonic-gate { 11417c478bd9Sstevel@tonic-gate ddi_softint_hdl_impl_t *hdlp = (ddi_softint_hdl_impl_t *)h; 11427c478bd9Sstevel@tonic-gate 11437c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_get_softint_pri: h = %p\n", 11447c478bd9Sstevel@tonic-gate (void *)h)); 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate if (hdlp == NULL) 11477c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_READER); 11507c478bd9Sstevel@tonic-gate *soft_prip = hdlp->ih_pri; 11517c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 11527c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 11537c478bd9Sstevel@tonic-gate } 11547c478bd9Sstevel@tonic-gate 11557c478bd9Sstevel@tonic-gate /* 11567c478bd9Sstevel@tonic-gate * Set the soft interrupt priority 11577c478bd9Sstevel@tonic-gate */ 11587c478bd9Sstevel@tonic-gate int 11597c478bd9Sstevel@tonic-gate ddi_intr_set_softint_pri(ddi_softint_handle_t h, uint_t soft_pri) 11607c478bd9Sstevel@tonic-gate { 11617c478bd9Sstevel@tonic-gate ddi_softint_hdl_impl_t *hdlp = (ddi_softint_hdl_impl_t *)h; 11627c478bd9Sstevel@tonic-gate int ret; 11637c478bd9Sstevel@tonic-gate uint_t orig_soft_pri; 11647c478bd9Sstevel@tonic-gate 11657c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_set_softint_pri: h = %p\n", 11667c478bd9Sstevel@tonic-gate (void *)h)); 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate if (hdlp == NULL) 11697c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate /* Validate priority argument */ 11727c478bd9Sstevel@tonic-gate if (soft_pri < DDI_INTR_SOFTPRI_MIN || 11737c478bd9Sstevel@tonic-gate soft_pri > DDI_INTR_SOFTPRI_MAX) { 11747c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_set_softint_pri: invalid " 11757c478bd9Sstevel@tonic-gate "soft_pri input given = %x\n", soft_pri)); 11767c478bd9Sstevel@tonic-gate return (DDI_EINVAL); 11777c478bd9Sstevel@tonic-gate } 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate rw_enter(&hdlp->ih_rwlock, RW_WRITER); 11807c478bd9Sstevel@tonic-gate orig_soft_pri = hdlp->ih_pri; 11817c478bd9Sstevel@tonic-gate hdlp->ih_pri = soft_pri; 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate if ((ret = i_ddi_set_softint_pri(hdlp, orig_soft_pri)) != DDI_SUCCESS) { 11847c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_set_softint_pri: failed, " 11857c478bd9Sstevel@tonic-gate " ret 0%x\n", ret)); 11867c478bd9Sstevel@tonic-gate hdlp->ih_pri = orig_soft_pri; 11877c478bd9Sstevel@tonic-gate } 11887c478bd9Sstevel@tonic-gate 11897c478bd9Sstevel@tonic-gate rw_exit(&hdlp->ih_rwlock); 11907c478bd9Sstevel@tonic-gate return (ret); 11917c478bd9Sstevel@tonic-gate } 11927c478bd9Sstevel@tonic-gate 11937c478bd9Sstevel@tonic-gate /* 11947c478bd9Sstevel@tonic-gate * Old DDI interrupt framework 1195a195726fSgovinda * 1196a195726fSgovinda * The following DDI interrupt interfaces are obsolete. 1197a195726fSgovinda * Use the above new DDI interrupt interfaces instead. 11987c478bd9Sstevel@tonic-gate */ 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate int 12017c478bd9Sstevel@tonic-gate ddi_intr_hilevel(dev_info_t *dip, uint_t inumber) 12027c478bd9Sstevel@tonic-gate { 12035febcb4aSScott Carter, SD IOSW ddi_intr_handle_t hdl; 12045febcb4aSScott Carter, SD IOSW ddi_intr_handle_t *hdl_p; 12055febcb4aSScott Carter, SD IOSW size_t hdl_sz = 0; 12067c478bd9Sstevel@tonic-gate int actual, ret; 12077c478bd9Sstevel@tonic-gate uint_t high_pri, pri; 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_hilevel: name=%s%d dip=0x%p " 12107c478bd9Sstevel@tonic-gate "inum=0x%x\n", ddi_driver_name(dip), ddi_get_instance(dip), 12117c478bd9Sstevel@tonic-gate (void *)dip, inumber)); 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate /* 12147c478bd9Sstevel@tonic-gate * The device driver may have already registed with the 12157c478bd9Sstevel@tonic-gate * framework. If so, first try to get the existing interrupt handle 12167c478bd9Sstevel@tonic-gate * for that given inumber and use that handle. 12177c478bd9Sstevel@tonic-gate */ 12185febcb4aSScott Carter, SD IOSW if ((hdl = i_ddi_get_intr_handle(dip, inumber)) == NULL) { 12195febcb4aSScott Carter, SD IOSW hdl_sz = sizeof (ddi_intr_handle_t) * (inumber + 1); 12205febcb4aSScott Carter, SD IOSW hdl_p = kmem_zalloc(hdl_sz, KM_SLEEP); 12215febcb4aSScott Carter, SD IOSW if ((ret = ddi_intr_alloc(dip, hdl_p, DDI_INTR_TYPE_FIXED, 12229c75c6bfSgovinda inumber, 1, &actual, 12239c75c6bfSgovinda DDI_INTR_ALLOC_NORMAL)) != DDI_SUCCESS) { 12247c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_hilevel: " 12257c478bd9Sstevel@tonic-gate "ddi_intr_alloc failed, ret 0x%x\n", ret)); 12265febcb4aSScott Carter, SD IOSW kmem_free(hdl_p, hdl_sz); 12277c478bd9Sstevel@tonic-gate return (0); 12287c478bd9Sstevel@tonic-gate } 12295febcb4aSScott Carter, SD IOSW hdl = hdl_p[inumber]; 12307c478bd9Sstevel@tonic-gate } 12317c478bd9Sstevel@tonic-gate 12327c478bd9Sstevel@tonic-gate if ((ret = ddi_intr_get_pri(hdl, &pri)) != DDI_SUCCESS) { 12337c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_hilevel: " 12347c478bd9Sstevel@tonic-gate "ddi_intr_get_pri failed, ret 0x%x\n", ret)); 12357c478bd9Sstevel@tonic-gate (void) ddi_intr_free(hdl); 12365febcb4aSScott Carter, SD IOSW if (hdl_sz) 12375febcb4aSScott Carter, SD IOSW kmem_free(hdl_p, hdl_sz); 12387c478bd9Sstevel@tonic-gate return (0); 12397c478bd9Sstevel@tonic-gate } 12407c478bd9Sstevel@tonic-gate 12417c478bd9Sstevel@tonic-gate high_pri = ddi_intr_get_hilevel_pri(); 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_intr_hilevel: pri = %x, " 12447c478bd9Sstevel@tonic-gate "high_pri = %x\n", pri, high_pri)); 12457c478bd9Sstevel@tonic-gate 12467c478bd9Sstevel@tonic-gate /* Free the handle allocated here only if no existing handle exists */ 12475febcb4aSScott Carter, SD IOSW if (hdl_sz) { 12487c478bd9Sstevel@tonic-gate (void) ddi_intr_free(hdl); 12495febcb4aSScott Carter, SD IOSW kmem_free(hdl_p, hdl_sz); 12505febcb4aSScott Carter, SD IOSW } 12517c478bd9Sstevel@tonic-gate 12527c478bd9Sstevel@tonic-gate return (pri >= high_pri); 12537c478bd9Sstevel@tonic-gate } 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate int 12567c478bd9Sstevel@tonic-gate ddi_dev_nintrs(dev_info_t *dip, int *result) 12577c478bd9Sstevel@tonic-gate { 12587c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_dev_nintrs: name=%s%d dip=0x%p\n", 12597c478bd9Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip), (void *)dip)); 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate if (ddi_intr_get_nintrs(dip, DDI_INTR_TYPE_FIXED, 12627c478bd9Sstevel@tonic-gate result) != DDI_SUCCESS) { 12637c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_dev_nintrs: " 12647c478bd9Sstevel@tonic-gate "ddi_intr_get_nintrs failed\n")); 12657c478bd9Sstevel@tonic-gate *result = 0; 12667c478bd9Sstevel@tonic-gate } 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 12697c478bd9Sstevel@tonic-gate } 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate int 12727c478bd9Sstevel@tonic-gate ddi_get_iblock_cookie(dev_info_t *dip, uint_t inumber, 12737c478bd9Sstevel@tonic-gate ddi_iblock_cookie_t *iblock_cookiep) 12747c478bd9Sstevel@tonic-gate { 12755febcb4aSScott Carter, SD IOSW ddi_intr_handle_t hdl; 12765febcb4aSScott Carter, SD IOSW ddi_intr_handle_t *hdl_p; 12775febcb4aSScott Carter, SD IOSW size_t hdl_sz = 0; 12787c478bd9Sstevel@tonic-gate int actual, ret; 12797c478bd9Sstevel@tonic-gate uint_t pri; 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_get_iblock_cookie: name=%s%d dip=0x%p " 12827c478bd9Sstevel@tonic-gate "inum=0x%x\n", ddi_driver_name(dip), ddi_get_instance(dip), 12837c478bd9Sstevel@tonic-gate (void *)dip, inumber)); 12847c478bd9Sstevel@tonic-gate 12857c478bd9Sstevel@tonic-gate ASSERT(iblock_cookiep != NULL); 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate /* 12887c478bd9Sstevel@tonic-gate * The device driver may have already registed with the 12897c478bd9Sstevel@tonic-gate * framework. If so, first try to get the existing interrupt handle 12907c478bd9Sstevel@tonic-gate * for that given inumber and use that handle. 12917c478bd9Sstevel@tonic-gate */ 12925febcb4aSScott Carter, SD IOSW if ((hdl = i_ddi_get_intr_handle(dip, inumber)) == NULL) { 12935febcb4aSScott Carter, SD IOSW hdl_sz = sizeof (ddi_intr_handle_t) * (inumber + 1); 12945febcb4aSScott Carter, SD IOSW hdl_p = kmem_zalloc(hdl_sz, KM_SLEEP); 12955febcb4aSScott Carter, SD IOSW if ((ret = ddi_intr_alloc(dip, hdl_p, 12965febcb4aSScott Carter, SD IOSW DDI_INTR_TYPE_FIXED, inumber, 1, &actual, 12979c75c6bfSgovinda DDI_INTR_ALLOC_NORMAL)) != DDI_SUCCESS) { 12987c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_get_iblock_cookie: " 12997c478bd9Sstevel@tonic-gate "ddi_intr_alloc failed, ret 0x%x\n", ret)); 13005febcb4aSScott Carter, SD IOSW kmem_free(hdl_p, hdl_sz); 13017c478bd9Sstevel@tonic-gate return (DDI_INTR_NOTFOUND); 13027c478bd9Sstevel@tonic-gate } 13035febcb4aSScott Carter, SD IOSW hdl = hdl_p[inumber]; 13047c478bd9Sstevel@tonic-gate } 13057c478bd9Sstevel@tonic-gate 13067c478bd9Sstevel@tonic-gate if ((ret = ddi_intr_get_pri(hdl, &pri)) != DDI_SUCCESS) { 13077c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_get_iblock_cookie: " 13087c478bd9Sstevel@tonic-gate "ddi_intr_get_pri failed, ret 0x%x\n", ret)); 13097c478bd9Sstevel@tonic-gate (void) ddi_intr_free(hdl); 13105febcb4aSScott Carter, SD IOSW if (hdl_sz) 13115febcb4aSScott Carter, SD IOSW kmem_free(hdl_p, hdl_sz); 13127c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 13137c478bd9Sstevel@tonic-gate } 13147c478bd9Sstevel@tonic-gate 1315abdbd06dSagiri *iblock_cookiep = (ddi_iblock_cookie_t)(uintptr_t)pri; 13167c478bd9Sstevel@tonic-gate /* Free the handle allocated here only if no existing handle exists */ 13175febcb4aSScott Carter, SD IOSW if (hdl_sz) { 13187c478bd9Sstevel@tonic-gate (void) ddi_intr_free(hdl); 13195febcb4aSScott Carter, SD IOSW kmem_free(hdl_p, hdl_sz); 13205febcb4aSScott Carter, SD IOSW } 13217c478bd9Sstevel@tonic-gate 13227c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 13237c478bd9Sstevel@tonic-gate } 13247c478bd9Sstevel@tonic-gate 13257c478bd9Sstevel@tonic-gate int 13267c478bd9Sstevel@tonic-gate ddi_add_intr(dev_info_t *dip, uint_t inumber, 13277c478bd9Sstevel@tonic-gate ddi_iblock_cookie_t *iblock_cookiep, 13287c478bd9Sstevel@tonic-gate ddi_idevice_cookie_t *idevice_cookiep, 13297c478bd9Sstevel@tonic-gate uint_t (*int_handler)(caddr_t int_handler_arg), 13307c478bd9Sstevel@tonic-gate caddr_t int_handler_arg) 13317c478bd9Sstevel@tonic-gate { 13327c478bd9Sstevel@tonic-gate ddi_intr_handle_t *hdl_p; 13335febcb4aSScott Carter, SD IOSW size_t hdl_sz; 13347c478bd9Sstevel@tonic-gate int actual, ret; 13357c478bd9Sstevel@tonic-gate uint_t pri; 13367c478bd9Sstevel@tonic-gate 13377c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_add_intr: name=%s%d dip=0x%p " 13387c478bd9Sstevel@tonic-gate "inum=0x%x\n", ddi_driver_name(dip), ddi_get_instance(dip), 13397c478bd9Sstevel@tonic-gate (void *)dip, inumber)); 13407c478bd9Sstevel@tonic-gate 13415febcb4aSScott Carter, SD IOSW hdl_sz = sizeof (ddi_intr_handle_t) * (inumber + 1); 13425febcb4aSScott Carter, SD IOSW hdl_p = kmem_zalloc(hdl_sz, KM_SLEEP); 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate if ((ret = ddi_intr_alloc(dip, hdl_p, DDI_INTR_TYPE_FIXED, 13459c75c6bfSgovinda inumber, 1, &actual, DDI_INTR_ALLOC_NORMAL)) != DDI_SUCCESS) { 13467c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_add_intr: " 13477c478bd9Sstevel@tonic-gate "ddi_intr_alloc failed, ret 0x%x\n", ret)); 13485febcb4aSScott Carter, SD IOSW kmem_free(hdl_p, hdl_sz); 13497c478bd9Sstevel@tonic-gate return (DDI_INTR_NOTFOUND); 13507c478bd9Sstevel@tonic-gate } 13517c478bd9Sstevel@tonic-gate 13525febcb4aSScott Carter, SD IOSW if ((ret = ddi_intr_get_pri(hdl_p[inumber], &pri)) != DDI_SUCCESS) { 13537c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_add_intr: " 13547c478bd9Sstevel@tonic-gate "ddi_intr_get_pri failed, ret 0x%x\n", ret)); 13555febcb4aSScott Carter, SD IOSW (void) ddi_intr_free(hdl_p[inumber]); 13565febcb4aSScott Carter, SD IOSW kmem_free(hdl_p, hdl_sz); 13577c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 13587c478bd9Sstevel@tonic-gate } 13597c478bd9Sstevel@tonic-gate 13605febcb4aSScott Carter, SD IOSW if ((ret = ddi_intr_add_handler(hdl_p[inumber], (ddi_intr_handler_t *) 13617c478bd9Sstevel@tonic-gate int_handler, int_handler_arg, NULL)) != DDI_SUCCESS) { 13627c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_add_intr: " 13637c478bd9Sstevel@tonic-gate "ddi_intr_add_handler failed, ret 0x%x\n", ret)); 13645febcb4aSScott Carter, SD IOSW (void) ddi_intr_free(hdl_p[inumber]); 13655febcb4aSScott Carter, SD IOSW kmem_free(hdl_p, hdl_sz); 13667c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 13677c478bd9Sstevel@tonic-gate } 13687c478bd9Sstevel@tonic-gate 13695febcb4aSScott Carter, SD IOSW if ((ret = ddi_intr_enable(hdl_p[inumber])) != DDI_SUCCESS) { 13707c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_add_intr: " 13717c478bd9Sstevel@tonic-gate "ddi_intr_enable failed, ret 0x%x\n", ret)); 13725febcb4aSScott Carter, SD IOSW (void) ddi_intr_remove_handler(hdl_p[inumber]); 13735febcb4aSScott Carter, SD IOSW (void) ddi_intr_free(hdl_p[inumber]); 13745febcb4aSScott Carter, SD IOSW kmem_free(hdl_p, hdl_sz); 13757c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 13767c478bd9Sstevel@tonic-gate } 13777c478bd9Sstevel@tonic-gate 13787c478bd9Sstevel@tonic-gate if (iblock_cookiep) 1379abdbd06dSagiri *iblock_cookiep = (ddi_iblock_cookie_t)(uintptr_t)pri; 13807c478bd9Sstevel@tonic-gate 13817c478bd9Sstevel@tonic-gate if (idevice_cookiep) { 13827c478bd9Sstevel@tonic-gate idevice_cookiep->idev_vector = 0; 13837c478bd9Sstevel@tonic-gate idevice_cookiep->idev_priority = pri; 13847c478bd9Sstevel@tonic-gate } 13857c478bd9Sstevel@tonic-gate 13865febcb4aSScott Carter, SD IOSW kmem_free(hdl_p, hdl_sz); 13875febcb4aSScott Carter, SD IOSW 13887c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 13897c478bd9Sstevel@tonic-gate } 13907c478bd9Sstevel@tonic-gate 13917c478bd9Sstevel@tonic-gate /* ARGSUSED */ 13927c478bd9Sstevel@tonic-gate int 13937c478bd9Sstevel@tonic-gate ddi_add_fastintr(dev_info_t *dip, uint_t inumber, 13947c478bd9Sstevel@tonic-gate ddi_iblock_cookie_t *iblock_cookiep, 13957c478bd9Sstevel@tonic-gate ddi_idevice_cookie_t *idevice_cookiep, 13967c478bd9Sstevel@tonic-gate uint_t (*hi_int_handler)(void)) 13977c478bd9Sstevel@tonic-gate { 13987c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_add_fastintr: name=%s%d dip=0x%p " 13997c478bd9Sstevel@tonic-gate "inum=0x%x: Not supported, return failure\n", ddi_driver_name(dip), 14007c478bd9Sstevel@tonic-gate ddi_get_instance(dip), (void *)dip, inumber)); 14017c478bd9Sstevel@tonic-gate 14027c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 14037c478bd9Sstevel@tonic-gate } 14047c478bd9Sstevel@tonic-gate 14057c478bd9Sstevel@tonic-gate /* ARGSUSED */ 14067c478bd9Sstevel@tonic-gate void 14077c478bd9Sstevel@tonic-gate ddi_remove_intr(dev_info_t *dip, uint_t inum, ddi_iblock_cookie_t iblock_cookie) 14087c478bd9Sstevel@tonic-gate { 14095febcb4aSScott Carter, SD IOSW ddi_intr_handle_t hdl; 14107c478bd9Sstevel@tonic-gate int ret; 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_remove_intr: name=%s%d dip=0x%p " 14137c478bd9Sstevel@tonic-gate "inum=0x%x\n", ddi_driver_name(dip), ddi_get_instance(dip), 14147c478bd9Sstevel@tonic-gate (void *)dip, inum)); 14157c478bd9Sstevel@tonic-gate 14165febcb4aSScott Carter, SD IOSW if ((hdl = i_ddi_get_intr_handle(dip, inum)) == NULL) { 14177c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_remove_intr: no handle " 14187c478bd9Sstevel@tonic-gate "found\n")); 14197c478bd9Sstevel@tonic-gate return; 14207c478bd9Sstevel@tonic-gate } 14217c478bd9Sstevel@tonic-gate 14225febcb4aSScott Carter, SD IOSW if ((ret = ddi_intr_disable(hdl)) != DDI_SUCCESS) { 14237c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_remove_intr: " 14247c478bd9Sstevel@tonic-gate "ddi_intr_disable failed, ret 0x%x\n", ret)); 14257c478bd9Sstevel@tonic-gate return; 14267c478bd9Sstevel@tonic-gate } 14277c478bd9Sstevel@tonic-gate 14285febcb4aSScott Carter, SD IOSW if ((ret = ddi_intr_remove_handler(hdl)) != DDI_SUCCESS) { 14297c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_remove_intr: " 14307c478bd9Sstevel@tonic-gate "ddi_intr_remove_handler failed, ret 0x%x\n", ret)); 14317c478bd9Sstevel@tonic-gate return; 14327c478bd9Sstevel@tonic-gate } 14337c478bd9Sstevel@tonic-gate 14345febcb4aSScott Carter, SD IOSW if ((ret = ddi_intr_free(hdl)) != DDI_SUCCESS) { 14357c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_remove_intr: " 14367c478bd9Sstevel@tonic-gate "ddi_intr_free failed, ret 0x%x\n", ret)); 14377c478bd9Sstevel@tonic-gate return; 14387c478bd9Sstevel@tonic-gate } 14397c478bd9Sstevel@tonic-gate } 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate /* ARGSUSED */ 14427c478bd9Sstevel@tonic-gate int 14437c478bd9Sstevel@tonic-gate ddi_get_soft_iblock_cookie(dev_info_t *dip, int preference, 14447c478bd9Sstevel@tonic-gate ddi_iblock_cookie_t *iblock_cookiep) 14457c478bd9Sstevel@tonic-gate { 14467c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_get_soft_iblock_cookie: name=%s%d " 14477c478bd9Sstevel@tonic-gate "dip=0x%p pref=0x%x\n", ddi_driver_name(dip), ddi_get_instance(dip), 14487c478bd9Sstevel@tonic-gate (void *)dip, preference)); 14497c478bd9Sstevel@tonic-gate 14507c478bd9Sstevel@tonic-gate ASSERT(iblock_cookiep != NULL); 14517c478bd9Sstevel@tonic-gate 14527c478bd9Sstevel@tonic-gate if (preference == DDI_SOFTINT_FIXED) 14537c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 14547c478bd9Sstevel@tonic-gate 1455abdbd06dSagiri *iblock_cookiep = (ddi_iblock_cookie_t)((uintptr_t) 14567c478bd9Sstevel@tonic-gate ((preference > DDI_SOFTINT_MED) ? DDI_SOFT_INTR_PRI_H : 14577c478bd9Sstevel@tonic-gate DDI_SOFT_INTR_PRI_M)); 14587c478bd9Sstevel@tonic-gate 14597c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 14607c478bd9Sstevel@tonic-gate } 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate int 14637c478bd9Sstevel@tonic-gate ddi_add_softintr(dev_info_t *dip, int preference, ddi_softintr_t *idp, 14647c478bd9Sstevel@tonic-gate ddi_iblock_cookie_t *iblock_cookiep, 14657c478bd9Sstevel@tonic-gate ddi_idevice_cookie_t *idevice_cookiep, 14667c478bd9Sstevel@tonic-gate uint_t (*int_handler)(caddr_t int_handler_arg), 14677c478bd9Sstevel@tonic-gate caddr_t int_handler_arg) 14687c478bd9Sstevel@tonic-gate { 14697c478bd9Sstevel@tonic-gate ddi_softint_handle_t *hdl_p; 14707c478bd9Sstevel@tonic-gate uint64_t softpri; 14717c478bd9Sstevel@tonic-gate int ret; 14727c478bd9Sstevel@tonic-gate 14737c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_add_softintr: name=%s%d dip=0x%p " 14747c478bd9Sstevel@tonic-gate "pref=0x%x\n", ddi_driver_name(dip), ddi_get_instance(dip), 14757c478bd9Sstevel@tonic-gate (void *)dip, preference)); 14767c478bd9Sstevel@tonic-gate 14777c478bd9Sstevel@tonic-gate if ((idp == NULL) || ((preference == DDI_SOFTINT_FIXED) && 14787c478bd9Sstevel@tonic-gate (iblock_cookiep == NULL))) 14797c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 14807c478bd9Sstevel@tonic-gate 14817c478bd9Sstevel@tonic-gate /* Translate the priority preference */ 14827c478bd9Sstevel@tonic-gate if (preference == DDI_SOFTINT_FIXED) { 1483b52a2671Seota softpri = (uint64_t)(uintptr_t)*iblock_cookiep; 14847c478bd9Sstevel@tonic-gate softpri = MIN(softpri, DDI_SOFT_INTR_PRI_H); 14857c478bd9Sstevel@tonic-gate } else { 14867c478bd9Sstevel@tonic-gate softpri = (uint64_t)((preference > DDI_SOFTINT_MED) ? 14877c478bd9Sstevel@tonic-gate DDI_SOFT_INTR_PRI_H : DDI_SOFT_INTR_PRI_M); 14887c478bd9Sstevel@tonic-gate } 14897c478bd9Sstevel@tonic-gate 14907c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_add_softintr: preference 0x%x " 14917c478bd9Sstevel@tonic-gate "softpri 0x%lx\n", preference, (long)softpri)); 14927c478bd9Sstevel@tonic-gate 14937c478bd9Sstevel@tonic-gate hdl_p = kmem_zalloc(sizeof (ddi_softint_handle_t), KM_SLEEP); 14947c478bd9Sstevel@tonic-gate if ((ret = ddi_intr_add_softint(dip, hdl_p, softpri, 14957c478bd9Sstevel@tonic-gate (ddi_intr_handler_t *)int_handler, int_handler_arg)) != 14967c478bd9Sstevel@tonic-gate DDI_SUCCESS) { 14977c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_add_softintr: " 14987c478bd9Sstevel@tonic-gate "ddi_intr_add_softint failed, ret 0x%x\n", ret)); 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate kmem_free(hdl_p, sizeof (ddi_softint_handle_t)); 15017c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 15027c478bd9Sstevel@tonic-gate } 15037c478bd9Sstevel@tonic-gate 15047c478bd9Sstevel@tonic-gate if (iblock_cookiep) 1505b52a2671Seota *iblock_cookiep = (ddi_iblock_cookie_t)(uintptr_t)softpri; 15067c478bd9Sstevel@tonic-gate 15077c478bd9Sstevel@tonic-gate if (idevice_cookiep) { 15087c478bd9Sstevel@tonic-gate idevice_cookiep->idev_vector = 0; 15097c478bd9Sstevel@tonic-gate idevice_cookiep->idev_priority = softpri; 15107c478bd9Sstevel@tonic-gate } 15117c478bd9Sstevel@tonic-gate 15127c478bd9Sstevel@tonic-gate *idp = (ddi_softintr_t)hdl_p; 15137c478bd9Sstevel@tonic-gate 15147c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_add_softintr: dip = 0x%p, " 15157c478bd9Sstevel@tonic-gate "idp = 0x%p, ret = %x\n", (void *)dip, (void *)*idp, ret)); 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 15187c478bd9Sstevel@tonic-gate } 15197c478bd9Sstevel@tonic-gate 15207c478bd9Sstevel@tonic-gate void 15217c478bd9Sstevel@tonic-gate ddi_remove_softintr(ddi_softintr_t id) 15227c478bd9Sstevel@tonic-gate { 15237c478bd9Sstevel@tonic-gate ddi_softint_handle_t *h_p = (ddi_softint_handle_t *)id; 15247c478bd9Sstevel@tonic-gate 15257c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_remove_softintr: id=0x%p\n", 15267c478bd9Sstevel@tonic-gate (void *)id)); 15277c478bd9Sstevel@tonic-gate 15287c478bd9Sstevel@tonic-gate if (h_p == NULL) 15297c478bd9Sstevel@tonic-gate return; 15307c478bd9Sstevel@tonic-gate 15317c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_remove_softintr: handle 0x%p\n", 15327c478bd9Sstevel@tonic-gate (void *)h_p)); 15337c478bd9Sstevel@tonic-gate 15347c478bd9Sstevel@tonic-gate (void) ddi_intr_remove_softint(*h_p); 15357c478bd9Sstevel@tonic-gate kmem_free(h_p, sizeof (ddi_softint_handle_t)); 15367c478bd9Sstevel@tonic-gate } 15377c478bd9Sstevel@tonic-gate 15387c478bd9Sstevel@tonic-gate void 15397c478bd9Sstevel@tonic-gate ddi_trigger_softintr(ddi_softintr_t id) 15407c478bd9Sstevel@tonic-gate { 15417c478bd9Sstevel@tonic-gate ddi_softint_handle_t *h_p = (ddi_softint_handle_t *)id; 15427c478bd9Sstevel@tonic-gate int ret; 15437c478bd9Sstevel@tonic-gate 15447c478bd9Sstevel@tonic-gate if (h_p == NULL) 15457c478bd9Sstevel@tonic-gate return; 15467c478bd9Sstevel@tonic-gate 15477c478bd9Sstevel@tonic-gate if ((ret = ddi_intr_trigger_softint(*h_p, NULL)) != DDI_SUCCESS) { 15487c478bd9Sstevel@tonic-gate DDI_INTR_APIDBG((CE_CONT, "ddi_trigger_softintr: " 15497c478bd9Sstevel@tonic-gate "ddi_intr_trigger_softint failed, hdlp 0x%p " 15507c478bd9Sstevel@tonic-gate "ret 0x%x\n", (void *)h_p, ret)); 15517c478bd9Sstevel@tonic-gate } 15527c478bd9Sstevel@tonic-gate } 1553