110535SVikram.Hegde@Sun.COM /*
210535SVikram.Hegde@Sun.COM * CDDL HEADER START
310535SVikram.Hegde@Sun.COM *
410535SVikram.Hegde@Sun.COM * The contents of this file are subject to the terms of the
510535SVikram.Hegde@Sun.COM * Common Development and Distribution License (the "License").
610535SVikram.Hegde@Sun.COM * You may not use this file except in compliance with the License.
710535SVikram.Hegde@Sun.COM *
810535SVikram.Hegde@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910535SVikram.Hegde@Sun.COM * or http://www.opensolaris.org/os/licensing.
1010535SVikram.Hegde@Sun.COM * See the License for the specific language governing permissions
1110535SVikram.Hegde@Sun.COM * and limitations under the License.
1210535SVikram.Hegde@Sun.COM *
1310535SVikram.Hegde@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1410535SVikram.Hegde@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510535SVikram.Hegde@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1610535SVikram.Hegde@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1710535SVikram.Hegde@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1810535SVikram.Hegde@Sun.COM *
1910535SVikram.Hegde@Sun.COM * CDDL HEADER END
2010535SVikram.Hegde@Sun.COM */
2110535SVikram.Hegde@Sun.COM
2210535SVikram.Hegde@Sun.COM /*
2310535SVikram.Hegde@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2410535SVikram.Hegde@Sun.COM * Use is subject to license terms.
2510535SVikram.Hegde@Sun.COM */
2610535SVikram.Hegde@Sun.COM
2710535SVikram.Hegde@Sun.COM #include <sys/types.h>
2810535SVikram.Hegde@Sun.COM #include <sys/file.h>
2910535SVikram.Hegde@Sun.COM #include <sys/errno.h>
3010535SVikram.Hegde@Sun.COM #include <sys/open.h>
3110535SVikram.Hegde@Sun.COM #include <sys/stat.h>
3210535SVikram.Hegde@Sun.COM #include <sys/cred.h>
3310535SVikram.Hegde@Sun.COM #include <sys/modctl.h>
3410535SVikram.Hegde@Sun.COM #include <sys/conf.h>
3510535SVikram.Hegde@Sun.COM #include <sys/devops.h>
3610535SVikram.Hegde@Sun.COM #include <sys/ddi.h>
3710535SVikram.Hegde@Sun.COM #include <sys/x86_archext.h>
3810535SVikram.Hegde@Sun.COM
3910535SVikram.Hegde@Sun.COM #include <sys/amd_iommu.h>
4010535SVikram.Hegde@Sun.COM #include "amd_iommu_impl.h"
4110535SVikram.Hegde@Sun.COM #include "amd_iommu_acpi.h"
4210535SVikram.Hegde@Sun.COM
4310535SVikram.Hegde@Sun.COM
4410535SVikram.Hegde@Sun.COM #define AMD_IOMMU_MINOR2INST(x) (x)
4510535SVikram.Hegde@Sun.COM #define AMD_IOMMU_INST2MINOR(x) (x)
4610535SVikram.Hegde@Sun.COM #define AMD_IOMMU_NODETYPE "ddi_iommu"
4710535SVikram.Hegde@Sun.COM #define AMD_IOMMU_MINOR_NAME "amd-iommu"
4810535SVikram.Hegde@Sun.COM
4910535SVikram.Hegde@Sun.COM static int amd_iommu_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
5010535SVikram.Hegde@Sun.COM void **result);
5110535SVikram.Hegde@Sun.COM static int amd_iommu_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
5210535SVikram.Hegde@Sun.COM static int amd_iommu_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
5310535SVikram.Hegde@Sun.COM static int amd_iommu_open(dev_t *devp, int flag, int otyp, cred_t *credp);
5410535SVikram.Hegde@Sun.COM static int amd_iommu_close(dev_t dev, int flag, int otyp, cred_t *credp);
5510535SVikram.Hegde@Sun.COM static int amd_iommu_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
5610535SVikram.Hegde@Sun.COM cred_t *credp, int *rvalp);
57*10536SVikram.Hegde@Sun.COM static int amd_iommu_quiesce(dev_info_t *dip);
5810535SVikram.Hegde@Sun.COM
5910535SVikram.Hegde@Sun.COM static struct cb_ops amd_iommu_cb_ops = {
6010535SVikram.Hegde@Sun.COM amd_iommu_open, /* cb_open */
6110535SVikram.Hegde@Sun.COM amd_iommu_close, /* cb_close */
6210535SVikram.Hegde@Sun.COM nodev, /* cb_strategy */
6310535SVikram.Hegde@Sun.COM nodev, /* cb_print */
6410535SVikram.Hegde@Sun.COM nodev, /* cb_dump */
6510535SVikram.Hegde@Sun.COM nodev, /* cb_read */
6610535SVikram.Hegde@Sun.COM nodev, /* cb_write */
6710535SVikram.Hegde@Sun.COM amd_iommu_ioctl, /* cb_ioctl */
6810535SVikram.Hegde@Sun.COM nodev, /* cb_devmap */
6910535SVikram.Hegde@Sun.COM nodev, /* cb_mmap */
7010535SVikram.Hegde@Sun.COM nodev, /* cb_segmap */
7110535SVikram.Hegde@Sun.COM nochpoll, /* cb_chpoll */
7210535SVikram.Hegde@Sun.COM ddi_prop_op, /* cb_prop_op */
7310535SVikram.Hegde@Sun.COM NULL, /* cb_str */
7410535SVikram.Hegde@Sun.COM D_NEW | D_MP, /* cb_flag */
7510535SVikram.Hegde@Sun.COM CB_REV, /* cb_rev */
7610535SVikram.Hegde@Sun.COM nodev, /* cb_aread */
7710535SVikram.Hegde@Sun.COM nodev /* cb_awrite */
7810535SVikram.Hegde@Sun.COM };
7910535SVikram.Hegde@Sun.COM
8010535SVikram.Hegde@Sun.COM static struct dev_ops amd_iommu_dev_ops = {
8110535SVikram.Hegde@Sun.COM DEVO_REV, /* devo_rev */
8210535SVikram.Hegde@Sun.COM 0, /* devo_refcnt */
8310535SVikram.Hegde@Sun.COM amd_iommu_getinfo, /* devo_getinfo */
8410535SVikram.Hegde@Sun.COM nulldev, /* devo_identify */
8510535SVikram.Hegde@Sun.COM nulldev, /* devo_probe */
8610535SVikram.Hegde@Sun.COM amd_iommu_attach, /* devo_attach */
8710535SVikram.Hegde@Sun.COM amd_iommu_detach, /* devo_detach */
8810535SVikram.Hegde@Sun.COM nodev, /* devo_reset */
8910535SVikram.Hegde@Sun.COM &amd_iommu_cb_ops, /* devo_cb_ops */
9010535SVikram.Hegde@Sun.COM NULL, /* devo_bus_ops */
91*10536SVikram.Hegde@Sun.COM nulldev, /* devo_power */
92*10536SVikram.Hegde@Sun.COM amd_iommu_quiesce, /* devo_quiesce */
9310535SVikram.Hegde@Sun.COM };
9410535SVikram.Hegde@Sun.COM
9510535SVikram.Hegde@Sun.COM static struct modldrv modldrv = {
9610535SVikram.Hegde@Sun.COM &mod_driverops,
9710535SVikram.Hegde@Sun.COM "AMD IOMMU 0.1",
9810535SVikram.Hegde@Sun.COM &amd_iommu_dev_ops
9910535SVikram.Hegde@Sun.COM };
10010535SVikram.Hegde@Sun.COM
10110535SVikram.Hegde@Sun.COM static struct modlinkage modlinkage = {
10210535SVikram.Hegde@Sun.COM MODREV_1,
10310535SVikram.Hegde@Sun.COM (void *)&modldrv,
10410535SVikram.Hegde@Sun.COM NULL
10510535SVikram.Hegde@Sun.COM };
10610535SVikram.Hegde@Sun.COM
10710535SVikram.Hegde@Sun.COM amd_iommu_debug_t amd_iommu_debug;
10810535SVikram.Hegde@Sun.COM kmutex_t amd_iommu_global_lock;
10910535SVikram.Hegde@Sun.COM const char *amd_iommu_modname = "amd_iommu";
11010535SVikram.Hegde@Sun.COM amd_iommu_alias_t **amd_iommu_alias;
11110535SVikram.Hegde@Sun.COM amd_iommu_page_table_hash_t amd_iommu_page_table_hash;
11210535SVikram.Hegde@Sun.COM static void *amd_iommu_statep;
11310535SVikram.Hegde@Sun.COM int amd_iommu_64bit_bug;
11410535SVikram.Hegde@Sun.COM int amd_iommu_unity_map;
11510535SVikram.Hegde@Sun.COM int amd_iommu_no_RW_perms;
11610535SVikram.Hegde@Sun.COM int amd_iommu_no_unmap;
11710535SVikram.Hegde@Sun.COM int amd_iommu_pageva_inval_all;
11810535SVikram.Hegde@Sun.COM int amd_iommu_disable; /* disable IOMMU */
11910535SVikram.Hegde@Sun.COM char *amd_iommu_disable_list; /* list of drivers bypassing IOMMU */
12010535SVikram.Hegde@Sun.COM
12110535SVikram.Hegde@Sun.COM int
_init(void)12210535SVikram.Hegde@Sun.COM _init(void)
12310535SVikram.Hegde@Sun.COM {
12410535SVikram.Hegde@Sun.COM int error = ENOTSUP;
12510535SVikram.Hegde@Sun.COM
12610535SVikram.Hegde@Sun.COM #if defined(__amd64) && !defined(__xpv)
12710535SVikram.Hegde@Sun.COM
12810535SVikram.Hegde@Sun.COM if (get_hwenv() != HW_NATIVE)
12910535SVikram.Hegde@Sun.COM return (ENOTSUP);
13010535SVikram.Hegde@Sun.COM
13110535SVikram.Hegde@Sun.COM error = ddi_soft_state_init(&amd_iommu_statep,
13210535SVikram.Hegde@Sun.COM sizeof (struct amd_iommu_state), 1);
13310535SVikram.Hegde@Sun.COM if (error) {
13410535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: _init: failed to init soft state.",
13510535SVikram.Hegde@Sun.COM amd_iommu_modname);
13610535SVikram.Hegde@Sun.COM return (error);
13710535SVikram.Hegde@Sun.COM }
13810535SVikram.Hegde@Sun.COM
13910535SVikram.Hegde@Sun.COM if (amd_iommu_acpi_init() != DDI_SUCCESS) {
14010535SVikram.Hegde@Sun.COM if (amd_iommu_debug) {
14110535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: _init: ACPI init failed.",
14210535SVikram.Hegde@Sun.COM amd_iommu_modname);
14310535SVikram.Hegde@Sun.COM }
14410535SVikram.Hegde@Sun.COM ddi_soft_state_fini(&amd_iommu_statep);
14510535SVikram.Hegde@Sun.COM return (ENOTSUP);
14610535SVikram.Hegde@Sun.COM }
14710535SVikram.Hegde@Sun.COM
14810535SVikram.Hegde@Sun.COM amd_iommu_read_boot_props();
14910535SVikram.Hegde@Sun.COM
15010535SVikram.Hegde@Sun.COM if (amd_iommu_page_table_hash_init(&amd_iommu_page_table_hash)
15110535SVikram.Hegde@Sun.COM != DDI_SUCCESS) {
15210535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: _init: Page table hash init failed.",
15310535SVikram.Hegde@Sun.COM amd_iommu_modname);
15410535SVikram.Hegde@Sun.COM if (amd_iommu_disable_list) {
15510535SVikram.Hegde@Sun.COM kmem_free(amd_iommu_disable_list,
15610535SVikram.Hegde@Sun.COM strlen(amd_iommu_disable_list) + 1);
15710535SVikram.Hegde@Sun.COM amd_iommu_disable_list = NULL;
15810535SVikram.Hegde@Sun.COM }
15910535SVikram.Hegde@Sun.COM amd_iommu_acpi_fini();
16010535SVikram.Hegde@Sun.COM ddi_soft_state_fini(&amd_iommu_statep);
16110535SVikram.Hegde@Sun.COM amd_iommu_statep = NULL;
16210535SVikram.Hegde@Sun.COM return (EFAULT);
16310535SVikram.Hegde@Sun.COM }
16410535SVikram.Hegde@Sun.COM
16510535SVikram.Hegde@Sun.COM error = mod_install(&modlinkage);
16610535SVikram.Hegde@Sun.COM if (error) {
16710535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: _init: mod_install failed.",
16810535SVikram.Hegde@Sun.COM amd_iommu_modname);
16910535SVikram.Hegde@Sun.COM amd_iommu_page_table_hash_fini(&amd_iommu_page_table_hash);
17010535SVikram.Hegde@Sun.COM if (amd_iommu_disable_list) {
17110535SVikram.Hegde@Sun.COM kmem_free(amd_iommu_disable_list,
17210535SVikram.Hegde@Sun.COM strlen(amd_iommu_disable_list) + 1);
17310535SVikram.Hegde@Sun.COM amd_iommu_disable_list = NULL;
17410535SVikram.Hegde@Sun.COM }
17510535SVikram.Hegde@Sun.COM amd_iommu_acpi_fini();
17610535SVikram.Hegde@Sun.COM ddi_soft_state_fini(&amd_iommu_statep);
17710535SVikram.Hegde@Sun.COM amd_iommu_statep = NULL;
17810535SVikram.Hegde@Sun.COM return (error);
17910535SVikram.Hegde@Sun.COM }
18010535SVikram.Hegde@Sun.COM error = 0;
18110535SVikram.Hegde@Sun.COM #endif
18210535SVikram.Hegde@Sun.COM
18310535SVikram.Hegde@Sun.COM return (error);
18410535SVikram.Hegde@Sun.COM }
18510535SVikram.Hegde@Sun.COM
18610535SVikram.Hegde@Sun.COM int
_info(struct modinfo * modinfop)18710535SVikram.Hegde@Sun.COM _info(struct modinfo *modinfop)
18810535SVikram.Hegde@Sun.COM {
18910535SVikram.Hegde@Sun.COM return (mod_info(&modlinkage, modinfop));
19010535SVikram.Hegde@Sun.COM }
19110535SVikram.Hegde@Sun.COM
19210535SVikram.Hegde@Sun.COM int
_fini(void)19310535SVikram.Hegde@Sun.COM _fini(void)
19410535SVikram.Hegde@Sun.COM {
19510535SVikram.Hegde@Sun.COM int error;
19610535SVikram.Hegde@Sun.COM
19710535SVikram.Hegde@Sun.COM error = mod_remove(&modlinkage);
19810535SVikram.Hegde@Sun.COM if (error)
19910535SVikram.Hegde@Sun.COM return (error);
20010535SVikram.Hegde@Sun.COM
20110535SVikram.Hegde@Sun.COM amd_iommu_page_table_hash_fini(&amd_iommu_page_table_hash);
20210535SVikram.Hegde@Sun.COM if (amd_iommu_disable_list) {
20310535SVikram.Hegde@Sun.COM kmem_free(amd_iommu_disable_list,
20410535SVikram.Hegde@Sun.COM strlen(amd_iommu_disable_list) + 1);
20510535SVikram.Hegde@Sun.COM amd_iommu_disable_list = NULL;
20610535SVikram.Hegde@Sun.COM }
20710535SVikram.Hegde@Sun.COM amd_iommu_acpi_fini();
20810535SVikram.Hegde@Sun.COM ddi_soft_state_fini(&amd_iommu_statep);
20910535SVikram.Hegde@Sun.COM amd_iommu_statep = NULL;
21010535SVikram.Hegde@Sun.COM
21110535SVikram.Hegde@Sun.COM return (0);
21210535SVikram.Hegde@Sun.COM }
21310535SVikram.Hegde@Sun.COM
21410535SVikram.Hegde@Sun.COM /*ARGSUSED*/
21510535SVikram.Hegde@Sun.COM static int
amd_iommu_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)21610535SVikram.Hegde@Sun.COM amd_iommu_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
21710535SVikram.Hegde@Sun.COM {
21810535SVikram.Hegde@Sun.COM struct amd_iommu_state *statep;
21910535SVikram.Hegde@Sun.COM
22010535SVikram.Hegde@Sun.COM ASSERT(result);
22110535SVikram.Hegde@Sun.COM
22210535SVikram.Hegde@Sun.COM *result = NULL;
22310535SVikram.Hegde@Sun.COM
22410535SVikram.Hegde@Sun.COM switch (cmd) {
22510535SVikram.Hegde@Sun.COM case DDI_INFO_DEVT2DEVINFO:
22610535SVikram.Hegde@Sun.COM statep = ddi_get_soft_state(amd_iommu_statep,
22710535SVikram.Hegde@Sun.COM AMD_IOMMU_MINOR2INST(getminor((dev_t)arg)));
22810535SVikram.Hegde@Sun.COM if (statep) {
22910535SVikram.Hegde@Sun.COM *result = statep->aioms_devi;
23010535SVikram.Hegde@Sun.COM return (DDI_SUCCESS);
23110535SVikram.Hegde@Sun.COM }
23210535SVikram.Hegde@Sun.COM break;
23310535SVikram.Hegde@Sun.COM case DDI_INFO_DEVT2INSTANCE:
23410535SVikram.Hegde@Sun.COM *result = (void *)(uintptr_t)
23510535SVikram.Hegde@Sun.COM AMD_IOMMU_MINOR2INST(getminor((dev_t)arg));
23610535SVikram.Hegde@Sun.COM return (DDI_SUCCESS);
23710535SVikram.Hegde@Sun.COM }
23810535SVikram.Hegde@Sun.COM
23910535SVikram.Hegde@Sun.COM return (DDI_FAILURE);
24010535SVikram.Hegde@Sun.COM }
24110535SVikram.Hegde@Sun.COM
24210535SVikram.Hegde@Sun.COM static int
amd_iommu_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)24310535SVikram.Hegde@Sun.COM amd_iommu_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
24410535SVikram.Hegde@Sun.COM {
24510535SVikram.Hegde@Sun.COM int instance = ddi_get_instance(dip);
24610535SVikram.Hegde@Sun.COM const char *driver = ddi_driver_name(dip);
24710535SVikram.Hegde@Sun.COM struct amd_iommu_state *statep;
24810535SVikram.Hegde@Sun.COM
24910535SVikram.Hegde@Sun.COM ASSERT(instance >= 0);
25010535SVikram.Hegde@Sun.COM ASSERT(driver);
25110535SVikram.Hegde@Sun.COM
25210535SVikram.Hegde@Sun.COM switch (cmd) {
25310535SVikram.Hegde@Sun.COM case DDI_ATTACH:
25410535SVikram.Hegde@Sun.COM if (ddi_soft_state_zalloc(amd_iommu_statep, instance)
25510535SVikram.Hegde@Sun.COM != DDI_SUCCESS) {
25610535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "Unable to allocate soft state for "
25710535SVikram.Hegde@Sun.COM "%s%d", driver, instance);
25810535SVikram.Hegde@Sun.COM return (DDI_FAILURE);
25910535SVikram.Hegde@Sun.COM }
26010535SVikram.Hegde@Sun.COM
26110535SVikram.Hegde@Sun.COM statep = ddi_get_soft_state(amd_iommu_statep, instance);
26210535SVikram.Hegde@Sun.COM if (statep == NULL) {
26310535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "Unable to get soft state for "
26410535SVikram.Hegde@Sun.COM "%s%d", driver, instance);
26510535SVikram.Hegde@Sun.COM ddi_soft_state_free(amd_iommu_statep, instance);
26610535SVikram.Hegde@Sun.COM return (DDI_FAILURE);
26710535SVikram.Hegde@Sun.COM }
26810535SVikram.Hegde@Sun.COM
26910535SVikram.Hegde@Sun.COM if (ddi_create_minor_node(dip, AMD_IOMMU_MINOR_NAME, S_IFCHR,
27010535SVikram.Hegde@Sun.COM AMD_IOMMU_INST2MINOR(instance), AMD_IOMMU_NODETYPE,
27110535SVikram.Hegde@Sun.COM 0) != DDI_SUCCESS) {
27210535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "Unable to create minor node for "
27310535SVikram.Hegde@Sun.COM "%s%d", driver, instance);
27410535SVikram.Hegde@Sun.COM ddi_remove_minor_node(dip, NULL);
27510535SVikram.Hegde@Sun.COM ddi_soft_state_free(amd_iommu_statep, instance);
27610535SVikram.Hegde@Sun.COM return (DDI_FAILURE);
27710535SVikram.Hegde@Sun.COM }
27810535SVikram.Hegde@Sun.COM
27910535SVikram.Hegde@Sun.COM statep->aioms_devi = dip;
28010535SVikram.Hegde@Sun.COM statep->aioms_instance = instance;
28110535SVikram.Hegde@Sun.COM statep->aioms_iommu_start = NULL;
28210535SVikram.Hegde@Sun.COM statep->aioms_iommu_end = NULL;
28310535SVikram.Hegde@Sun.COM
28410535SVikram.Hegde@Sun.COM amd_iommu_lookup_conf_props(dip);
28510535SVikram.Hegde@Sun.COM
28610535SVikram.Hegde@Sun.COM if (amd_iommu_disable_list) {
28710535SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "AMD IOMMU disabled for the following"
28810535SVikram.Hegde@Sun.COM " drivers:\n%s", amd_iommu_disable_list);
28910535SVikram.Hegde@Sun.COM }
29010535SVikram.Hegde@Sun.COM
29110535SVikram.Hegde@Sun.COM if (amd_iommu_disable) {
29210535SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "AMD IOMMU disabled by user");
29310535SVikram.Hegde@Sun.COM } else if (amd_iommu_setup(dip, statep) != DDI_SUCCESS) {
29410535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "Unable to initialize AMD IOMMU "
29510535SVikram.Hegde@Sun.COM "%s%d", driver, instance);
29610535SVikram.Hegde@Sun.COM ddi_remove_minor_node(dip, NULL);
29710535SVikram.Hegde@Sun.COM ddi_soft_state_free(amd_iommu_statep, instance);
29810535SVikram.Hegde@Sun.COM return (DDI_FAILURE);
29910535SVikram.Hegde@Sun.COM }
30010535SVikram.Hegde@Sun.COM
30110535SVikram.Hegde@Sun.COM ddi_report_dev(dip);
30210535SVikram.Hegde@Sun.COM
30310535SVikram.Hegde@Sun.COM return (DDI_SUCCESS);
30410535SVikram.Hegde@Sun.COM
30510535SVikram.Hegde@Sun.COM case DDI_RESUME:
30610535SVikram.Hegde@Sun.COM return (DDI_SUCCESS);
30710535SVikram.Hegde@Sun.COM default:
30810535SVikram.Hegde@Sun.COM return (DDI_FAILURE);
30910535SVikram.Hegde@Sun.COM }
31010535SVikram.Hegde@Sun.COM }
31110535SVikram.Hegde@Sun.COM
31210535SVikram.Hegde@Sun.COM static int
amd_iommu_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)31310535SVikram.Hegde@Sun.COM amd_iommu_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
31410535SVikram.Hegde@Sun.COM {
31510535SVikram.Hegde@Sun.COM int instance = ddi_get_instance(dip);
31610535SVikram.Hegde@Sun.COM const char *driver = ddi_driver_name(dip);
31710535SVikram.Hegde@Sun.COM struct amd_iommu_state *statep;
31810535SVikram.Hegde@Sun.COM
31910535SVikram.Hegde@Sun.COM ASSERT(instance >= 0);
32010535SVikram.Hegde@Sun.COM ASSERT(driver);
32110535SVikram.Hegde@Sun.COM
32210535SVikram.Hegde@Sun.COM switch (cmd) {
32310535SVikram.Hegde@Sun.COM case DDI_DETACH:
32410535SVikram.Hegde@Sun.COM statep = ddi_get_soft_state(amd_iommu_statep, instance);
32510535SVikram.Hegde@Sun.COM if (statep == NULL) {
32610535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s%d: Cannot get soft state",
32710535SVikram.Hegde@Sun.COM driver, instance);
32810535SVikram.Hegde@Sun.COM return (DDI_FAILURE);
32910535SVikram.Hegde@Sun.COM }
33010535SVikram.Hegde@Sun.COM return (DDI_FAILURE);
33110535SVikram.Hegde@Sun.COM case DDI_SUSPEND:
33210535SVikram.Hegde@Sun.COM return (DDI_SUCCESS);
33310535SVikram.Hegde@Sun.COM default:
33410535SVikram.Hegde@Sun.COM return (DDI_FAILURE);
33510535SVikram.Hegde@Sun.COM }
33610535SVikram.Hegde@Sun.COM }
33710535SVikram.Hegde@Sun.COM
33810535SVikram.Hegde@Sun.COM /*ARGSUSED*/
33910535SVikram.Hegde@Sun.COM static int
amd_iommu_open(dev_t * devp,int flag,int otyp,cred_t * credp)34010535SVikram.Hegde@Sun.COM amd_iommu_open(dev_t *devp, int flag, int otyp, cred_t *credp)
34110535SVikram.Hegde@Sun.COM {
34210535SVikram.Hegde@Sun.COM int instance = AMD_IOMMU_MINOR2INST(getminor(*devp));
34310535SVikram.Hegde@Sun.COM struct amd_iommu_state *statep;
34410535SVikram.Hegde@Sun.COM const char *f = "amd_iommu_open";
34510535SVikram.Hegde@Sun.COM
34610535SVikram.Hegde@Sun.COM if (instance < 0) {
34710535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: invalid instance %d",
34810535SVikram.Hegde@Sun.COM f, instance);
34910535SVikram.Hegde@Sun.COM return (ENXIO);
35010535SVikram.Hegde@Sun.COM }
35110535SVikram.Hegde@Sun.COM
35210535SVikram.Hegde@Sun.COM if (!(flag & (FREAD|FWRITE))) {
35310535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: invalid flags %d", f, flag);
35410535SVikram.Hegde@Sun.COM return (EINVAL);
35510535SVikram.Hegde@Sun.COM }
35610535SVikram.Hegde@Sun.COM
35710535SVikram.Hegde@Sun.COM if (otyp != OTYP_CHR) {
35810535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: invalid otyp %d", f, otyp);
35910535SVikram.Hegde@Sun.COM return (EINVAL);
36010535SVikram.Hegde@Sun.COM }
36110535SVikram.Hegde@Sun.COM
36210535SVikram.Hegde@Sun.COM statep = ddi_get_soft_state(amd_iommu_statep, instance);
36310535SVikram.Hegde@Sun.COM if (statep == NULL) {
36410535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: cannot get soft state: instance %d",
36510535SVikram.Hegde@Sun.COM f, instance);
36610535SVikram.Hegde@Sun.COM return (ENXIO);
36710535SVikram.Hegde@Sun.COM }
36810535SVikram.Hegde@Sun.COM
36910535SVikram.Hegde@Sun.COM ASSERT(statep->aioms_instance == instance);
37010535SVikram.Hegde@Sun.COM
37110535SVikram.Hegde@Sun.COM return (0);
37210535SVikram.Hegde@Sun.COM }
37310535SVikram.Hegde@Sun.COM
37410535SVikram.Hegde@Sun.COM /*ARGSUSED*/
37510535SVikram.Hegde@Sun.COM static int
amd_iommu_close(dev_t dev,int flag,int otyp,cred_t * credp)37610535SVikram.Hegde@Sun.COM amd_iommu_close(dev_t dev, int flag, int otyp, cred_t *credp)
37710535SVikram.Hegde@Sun.COM {
37810535SVikram.Hegde@Sun.COM int instance = AMD_IOMMU_MINOR2INST(getminor(dev));
37910535SVikram.Hegde@Sun.COM struct amd_iommu_state *statep;
38010535SVikram.Hegde@Sun.COM const char *f = "amd_iommu_close";
38110535SVikram.Hegde@Sun.COM
38210535SVikram.Hegde@Sun.COM if (instance < 0) {
38310535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: invalid instance %d", f, instance);
38410535SVikram.Hegde@Sun.COM return (ENXIO);
38510535SVikram.Hegde@Sun.COM }
38610535SVikram.Hegde@Sun.COM
38710535SVikram.Hegde@Sun.COM if (!(flag & (FREAD|FWRITE))) {
38810535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: invalid flags %d", f, flag);
38910535SVikram.Hegde@Sun.COM return (EINVAL);
39010535SVikram.Hegde@Sun.COM }
39110535SVikram.Hegde@Sun.COM
39210535SVikram.Hegde@Sun.COM if (otyp != OTYP_CHR) {
39310535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: invalid otyp %d", f, otyp);
39410535SVikram.Hegde@Sun.COM return (EINVAL);
39510535SVikram.Hegde@Sun.COM }
39610535SVikram.Hegde@Sun.COM
39710535SVikram.Hegde@Sun.COM statep = ddi_get_soft_state(amd_iommu_statep, instance);
39810535SVikram.Hegde@Sun.COM if (statep == NULL) {
39910535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: cannot get soft state: instance %d",
40010535SVikram.Hegde@Sun.COM f, instance);
40110535SVikram.Hegde@Sun.COM return (ENXIO);
40210535SVikram.Hegde@Sun.COM }
40310535SVikram.Hegde@Sun.COM
40410535SVikram.Hegde@Sun.COM ASSERT(statep->aioms_instance == instance);
40510535SVikram.Hegde@Sun.COM return (0);
40610535SVikram.Hegde@Sun.COM
40710535SVikram.Hegde@Sun.COM }
40810535SVikram.Hegde@Sun.COM
40910535SVikram.Hegde@Sun.COM /*ARGSUSED*/
41010535SVikram.Hegde@Sun.COM static int
amd_iommu_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)41110535SVikram.Hegde@Sun.COM amd_iommu_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
41210535SVikram.Hegde@Sun.COM int *rvalp)
41310535SVikram.Hegde@Sun.COM {
41410535SVikram.Hegde@Sun.COM int instance = AMD_IOMMU_MINOR2INST(getminor(dev));
41510535SVikram.Hegde@Sun.COM struct amd_iommu_state *statep;
41610535SVikram.Hegde@Sun.COM const char *f = "amd_iommu_ioctl";
41710535SVikram.Hegde@Sun.COM
41810535SVikram.Hegde@Sun.COM ASSERT(*rvalp);
41910535SVikram.Hegde@Sun.COM
42010535SVikram.Hegde@Sun.COM if (instance < 0) {
42110535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: invalid instance %d", f, instance);
42210535SVikram.Hegde@Sun.COM return (ENXIO);
42310535SVikram.Hegde@Sun.COM }
42410535SVikram.Hegde@Sun.COM
42510535SVikram.Hegde@Sun.COM
42610535SVikram.Hegde@Sun.COM if (!(mode & (FREAD|FWRITE))) {
42710535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: invalid mode %d", f, mode);
42810535SVikram.Hegde@Sun.COM return (EINVAL);
42910535SVikram.Hegde@Sun.COM }
43010535SVikram.Hegde@Sun.COM
43110535SVikram.Hegde@Sun.COM if (mode & FKIOCTL) {
43210535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: FKIOCTL unsupported mode %d", f, mode);
43310535SVikram.Hegde@Sun.COM return (EINVAL);
43410535SVikram.Hegde@Sun.COM }
43510535SVikram.Hegde@Sun.COM
43610535SVikram.Hegde@Sun.COM statep = ddi_get_soft_state(amd_iommu_statep, instance);
43710535SVikram.Hegde@Sun.COM if (statep == NULL) {
43810535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: cannot get soft state: instance %d",
43910535SVikram.Hegde@Sun.COM f, instance);
44010535SVikram.Hegde@Sun.COM return (ENXIO);
44110535SVikram.Hegde@Sun.COM }
44210535SVikram.Hegde@Sun.COM
44310535SVikram.Hegde@Sun.COM ASSERT(statep->aioms_instance == instance);
44410535SVikram.Hegde@Sun.COM
44510535SVikram.Hegde@Sun.COM return (ENOTTY);
44610535SVikram.Hegde@Sun.COM }
447*10536SVikram.Hegde@Sun.COM
448*10536SVikram.Hegde@Sun.COM static int
amd_iommu_quiesce(dev_info_t * dip)449*10536SVikram.Hegde@Sun.COM amd_iommu_quiesce(dev_info_t *dip)
450*10536SVikram.Hegde@Sun.COM {
451*10536SVikram.Hegde@Sun.COM int instance = ddi_get_instance(dip);
452*10536SVikram.Hegde@Sun.COM struct amd_iommu_state *statep;
453*10536SVikram.Hegde@Sun.COM const char *f = "amd_iommu_quiesce";
454*10536SVikram.Hegde@Sun.COM
455*10536SVikram.Hegde@Sun.COM statep = ddi_get_soft_state(amd_iommu_statep, instance);
456*10536SVikram.Hegde@Sun.COM if (statep == NULL) {
457*10536SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: cannot get soft state: instance %d",
458*10536SVikram.Hegde@Sun.COM f, instance);
459*10536SVikram.Hegde@Sun.COM return (DDI_FAILURE);
460*10536SVikram.Hegde@Sun.COM }
461*10536SVikram.Hegde@Sun.COM
462*10536SVikram.Hegde@Sun.COM if (amd_iommu_teardown(dip, statep, AMD_IOMMU_QUIESCE) != DDI_SUCCESS) {
463*10536SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: Unable to quiesce AMD IOMMU "
464*10536SVikram.Hegde@Sun.COM "%s%d", f, ddi_driver_name(dip), instance);
465*10536SVikram.Hegde@Sun.COM return (DDI_FAILURE);
466*10536SVikram.Hegde@Sun.COM }
467*10536SVikram.Hegde@Sun.COM
468*10536SVikram.Hegde@Sun.COM return (DDI_SUCCESS);
469*10536SVikram.Hegde@Sun.COM }
470