17613SVikram.Hegde@Sun.COM /* 27613SVikram.Hegde@Sun.COM * CDDL HEADER START 37613SVikram.Hegde@Sun.COM * 47613SVikram.Hegde@Sun.COM * The contents of this file are subject to the terms of the 57613SVikram.Hegde@Sun.COM * Common Development and Distribution License (the "License"). 67613SVikram.Hegde@Sun.COM * You may not use this file except in compliance with the License. 77613SVikram.Hegde@Sun.COM * 87613SVikram.Hegde@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97613SVikram.Hegde@Sun.COM * or http://www.opensolaris.org/os/licensing. 107613SVikram.Hegde@Sun.COM * See the License for the specific language governing permissions 117613SVikram.Hegde@Sun.COM * and limitations under the License. 127613SVikram.Hegde@Sun.COM * 137613SVikram.Hegde@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 147613SVikram.Hegde@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157613SVikram.Hegde@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 167613SVikram.Hegde@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 177613SVikram.Hegde@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 187613SVikram.Hegde@Sun.COM * 197613SVikram.Hegde@Sun.COM * CDDL HEADER END 207613SVikram.Hegde@Sun.COM */ 217613SVikram.Hegde@Sun.COM /* 227613SVikram.Hegde@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237613SVikram.Hegde@Sun.COM * Use is subject to license terms. 247613SVikram.Hegde@Sun.COM */ 257613SVikram.Hegde@Sun.COM 267613SVikram.Hegde@Sun.COM #pragma ident "@(#)iommulib.c 1.6 08/09/07 SMI" 277613SVikram.Hegde@Sun.COM 287613SVikram.Hegde@Sun.COM #include <sys/sunddi.h> 297613SVikram.Hegde@Sun.COM #include <sys/sunndi.h> 307613SVikram.Hegde@Sun.COM #include <sys/errno.h> 317613SVikram.Hegde@Sun.COM #include <sys/modctl.h> 327613SVikram.Hegde@Sun.COM #include <sys/iommulib.h> 337613SVikram.Hegde@Sun.COM 347613SVikram.Hegde@Sun.COM /* ******** Type definitions private to this file ********************** */ 357613SVikram.Hegde@Sun.COM 367613SVikram.Hegde@Sun.COM /* 1 per IOMMU unit. There may be more than one per dip */ 377613SVikram.Hegde@Sun.COM typedef struct iommulib_unit { 387613SVikram.Hegde@Sun.COM kmutex_t ilu_lock; 397613SVikram.Hegde@Sun.COM uint64_t ilu_ref; 407613SVikram.Hegde@Sun.COM uint32_t ilu_unitid; 417613SVikram.Hegde@Sun.COM dev_info_t *ilu_dip; 427613SVikram.Hegde@Sun.COM iommulib_ops_t *ilu_ops; 437613SVikram.Hegde@Sun.COM void* ilu_data; 447613SVikram.Hegde@Sun.COM struct iommulib_unit *ilu_next; 457613SVikram.Hegde@Sun.COM struct iommulib_unit *ilu_prev; 467613SVikram.Hegde@Sun.COM } iommulib_unit_t; 477613SVikram.Hegde@Sun.COM 487613SVikram.Hegde@Sun.COM typedef struct iommulib_nex { 497613SVikram.Hegde@Sun.COM dev_info_t *nex_dip; 507613SVikram.Hegde@Sun.COM iommulib_nexops_t nex_ops; 517613SVikram.Hegde@Sun.COM struct iommulib_nex *nex_next; 527613SVikram.Hegde@Sun.COM struct iommulib_nex *nex_prev; 537613SVikram.Hegde@Sun.COM } iommulib_nex_t; 547613SVikram.Hegde@Sun.COM 557613SVikram.Hegde@Sun.COM /* ********* Globals ************************ */ 567613SVikram.Hegde@Sun.COM 57*8371SVikram.Hegde@Sun.COM /* For IOMMU drivers */ 58*8371SVikram.Hegde@Sun.COM smbios_hdl_t *iommulib_smbios; 59*8371SVikram.Hegde@Sun.COM 607613SVikram.Hegde@Sun.COM /* IOMMU side: Following data protected by lock */ 617613SVikram.Hegde@Sun.COM static kmutex_t iommulib_lock; 627613SVikram.Hegde@Sun.COM static iommulib_unit_t *iommulib_list; 637613SVikram.Hegde@Sun.COM static uint64_t iommulib_unit_ids = 0; 647613SVikram.Hegde@Sun.COM static uint64_t iommulib_num_units = 0; 657613SVikram.Hegde@Sun.COM 667613SVikram.Hegde@Sun.COM /* rootnex side data */ 677613SVikram.Hegde@Sun.COM 687613SVikram.Hegde@Sun.COM static kmutex_t iommulib_nexus_lock; 697613SVikram.Hegde@Sun.COM static iommulib_nex_t *iommulib_nexus_list; 707613SVikram.Hegde@Sun.COM 717613SVikram.Hegde@Sun.COM /* can be set atomically without lock */ 727613SVikram.Hegde@Sun.COM static volatile uint32_t iommulib_fini; 737613SVikram.Hegde@Sun.COM 747613SVikram.Hegde@Sun.COM /* debug flag */ 757613SVikram.Hegde@Sun.COM static int iommulib_debug; 767613SVikram.Hegde@Sun.COM 777613SVikram.Hegde@Sun.COM /* 787613SVikram.Hegde@Sun.COM * Module linkage information for the kernel. 797613SVikram.Hegde@Sun.COM */ 807613SVikram.Hegde@Sun.COM static struct modlmisc modlmisc = { 817613SVikram.Hegde@Sun.COM &mod_miscops, "IOMMU library module" 827613SVikram.Hegde@Sun.COM }; 837613SVikram.Hegde@Sun.COM 847613SVikram.Hegde@Sun.COM static struct modlinkage modlinkage = { 857613SVikram.Hegde@Sun.COM MODREV_1, (void *)&modlmisc, NULL 867613SVikram.Hegde@Sun.COM }; 877613SVikram.Hegde@Sun.COM 887613SVikram.Hegde@Sun.COM int 897613SVikram.Hegde@Sun.COM _init(void) 907613SVikram.Hegde@Sun.COM { 917613SVikram.Hegde@Sun.COM return (mod_install(&modlinkage)); 927613SVikram.Hegde@Sun.COM } 937613SVikram.Hegde@Sun.COM 947613SVikram.Hegde@Sun.COM int 957613SVikram.Hegde@Sun.COM _fini(void) 967613SVikram.Hegde@Sun.COM { 977613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 987613SVikram.Hegde@Sun.COM if (iommulib_list != NULL || iommulib_nexus_list != NULL) { 997613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 1007613SVikram.Hegde@Sun.COM return (EBUSY); 1017613SVikram.Hegde@Sun.COM } 1027613SVikram.Hegde@Sun.COM iommulib_fini = 1; 1037613SVikram.Hegde@Sun.COM 1047613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 1057613SVikram.Hegde@Sun.COM return (mod_remove(&modlinkage)); 1067613SVikram.Hegde@Sun.COM } 1077613SVikram.Hegde@Sun.COM 1087613SVikram.Hegde@Sun.COM int 1097613SVikram.Hegde@Sun.COM _info(struct modinfo *modinfop) 1107613SVikram.Hegde@Sun.COM { 1117613SVikram.Hegde@Sun.COM return (mod_info(&modlinkage, modinfop)); 1127613SVikram.Hegde@Sun.COM } 1137613SVikram.Hegde@Sun.COM 1147613SVikram.Hegde@Sun.COM /* 1157613SVikram.Hegde@Sun.COM * Routines with iommulib_iommu_* are invoked from the 1167613SVikram.Hegde@Sun.COM * IOMMU driver. 1177613SVikram.Hegde@Sun.COM * Routines with iommulib_nex* are invoked from the 1187613SVikram.Hegde@Sun.COM * nexus driver (typically rootnex) 1197613SVikram.Hegde@Sun.COM */ 1207613SVikram.Hegde@Sun.COM 1217613SVikram.Hegde@Sun.COM int 1227613SVikram.Hegde@Sun.COM iommulib_nexus_register(dev_info_t *dip, iommulib_nexops_t *nexops, 1237613SVikram.Hegde@Sun.COM iommulib_nexhandle_t *handle) 1247613SVikram.Hegde@Sun.COM { 1257613SVikram.Hegde@Sun.COM iommulib_nex_t *nexp; 1267613SVikram.Hegde@Sun.COM int instance = ddi_get_instance(dip); 1277613SVikram.Hegde@Sun.COM const char *driver = ddi_driver_name(dip); 1287613SVikram.Hegde@Sun.COM dev_info_t *pdip = ddi_get_parent(dip); 1297613SVikram.Hegde@Sun.COM const char *f = "iommulib_nexus_register"; 1307613SVikram.Hegde@Sun.COM 1317613SVikram.Hegde@Sun.COM ASSERT(nexops); 1327613SVikram.Hegde@Sun.COM ASSERT(handle); 1337613SVikram.Hegde@Sun.COM 1347613SVikram.Hegde@Sun.COM *handle = NULL; 1357613SVikram.Hegde@Sun.COM 1367613SVikram.Hegde@Sun.COM /* 1377613SVikram.Hegde@Sun.COM * Root node is never busy held 1387613SVikram.Hegde@Sun.COM */ 1397613SVikram.Hegde@Sun.COM if (dip != ddi_root_node() && (i_ddi_node_state(dip) < DS_PROBED || 1407613SVikram.Hegde@Sun.COM !DEVI_BUSY_OWNED(pdip))) { 1417613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: NEXUS devinfo node not in DS_PROBED " 1427613SVikram.Hegde@Sun.COM "or busy held for nexops vector (%p). Failing registration", 1437613SVikram.Hegde@Sun.COM f, (void *)nexops); 1447613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1457613SVikram.Hegde@Sun.COM } 1467613SVikram.Hegde@Sun.COM 1477613SVikram.Hegde@Sun.COM if (nexops->nops_vers != IOMMU_NEXOPS_VERSION) { 1487613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: Invalid IOMMULIB nexops version " 1497613SVikram.Hegde@Sun.COM "in nexops vector (%p). Failing NEXUS registration", 1507613SVikram.Hegde@Sun.COM f, driver, instance, (void *)nexops); 1517613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1527613SVikram.Hegde@Sun.COM } 1537613SVikram.Hegde@Sun.COM 1547613SVikram.Hegde@Sun.COM ASSERT(nexops->nops_data == NULL); 1557613SVikram.Hegde@Sun.COM 1567613SVikram.Hegde@Sun.COM if (nexops->nops_id == NULL) { 1577613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL ID field. " 1587613SVikram.Hegde@Sun.COM "Failing registration for nexops vector: %p", 1597613SVikram.Hegde@Sun.COM f, driver, instance, (void *)nexops); 1607613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1617613SVikram.Hegde@Sun.COM } 1627613SVikram.Hegde@Sun.COM 1637613SVikram.Hegde@Sun.COM if (nexops->nops_dma_allochdl == NULL) { 1647613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_allochdl op. " 1657613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 1667613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 1677613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1687613SVikram.Hegde@Sun.COM } 1697613SVikram.Hegde@Sun.COM 1707613SVikram.Hegde@Sun.COM if (nexops->nops_dma_freehdl == NULL) { 1717613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_freehdl op. " 1727613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 1737613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 1747613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1757613SVikram.Hegde@Sun.COM } 1767613SVikram.Hegde@Sun.COM 1777613SVikram.Hegde@Sun.COM if (nexops->nops_dma_bindhdl == NULL) { 1787613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_bindhdl op. " 1797613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 1807613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 1817613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1827613SVikram.Hegde@Sun.COM } 1837613SVikram.Hegde@Sun.COM 1847613SVikram.Hegde@Sun.COM if (nexops->nops_dma_sync == NULL) { 1857613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_sync op. " 1867613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 1877613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 1887613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1897613SVikram.Hegde@Sun.COM } 1907613SVikram.Hegde@Sun.COM 1917613SVikram.Hegde@Sun.COM if (nexops->nops_dma_reset_cookies == NULL) { 1927613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_reset_cookies op. " 1937613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 1947613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 1957613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 1967613SVikram.Hegde@Sun.COM } 1977613SVikram.Hegde@Sun.COM 1987613SVikram.Hegde@Sun.COM if (nexops->nops_dma_get_cookies == NULL) { 1997613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_get_cookies op. " 2007613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 2017613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 2027613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2037613SVikram.Hegde@Sun.COM } 2047613SVikram.Hegde@Sun.COM 2058215SVikram.Hegde@Sun.COM if (nexops->nops_dma_set_cookies == NULL) { 2068215SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_set_cookies op. " 2078215SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 2088215SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 2098215SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2108215SVikram.Hegde@Sun.COM } 2118215SVikram.Hegde@Sun.COM 2128215SVikram.Hegde@Sun.COM if (nexops->nops_dma_clear_cookies == NULL) { 2138215SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_clear_cookies op. " 2148215SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 2158215SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 2168215SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2178215SVikram.Hegde@Sun.COM } 2188215SVikram.Hegde@Sun.COM 2198215SVikram.Hegde@Sun.COM if (nexops->nops_dma_get_sleep_flags == NULL) { 2208215SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_get_sleep_flags op. " 2218215SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 2228215SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 2238215SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2248215SVikram.Hegde@Sun.COM } 2258215SVikram.Hegde@Sun.COM 2267613SVikram.Hegde@Sun.COM if (nexops->nops_dma_win == NULL) { 2277613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_win op. " 2287613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 2297613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 2307613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2317613SVikram.Hegde@Sun.COM } 2327613SVikram.Hegde@Sun.COM 2337613SVikram.Hegde@Sun.COM /* Check for legacy ops */ 2347613SVikram.Hegde@Sun.COM if (nexops->nops_dma_map == NULL) { 2357613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL legacy nops_dma_map op. " 2367613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 2377613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 2387613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2397613SVikram.Hegde@Sun.COM } 2407613SVikram.Hegde@Sun.COM 2417613SVikram.Hegde@Sun.COM if (nexops->nops_dma_mctl == NULL) { 2427613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL legacy nops_dma_mctl op. " 2437613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 2447613SVikram.Hegde@Sun.COM driver, instance, (void *)nexops); 2457613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2467613SVikram.Hegde@Sun.COM } 2477613SVikram.Hegde@Sun.COM 2487613SVikram.Hegde@Sun.COM nexp = kmem_zalloc(sizeof (iommulib_nex_t), KM_SLEEP); 2497613SVikram.Hegde@Sun.COM 2507613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 2517613SVikram.Hegde@Sun.COM if (iommulib_fini == 1) { 2527613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 2537613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: IOMMULIB unloading. " 2547613SVikram.Hegde@Sun.COM "Failing NEXUS register.", f); 2557613SVikram.Hegde@Sun.COM kmem_free(nexp, sizeof (iommulib_nex_t)); 2567613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 2577613SVikram.Hegde@Sun.COM } 2587613SVikram.Hegde@Sun.COM 2597613SVikram.Hegde@Sun.COM /* 2607613SVikram.Hegde@Sun.COM * fini/register race conditions have been handled. Now create the 2617613SVikram.Hegde@Sun.COM * nexus struct 2627613SVikram.Hegde@Sun.COM */ 2637613SVikram.Hegde@Sun.COM ndi_hold_devi(dip); 2647613SVikram.Hegde@Sun.COM nexp->nex_dip = dip; 2657613SVikram.Hegde@Sun.COM nexp->nex_ops = *nexops; 2667613SVikram.Hegde@Sun.COM 2677613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_nexus_lock); 2687613SVikram.Hegde@Sun.COM nexp->nex_next = iommulib_nexus_list; 2697613SVikram.Hegde@Sun.COM iommulib_nexus_list = nexp; 2707613SVikram.Hegde@Sun.COM nexp->nex_prev = NULL; 2717613SVikram.Hegde@Sun.COM 2727613SVikram.Hegde@Sun.COM if (nexp->nex_next != NULL) 2737613SVikram.Hegde@Sun.COM nexp->nex_next->nex_prev = nexp; 2747613SVikram.Hegde@Sun.COM 2757613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_nexus_lock); 2767613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 2777613SVikram.Hegde@Sun.COM 2787613SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "!%s: %s%d: Succesfully registered NEXUS %s " 2797613SVikram.Hegde@Sun.COM "nexops=%p", f, driver, instance, ddi_node_name(dip), 2807613SVikram.Hegde@Sun.COM (void *)nexops); 2817613SVikram.Hegde@Sun.COM 2827613SVikram.Hegde@Sun.COM *handle = nexp; 2837613SVikram.Hegde@Sun.COM 2847613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 2857613SVikram.Hegde@Sun.COM } 2867613SVikram.Hegde@Sun.COM 2877613SVikram.Hegde@Sun.COM int 2887613SVikram.Hegde@Sun.COM iommulib_nexus_unregister(iommulib_nexhandle_t handle) 2897613SVikram.Hegde@Sun.COM { 2907613SVikram.Hegde@Sun.COM dev_info_t *dip; 2917613SVikram.Hegde@Sun.COM int instance; 2927613SVikram.Hegde@Sun.COM const char *driver; 2937613SVikram.Hegde@Sun.COM iommulib_nex_t *nexp = (iommulib_nex_t *)handle; 2947613SVikram.Hegde@Sun.COM const char *f = "iommulib_nexus_unregister"; 2957613SVikram.Hegde@Sun.COM 2967613SVikram.Hegde@Sun.COM ASSERT(nexp); 2977613SVikram.Hegde@Sun.COM 2987613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_nexus_lock); 2997613SVikram.Hegde@Sun.COM 3007613SVikram.Hegde@Sun.COM dip = nexp->nex_dip; 3017613SVikram.Hegde@Sun.COM driver = ddi_driver_name(dip); 3027613SVikram.Hegde@Sun.COM instance = ddi_get_instance(dip); 3037613SVikram.Hegde@Sun.COM 3047613SVikram.Hegde@Sun.COM /* A future enhancement would be to add ref-counts */ 3057613SVikram.Hegde@Sun.COM 3067613SVikram.Hegde@Sun.COM if (nexp->nex_prev == NULL) { 3077613SVikram.Hegde@Sun.COM iommulib_nexus_list = nexp->nex_next; 3087613SVikram.Hegde@Sun.COM } else { 3097613SVikram.Hegde@Sun.COM nexp->nex_prev->nex_next = nexp->nex_next; 3107613SVikram.Hegde@Sun.COM } 3117613SVikram.Hegde@Sun.COM 3127613SVikram.Hegde@Sun.COM if (nexp->nex_next != NULL) 3137613SVikram.Hegde@Sun.COM nexp->nex_next->nex_prev = nexp->nex_prev; 3147613SVikram.Hegde@Sun.COM 3157613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_nexus_lock); 3167613SVikram.Hegde@Sun.COM 3177613SVikram.Hegde@Sun.COM kmem_free(nexp, sizeof (iommulib_nex_t)); 3187613SVikram.Hegde@Sun.COM 3198215SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "!%s: %s%d: NEXUS (%s) handle successfully " 3207613SVikram.Hegde@Sun.COM "unregistered from IOMMULIB", f, driver, instance, 3217613SVikram.Hegde@Sun.COM ddi_node_name(dip)); 3227613SVikram.Hegde@Sun.COM 3237613SVikram.Hegde@Sun.COM ndi_rele_devi(dip); 3247613SVikram.Hegde@Sun.COM 3257613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 3267613SVikram.Hegde@Sun.COM } 3277613SVikram.Hegde@Sun.COM 3287613SVikram.Hegde@Sun.COM static iommulib_nexops_t * 3297613SVikram.Hegde@Sun.COM lookup_nexops(dev_info_t *dip) 3307613SVikram.Hegde@Sun.COM { 3317613SVikram.Hegde@Sun.COM iommulib_nex_t *nexp; 3327613SVikram.Hegde@Sun.COM 3337613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_nexus_lock); 3347613SVikram.Hegde@Sun.COM nexp = iommulib_nexus_list; 3357613SVikram.Hegde@Sun.COM while (nexp) { 3367613SVikram.Hegde@Sun.COM if (nexp->nex_dip == dip) 3377613SVikram.Hegde@Sun.COM break; 3387613SVikram.Hegde@Sun.COM nexp = nexp->nex_next; 3397613SVikram.Hegde@Sun.COM } 3407613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_nexus_lock); 3417613SVikram.Hegde@Sun.COM 3427613SVikram.Hegde@Sun.COM return (nexp ? &nexp->nex_ops : NULL); 3437613SVikram.Hegde@Sun.COM } 3447613SVikram.Hegde@Sun.COM 3457613SVikram.Hegde@Sun.COM int 3467613SVikram.Hegde@Sun.COM iommulib_iommu_register(dev_info_t *dip, iommulib_ops_t *ops, 3477613SVikram.Hegde@Sun.COM iommulib_handle_t *handle) 3487613SVikram.Hegde@Sun.COM { 3497613SVikram.Hegde@Sun.COM const char *vendor; 3507613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 3517613SVikram.Hegde@Sun.COM int instance = ddi_get_instance(dip); 3527613SVikram.Hegde@Sun.COM const char *driver = ddi_driver_name(dip); 3537613SVikram.Hegde@Sun.COM dev_info_t *pdip = ddi_get_parent(dip); 3547613SVikram.Hegde@Sun.COM const char *f = "iommulib_register"; 3557613SVikram.Hegde@Sun.COM 3567613SVikram.Hegde@Sun.COM ASSERT(ops); 3577613SVikram.Hegde@Sun.COM ASSERT(handle); 3587613SVikram.Hegde@Sun.COM 3597613SVikram.Hegde@Sun.COM if (i_ddi_node_state(dip) < DS_PROBED || !DEVI_BUSY_OWNED(pdip)) { 3607613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: devinfo node not in DS_PROBED or " 3617613SVikram.Hegde@Sun.COM "busy held for ops vector (%p). Failing registration", 3627613SVikram.Hegde@Sun.COM f, (void *)ops); 3637613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 3647613SVikram.Hegde@Sun.COM } 3657613SVikram.Hegde@Sun.COM 3667613SVikram.Hegde@Sun.COM 3677613SVikram.Hegde@Sun.COM if (ops->ilops_vers != IOMMU_OPS_VERSION) { 3687613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: Invalid IOMMULIB ops version " 3697613SVikram.Hegde@Sun.COM "in ops vector (%p). Failing registration", f, driver, 3707613SVikram.Hegde@Sun.COM instance, (void *)ops); 3717613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 3727613SVikram.Hegde@Sun.COM } 3737613SVikram.Hegde@Sun.COM 3747613SVikram.Hegde@Sun.COM switch (ops->ilops_vendor) { 3757613SVikram.Hegde@Sun.COM case AMD_IOMMU: 3767613SVikram.Hegde@Sun.COM vendor = "AMD"; 3777613SVikram.Hegde@Sun.COM break; 3787613SVikram.Hegde@Sun.COM case INTEL_IOMMU: 3797613SVikram.Hegde@Sun.COM vendor = "Intel"; 3807613SVikram.Hegde@Sun.COM break; 3817613SVikram.Hegde@Sun.COM case INVALID_VENDOR: 3827613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: vendor field (%x) not initialized. " 3837613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 3847613SVikram.Hegde@Sun.COM driver, instance, ops->ilops_vendor, (void *)ops); 3857613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 3867613SVikram.Hegde@Sun.COM default: 3877613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: Invalid vendor field (%x). " 3887613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 3897613SVikram.Hegde@Sun.COM driver, instance, ops->ilops_vendor, (void *)ops); 3907613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 3917613SVikram.Hegde@Sun.COM } 3927613SVikram.Hegde@Sun.COM 3938215SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "!%s: %s%d: Detected IOMMU registration from vendor" 3948215SVikram.Hegde@Sun.COM " %s", f, driver, instance, vendor); 3957613SVikram.Hegde@Sun.COM 3967613SVikram.Hegde@Sun.COM if (ops->ilops_data == NULL) { 3977613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL IOMMU data field. " 3987613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 3997613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4007613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4017613SVikram.Hegde@Sun.COM } 4027613SVikram.Hegde@Sun.COM 4037613SVikram.Hegde@Sun.COM if (ops->ilops_id == NULL) { 4047613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL ID field. " 4057613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4067613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4077613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4087613SVikram.Hegde@Sun.COM } 4097613SVikram.Hegde@Sun.COM 4107613SVikram.Hegde@Sun.COM if (ops->ilops_probe == NULL) { 4117613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL probe op. " 4127613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4137613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4147613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4157613SVikram.Hegde@Sun.COM } 4167613SVikram.Hegde@Sun.COM 4177613SVikram.Hegde@Sun.COM if (ops->ilops_dma_allochdl == NULL) { 4187613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_allochdl op. " 4197613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4207613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4217613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4227613SVikram.Hegde@Sun.COM } 4237613SVikram.Hegde@Sun.COM 4247613SVikram.Hegde@Sun.COM if (ops->ilops_dma_freehdl == NULL) { 4257613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_freehdl op. " 4267613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4277613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4287613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4297613SVikram.Hegde@Sun.COM } 4307613SVikram.Hegde@Sun.COM 4317613SVikram.Hegde@Sun.COM if (ops->ilops_dma_bindhdl == NULL) { 4327613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_bindhdl op. " 4337613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4347613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4357613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4367613SVikram.Hegde@Sun.COM } 4377613SVikram.Hegde@Sun.COM 4387613SVikram.Hegde@Sun.COM if (ops->ilops_dma_sync == NULL) { 4397613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_sync op. " 4407613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4417613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4427613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4437613SVikram.Hegde@Sun.COM } 4447613SVikram.Hegde@Sun.COM 4457613SVikram.Hegde@Sun.COM if (ops->ilops_dma_win == NULL) { 4467613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL dma_win op. " 4477613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4487613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4497613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4507613SVikram.Hegde@Sun.COM } 4517613SVikram.Hegde@Sun.COM 4527613SVikram.Hegde@Sun.COM /* Check for legacy ops */ 4537613SVikram.Hegde@Sun.COM if (ops->ilops_dma_map == NULL) { 4547613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL legacy dma_map op. " 4557613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4567613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4577613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4587613SVikram.Hegde@Sun.COM } 4597613SVikram.Hegde@Sun.COM 4607613SVikram.Hegde@Sun.COM if (ops->ilops_dma_mctl == NULL) { 4617613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: NULL legacy dma_mctl op. " 4627613SVikram.Hegde@Sun.COM "Failing registration for ops vector: %p", f, 4637613SVikram.Hegde@Sun.COM driver, instance, (void *)ops); 4647613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4657613SVikram.Hegde@Sun.COM } 4667613SVikram.Hegde@Sun.COM 4677613SVikram.Hegde@Sun.COM unitp = kmem_zalloc(sizeof (iommulib_unit_t), KM_SLEEP); 4687613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 4697613SVikram.Hegde@Sun.COM if (iommulib_fini == 1) { 4707613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 4717613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: IOMMULIB unloading. Failing register.", 4727613SVikram.Hegde@Sun.COM f); 4737613SVikram.Hegde@Sun.COM kmem_free(unitp, sizeof (iommulib_unit_t)); 4747613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 4757613SVikram.Hegde@Sun.COM } 4767613SVikram.Hegde@Sun.COM 4777613SVikram.Hegde@Sun.COM /* 4787613SVikram.Hegde@Sun.COM * fini/register race conditions have been handled. Now create the 4797613SVikram.Hegde@Sun.COM * IOMMU unit 4807613SVikram.Hegde@Sun.COM */ 4817613SVikram.Hegde@Sun.COM mutex_init(&unitp->ilu_lock, NULL, MUTEX_DEFAULT, NULL); 4827613SVikram.Hegde@Sun.COM 4837613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 4847613SVikram.Hegde@Sun.COM unitp->ilu_unitid = ++iommulib_unit_ids; 4857613SVikram.Hegde@Sun.COM unitp->ilu_ref = 0; 4867613SVikram.Hegde@Sun.COM ndi_hold_devi(dip); 4877613SVikram.Hegde@Sun.COM unitp->ilu_dip = dip; 4887613SVikram.Hegde@Sun.COM unitp->ilu_ops = ops; 4897613SVikram.Hegde@Sun.COM unitp->ilu_data = ops->ilops_data; 4907613SVikram.Hegde@Sun.COM 4917613SVikram.Hegde@Sun.COM unitp->ilu_next = iommulib_list; 4928215SVikram.Hegde@Sun.COM iommulib_list = unitp; 4937613SVikram.Hegde@Sun.COM unitp->ilu_prev = NULL; 4948215SVikram.Hegde@Sun.COM if (unitp->ilu_next) 4958215SVikram.Hegde@Sun.COM unitp->ilu_next->ilu_prev = unitp; 4967613SVikram.Hegde@Sun.COM 4977613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 4987613SVikram.Hegde@Sun.COM 4997613SVikram.Hegde@Sun.COM iommulib_num_units++; 5007613SVikram.Hegde@Sun.COM 5017613SVikram.Hegde@Sun.COM *handle = unitp; 5027613SVikram.Hegde@Sun.COM 5037613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 5047613SVikram.Hegde@Sun.COM 5058215SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "!%s: %s%d: Succesfully registered IOMMU unit " 5067613SVikram.Hegde@Sun.COM "from vendor=%s, ops=%p, data=%p, IOMMULIB unitid=%u", 5077613SVikram.Hegde@Sun.COM f, driver, instance, vendor, (void *)ops, (void *)unitp->ilu_data, 5087613SVikram.Hegde@Sun.COM unitp->ilu_unitid); 5097613SVikram.Hegde@Sun.COM 5107613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 5117613SVikram.Hegde@Sun.COM } 5127613SVikram.Hegde@Sun.COM 5137613SVikram.Hegde@Sun.COM int 5147613SVikram.Hegde@Sun.COM iommulib_iommu_unregister(iommulib_handle_t handle) 5157613SVikram.Hegde@Sun.COM { 5167613SVikram.Hegde@Sun.COM uint32_t unitid; 5177613SVikram.Hegde@Sun.COM dev_info_t *dip; 5187613SVikram.Hegde@Sun.COM int instance; 5197613SVikram.Hegde@Sun.COM const char *driver; 5207613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 5217613SVikram.Hegde@Sun.COM const char *f = "iommulib_unregister"; 5227613SVikram.Hegde@Sun.COM 5237613SVikram.Hegde@Sun.COM ASSERT(unitp); 5247613SVikram.Hegde@Sun.COM 5257613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 5267613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 5277613SVikram.Hegde@Sun.COM 5287613SVikram.Hegde@Sun.COM unitid = unitp->ilu_unitid; 5297613SVikram.Hegde@Sun.COM dip = unitp->ilu_dip; 5307613SVikram.Hegde@Sun.COM driver = ddi_driver_name(dip); 5317613SVikram.Hegde@Sun.COM instance = ddi_get_instance(dip); 5327613SVikram.Hegde@Sun.COM 5337613SVikram.Hegde@Sun.COM if (unitp->ilu_ref != 0) { 5347613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 5357613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 5367613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: IOMMULIB handle is busy. Cannot " 5377613SVikram.Hegde@Sun.COM "unregister IOMMULIB unitid %u", 5387613SVikram.Hegde@Sun.COM f, driver, instance, unitid); 5397613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 5407613SVikram.Hegde@Sun.COM } 5417613SVikram.Hegde@Sun.COM unitp->ilu_unitid = 0; 5427613SVikram.Hegde@Sun.COM ASSERT(unitp->ilu_ref == 0); 5437613SVikram.Hegde@Sun.COM 5447613SVikram.Hegde@Sun.COM if (unitp->ilu_prev == NULL) { 5457613SVikram.Hegde@Sun.COM iommulib_list = unitp->ilu_next; 5467613SVikram.Hegde@Sun.COM unitp->ilu_next->ilu_prev = NULL; 5477613SVikram.Hegde@Sun.COM } else { 5487613SVikram.Hegde@Sun.COM unitp->ilu_prev->ilu_next = unitp->ilu_next; 5497613SVikram.Hegde@Sun.COM unitp->ilu_next->ilu_prev = unitp->ilu_prev; 5507613SVikram.Hegde@Sun.COM } 5517613SVikram.Hegde@Sun.COM 5527613SVikram.Hegde@Sun.COM iommulib_num_units--; 5537613SVikram.Hegde@Sun.COM 5547613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 5557613SVikram.Hegde@Sun.COM 5567613SVikram.Hegde@Sun.COM mutex_destroy(&unitp->ilu_lock); 5577613SVikram.Hegde@Sun.COM kmem_free(unitp, sizeof (iommulib_unit_t)); 5587613SVikram.Hegde@Sun.COM 5597613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 5607613SVikram.Hegde@Sun.COM 5617613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: IOMMULIB handle (unitid=%u) successfully " 5627613SVikram.Hegde@Sun.COM "unregistered", f, driver, instance, unitid); 5637613SVikram.Hegde@Sun.COM 5647613SVikram.Hegde@Sun.COM ndi_rele_devi(dip); 5657613SVikram.Hegde@Sun.COM 5667613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 5677613SVikram.Hegde@Sun.COM } 5687613SVikram.Hegde@Sun.COM 5697613SVikram.Hegde@Sun.COM int 5707613SVikram.Hegde@Sun.COM iommulib_nex_open(dev_info_t *rdip, uint_t *errorp) 5717613SVikram.Hegde@Sun.COM { 5727613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 5737613SVikram.Hegde@Sun.COM int instance = ddi_get_instance(rdip); 5747613SVikram.Hegde@Sun.COM const char *driver = ddi_driver_name(rdip); 5757613SVikram.Hegde@Sun.COM const char *f = "iommulib_nex_open"; 5767613SVikram.Hegde@Sun.COM 5777613SVikram.Hegde@Sun.COM *errorp = 0; 5788215SVikram.Hegde@Sun.COM 5798215SVikram.Hegde@Sun.COM if (IOMMU_USED(rdip)) 5808215SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 5818215SVikram.Hegde@Sun.COM 5828215SVikram.Hegde@Sun.COM ASSERT(DEVI(rdip)->devi_iommulib_handle == NULL); 5837613SVikram.Hegde@Sun.COM 5847613SVikram.Hegde@Sun.COM /* prevent use of IOMMU for AMD IOMMU's DMA */ 5857613SVikram.Hegde@Sun.COM if (strcmp(driver, "amd_iommu") == 0) { 5867613SVikram.Hegde@Sun.COM *errorp = ENOTSUP; 5877613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 5887613SVikram.Hegde@Sun.COM } 5897613SVikram.Hegde@Sun.COM 5907613SVikram.Hegde@Sun.COM /* 5918215SVikram.Hegde@Sun.COM * Use the probe entry point to determine in a hardware specific 5928215SVikram.Hegde@Sun.COM * manner whether this dip is controlled by an IOMMU. If yes, 5938215SVikram.Hegde@Sun.COM * return the handle corresponding to the IOMMU unit. 5947613SVikram.Hegde@Sun.COM */ 5957613SVikram.Hegde@Sun.COM 5967613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 5977613SVikram.Hegde@Sun.COM for (unitp = iommulib_list; unitp; unitp = unitp->ilu_next) { 5988215SVikram.Hegde@Sun.COM if (unitp->ilu_ops->ilops_probe(unitp, rdip) == DDI_SUCCESS) 5997613SVikram.Hegde@Sun.COM break; 6007613SVikram.Hegde@Sun.COM } 6017613SVikram.Hegde@Sun.COM 6027613SVikram.Hegde@Sun.COM if (unitp == NULL) { 6037613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 6047613SVikram.Hegde@Sun.COM if (iommulib_debug) { 6057717SVikram.Hegde@Sun.COM char *buf = kmem_alloc(MAXPATHLEN, KM_SLEEP); 6067613SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: %s%d: devinfo node (%p): is not " 6077613SVikram.Hegde@Sun.COM "controlled by an IOMMU: path=%s", f, driver, 6087613SVikram.Hegde@Sun.COM instance, (void *)rdip, ddi_pathname(rdip, buf)); 6097717SVikram.Hegde@Sun.COM kmem_free(buf, MAXPATHLEN); 6107613SVikram.Hegde@Sun.COM } 6117613SVikram.Hegde@Sun.COM *errorp = ENOTSUP; 6127613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 6137613SVikram.Hegde@Sun.COM } 6147613SVikram.Hegde@Sun.COM 6157613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 6167613SVikram.Hegde@Sun.COM unitp->ilu_ref++; 6177613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 6187613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 6197613SVikram.Hegde@Sun.COM 6207613SVikram.Hegde@Sun.COM DEVI(rdip)->devi_iommulib_handle = unitp; 6217613SVikram.Hegde@Sun.COM 6227613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 6237613SVikram.Hegde@Sun.COM } 6247613SVikram.Hegde@Sun.COM 6257613SVikram.Hegde@Sun.COM void 6267613SVikram.Hegde@Sun.COM iommulib_nex_close(dev_info_t *rdip) 6277613SVikram.Hegde@Sun.COM { 6287613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 6297613SVikram.Hegde@Sun.COM const char *driver; 6307613SVikram.Hegde@Sun.COM int instance; 6317613SVikram.Hegde@Sun.COM uint32_t unitid; 6327613SVikram.Hegde@Sun.COM const char *f = "iommulib_nex_close"; 6337613SVikram.Hegde@Sun.COM 6347613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)DEVI(rdip)->devi_iommulib_handle; 6357613SVikram.Hegde@Sun.COM if (unitp == NULL) 6367613SVikram.Hegde@Sun.COM return; 6377613SVikram.Hegde@Sun.COM 6387613SVikram.Hegde@Sun.COM DEVI(rdip)->devi_iommulib_handle = NULL; 6397613SVikram.Hegde@Sun.COM 6407613SVikram.Hegde@Sun.COM mutex_enter(&iommulib_lock); 6417613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 6427613SVikram.Hegde@Sun.COM unitid = unitp->ilu_unitid; 6437613SVikram.Hegde@Sun.COM driver = ddi_driver_name(unitp->ilu_dip); 6447613SVikram.Hegde@Sun.COM instance = ddi_get_instance(unitp->ilu_dip); 6457613SVikram.Hegde@Sun.COM unitp->ilu_ref--; 6467613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 6477613SVikram.Hegde@Sun.COM mutex_exit(&iommulib_lock); 6487613SVikram.Hegde@Sun.COM 6497613SVikram.Hegde@Sun.COM if (iommulib_debug) { 6507717SVikram.Hegde@Sun.COM char *buf = kmem_alloc(MAXPATHLEN, KM_SLEEP); 6517717SVikram.Hegde@Sun.COM (void) ddi_pathname(rdip, buf); 6527613SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "%s: %s%d: closing IOMMU for dip (%p), " 6537613SVikram.Hegde@Sun.COM "unitid=%u rdip path = %s", f, driver, instance, 6547613SVikram.Hegde@Sun.COM (void *)rdip, unitid, buf); 6557717SVikram.Hegde@Sun.COM kmem_free(buf, MAXPATHLEN); 6567613SVikram.Hegde@Sun.COM } 6577613SVikram.Hegde@Sun.COM } 6587613SVikram.Hegde@Sun.COM 6597613SVikram.Hegde@Sun.COM int 6607613SVikram.Hegde@Sun.COM iommulib_nexdma_allochdl(dev_info_t *dip, dev_info_t *rdip, 6617613SVikram.Hegde@Sun.COM ddi_dma_attr_t *attr, int (*waitfp)(caddr_t), 6627613SVikram.Hegde@Sun.COM caddr_t arg, ddi_dma_handle_t *dma_handlep) 6637613SVikram.Hegde@Sun.COM { 6647613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 6657613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 6667613SVikram.Hegde@Sun.COM 6677613SVikram.Hegde@Sun.COM ASSERT(unitp); 6687613SVikram.Hegde@Sun.COM 6697613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 6707613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_allochdl(handle, dip, rdip, 6717613SVikram.Hegde@Sun.COM attr, waitfp, arg, dma_handlep)); 6727613SVikram.Hegde@Sun.COM } 6737613SVikram.Hegde@Sun.COM 6747613SVikram.Hegde@Sun.COM int 6757613SVikram.Hegde@Sun.COM iommulib_nexdma_freehdl(dev_info_t *dip, dev_info_t *rdip, 6767613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle) 6777613SVikram.Hegde@Sun.COM { 6787613SVikram.Hegde@Sun.COM int error; 6797613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 6807613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 6817613SVikram.Hegde@Sun.COM 6827613SVikram.Hegde@Sun.COM ASSERT(unitp); 6837613SVikram.Hegde@Sun.COM 6847613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 6857613SVikram.Hegde@Sun.COM error = unitp->ilu_ops->ilops_dma_freehdl(handle, dip, 6867613SVikram.Hegde@Sun.COM rdip, dma_handle); 6877613SVikram.Hegde@Sun.COM 6887613SVikram.Hegde@Sun.COM return (error); 6897613SVikram.Hegde@Sun.COM } 6907613SVikram.Hegde@Sun.COM 6917613SVikram.Hegde@Sun.COM int 6927613SVikram.Hegde@Sun.COM iommulib_nexdma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 6937613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle, struct ddi_dma_req *dmareq, 6947613SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t *ccountp) 6957613SVikram.Hegde@Sun.COM { 6967613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 6977613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 6987613SVikram.Hegde@Sun.COM 6997613SVikram.Hegde@Sun.COM ASSERT(unitp); 7007613SVikram.Hegde@Sun.COM 7017613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 7027613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_bindhdl(handle, dip, rdip, dma_handle, 7037613SVikram.Hegde@Sun.COM dmareq, cookiep, ccountp)); 7047613SVikram.Hegde@Sun.COM } 7057613SVikram.Hegde@Sun.COM 7067613SVikram.Hegde@Sun.COM int 7077613SVikram.Hegde@Sun.COM iommulib_nexdma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, 7087613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle) 7097613SVikram.Hegde@Sun.COM { 7107613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 7117613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 7127613SVikram.Hegde@Sun.COM 7137613SVikram.Hegde@Sun.COM ASSERT(unitp); 7147613SVikram.Hegde@Sun.COM 7157613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 7167613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_unbindhdl(handle, dip, rdip, 7177613SVikram.Hegde@Sun.COM dma_handle)); 7187613SVikram.Hegde@Sun.COM } 7197613SVikram.Hegde@Sun.COM 7207613SVikram.Hegde@Sun.COM int 7217613SVikram.Hegde@Sun.COM iommulib_nexdma_sync(dev_info_t *dip, dev_info_t *rdip, 7227613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle, off_t off, size_t len, 7237613SVikram.Hegde@Sun.COM uint_t cache_flags) 7247613SVikram.Hegde@Sun.COM { 7257613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 7267613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 7277613SVikram.Hegde@Sun.COM 7287613SVikram.Hegde@Sun.COM ASSERT(unitp); 7297613SVikram.Hegde@Sun.COM 7307613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 7317613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_sync(handle, dip, rdip, dma_handle, 7327613SVikram.Hegde@Sun.COM off, len, cache_flags)); 7337613SVikram.Hegde@Sun.COM } 7347613SVikram.Hegde@Sun.COM 7357613SVikram.Hegde@Sun.COM int 7367613SVikram.Hegde@Sun.COM iommulib_nexdma_win(dev_info_t *dip, dev_info_t *rdip, 7377613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle, uint_t win, off_t *offp, size_t *lenp, 7387613SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t *ccountp) 7397613SVikram.Hegde@Sun.COM { 7407613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 7417613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 7427613SVikram.Hegde@Sun.COM 7437613SVikram.Hegde@Sun.COM ASSERT(unitp); 7447613SVikram.Hegde@Sun.COM 7457613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 7467613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_win(handle, dip, rdip, dma_handle, 7477613SVikram.Hegde@Sun.COM win, offp, lenp, cookiep, ccountp)); 7487613SVikram.Hegde@Sun.COM } 7497613SVikram.Hegde@Sun.COM 7507613SVikram.Hegde@Sun.COM /* Obsolete DMA routines */ 7517613SVikram.Hegde@Sun.COM 7527613SVikram.Hegde@Sun.COM int 7537613SVikram.Hegde@Sun.COM iommulib_nexdma_map(dev_info_t *dip, dev_info_t *rdip, 7547613SVikram.Hegde@Sun.COM struct ddi_dma_req *dmareq, ddi_dma_handle_t *dma_handle) 7557613SVikram.Hegde@Sun.COM { 7567613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 7577613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = handle; 7587613SVikram.Hegde@Sun.COM 7597613SVikram.Hegde@Sun.COM ASSERT(unitp); 7607613SVikram.Hegde@Sun.COM 7617613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 7627613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_map(handle, dip, rdip, dmareq, 7637613SVikram.Hegde@Sun.COM dma_handle)); 7647613SVikram.Hegde@Sun.COM } 7657613SVikram.Hegde@Sun.COM 7667613SVikram.Hegde@Sun.COM int 7677613SVikram.Hegde@Sun.COM iommulib_nexdma_mctl(dev_info_t *dip, dev_info_t *rdip, 7687613SVikram.Hegde@Sun.COM ddi_dma_handle_t dma_handle, enum ddi_dma_ctlops request, 7697613SVikram.Hegde@Sun.COM off_t *offp, size_t *lenp, caddr_t *objpp, uint_t cache_flags) 7707613SVikram.Hegde@Sun.COM { 7717613SVikram.Hegde@Sun.COM iommulib_handle_t handle = DEVI(rdip)->devi_iommulib_handle; 7727613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp = (iommulib_unit_t *)handle; 7737613SVikram.Hegde@Sun.COM 7747613SVikram.Hegde@Sun.COM ASSERT(unitp); 7757613SVikram.Hegde@Sun.COM 7767613SVikram.Hegde@Sun.COM /* No need to grab lock - the handle is reference counted */ 7777613SVikram.Hegde@Sun.COM return (unitp->ilu_ops->ilops_dma_mctl(handle, dip, rdip, dma_handle, 7787613SVikram.Hegde@Sun.COM request, offp, lenp, objpp, cache_flags)); 7797613SVikram.Hegde@Sun.COM } 7807613SVikram.Hegde@Sun.COM 7817613SVikram.Hegde@Sun.COM /* Utility routines invoked by IOMMU drivers */ 7827613SVikram.Hegde@Sun.COM int 7837613SVikram.Hegde@Sun.COM iommulib_iommu_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, 7847613SVikram.Hegde@Sun.COM ddi_dma_attr_t *attr, int (*waitfp)(caddr_t), caddr_t arg, 7857613SVikram.Hegde@Sun.COM ddi_dma_handle_t *handlep) 7867613SVikram.Hegde@Sun.COM { 7877613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 7887613SVikram.Hegde@Sun.COM if (nexops == NULL) 7897613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 7907613SVikram.Hegde@Sun.COM return (nexops->nops_dma_allochdl(dip, rdip, attr, waitfp, arg, 7917613SVikram.Hegde@Sun.COM handlep)); 7927613SVikram.Hegde@Sun.COM } 7937613SVikram.Hegde@Sun.COM 7947613SVikram.Hegde@Sun.COM int 7957613SVikram.Hegde@Sun.COM iommulib_iommu_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, 7967613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle) 7977613SVikram.Hegde@Sun.COM { 7987613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 7997613SVikram.Hegde@Sun.COM if (nexops == NULL) 8007613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 8017613SVikram.Hegde@Sun.COM return (nexops->nops_dma_freehdl(dip, rdip, handle)); 8027613SVikram.Hegde@Sun.COM } 8037613SVikram.Hegde@Sun.COM 8047613SVikram.Hegde@Sun.COM int 8057613SVikram.Hegde@Sun.COM iommulib_iommu_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 8067613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle, struct ddi_dma_req *dmareq, 8077613SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t *ccountp) 8087613SVikram.Hegde@Sun.COM { 8097613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 8107613SVikram.Hegde@Sun.COM if (nexops == NULL) 8117613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 8127613SVikram.Hegde@Sun.COM return (nexops->nops_dma_bindhdl(dip, rdip, handle, dmareq, 8137613SVikram.Hegde@Sun.COM cookiep, ccountp)); 8147613SVikram.Hegde@Sun.COM } 8157613SVikram.Hegde@Sun.COM 8167613SVikram.Hegde@Sun.COM int 8177613SVikram.Hegde@Sun.COM iommulib_iommu_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, 8187613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle) 8197613SVikram.Hegde@Sun.COM { 8207613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 8217613SVikram.Hegde@Sun.COM if (nexops == NULL) 8227613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 8237613SVikram.Hegde@Sun.COM return (nexops->nops_dma_unbindhdl(dip, rdip, handle)); 8247613SVikram.Hegde@Sun.COM } 8257613SVikram.Hegde@Sun.COM 8267613SVikram.Hegde@Sun.COM void 8277613SVikram.Hegde@Sun.COM iommulib_iommu_dma_reset_cookies(dev_info_t *dip, ddi_dma_handle_t handle) 8287613SVikram.Hegde@Sun.COM { 8297613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 8307613SVikram.Hegde@Sun.COM nexops->nops_dma_reset_cookies(dip, handle); 8317613SVikram.Hegde@Sun.COM } 8327613SVikram.Hegde@Sun.COM 8337613SVikram.Hegde@Sun.COM int 8347613SVikram.Hegde@Sun.COM iommulib_iommu_dma_get_cookies(dev_info_t *dip, ddi_dma_handle_t handle, 8358215SVikram.Hegde@Sun.COM ddi_dma_cookie_t **cookiepp, uint_t *ccountp) 8368215SVikram.Hegde@Sun.COM { 8378215SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 8388215SVikram.Hegde@Sun.COM if (nexops == NULL) 8398215SVikram.Hegde@Sun.COM return (DDI_FAILURE); 8408215SVikram.Hegde@Sun.COM return (nexops->nops_dma_get_cookies(dip, handle, cookiepp, ccountp)); 8418215SVikram.Hegde@Sun.COM } 8428215SVikram.Hegde@Sun.COM 8438215SVikram.Hegde@Sun.COM int 8448215SVikram.Hegde@Sun.COM iommulib_iommu_dma_set_cookies(dev_info_t *dip, ddi_dma_handle_t handle, 8458215SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t ccount) 8467613SVikram.Hegde@Sun.COM { 8477613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 8487613SVikram.Hegde@Sun.COM if (nexops == NULL) 8497613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 8508215SVikram.Hegde@Sun.COM return (nexops->nops_dma_set_cookies(dip, handle, cookiep, ccount)); 8518215SVikram.Hegde@Sun.COM } 8528215SVikram.Hegde@Sun.COM 8538215SVikram.Hegde@Sun.COM int 8548215SVikram.Hegde@Sun.COM iommulib_iommu_dma_clear_cookies(dev_info_t *dip, ddi_dma_handle_t handle) 8558215SVikram.Hegde@Sun.COM { 8568215SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 8578215SVikram.Hegde@Sun.COM if (nexops == NULL) 8588215SVikram.Hegde@Sun.COM return (DDI_FAILURE); 8598215SVikram.Hegde@Sun.COM return (nexops->nops_dma_clear_cookies(dip, handle)); 8608215SVikram.Hegde@Sun.COM } 8618215SVikram.Hegde@Sun.COM 8628215SVikram.Hegde@Sun.COM int 8638215SVikram.Hegde@Sun.COM iommulib_iommu_dma_get_sleep_flags(dev_info_t *dip, ddi_dma_handle_t handle) 8648215SVikram.Hegde@Sun.COM { 8658215SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 8668215SVikram.Hegde@Sun.COM if (nexops == NULL) 8678215SVikram.Hegde@Sun.COM return (DDI_FAILURE); 8688215SVikram.Hegde@Sun.COM return (nexops->nops_dma_get_sleep_flags(handle)); 8697613SVikram.Hegde@Sun.COM } 8707613SVikram.Hegde@Sun.COM 8717613SVikram.Hegde@Sun.COM int 8727613SVikram.Hegde@Sun.COM iommulib_iommu_dma_sync(dev_info_t *dip, dev_info_t *rdip, 8737613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle, off_t off, size_t len, uint_t cache_flags) 8747613SVikram.Hegde@Sun.COM { 8757613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 8767613SVikram.Hegde@Sun.COM if (nexops == NULL) 8777613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 8787613SVikram.Hegde@Sun.COM return (nexops->nops_dma_sync(dip, rdip, handle, off, len, 8797613SVikram.Hegde@Sun.COM cache_flags)); 8807613SVikram.Hegde@Sun.COM } 8817613SVikram.Hegde@Sun.COM 8827613SVikram.Hegde@Sun.COM int 8837613SVikram.Hegde@Sun.COM iommulib_iommu_dma_win(dev_info_t *dip, dev_info_t *rdip, 8847613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle, uint_t win, off_t *offp, size_t *lenp, 8857613SVikram.Hegde@Sun.COM ddi_dma_cookie_t *cookiep, uint_t *ccountp) 8867613SVikram.Hegde@Sun.COM { 8877613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 8887613SVikram.Hegde@Sun.COM if (nexops == NULL) 8897613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 8907613SVikram.Hegde@Sun.COM return (nexops->nops_dma_win(dip, rdip, handle, win, offp, lenp, 8917613SVikram.Hegde@Sun.COM cookiep, ccountp)); 8927613SVikram.Hegde@Sun.COM } 8937613SVikram.Hegde@Sun.COM 8947613SVikram.Hegde@Sun.COM int 8957613SVikram.Hegde@Sun.COM iommulib_iommu_dma_map(dev_info_t *dip, dev_info_t *rdip, 8967613SVikram.Hegde@Sun.COM struct ddi_dma_req *dmareq, ddi_dma_handle_t *handlep) 8977613SVikram.Hegde@Sun.COM { 8987613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 8997613SVikram.Hegde@Sun.COM if (nexops == NULL) 9007613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 9017613SVikram.Hegde@Sun.COM return (nexops->nops_dma_map(dip, rdip, dmareq, handlep)); 9027613SVikram.Hegde@Sun.COM } 9037613SVikram.Hegde@Sun.COM 9047613SVikram.Hegde@Sun.COM int 9057613SVikram.Hegde@Sun.COM iommulib_iommu_dma_mctl(dev_info_t *dip, dev_info_t *rdip, 9067613SVikram.Hegde@Sun.COM ddi_dma_handle_t handle, enum ddi_dma_ctlops request, off_t *offp, 9077613SVikram.Hegde@Sun.COM size_t *lenp, caddr_t *objpp, uint_t cache_flags) 9087613SVikram.Hegde@Sun.COM { 9097613SVikram.Hegde@Sun.COM iommulib_nexops_t *nexops = lookup_nexops(dip); 9107613SVikram.Hegde@Sun.COM if (nexops == NULL) 9117613SVikram.Hegde@Sun.COM return (DDI_FAILURE); 9127613SVikram.Hegde@Sun.COM return (nexops->nops_dma_mctl(dip, rdip, handle, request, offp, lenp, 9137613SVikram.Hegde@Sun.COM objpp, cache_flags)); 9147613SVikram.Hegde@Sun.COM } 9157613SVikram.Hegde@Sun.COM 9167613SVikram.Hegde@Sun.COM int 9177613SVikram.Hegde@Sun.COM iommulib_iommu_getunitid(iommulib_handle_t handle, uint64_t *unitidp) 9187613SVikram.Hegde@Sun.COM { 9197613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 9207613SVikram.Hegde@Sun.COM uint64_t unitid; 9217613SVikram.Hegde@Sun.COM 9227613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)handle; 9237613SVikram.Hegde@Sun.COM 9247613SVikram.Hegde@Sun.COM ASSERT(unitp); 9257613SVikram.Hegde@Sun.COM ASSERT(unitidp); 9267613SVikram.Hegde@Sun.COM 9277613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 9287613SVikram.Hegde@Sun.COM unitid = unitp->ilu_unitid; 9297613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 9307613SVikram.Hegde@Sun.COM 9317613SVikram.Hegde@Sun.COM ASSERT(unitid > 0); 9327613SVikram.Hegde@Sun.COM *unitidp = (uint64_t)unitid; 9337613SVikram.Hegde@Sun.COM 9347613SVikram.Hegde@Sun.COM return (DDI_SUCCESS); 9357613SVikram.Hegde@Sun.COM } 9367613SVikram.Hegde@Sun.COM 9377613SVikram.Hegde@Sun.COM dev_info_t * 9387613SVikram.Hegde@Sun.COM iommulib_iommu_getdip(iommulib_handle_t handle) 9397613SVikram.Hegde@Sun.COM { 9407613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 9417613SVikram.Hegde@Sun.COM dev_info_t *dip; 9427613SVikram.Hegde@Sun.COM 9437613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)handle; 9447613SVikram.Hegde@Sun.COM 9457613SVikram.Hegde@Sun.COM ASSERT(unitp); 9467613SVikram.Hegde@Sun.COM 9477613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 9487613SVikram.Hegde@Sun.COM dip = unitp->ilu_dip; 9497613SVikram.Hegde@Sun.COM ASSERT(dip); 9507613SVikram.Hegde@Sun.COM ndi_hold_devi(dip); 9517613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 9527613SVikram.Hegde@Sun.COM 9537613SVikram.Hegde@Sun.COM return (dip); 9547613SVikram.Hegde@Sun.COM } 9557613SVikram.Hegde@Sun.COM 9567613SVikram.Hegde@Sun.COM iommulib_ops_t * 9577613SVikram.Hegde@Sun.COM iommulib_iommu_getops(iommulib_handle_t handle) 9587613SVikram.Hegde@Sun.COM { 9597613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 9607613SVikram.Hegde@Sun.COM iommulib_ops_t *ops; 9617613SVikram.Hegde@Sun.COM 9627613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)handle; 9637613SVikram.Hegde@Sun.COM 9647613SVikram.Hegde@Sun.COM ASSERT(unitp); 9657613SVikram.Hegde@Sun.COM 9667613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 9677613SVikram.Hegde@Sun.COM ops = unitp->ilu_ops; 9687613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 9697613SVikram.Hegde@Sun.COM 9707613SVikram.Hegde@Sun.COM ASSERT(ops); 9717613SVikram.Hegde@Sun.COM 9727613SVikram.Hegde@Sun.COM return (ops); 9737613SVikram.Hegde@Sun.COM } 9747613SVikram.Hegde@Sun.COM 9757613SVikram.Hegde@Sun.COM void * 9767613SVikram.Hegde@Sun.COM iommulib_iommu_getdata(iommulib_handle_t handle) 9777613SVikram.Hegde@Sun.COM { 9787613SVikram.Hegde@Sun.COM iommulib_unit_t *unitp; 9797613SVikram.Hegde@Sun.COM void *data; 9807613SVikram.Hegde@Sun.COM 9817613SVikram.Hegde@Sun.COM unitp = (iommulib_unit_t *)handle; 9827613SVikram.Hegde@Sun.COM 9837613SVikram.Hegde@Sun.COM ASSERT(unitp); 9847613SVikram.Hegde@Sun.COM 9857613SVikram.Hegde@Sun.COM mutex_enter(&unitp->ilu_lock); 9867613SVikram.Hegde@Sun.COM data = unitp->ilu_data; 9877613SVikram.Hegde@Sun.COM mutex_exit(&unitp->ilu_lock); 9887613SVikram.Hegde@Sun.COM 9897613SVikram.Hegde@Sun.COM ASSERT(data); 9907613SVikram.Hegde@Sun.COM 9917613SVikram.Hegde@Sun.COM return (data); 9927613SVikram.Hegde@Sun.COM } 993