16732dbb3SVikram Hegde /*
26732dbb3SVikram Hegde * CDDL HEADER START
36732dbb3SVikram Hegde *
46732dbb3SVikram Hegde * The contents of this file are subject to the terms of the
56732dbb3SVikram Hegde * Common Development and Distribution License (the "License").
66732dbb3SVikram Hegde * You may not use this file except in compliance with the License.
76732dbb3SVikram Hegde *
86732dbb3SVikram Hegde * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96732dbb3SVikram Hegde * or http://www.opensolaris.org/os/licensing.
106732dbb3SVikram Hegde * See the License for the specific language governing permissions
116732dbb3SVikram Hegde * and limitations under the License.
126732dbb3SVikram Hegde *
136732dbb3SVikram Hegde * When distributing Covered Code, include this CDDL HEADER in each
146732dbb3SVikram Hegde * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156732dbb3SVikram Hegde * If applicable, add the following below this CDDL HEADER, with the
166732dbb3SVikram Hegde * fields enclosed by brackets "[]" replaced with your own identifying
176732dbb3SVikram Hegde * information: Portions Copyright [yyyy] [name of copyright owner]
186732dbb3SVikram Hegde *
196732dbb3SVikram Hegde * CDDL HEADER END
206732dbb3SVikram Hegde */
216732dbb3SVikram Hegde
226732dbb3SVikram Hegde /*
236732dbb3SVikram Hegde * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
246732dbb3SVikram Hegde * Use is subject to license terms.
256732dbb3SVikram Hegde */
266732dbb3SVikram Hegde
276732dbb3SVikram Hegde #include <sys/types.h>
286732dbb3SVikram Hegde #include <sys/file.h>
296732dbb3SVikram Hegde #include <sys/errno.h>
306732dbb3SVikram Hegde #include <sys/open.h>
316732dbb3SVikram Hegde #include <sys/stat.h>
326732dbb3SVikram Hegde #include <sys/cred.h>
336732dbb3SVikram Hegde #include <sys/modctl.h>
346732dbb3SVikram Hegde #include <sys/conf.h>
356732dbb3SVikram Hegde #include <sys/devops.h>
366732dbb3SVikram Hegde #include <sys/ddi.h>
376732dbb3SVikram Hegde #include <sys/x86_archext.h>
386732dbb3SVikram Hegde
396732dbb3SVikram Hegde #include <sys/amd_iommu.h>
406732dbb3SVikram Hegde #include "amd_iommu_impl.h"
416732dbb3SVikram Hegde #include "amd_iommu_acpi.h"
426732dbb3SVikram Hegde
436732dbb3SVikram Hegde
446732dbb3SVikram Hegde #define AMD_IOMMU_MINOR2INST(x) (x)
456732dbb3SVikram Hegde #define AMD_IOMMU_INST2MINOR(x) (x)
466732dbb3SVikram Hegde #define AMD_IOMMU_NODETYPE "ddi_iommu"
476732dbb3SVikram Hegde #define AMD_IOMMU_MINOR_NAME "amd-iommu"
486732dbb3SVikram Hegde
496732dbb3SVikram Hegde static int amd_iommu_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
506732dbb3SVikram Hegde void **result);
516732dbb3SVikram Hegde static int amd_iommu_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
526732dbb3SVikram Hegde static int amd_iommu_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
536732dbb3SVikram Hegde static int amd_iommu_open(dev_t *devp, int flag, int otyp, cred_t *credp);
546732dbb3SVikram Hegde static int amd_iommu_close(dev_t dev, int flag, int otyp, cred_t *credp);
556732dbb3SVikram Hegde static int amd_iommu_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
566732dbb3SVikram Hegde cred_t *credp, int *rvalp);
57ac48dfe8SVikram Hegde static int amd_iommu_quiesce(dev_info_t *dip);
586732dbb3SVikram Hegde
596732dbb3SVikram Hegde static struct cb_ops amd_iommu_cb_ops = {
606732dbb3SVikram Hegde amd_iommu_open, /* cb_open */
616732dbb3SVikram Hegde amd_iommu_close, /* cb_close */
626732dbb3SVikram Hegde nodev, /* cb_strategy */
636732dbb3SVikram Hegde nodev, /* cb_print */
646732dbb3SVikram Hegde nodev, /* cb_dump */
656732dbb3SVikram Hegde nodev, /* cb_read */
666732dbb3SVikram Hegde nodev, /* cb_write */
676732dbb3SVikram Hegde amd_iommu_ioctl, /* cb_ioctl */
686732dbb3SVikram Hegde nodev, /* cb_devmap */
696732dbb3SVikram Hegde nodev, /* cb_mmap */
706732dbb3SVikram Hegde nodev, /* cb_segmap */
716732dbb3SVikram Hegde nochpoll, /* cb_chpoll */
726732dbb3SVikram Hegde ddi_prop_op, /* cb_prop_op */
736732dbb3SVikram Hegde NULL, /* cb_str */
746732dbb3SVikram Hegde D_NEW | D_MP, /* cb_flag */
756732dbb3SVikram Hegde CB_REV, /* cb_rev */
766732dbb3SVikram Hegde nodev, /* cb_aread */
776732dbb3SVikram Hegde nodev /* cb_awrite */
786732dbb3SVikram Hegde };
796732dbb3SVikram Hegde
806732dbb3SVikram Hegde static struct dev_ops amd_iommu_dev_ops = {
816732dbb3SVikram Hegde DEVO_REV, /* devo_rev */
826732dbb3SVikram Hegde 0, /* devo_refcnt */
836732dbb3SVikram Hegde amd_iommu_getinfo, /* devo_getinfo */
846732dbb3SVikram Hegde nulldev, /* devo_identify */
856732dbb3SVikram Hegde nulldev, /* devo_probe */
866732dbb3SVikram Hegde amd_iommu_attach, /* devo_attach */
876732dbb3SVikram Hegde amd_iommu_detach, /* devo_detach */
886732dbb3SVikram Hegde nodev, /* devo_reset */
896732dbb3SVikram Hegde &amd_iommu_cb_ops, /* devo_cb_ops */
906732dbb3SVikram Hegde NULL, /* devo_bus_ops */
91ac48dfe8SVikram Hegde nulldev, /* devo_power */
92ac48dfe8SVikram Hegde amd_iommu_quiesce, /* devo_quiesce */
936732dbb3SVikram Hegde };
946732dbb3SVikram Hegde
956732dbb3SVikram Hegde static struct modldrv modldrv = {
966732dbb3SVikram Hegde &mod_driverops,
976732dbb3SVikram Hegde "AMD IOMMU 0.1",
986732dbb3SVikram Hegde &amd_iommu_dev_ops
996732dbb3SVikram Hegde };
1006732dbb3SVikram Hegde
1016732dbb3SVikram Hegde static struct modlinkage modlinkage = {
1026732dbb3SVikram Hegde MODREV_1,
1036732dbb3SVikram Hegde (void *)&modldrv,
1046732dbb3SVikram Hegde NULL
1056732dbb3SVikram Hegde };
1066732dbb3SVikram Hegde
1076732dbb3SVikram Hegde amd_iommu_debug_t amd_iommu_debug;
1086732dbb3SVikram Hegde kmutex_t amd_iommu_global_lock;
1096732dbb3SVikram Hegde const char *amd_iommu_modname = "amd_iommu";
1106732dbb3SVikram Hegde amd_iommu_alias_t **amd_iommu_alias;
1116732dbb3SVikram Hegde amd_iommu_page_table_hash_t amd_iommu_page_table_hash;
1126732dbb3SVikram Hegde static void *amd_iommu_statep;
1136732dbb3SVikram Hegde int amd_iommu_64bit_bug;
1146732dbb3SVikram Hegde int amd_iommu_unity_map;
1156732dbb3SVikram Hegde int amd_iommu_no_RW_perms;
1166732dbb3SVikram Hegde int amd_iommu_no_unmap;
1176732dbb3SVikram Hegde int amd_iommu_pageva_inval_all;
1186732dbb3SVikram Hegde int amd_iommu_disable; /* disable IOMMU */
1196732dbb3SVikram Hegde char *amd_iommu_disable_list; /* list of drivers bypassing IOMMU */
1206732dbb3SVikram Hegde
1216732dbb3SVikram Hegde int
_init(void)1226732dbb3SVikram Hegde _init(void)
1236732dbb3SVikram Hegde {
1246732dbb3SVikram Hegde int error = ENOTSUP;
1256732dbb3SVikram Hegde
126*86ef0a63SRichard Lowe #if !defined(__xpv)
1276732dbb3SVikram Hegde
1286732dbb3SVikram Hegde if (get_hwenv() != HW_NATIVE)
1296732dbb3SVikram Hegde return (ENOTSUP);
1306732dbb3SVikram Hegde
1316732dbb3SVikram Hegde error = ddi_soft_state_init(&amd_iommu_statep,
1326732dbb3SVikram Hegde sizeof (struct amd_iommu_state), 1);
1336732dbb3SVikram Hegde if (error) {
1346732dbb3SVikram Hegde cmn_err(CE_WARN, "%s: _init: failed to init soft state.",
1356732dbb3SVikram Hegde amd_iommu_modname);
1366732dbb3SVikram Hegde return (error);
1376732dbb3SVikram Hegde }
1386732dbb3SVikram Hegde
1396732dbb3SVikram Hegde if (amd_iommu_acpi_init() != DDI_SUCCESS) {
1406732dbb3SVikram Hegde if (amd_iommu_debug) {
1416732dbb3SVikram Hegde cmn_err(CE_WARN, "%s: _init: ACPI init failed.",
1426732dbb3SVikram Hegde amd_iommu_modname);
1436732dbb3SVikram Hegde }
1446732dbb3SVikram Hegde ddi_soft_state_fini(&amd_iommu_statep);
1456732dbb3SVikram Hegde return (ENOTSUP);
1466732dbb3SVikram Hegde }
1476732dbb3SVikram Hegde
1486732dbb3SVikram Hegde amd_iommu_read_boot_props();
1496732dbb3SVikram Hegde
1506732dbb3SVikram Hegde if (amd_iommu_page_table_hash_init(&amd_iommu_page_table_hash)
1516732dbb3SVikram Hegde != DDI_SUCCESS) {
1526732dbb3SVikram Hegde cmn_err(CE_WARN, "%s: _init: Page table hash init failed.",
1536732dbb3SVikram Hegde amd_iommu_modname);
1546732dbb3SVikram Hegde if (amd_iommu_disable_list) {
1556732dbb3SVikram Hegde kmem_free(amd_iommu_disable_list,
1566732dbb3SVikram Hegde strlen(amd_iommu_disable_list) + 1);
1576732dbb3SVikram Hegde amd_iommu_disable_list = NULL;
1586732dbb3SVikram Hegde }
1596732dbb3SVikram Hegde amd_iommu_acpi_fini();
1606732dbb3SVikram Hegde ddi_soft_state_fini(&amd_iommu_statep);
1616732dbb3SVikram Hegde amd_iommu_statep = NULL;
1626732dbb3SVikram Hegde return (EFAULT);
1636732dbb3SVikram Hegde }
1646732dbb3SVikram Hegde
1656732dbb3SVikram Hegde error = mod_install(&modlinkage);
1666732dbb3SVikram Hegde if (error) {
1676732dbb3SVikram Hegde cmn_err(CE_WARN, "%s: _init: mod_install failed.",
1686732dbb3SVikram Hegde amd_iommu_modname);
1696732dbb3SVikram Hegde amd_iommu_page_table_hash_fini(&amd_iommu_page_table_hash);
1706732dbb3SVikram Hegde if (amd_iommu_disable_list) {
1716732dbb3SVikram Hegde kmem_free(amd_iommu_disable_list,
1726732dbb3SVikram Hegde strlen(amd_iommu_disable_list) + 1);
1736732dbb3SVikram Hegde amd_iommu_disable_list = NULL;
1746732dbb3SVikram Hegde }
1756732dbb3SVikram Hegde amd_iommu_acpi_fini();
1766732dbb3SVikram Hegde ddi_soft_state_fini(&amd_iommu_statep);
1776732dbb3SVikram Hegde amd_iommu_statep = NULL;
1786732dbb3SVikram Hegde return (error);
1796732dbb3SVikram Hegde }
1806732dbb3SVikram Hegde error = 0;
1816732dbb3SVikram Hegde #endif
1826732dbb3SVikram Hegde
1836732dbb3SVikram Hegde return (error);
1846732dbb3SVikram Hegde }
1856732dbb3SVikram Hegde
1866732dbb3SVikram Hegde int
_info(struct modinfo * modinfop)1876732dbb3SVikram Hegde _info(struct modinfo *modinfop)
1886732dbb3SVikram Hegde {
1896732dbb3SVikram Hegde return (mod_info(&modlinkage, modinfop));
1906732dbb3SVikram Hegde }
1916732dbb3SVikram Hegde
1926732dbb3SVikram Hegde int
_fini(void)1936732dbb3SVikram Hegde _fini(void)
1946732dbb3SVikram Hegde {
1956732dbb3SVikram Hegde int error;
1966732dbb3SVikram Hegde
1976732dbb3SVikram Hegde error = mod_remove(&modlinkage);
1986732dbb3SVikram Hegde if (error)
1996732dbb3SVikram Hegde return (error);
2006732dbb3SVikram Hegde
2016732dbb3SVikram Hegde amd_iommu_page_table_hash_fini(&amd_iommu_page_table_hash);
2026732dbb3SVikram Hegde if (amd_iommu_disable_list) {
2036732dbb3SVikram Hegde kmem_free(amd_iommu_disable_list,
2046732dbb3SVikram Hegde strlen(amd_iommu_disable_list) + 1);
2056732dbb3SVikram Hegde amd_iommu_disable_list = NULL;
2066732dbb3SVikram Hegde }
2076732dbb3SVikram Hegde amd_iommu_acpi_fini();
2086732dbb3SVikram Hegde ddi_soft_state_fini(&amd_iommu_statep);
2096732dbb3SVikram Hegde amd_iommu_statep = NULL;
2106732dbb3SVikram Hegde
2116732dbb3SVikram Hegde return (0);
2126732dbb3SVikram Hegde }
2136732dbb3SVikram Hegde
2146732dbb3SVikram Hegde /*ARGSUSED*/
2156732dbb3SVikram Hegde static int
amd_iommu_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)2166732dbb3SVikram Hegde amd_iommu_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
2176732dbb3SVikram Hegde {
2186732dbb3SVikram Hegde struct amd_iommu_state *statep;
2196732dbb3SVikram Hegde
2206732dbb3SVikram Hegde ASSERT(result);
2216732dbb3SVikram Hegde
2226732dbb3SVikram Hegde *result = NULL;
2236732dbb3SVikram Hegde
2246732dbb3SVikram Hegde switch (cmd) {
2256732dbb3SVikram Hegde case DDI_INFO_DEVT2DEVINFO:
2266732dbb3SVikram Hegde statep = ddi_get_soft_state(amd_iommu_statep,
2276732dbb3SVikram Hegde AMD_IOMMU_MINOR2INST(getminor((dev_t)arg)));
2286732dbb3SVikram Hegde if (statep) {
2296732dbb3SVikram Hegde *result = statep->aioms_devi;
2306732dbb3SVikram Hegde return (DDI_SUCCESS);
2316732dbb3SVikram Hegde }
2326732dbb3SVikram Hegde break;
2336732dbb3SVikram Hegde case DDI_INFO_DEVT2INSTANCE:
2346732dbb3SVikram Hegde *result = (void *)(uintptr_t)
2356732dbb3SVikram Hegde AMD_IOMMU_MINOR2INST(getminor((dev_t)arg));
2366732dbb3SVikram Hegde return (DDI_SUCCESS);
2376732dbb3SVikram Hegde }
2386732dbb3SVikram Hegde
2396732dbb3SVikram Hegde return (DDI_FAILURE);
2406732dbb3SVikram Hegde }
2416732dbb3SVikram Hegde
2426732dbb3SVikram Hegde static int
amd_iommu_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)2436732dbb3SVikram Hegde amd_iommu_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2446732dbb3SVikram Hegde {
2456732dbb3SVikram Hegde int instance = ddi_get_instance(dip);
2466732dbb3SVikram Hegde const char *driver = ddi_driver_name(dip);
2476732dbb3SVikram Hegde struct amd_iommu_state *statep;
2486732dbb3SVikram Hegde
2496732dbb3SVikram Hegde ASSERT(instance >= 0);
2506732dbb3SVikram Hegde ASSERT(driver);
2516732dbb3SVikram Hegde
2526732dbb3SVikram Hegde switch (cmd) {
2536732dbb3SVikram Hegde case DDI_ATTACH:
2546732dbb3SVikram Hegde if (ddi_soft_state_zalloc(amd_iommu_statep, instance)
2556732dbb3SVikram Hegde != DDI_SUCCESS) {
2566732dbb3SVikram Hegde cmn_err(CE_WARN, "Unable to allocate soft state for "
2576732dbb3SVikram Hegde "%s%d", driver, instance);
2586732dbb3SVikram Hegde return (DDI_FAILURE);
2596732dbb3SVikram Hegde }
2606732dbb3SVikram Hegde
2616732dbb3SVikram Hegde statep = ddi_get_soft_state(amd_iommu_statep, instance);
2626732dbb3SVikram Hegde if (statep == NULL) {
2636732dbb3SVikram Hegde cmn_err(CE_WARN, "Unable to get soft state for "
2646732dbb3SVikram Hegde "%s%d", driver, instance);
2656732dbb3SVikram Hegde ddi_soft_state_free(amd_iommu_statep, instance);
2666732dbb3SVikram Hegde return (DDI_FAILURE);
2676732dbb3SVikram Hegde }
2686732dbb3SVikram Hegde
2696732dbb3SVikram Hegde if (ddi_create_minor_node(dip, AMD_IOMMU_MINOR_NAME, S_IFCHR,
2706732dbb3SVikram Hegde AMD_IOMMU_INST2MINOR(instance), AMD_IOMMU_NODETYPE,
2716732dbb3SVikram Hegde 0) != DDI_SUCCESS) {
2726732dbb3SVikram Hegde cmn_err(CE_WARN, "Unable to create minor node for "
2736732dbb3SVikram Hegde "%s%d", driver, instance);
2746732dbb3SVikram Hegde ddi_remove_minor_node(dip, NULL);
2756732dbb3SVikram Hegde ddi_soft_state_free(amd_iommu_statep, instance);
2766732dbb3SVikram Hegde return (DDI_FAILURE);
2776732dbb3SVikram Hegde }
2786732dbb3SVikram Hegde
2796732dbb3SVikram Hegde statep->aioms_devi = dip;
2806732dbb3SVikram Hegde statep->aioms_instance = instance;
2816732dbb3SVikram Hegde statep->aioms_iommu_start = NULL;
2826732dbb3SVikram Hegde statep->aioms_iommu_end = NULL;
2836732dbb3SVikram Hegde
2846732dbb3SVikram Hegde amd_iommu_lookup_conf_props(dip);
2856732dbb3SVikram Hegde
2866732dbb3SVikram Hegde if (amd_iommu_disable_list) {
2876732dbb3SVikram Hegde cmn_err(CE_NOTE, "AMD IOMMU disabled for the following"
2886732dbb3SVikram Hegde " drivers:\n%s", amd_iommu_disable_list);
2896732dbb3SVikram Hegde }
2906732dbb3SVikram Hegde
2916732dbb3SVikram Hegde if (amd_iommu_disable) {
2926732dbb3SVikram Hegde cmn_err(CE_NOTE, "AMD IOMMU disabled by user");
2936732dbb3SVikram Hegde } else if (amd_iommu_setup(dip, statep) != DDI_SUCCESS) {
2946732dbb3SVikram Hegde cmn_err(CE_WARN, "Unable to initialize AMD IOMMU "
2956732dbb3SVikram Hegde "%s%d", driver, instance);
2966732dbb3SVikram Hegde ddi_remove_minor_node(dip, NULL);
2976732dbb3SVikram Hegde ddi_soft_state_free(amd_iommu_statep, instance);
2986732dbb3SVikram Hegde return (DDI_FAILURE);
2996732dbb3SVikram Hegde }
3006732dbb3SVikram Hegde
3016732dbb3SVikram Hegde ddi_report_dev(dip);
3026732dbb3SVikram Hegde
3036732dbb3SVikram Hegde return (DDI_SUCCESS);
3046732dbb3SVikram Hegde
3056732dbb3SVikram Hegde case DDI_RESUME:
3066732dbb3SVikram Hegde return (DDI_SUCCESS);
3076732dbb3SVikram Hegde default:
3086732dbb3SVikram Hegde return (DDI_FAILURE);
3096732dbb3SVikram Hegde }
3106732dbb3SVikram Hegde }
3116732dbb3SVikram Hegde
3126732dbb3SVikram Hegde static int
amd_iommu_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)3136732dbb3SVikram Hegde amd_iommu_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
3146732dbb3SVikram Hegde {
3156732dbb3SVikram Hegde int instance = ddi_get_instance(dip);
3166732dbb3SVikram Hegde const char *driver = ddi_driver_name(dip);
3176732dbb3SVikram Hegde struct amd_iommu_state *statep;
3186732dbb3SVikram Hegde
3196732dbb3SVikram Hegde ASSERT(instance >= 0);
3206732dbb3SVikram Hegde ASSERT(driver);
3216732dbb3SVikram Hegde
3226732dbb3SVikram Hegde switch (cmd) {
3236732dbb3SVikram Hegde case DDI_DETACH:
3246732dbb3SVikram Hegde statep = ddi_get_soft_state(amd_iommu_statep, instance);
3256732dbb3SVikram Hegde if (statep == NULL) {
3266732dbb3SVikram Hegde cmn_err(CE_WARN, "%s%d: Cannot get soft state",
3276732dbb3SVikram Hegde driver, instance);
3286732dbb3SVikram Hegde return (DDI_FAILURE);
3296732dbb3SVikram Hegde }
3306732dbb3SVikram Hegde return (DDI_FAILURE);
3316732dbb3SVikram Hegde case DDI_SUSPEND:
3326732dbb3SVikram Hegde return (DDI_SUCCESS);
3336732dbb3SVikram Hegde default:
3346732dbb3SVikram Hegde return (DDI_FAILURE);
3356732dbb3SVikram Hegde }
3366732dbb3SVikram Hegde }
3376732dbb3SVikram Hegde
3386732dbb3SVikram Hegde /*ARGSUSED*/
3396732dbb3SVikram Hegde static int
amd_iommu_open(dev_t * devp,int flag,int otyp,cred_t * credp)3406732dbb3SVikram Hegde amd_iommu_open(dev_t *devp, int flag, int otyp, cred_t *credp)
3416732dbb3SVikram Hegde {
3426732dbb3SVikram Hegde int instance = AMD_IOMMU_MINOR2INST(getminor(*devp));
3436732dbb3SVikram Hegde struct amd_iommu_state *statep;
3446732dbb3SVikram Hegde const char *f = "amd_iommu_open";
3456732dbb3SVikram Hegde
3466732dbb3SVikram Hegde if (instance < 0) {
3476732dbb3SVikram Hegde cmn_err(CE_WARN, "%s: invalid instance %d",
3486732dbb3SVikram Hegde f, instance);
3496732dbb3SVikram Hegde return (ENXIO);
3506732dbb3SVikram Hegde }
3516732dbb3SVikram Hegde
3526732dbb3SVikram Hegde if (!(flag & (FREAD|FWRITE))) {
3536732dbb3SVikram Hegde cmn_err(CE_WARN, "%s: invalid flags %d", f, flag);
3546732dbb3SVikram Hegde return (EINVAL);
3556732dbb3SVikram Hegde }
3566732dbb3SVikram Hegde
3576732dbb3SVikram Hegde if (otyp != OTYP_CHR) {
3586732dbb3SVikram Hegde cmn_err(CE_WARN, "%s: invalid otyp %d", f, otyp);
3596732dbb3SVikram Hegde return (EINVAL);
3606732dbb3SVikram Hegde }
3616732dbb3SVikram Hegde
3626732dbb3SVikram Hegde statep = ddi_get_soft_state(amd_iommu_statep, instance);
3636732dbb3SVikram Hegde if (statep == NULL) {
3646732dbb3SVikram Hegde cmn_err(CE_WARN, "%s: cannot get soft state: instance %d",
3656732dbb3SVikram Hegde f, instance);
3666732dbb3SVikram Hegde return (ENXIO);
3676732dbb3SVikram Hegde }
3686732dbb3SVikram Hegde
3696732dbb3SVikram Hegde ASSERT(statep->aioms_instance == instance);
3706732dbb3SVikram Hegde
3716732dbb3SVikram Hegde return (0);
3726732dbb3SVikram Hegde }
3736732dbb3SVikram Hegde
3746732dbb3SVikram Hegde /*ARGSUSED*/
3756732dbb3SVikram Hegde static int
amd_iommu_close(dev_t dev,int flag,int otyp,cred_t * credp)3766732dbb3SVikram Hegde amd_iommu_close(dev_t dev, int flag, int otyp, cred_t *credp)
3776732dbb3SVikram Hegde {
3786732dbb3SVikram Hegde int instance = AMD_IOMMU_MINOR2INST(getminor(dev));
3796732dbb3SVikram Hegde struct amd_iommu_state *statep;
3806732dbb3SVikram Hegde const char *f = "amd_iommu_close";
3816732dbb3SVikram Hegde
3826732dbb3SVikram Hegde if (instance < 0) {
3836732dbb3SVikram Hegde cmn_err(CE_WARN, "%s: invalid instance %d", f, instance);
3846732dbb3SVikram Hegde return (ENXIO);
3856732dbb3SVikram Hegde }
3866732dbb3SVikram Hegde
3876732dbb3SVikram Hegde if (!(flag & (FREAD|FWRITE))) {
3886732dbb3SVikram Hegde cmn_err(CE_WARN, "%s: invalid flags %d", f, flag);
3896732dbb3SVikram Hegde return (EINVAL);
3906732dbb3SVikram Hegde }
3916732dbb3SVikram Hegde
3926732dbb3SVikram Hegde if (otyp != OTYP_CHR) {
3936732dbb3SVikram Hegde cmn_err(CE_WARN, "%s: invalid otyp %d", f, otyp);
3946732dbb3SVikram Hegde return (EINVAL);
3956732dbb3SVikram Hegde }
3966732dbb3SVikram Hegde
3976732dbb3SVikram Hegde statep = ddi_get_soft_state(amd_iommu_statep, instance);
3986732dbb3SVikram Hegde if (statep == NULL) {
3996732dbb3SVikram Hegde cmn_err(CE_WARN, "%s: cannot get soft state: instance %d",
4006732dbb3SVikram Hegde f, instance);
4016732dbb3SVikram Hegde return (ENXIO);
4026732dbb3SVikram Hegde }
4036732dbb3SVikram Hegde
4046732dbb3SVikram Hegde ASSERT(statep->aioms_instance == instance);
4056732dbb3SVikram Hegde return (0);
4066732dbb3SVikram Hegde
4076732dbb3SVikram Hegde }
4086732dbb3SVikram Hegde
4096732dbb3SVikram Hegde /*ARGSUSED*/
4106732dbb3SVikram Hegde static int
amd_iommu_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)4116732dbb3SVikram Hegde amd_iommu_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
4126732dbb3SVikram Hegde int *rvalp)
4136732dbb3SVikram Hegde {
4146732dbb3SVikram Hegde int instance = AMD_IOMMU_MINOR2INST(getminor(dev));
4156732dbb3SVikram Hegde struct amd_iommu_state *statep;
4166732dbb3SVikram Hegde const char *f = "amd_iommu_ioctl";
4176732dbb3SVikram Hegde
4186732dbb3SVikram Hegde ASSERT(*rvalp);
4196732dbb3SVikram Hegde
4206732dbb3SVikram Hegde if (instance < 0) {
4216732dbb3SVikram Hegde cmn_err(CE_WARN, "%s: invalid instance %d", f, instance);
4226732dbb3SVikram Hegde return (ENXIO);
4236732dbb3SVikram Hegde }
4246732dbb3SVikram Hegde
4256732dbb3SVikram Hegde
4266732dbb3SVikram Hegde if (!(mode & (FREAD|FWRITE))) {
4276732dbb3SVikram Hegde cmn_err(CE_WARN, "%s: invalid mode %d", f, mode);
4286732dbb3SVikram Hegde return (EINVAL);
4296732dbb3SVikram Hegde }
4306732dbb3SVikram Hegde
4316732dbb3SVikram Hegde if (mode & FKIOCTL) {
4326732dbb3SVikram Hegde cmn_err(CE_WARN, "%s: FKIOCTL unsupported mode %d", f, mode);
4336732dbb3SVikram Hegde return (EINVAL);
4346732dbb3SVikram Hegde }
4356732dbb3SVikram Hegde
4366732dbb3SVikram Hegde statep = ddi_get_soft_state(amd_iommu_statep, instance);
4376732dbb3SVikram Hegde if (statep == NULL) {
4386732dbb3SVikram Hegde cmn_err(CE_WARN, "%s: cannot get soft state: instance %d",
4396732dbb3SVikram Hegde f, instance);
4406732dbb3SVikram Hegde return (ENXIO);
4416732dbb3SVikram Hegde }
4426732dbb3SVikram Hegde
4436732dbb3SVikram Hegde ASSERT(statep->aioms_instance == instance);
4446732dbb3SVikram Hegde
4456732dbb3SVikram Hegde return (ENOTTY);
4466732dbb3SVikram Hegde }
447ac48dfe8SVikram Hegde
448ac48dfe8SVikram Hegde static int
amd_iommu_quiesce(dev_info_t * dip)449ac48dfe8SVikram Hegde amd_iommu_quiesce(dev_info_t *dip)
450ac48dfe8SVikram Hegde {
451ac48dfe8SVikram Hegde int instance = ddi_get_instance(dip);
452ac48dfe8SVikram Hegde struct amd_iommu_state *statep;
453ac48dfe8SVikram Hegde const char *f = "amd_iommu_quiesce";
454ac48dfe8SVikram Hegde
455ac48dfe8SVikram Hegde statep = ddi_get_soft_state(amd_iommu_statep, instance);
456ac48dfe8SVikram Hegde if (statep == NULL) {
457ac48dfe8SVikram Hegde cmn_err(CE_WARN, "%s: cannot get soft state: instance %d",
458ac48dfe8SVikram Hegde f, instance);
459ac48dfe8SVikram Hegde return (DDI_FAILURE);
460ac48dfe8SVikram Hegde }
461ac48dfe8SVikram Hegde
462ac48dfe8SVikram Hegde if (amd_iommu_teardown(dip, statep, AMD_IOMMU_QUIESCE) != DDI_SUCCESS) {
463ac48dfe8SVikram Hegde cmn_err(CE_WARN, "%s: Unable to quiesce AMD IOMMU "
464ac48dfe8SVikram Hegde "%s%d", f, ddi_driver_name(dip), instance);
465ac48dfe8SVikram Hegde return (DDI_FAILURE);
466ac48dfe8SVikram Hegde }
467ac48dfe8SVikram Hegde
468ac48dfe8SVikram Hegde return (DDI_SUCCESS);
469ac48dfe8SVikram Hegde }
470