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 /*
23*12203SJerry.Gilliam@Sun.COM * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2410535SVikram.Hegde@Sun.COM */
2510535SVikram.Hegde@Sun.COM
2610535SVikram.Hegde@Sun.COM #include "amd_iommu_acpi.h"
2710535SVikram.Hegde@Sun.COM #include "amd_iommu_impl.h"
2810535SVikram.Hegde@Sun.COM
2910535SVikram.Hegde@Sun.COM static int create_acpi_hash(amd_iommu_acpi_t *acpi);
3010535SVikram.Hegde@Sun.COM static void amd_iommu_acpi_table_fini(amd_iommu_acpi_t **acpipp);
3110535SVikram.Hegde@Sun.COM
3210535SVikram.Hegde@Sun.COM static void dump_acpi_aliases(void);
3310535SVikram.Hegde@Sun.COM
3410535SVikram.Hegde@Sun.COM
3510535SVikram.Hegde@Sun.COM /*
3610535SVikram.Hegde@Sun.COM * Globals
3710535SVikram.Hegde@Sun.COM */
3810535SVikram.Hegde@Sun.COM static amd_iommu_acpi_global_t *amd_iommu_acpi_global;
3910535SVikram.Hegde@Sun.COM static amd_iommu_acpi_ivhd_t **amd_iommu_acpi_ivhd_hash;
4010535SVikram.Hegde@Sun.COM static amd_iommu_acpi_ivmd_t **amd_iommu_acpi_ivmd_hash;
4110535SVikram.Hegde@Sun.COM
4210535SVikram.Hegde@Sun.COM static int
type_byte_size(char * cp)4310535SVikram.Hegde@Sun.COM type_byte_size(char *cp)
4410535SVikram.Hegde@Sun.COM {
4510535SVikram.Hegde@Sun.COM uint8_t type8 = *((uint8_t *)cp);
4610535SVikram.Hegde@Sun.COM uint8_t len_bits;
4710535SVikram.Hegde@Sun.COM
4810535SVikram.Hegde@Sun.COM len_bits = AMD_IOMMU_REG_GET8(&type8, AMD_IOMMU_ACPI_DEVENTRY_LEN);
4910535SVikram.Hegde@Sun.COM
5010535SVikram.Hegde@Sun.COM switch (len_bits) {
5110535SVikram.Hegde@Sun.COM case 0:
5210535SVikram.Hegde@Sun.COM return (4);
5310535SVikram.Hegde@Sun.COM case 1:
5410535SVikram.Hegde@Sun.COM return (8);
5510535SVikram.Hegde@Sun.COM case 2:
5610535SVikram.Hegde@Sun.COM return (16);
5710535SVikram.Hegde@Sun.COM case 3:
5810535SVikram.Hegde@Sun.COM return (32);
5910535SVikram.Hegde@Sun.COM default:
6010535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: Invalid deventry len: %d",
6110535SVikram.Hegde@Sun.COM amd_iommu_modname, len_bits);
6210535SVikram.Hegde@Sun.COM return (len_bits);
6310535SVikram.Hegde@Sun.COM }
6410535SVikram.Hegde@Sun.COM /*NOTREACHED*/
6510535SVikram.Hegde@Sun.COM }
6610535SVikram.Hegde@Sun.COM
6710535SVikram.Hegde@Sun.COM static void
process_4byte_deventry(ivhd_container_t * c,char * cp)6810535SVikram.Hegde@Sun.COM process_4byte_deventry(ivhd_container_t *c, char *cp)
6910535SVikram.Hegde@Sun.COM {
7010535SVikram.Hegde@Sun.COM int entry_type = *((uint8_t *)cp);
7110535SVikram.Hegde@Sun.COM ivhd_deventry_t deventry = {0};
7210535SVikram.Hegde@Sun.COM ivhd_deventry_t *devp;
7310535SVikram.Hegde@Sun.COM uint8_t datsetting8;
7410535SVikram.Hegde@Sun.COM align_16_t al = {0};
7510535SVikram.Hegde@Sun.COM int i;
7610535SVikram.Hegde@Sun.COM
7710535SVikram.Hegde@Sun.COM /* 4 byte entry */
7810535SVikram.Hegde@Sun.COM deventry.idev_len = 4;
7910535SVikram.Hegde@Sun.COM deventry.idev_deviceid = -1;
8010535SVikram.Hegde@Sun.COM deventry.idev_src_deviceid = -1;
8110535SVikram.Hegde@Sun.COM
8210535SVikram.Hegde@Sun.COM for (i = 0; i < 2; i++) {
8310535SVikram.Hegde@Sun.COM al.ent8[i] = *((uint8_t *)&cp[i + 1]);
8410535SVikram.Hegde@Sun.COM }
8510535SVikram.Hegde@Sun.COM
8610535SVikram.Hegde@Sun.COM switch (entry_type) {
8710535SVikram.Hegde@Sun.COM case 1:
8810535SVikram.Hegde@Sun.COM deventry.idev_type = DEVENTRY_ALL;
8910535SVikram.Hegde@Sun.COM break;
9010535SVikram.Hegde@Sun.COM case 2:
9110535SVikram.Hegde@Sun.COM deventry.idev_type = DEVENTRY_SELECT;
9210535SVikram.Hegde@Sun.COM deventry.idev_deviceid = al.ent16;
9310535SVikram.Hegde@Sun.COM break;
9410535SVikram.Hegde@Sun.COM case 3:
9510535SVikram.Hegde@Sun.COM deventry.idev_type = DEVENTRY_RANGE;
9610535SVikram.Hegde@Sun.COM deventry.idev_deviceid = al.ent16;
9710535SVikram.Hegde@Sun.COM break;
9810535SVikram.Hegde@Sun.COM case 4:
9910535SVikram.Hegde@Sun.COM deventry.idev_type = DEVENTRY_RANGE_END;
10010535SVikram.Hegde@Sun.COM deventry.idev_deviceid = al.ent16;
10110535SVikram.Hegde@Sun.COM ASSERT(cp[3] == 0);
10210535SVikram.Hegde@Sun.COM break;
10310535SVikram.Hegde@Sun.COM case 0:
10410535SVikram.Hegde@Sun.COM ASSERT(al.ent16 == 0);
10510535SVikram.Hegde@Sun.COM ASSERT(cp[3] == 0);
10610535SVikram.Hegde@Sun.COM default:
10710535SVikram.Hegde@Sun.COM return;
10810535SVikram.Hegde@Sun.COM }
10910535SVikram.Hegde@Sun.COM
11010535SVikram.Hegde@Sun.COM
11110535SVikram.Hegde@Sun.COM devp = kmem_alloc(sizeof (ivhd_deventry_t), KM_SLEEP);
11210535SVikram.Hegde@Sun.COM *devp = deventry;
11310535SVikram.Hegde@Sun.COM
11410535SVikram.Hegde@Sun.COM if (c->ivhdc_first_deventry == NULL)
11510535SVikram.Hegde@Sun.COM c->ivhdc_first_deventry = devp;
11610535SVikram.Hegde@Sun.COM else
11710535SVikram.Hegde@Sun.COM c->ivhdc_last_deventry->idev_next = devp;
11810535SVikram.Hegde@Sun.COM
11910535SVikram.Hegde@Sun.COM c->ivhdc_last_deventry = devp;
12010535SVikram.Hegde@Sun.COM
12110535SVikram.Hegde@Sun.COM if (entry_type == 4)
12210535SVikram.Hegde@Sun.COM return;
12310535SVikram.Hegde@Sun.COM
12410535SVikram.Hegde@Sun.COM datsetting8 = (*((uint8_t *)&cp[3]));
12510535SVikram.Hegde@Sun.COM
12610535SVikram.Hegde@Sun.COM devp->idev_Lint1Pass = AMD_IOMMU_REG_GET8(&datsetting8,
12710535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_LINT1PASS);
12810535SVikram.Hegde@Sun.COM
12910535SVikram.Hegde@Sun.COM devp->idev_Lint0Pass = AMD_IOMMU_REG_GET8(&datsetting8,
13010535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_LINT0PASS);
13110535SVikram.Hegde@Sun.COM
13210535SVikram.Hegde@Sun.COM devp->idev_SysMgt = AMD_IOMMU_REG_GET8(&datsetting8,
13310535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_SYSMGT);
13410535SVikram.Hegde@Sun.COM
13510535SVikram.Hegde@Sun.COM ASSERT(AMD_IOMMU_REG_GET8(&datsetting8,
13610535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_DATRSV) == 0);
13710535SVikram.Hegde@Sun.COM
13810535SVikram.Hegde@Sun.COM devp->idev_NMIPass = AMD_IOMMU_REG_GET8(&datsetting8,
13910535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_NMIPASS);
14010535SVikram.Hegde@Sun.COM
14110535SVikram.Hegde@Sun.COM devp->idev_ExtIntPass = AMD_IOMMU_REG_GET8(&datsetting8,
14210535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_EXTINTPASS);
14310535SVikram.Hegde@Sun.COM
14410535SVikram.Hegde@Sun.COM devp->idev_INITPass = AMD_IOMMU_REG_GET8(&datsetting8,
14510535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_INITPASS);
14610535SVikram.Hegde@Sun.COM }
14710535SVikram.Hegde@Sun.COM
14810535SVikram.Hegde@Sun.COM static void
process_8byte_deventry(ivhd_container_t * c,char * cp)14910535SVikram.Hegde@Sun.COM process_8byte_deventry(ivhd_container_t *c, char *cp)
15010535SVikram.Hegde@Sun.COM {
15110535SVikram.Hegde@Sun.COM uint8_t datsetting8;
15210535SVikram.Hegde@Sun.COM int entry_type = (uint8_t)*cp;
15310535SVikram.Hegde@Sun.COM ivhd_deventry_t deventry = {0};
15410535SVikram.Hegde@Sun.COM ivhd_deventry_t *devp;
15510535SVikram.Hegde@Sun.COM align_16_t al1 = {0};
15610535SVikram.Hegde@Sun.COM align_16_t al2 = {0};
15710535SVikram.Hegde@Sun.COM align_32_t al3 = {0};
15810535SVikram.Hegde@Sun.COM int i;
15910535SVikram.Hegde@Sun.COM
16010535SVikram.Hegde@Sun.COM /* Length is 8 bytes */
16110535SVikram.Hegde@Sun.COM deventry.idev_len = 8;
16210535SVikram.Hegde@Sun.COM deventry.idev_deviceid = -1;
16310535SVikram.Hegde@Sun.COM deventry.idev_src_deviceid = -1;
16410535SVikram.Hegde@Sun.COM
16510535SVikram.Hegde@Sun.COM for (i = 0; i < 2; i++) {
16610535SVikram.Hegde@Sun.COM al1.ent8[i] = *((uint8_t *)&cp[i+1]);
16710535SVikram.Hegde@Sun.COM al2.ent8[i] = *((uint8_t *)&cp[i+5]);
16810535SVikram.Hegde@Sun.COM }
16910535SVikram.Hegde@Sun.COM
17010535SVikram.Hegde@Sun.COM datsetting8 = *((uint8_t *)&cp[3]);
17110535SVikram.Hegde@Sun.COM
17210535SVikram.Hegde@Sun.COM switch (entry_type) {
17310535SVikram.Hegde@Sun.COM case 66:
17410535SVikram.Hegde@Sun.COM deventry.idev_type = DEVENTRY_ALIAS_SELECT;
17510535SVikram.Hegde@Sun.COM deventry.idev_deviceid = al1.ent16;
17610535SVikram.Hegde@Sun.COM deventry.idev_src_deviceid = al2.ent16;
17710535SVikram.Hegde@Sun.COM ASSERT(cp[4] == 0);
17810535SVikram.Hegde@Sun.COM ASSERT(cp[7] == 0);
17910535SVikram.Hegde@Sun.COM break;
18010535SVikram.Hegde@Sun.COM case 67:
18110535SVikram.Hegde@Sun.COM deventry.idev_type = DEVENTRY_ALIAS_RANGE;
18210535SVikram.Hegde@Sun.COM deventry.idev_deviceid = al1.ent16;
18310535SVikram.Hegde@Sun.COM deventry.idev_src_deviceid = al2.ent16;
18410535SVikram.Hegde@Sun.COM ASSERT(cp[4] == 0);
18510535SVikram.Hegde@Sun.COM ASSERT(cp[7] == 0);
18610535SVikram.Hegde@Sun.COM break;
18710535SVikram.Hegde@Sun.COM case 70:
18810535SVikram.Hegde@Sun.COM deventry.idev_type = DEVENTRY_EXTENDED_SELECT;
18910535SVikram.Hegde@Sun.COM deventry.idev_deviceid = al1.ent16;
19010535SVikram.Hegde@Sun.COM break;
19110535SVikram.Hegde@Sun.COM case 71:
19210535SVikram.Hegde@Sun.COM deventry.idev_type = DEVENTRY_EXTENDED_RANGE;
19310535SVikram.Hegde@Sun.COM deventry.idev_deviceid = al1.ent16;
19410535SVikram.Hegde@Sun.COM break;
19510535SVikram.Hegde@Sun.COM case 72:
19610535SVikram.Hegde@Sun.COM deventry.idev_type = DEVENTRY_SPECIAL_DEVICE;
19710535SVikram.Hegde@Sun.COM ASSERT(al1.ent16 == 0);
19810535SVikram.Hegde@Sun.COM deventry.idev_deviceid = -1;
19910535SVikram.Hegde@Sun.COM deventry.idev_handle = cp[4];
20010535SVikram.Hegde@Sun.COM deventry.idev_variety = cp[7];
20110535SVikram.Hegde@Sun.COM deventry.idev_src_deviceid = al2.ent16;
20210535SVikram.Hegde@Sun.COM default:
20310535SVikram.Hegde@Sun.COM #ifdef BROKEN_ASSERT
20410535SVikram.Hegde@Sun.COM for (i = 0; i < 7; i++) {
20510535SVikram.Hegde@Sun.COM ASSERT(cp[i] == 0);
20610535SVikram.Hegde@Sun.COM }
20710535SVikram.Hegde@Sun.COM #endif
20810535SVikram.Hegde@Sun.COM return;
20910535SVikram.Hegde@Sun.COM }
21010535SVikram.Hegde@Sun.COM
21110535SVikram.Hegde@Sun.COM
21210535SVikram.Hegde@Sun.COM devp = kmem_alloc(sizeof (ivhd_deventry_t), KM_SLEEP);
21310535SVikram.Hegde@Sun.COM *devp = deventry;
21410535SVikram.Hegde@Sun.COM
21510535SVikram.Hegde@Sun.COM if (c->ivhdc_first_deventry == NULL)
21610535SVikram.Hegde@Sun.COM c->ivhdc_first_deventry = devp;
21710535SVikram.Hegde@Sun.COM else
21810535SVikram.Hegde@Sun.COM c->ivhdc_last_deventry->idev_next = devp;
21910535SVikram.Hegde@Sun.COM
22010535SVikram.Hegde@Sun.COM c->ivhdc_last_deventry = devp;
22110535SVikram.Hegde@Sun.COM
22210535SVikram.Hegde@Sun.COM devp->idev_Lint1Pass = AMD_IOMMU_REG_GET8(&datsetting8,
22310535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_LINT1PASS);
22410535SVikram.Hegde@Sun.COM
22510535SVikram.Hegde@Sun.COM devp->idev_Lint0Pass = AMD_IOMMU_REG_GET8(&datsetting8,
22610535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_LINT0PASS);
22710535SVikram.Hegde@Sun.COM
22810535SVikram.Hegde@Sun.COM devp->idev_SysMgt = AMD_IOMMU_REG_GET8(&datsetting8,
22910535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_SYSMGT);
23010535SVikram.Hegde@Sun.COM
23110535SVikram.Hegde@Sun.COM ASSERT(AMD_IOMMU_REG_GET8(&datsetting8,
23210535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_DATRSV) == 0);
23310535SVikram.Hegde@Sun.COM
23410535SVikram.Hegde@Sun.COM devp->idev_NMIPass = AMD_IOMMU_REG_GET8(&datsetting8,
23510535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_NMIPASS);
23610535SVikram.Hegde@Sun.COM
23710535SVikram.Hegde@Sun.COM devp->idev_ExtIntPass = AMD_IOMMU_REG_GET8(&datsetting8,
23810535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_EXTINTPASS);
23910535SVikram.Hegde@Sun.COM
24010535SVikram.Hegde@Sun.COM devp->idev_INITPass = AMD_IOMMU_REG_GET8(&datsetting8,
24110535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_INITPASS);
24210535SVikram.Hegde@Sun.COM
24310535SVikram.Hegde@Sun.COM if (entry_type != 70 && entry_type != 71) {
24410535SVikram.Hegde@Sun.COM return;
24510535SVikram.Hegde@Sun.COM }
24610535SVikram.Hegde@Sun.COM
24710535SVikram.Hegde@Sun.COM /* Type 70 and 71 */
24810535SVikram.Hegde@Sun.COM for (i = 0; i < 4; i++) {
24910535SVikram.Hegde@Sun.COM al3.ent8[i] = *((uint8_t *)&cp[i+4]);
25010535SVikram.Hegde@Sun.COM }
25110535SVikram.Hegde@Sun.COM
25210535SVikram.Hegde@Sun.COM devp->idev_AtsDisabled = AMD_IOMMU_REG_GET8(&al3.ent32,
25310535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_ATSDISABLED);
25410535SVikram.Hegde@Sun.COM
25510535SVikram.Hegde@Sun.COM ASSERT(AMD_IOMMU_REG_GET8(&al3.ent32, AMD_IOMMU_ACPI_EXTDATRSV) == 0);
25610535SVikram.Hegde@Sun.COM }
25710535SVikram.Hegde@Sun.COM
25810535SVikram.Hegde@Sun.COM static void
process_ivhd(amd_iommu_acpi_t * acpi,ivhd_t * ivhdp)25910535SVikram.Hegde@Sun.COM process_ivhd(amd_iommu_acpi_t *acpi, ivhd_t *ivhdp)
26010535SVikram.Hegde@Sun.COM {
26110535SVikram.Hegde@Sun.COM ivhd_container_t *c;
26210535SVikram.Hegde@Sun.COM caddr_t ivhd_end;
26310535SVikram.Hegde@Sun.COM caddr_t ivhd_tot_end;
26410535SVikram.Hegde@Sun.COM caddr_t cp;
26510535SVikram.Hegde@Sun.COM
26610535SVikram.Hegde@Sun.COM ASSERT(ivhdp->ivhd_type == 0x10);
26710535SVikram.Hegde@Sun.COM
26810535SVikram.Hegde@Sun.COM c = kmem_zalloc(sizeof (ivhd_container_t), KM_SLEEP);
26910535SVikram.Hegde@Sun.COM c->ivhdc_ivhd = kmem_alloc(sizeof (ivhd_t), KM_SLEEP);
27010535SVikram.Hegde@Sun.COM *(c->ivhdc_ivhd) = *ivhdp;
27110535SVikram.Hegde@Sun.COM
27210535SVikram.Hegde@Sun.COM if (acpi->acp_first_ivhdc == NULL)
27310535SVikram.Hegde@Sun.COM acpi->acp_first_ivhdc = c;
27410535SVikram.Hegde@Sun.COM else
27510535SVikram.Hegde@Sun.COM acpi->acp_last_ivhdc->ivhdc_next = c;
27610535SVikram.Hegde@Sun.COM
27710535SVikram.Hegde@Sun.COM acpi->acp_last_ivhdc = c;
27810535SVikram.Hegde@Sun.COM
27910535SVikram.Hegde@Sun.COM ivhd_end = (caddr_t)ivhdp + sizeof (ivhd_t);
28010535SVikram.Hegde@Sun.COM ivhd_tot_end = (caddr_t)ivhdp + ivhdp->ivhd_len;
28110535SVikram.Hegde@Sun.COM
28210535SVikram.Hegde@Sun.COM for (cp = ivhd_end; cp < ivhd_tot_end; cp += type_byte_size(cp)) {
28310535SVikram.Hegde@Sun.COM /* 16 byte and 32 byte size are currently reserved */
28410535SVikram.Hegde@Sun.COM switch (type_byte_size(cp)) {
28510535SVikram.Hegde@Sun.COM case 4:
28610535SVikram.Hegde@Sun.COM process_4byte_deventry(c, cp);
28710535SVikram.Hegde@Sun.COM break;
28810535SVikram.Hegde@Sun.COM case 8:
28910535SVikram.Hegde@Sun.COM process_8byte_deventry(c, cp);
29010535SVikram.Hegde@Sun.COM break;
29110535SVikram.Hegde@Sun.COM case 16:
29210535SVikram.Hegde@Sun.COM case 32:
29310535SVikram.Hegde@Sun.COM /* Reserved */
29410535SVikram.Hegde@Sun.COM break;
29510535SVikram.Hegde@Sun.COM default:
29610535SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "%s: unsupported length for device "
29710535SVikram.Hegde@Sun.COM "entry in ACPI IVRS table's IVHD entry",
29810535SVikram.Hegde@Sun.COM amd_iommu_modname);
29910535SVikram.Hegde@Sun.COM break;
30010535SVikram.Hegde@Sun.COM }
30110535SVikram.Hegde@Sun.COM }
30210535SVikram.Hegde@Sun.COM }
30310535SVikram.Hegde@Sun.COM
30410535SVikram.Hegde@Sun.COM static void
process_ivmd(amd_iommu_acpi_t * acpi,ivmd_t * ivmdp)30510535SVikram.Hegde@Sun.COM process_ivmd(amd_iommu_acpi_t *acpi, ivmd_t *ivmdp)
30610535SVikram.Hegde@Sun.COM {
30710535SVikram.Hegde@Sun.COM ivmd_container_t *c;
30810535SVikram.Hegde@Sun.COM
30910535SVikram.Hegde@Sun.COM ASSERT(ivmdp->ivmd_type != 0x10);
31010535SVikram.Hegde@Sun.COM
31110535SVikram.Hegde@Sun.COM c = kmem_zalloc(sizeof (ivmd_container_t), KM_SLEEP);
31210535SVikram.Hegde@Sun.COM c->ivmdc_ivmd = kmem_alloc(sizeof (ivmd_t), KM_SLEEP);
31310535SVikram.Hegde@Sun.COM *(c->ivmdc_ivmd) = *ivmdp;
31410535SVikram.Hegde@Sun.COM
31510535SVikram.Hegde@Sun.COM if (acpi->acp_first_ivmdc == NULL)
31610535SVikram.Hegde@Sun.COM acpi->acp_first_ivmdc = c;
31710535SVikram.Hegde@Sun.COM else
31810535SVikram.Hegde@Sun.COM acpi->acp_last_ivmdc->ivmdc_next = c;
31910535SVikram.Hegde@Sun.COM
32010535SVikram.Hegde@Sun.COM acpi->acp_last_ivmdc = c;
32110535SVikram.Hegde@Sun.COM }
32210535SVikram.Hegde@Sun.COM
32310535SVikram.Hegde@Sun.COM int
amd_iommu_acpi_init(void)32410535SVikram.Hegde@Sun.COM amd_iommu_acpi_init(void)
32510535SVikram.Hegde@Sun.COM {
32610535SVikram.Hegde@Sun.COM ivrs_t *ivrsp;
32710535SVikram.Hegde@Sun.COM caddr_t ivrsp_end;
32810535SVikram.Hegde@Sun.COM caddr_t table_end;
32910535SVikram.Hegde@Sun.COM caddr_t cp;
33010535SVikram.Hegde@Sun.COM uint8_t type8;
33110535SVikram.Hegde@Sun.COM amd_iommu_acpi_t *acpi;
33210535SVikram.Hegde@Sun.COM align_ivhd_t al_vhd = {0};
33310535SVikram.Hegde@Sun.COM align_ivmd_t al_vmd = {0};
33410535SVikram.Hegde@Sun.COM
33510535SVikram.Hegde@Sun.COM if (AcpiGetTable(IVRS_SIG, 1, (ACPI_TABLE_HEADER **)&ivrsp) != AE_OK) {
33610535SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "!amd_iommu: No AMD IOMMU ACPI IVRS table");
33710535SVikram.Hegde@Sun.COM return (DDI_FAILURE);
33810535SVikram.Hegde@Sun.COM }
33910535SVikram.Hegde@Sun.COM
34010535SVikram.Hegde@Sun.COM /*
34110535SVikram.Hegde@Sun.COM * Reserved field must be 0
34210535SVikram.Hegde@Sun.COM */
34310535SVikram.Hegde@Sun.COM ASSERT(ivrsp->ivrs_resv == 0);
34410535SVikram.Hegde@Sun.COM
34510535SVikram.Hegde@Sun.COM ASSERT(AMD_IOMMU_REG_GET32(&ivrsp->ivrs_ivinfo,
34610535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_IVINFO_RSV1) == 0);
34710535SVikram.Hegde@Sun.COM ASSERT(AMD_IOMMU_REG_GET32(&ivrsp->ivrs_ivinfo,
34810535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_IVINFO_RSV2) == 0);
34910535SVikram.Hegde@Sun.COM
35010535SVikram.Hegde@Sun.COM ivrsp_end = (caddr_t)ivrsp + sizeof (struct ivrs);
35110535SVikram.Hegde@Sun.COM table_end = (caddr_t)ivrsp + ivrsp->ivrs_hdr.Length;
35210535SVikram.Hegde@Sun.COM
35310535SVikram.Hegde@Sun.COM acpi = kmem_zalloc(sizeof (amd_iommu_acpi_t), KM_SLEEP);
35410535SVikram.Hegde@Sun.COM acpi->acp_ivrs = kmem_alloc(sizeof (ivrs_t), KM_SLEEP);
35510535SVikram.Hegde@Sun.COM *(acpi->acp_ivrs) = *ivrsp;
35610535SVikram.Hegde@Sun.COM
35710535SVikram.Hegde@Sun.COM for (cp = ivrsp_end; cp < table_end; cp += (al_vhd.ivhdp)->ivhd_len) {
35810535SVikram.Hegde@Sun.COM al_vhd.cp = cp;
35910535SVikram.Hegde@Sun.COM if (al_vhd.ivhdp->ivhd_type == 0x10)
36010535SVikram.Hegde@Sun.COM process_ivhd(acpi, al_vhd.ivhdp);
36110535SVikram.Hegde@Sun.COM }
36210535SVikram.Hegde@Sun.COM
36310535SVikram.Hegde@Sun.COM for (cp = ivrsp_end; cp < table_end; cp += (al_vmd.ivmdp)->ivmd_len) {
36410535SVikram.Hegde@Sun.COM al_vmd.cp = cp;
36510535SVikram.Hegde@Sun.COM type8 = al_vmd.ivmdp->ivmd_type;
36610535SVikram.Hegde@Sun.COM if (type8 == 0x20 || type8 == 0x21 || type8 == 0x22)
36710535SVikram.Hegde@Sun.COM process_ivmd(acpi, al_vmd.ivmdp);
36810535SVikram.Hegde@Sun.COM }
36910535SVikram.Hegde@Sun.COM
37010535SVikram.Hegde@Sun.COM if (create_acpi_hash(acpi) != DDI_SUCCESS) {
37110535SVikram.Hegde@Sun.COM return (DDI_FAILURE);
37210535SVikram.Hegde@Sun.COM }
37310535SVikram.Hegde@Sun.COM
37410535SVikram.Hegde@Sun.COM amd_iommu_acpi_table_fini(&acpi);
37510535SVikram.Hegde@Sun.COM
37610535SVikram.Hegde@Sun.COM ASSERT(acpi == NULL);
37710535SVikram.Hegde@Sun.COM
37810535SVikram.Hegde@Sun.COM if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
37910535SVikram.Hegde@Sun.COM dump_acpi_aliases();
38010535SVikram.Hegde@Sun.COM debug_enter("dump");
38110535SVikram.Hegde@Sun.COM }
38210535SVikram.Hegde@Sun.COM
38310535SVikram.Hegde@Sun.COM return (DDI_SUCCESS);
38410535SVikram.Hegde@Sun.COM }
38510535SVikram.Hegde@Sun.COM
38610535SVikram.Hegde@Sun.COM static ivhd_deventry_t *
free_ivhd_deventry(ivhd_deventry_t * devp)38710535SVikram.Hegde@Sun.COM free_ivhd_deventry(ivhd_deventry_t *devp)
38810535SVikram.Hegde@Sun.COM {
38910535SVikram.Hegde@Sun.COM ivhd_deventry_t *next = devp->idev_next;
39010535SVikram.Hegde@Sun.COM
39110535SVikram.Hegde@Sun.COM kmem_free(devp, sizeof (ivhd_deventry_t));
39210535SVikram.Hegde@Sun.COM
39310535SVikram.Hegde@Sun.COM return (next);
39410535SVikram.Hegde@Sun.COM }
39510535SVikram.Hegde@Sun.COM
39610535SVikram.Hegde@Sun.COM static ivhd_container_t *
free_ivhd_container(ivhd_container_t * ivhdcp)39710535SVikram.Hegde@Sun.COM free_ivhd_container(ivhd_container_t *ivhdcp)
39810535SVikram.Hegde@Sun.COM {
39910535SVikram.Hegde@Sun.COM ivhd_container_t *next = ivhdcp->ivhdc_next;
40010535SVikram.Hegde@Sun.COM ivhd_deventry_t *devp;
40110535SVikram.Hegde@Sun.COM
40210535SVikram.Hegde@Sun.COM for (devp = ivhdcp->ivhdc_first_deventry; devp; ) {
40310535SVikram.Hegde@Sun.COM devp = free_ivhd_deventry(devp);
40410535SVikram.Hegde@Sun.COM }
40510535SVikram.Hegde@Sun.COM
40610535SVikram.Hegde@Sun.COM kmem_free(ivhdcp->ivhdc_ivhd, sizeof (ivhd_t));
40710535SVikram.Hegde@Sun.COM kmem_free(ivhdcp, sizeof (ivhd_container_t));
40810535SVikram.Hegde@Sun.COM
40910535SVikram.Hegde@Sun.COM return (next);
41010535SVikram.Hegde@Sun.COM }
41110535SVikram.Hegde@Sun.COM
41210535SVikram.Hegde@Sun.COM static ivmd_container_t *
free_ivmd_container(ivmd_container_t * ivmdcp)41310535SVikram.Hegde@Sun.COM free_ivmd_container(ivmd_container_t *ivmdcp)
41410535SVikram.Hegde@Sun.COM {
41510535SVikram.Hegde@Sun.COM ivmd_container_t *next = ivmdcp->ivmdc_next;
41610535SVikram.Hegde@Sun.COM
41710535SVikram.Hegde@Sun.COM kmem_free(ivmdcp->ivmdc_ivmd, sizeof (ivmd_t));
41810535SVikram.Hegde@Sun.COM kmem_free(ivmdcp, sizeof (ivmd_container_t));
41910535SVikram.Hegde@Sun.COM
42010535SVikram.Hegde@Sun.COM return (next);
42110535SVikram.Hegde@Sun.COM }
42210535SVikram.Hegde@Sun.COM
42310535SVikram.Hegde@Sun.COM void
amd_iommu_acpi_fini(void)42410535SVikram.Hegde@Sun.COM amd_iommu_acpi_fini(void)
42510535SVikram.Hegde@Sun.COM {
42610535SVikram.Hegde@Sun.COM }
42710535SVikram.Hegde@Sun.COM
42810535SVikram.Hegde@Sun.COM /*
42910535SVikram.Hegde@Sun.COM * TODO: Do we need to free the ACPI table for om GetFirmwareTable()
43010535SVikram.Hegde@Sun.COM */
43110535SVikram.Hegde@Sun.COM static void
amd_iommu_acpi_table_fini(amd_iommu_acpi_t ** acpipp)43210535SVikram.Hegde@Sun.COM amd_iommu_acpi_table_fini(amd_iommu_acpi_t **acpipp)
43310535SVikram.Hegde@Sun.COM {
43410535SVikram.Hegde@Sun.COM amd_iommu_acpi_t *acpi = *acpipp;
43510535SVikram.Hegde@Sun.COM ivhd_container_t *ivhdcp;
43610535SVikram.Hegde@Sun.COM ivmd_container_t *ivmdcp;
43710535SVikram.Hegde@Sun.COM
43810535SVikram.Hegde@Sun.COM ASSERT(acpi);
43910535SVikram.Hegde@Sun.COM
44010535SVikram.Hegde@Sun.COM for (ivhdcp = acpi->acp_first_ivhdc; ivhdcp; ) {
44110535SVikram.Hegde@Sun.COM ivhdcp = free_ivhd_container(ivhdcp);
44210535SVikram.Hegde@Sun.COM }
44310535SVikram.Hegde@Sun.COM for (ivmdcp = acpi->acp_first_ivmdc; ivmdcp; ) {
44410535SVikram.Hegde@Sun.COM ivmdcp = free_ivmd_container(ivmdcp);
44510535SVikram.Hegde@Sun.COM }
44610535SVikram.Hegde@Sun.COM
44710535SVikram.Hegde@Sun.COM kmem_free(acpi->acp_ivrs, sizeof (struct ivrs));
44810535SVikram.Hegde@Sun.COM kmem_free(acpi, sizeof (amd_iommu_acpi_t));
44910535SVikram.Hegde@Sun.COM
45010535SVikram.Hegde@Sun.COM *acpipp = NULL;
45110535SVikram.Hegde@Sun.COM }
45210535SVikram.Hegde@Sun.COM
45310535SVikram.Hegde@Sun.COM static uint16_t
deviceid_hashfn(uint16_t deviceid)45410535SVikram.Hegde@Sun.COM deviceid_hashfn(uint16_t deviceid)
45510535SVikram.Hegde@Sun.COM {
45610535SVikram.Hegde@Sun.COM return (deviceid % AMD_IOMMU_ACPI_INFO_HASH_SZ);
45710535SVikram.Hegde@Sun.COM }
45810535SVikram.Hegde@Sun.COM
45910535SVikram.Hegde@Sun.COM static void
add_deventry_info(ivhd_t * ivhdp,ivhd_deventry_t * deventry,amd_iommu_acpi_ivhd_t ** hash)46010535SVikram.Hegde@Sun.COM add_deventry_info(ivhd_t *ivhdp, ivhd_deventry_t *deventry,
46110535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivhd_t **hash)
46210535SVikram.Hegde@Sun.COM {
46310535SVikram.Hegde@Sun.COM static amd_iommu_acpi_ivhd_t *last;
46410535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivhd_t *acpi_ivhdp;
46510535SVikram.Hegde@Sun.COM uint8_t uint8_flags;
46610535SVikram.Hegde@Sun.COM uint16_t uint16_info;
46710535SVikram.Hegde@Sun.COM uint16_t idx;
46810535SVikram.Hegde@Sun.COM
46910535SVikram.Hegde@Sun.COM if (deventry->idev_type == DEVENTRY_RANGE_END) {
47010535SVikram.Hegde@Sun.COM ASSERT(last);
47110535SVikram.Hegde@Sun.COM acpi_ivhdp = last;
47210535SVikram.Hegde@Sun.COM last = NULL;
47310535SVikram.Hegde@Sun.COM ASSERT(acpi_ivhdp->ach_dev_type == DEVENTRY_RANGE ||
47410535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_dev_type == DEVENTRY_ALIAS_RANGE ||
47510535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_dev_type == DEVENTRY_EXTENDED_RANGE);
47610535SVikram.Hegde@Sun.COM ASSERT(acpi_ivhdp->ach_deviceid_end == -1);
47710535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_end = deventry->idev_deviceid;
47810535SVikram.Hegde@Sun.COM /* TODO ASSERT data is 0 */
47910535SVikram.Hegde@Sun.COM return;
48010535SVikram.Hegde@Sun.COM }
48110535SVikram.Hegde@Sun.COM
48210535SVikram.Hegde@Sun.COM ASSERT(last == NULL);
48310535SVikram.Hegde@Sun.COM acpi_ivhdp = kmem_zalloc(sizeof (*acpi_ivhdp), KM_SLEEP);
48410535SVikram.Hegde@Sun.COM
48510535SVikram.Hegde@Sun.COM uint8_flags = ivhdp->ivhd_flags;
48610535SVikram.Hegde@Sun.COM
48710535SVikram.Hegde@Sun.COM #ifdef BROKEN_ASSERT
48810535SVikram.Hegde@Sun.COM ASSERT(AMD_IOMMU_REG_GET8(&uint8_flags,
48910535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_IVHD_FLAGS_RSV) == 0);
49010535SVikram.Hegde@Sun.COM #endif
49110535SVikram.Hegde@Sun.COM
49210535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_IotlbSup = AMD_IOMMU_REG_GET8(&uint8_flags,
49310535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_IVHD_FLAGS_IOTLBSUP);
49410535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_Isoc = AMD_IOMMU_REG_GET8(&uint8_flags,
49510535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_IVHD_FLAGS_ISOC);
49610535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_ResPassPW = AMD_IOMMU_REG_GET8(&uint8_flags,
49710535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_IVHD_FLAGS_RESPASSPW);
49810535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_PassPW = AMD_IOMMU_REG_GET8(&uint8_flags,
49910535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_IVHD_FLAGS_PASSPW);
50010535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_HtTunEn = AMD_IOMMU_REG_GET8(&uint8_flags,
50110535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_IVHD_FLAGS_HTTUNEN);
50210535SVikram.Hegde@Sun.COM
50310535SVikram.Hegde@Sun.COM /* IVHD fields */
50410535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_IOMMU_deviceid = ivhdp->ivhd_deviceid;
50510535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_IOMMU_cap_off = ivhdp->ivhd_cap_off;
50610535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_IOMMU_reg_base = ivhdp->ivhd_reg_base;
50710535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_IOMMU_pci_seg = ivhdp->ivhd_pci_seg;
50810535SVikram.Hegde@Sun.COM
50910535SVikram.Hegde@Sun.COM /* IVHD IOMMU info fields */
51010535SVikram.Hegde@Sun.COM uint16_info = ivhdp->ivhd_iommu_info;
51110535SVikram.Hegde@Sun.COM
51210535SVikram.Hegde@Sun.COM #ifdef BROKEN_ASSERT
51310535SVikram.Hegde@Sun.COM ASSERT(AMD_IOMMU_REG_GET16(&uint16_info,
51410535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_IOMMU_INFO_RSV1) == 0);
51510535SVikram.Hegde@Sun.COM #endif
51610535SVikram.Hegde@Sun.COM
51710535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_IOMMU_UnitID = AMD_IOMMU_REG_GET16(&uint16_info,
51810535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_IOMMU_INFO_UNITID);
51910535SVikram.Hegde@Sun.COM ASSERT(AMD_IOMMU_REG_GET16(&uint16_info,
52010535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_IOMMU_INFO_RSV2) == 0);
52110535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_IOMMU_MSInum = AMD_IOMMU_REG_GET16(&uint16_info,
52210535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_IOMMU_INFO_MSINUM);
52310535SVikram.Hegde@Sun.COM
52410535SVikram.Hegde@Sun.COM /* Initialize deviceids to -1 */
52510535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_start = -1;
52610535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_end = -1;
52710535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_src_deviceid = -1;
52810535SVikram.Hegde@Sun.COM
52910535SVikram.Hegde@Sun.COM /* All range type entries are put on hash entry 0 */
53010535SVikram.Hegde@Sun.COM switch (deventry->idev_type) {
53110535SVikram.Hegde@Sun.COM case DEVENTRY_ALL:
53210535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_start = 0;
53310535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_end = (uint16_t)-1;
53410535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_dev_type = DEVENTRY_ALL;
53510535SVikram.Hegde@Sun.COM idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
53610535SVikram.Hegde@Sun.COM break;
53710535SVikram.Hegde@Sun.COM case DEVENTRY_SELECT:
53810535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
53910535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_end = deventry->idev_deviceid;
54010535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_dev_type = DEVENTRY_SELECT;
54110535SVikram.Hegde@Sun.COM idx = deviceid_hashfn(deventry->idev_deviceid);
54210535SVikram.Hegde@Sun.COM break;
54310535SVikram.Hegde@Sun.COM case DEVENTRY_RANGE:
54410535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
54510535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_end = -1;
54610535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_dev_type = DEVENTRY_RANGE;
54710535SVikram.Hegde@Sun.COM idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
54810535SVikram.Hegde@Sun.COM last = acpi_ivhdp;
54910535SVikram.Hegde@Sun.COM break;
55010535SVikram.Hegde@Sun.COM case DEVENTRY_RANGE_END:
55110535SVikram.Hegde@Sun.COM cmn_err(CE_PANIC, "%s: Unexpected Range End Deventry",
55210535SVikram.Hegde@Sun.COM amd_iommu_modname);
55310535SVikram.Hegde@Sun.COM /*NOTREACHED*/
55410535SVikram.Hegde@Sun.COM case DEVENTRY_ALIAS_SELECT:
55510535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
55610535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_end = deventry->idev_deviceid;
55710535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_src_deviceid = deventry->idev_src_deviceid;
55810535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_dev_type = DEVENTRY_ALIAS_SELECT;
55910535SVikram.Hegde@Sun.COM idx = deviceid_hashfn(deventry->idev_deviceid);
56010535SVikram.Hegde@Sun.COM break;
56110535SVikram.Hegde@Sun.COM case DEVENTRY_ALIAS_RANGE:
56210535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
56310535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_end = -1;
56410535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_src_deviceid = deventry->idev_src_deviceid;
56510535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_dev_type = DEVENTRY_ALIAS_RANGE;
56610535SVikram.Hegde@Sun.COM idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
56710535SVikram.Hegde@Sun.COM last = acpi_ivhdp;
56810535SVikram.Hegde@Sun.COM break;
56910535SVikram.Hegde@Sun.COM case DEVENTRY_EXTENDED_SELECT:
57010535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
57110535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_end = deventry->idev_deviceid;
57210535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_dev_type = DEVENTRY_EXTENDED_SELECT;
57310535SVikram.Hegde@Sun.COM idx = deviceid_hashfn(deventry->idev_deviceid);
57410535SVikram.Hegde@Sun.COM break;
57510535SVikram.Hegde@Sun.COM case DEVENTRY_EXTENDED_RANGE:
57610535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
57710535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_end = -1;
57810535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_dev_type = DEVENTRY_EXTENDED_RANGE;
57910535SVikram.Hegde@Sun.COM idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
58010535SVikram.Hegde@Sun.COM last = acpi_ivhdp;
58110535SVikram.Hegde@Sun.COM break;
58210535SVikram.Hegde@Sun.COM case DEVENTRY_SPECIAL_DEVICE:
58310535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_start = -1;
58410535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_deviceid_end = -1;
58510535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_src_deviceid = deventry->idev_src_deviceid;
58610535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_special_handle = deventry->idev_handle;
58710535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_special_variety = deventry->idev_variety;
58810535SVikram.Hegde@Sun.COM idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
58910535SVikram.Hegde@Sun.COM default:
59010535SVikram.Hegde@Sun.COM cmn_err(CE_PANIC, "%s: Unsupported deventry type",
59110535SVikram.Hegde@Sun.COM amd_iommu_modname);
59210535SVikram.Hegde@Sun.COM /*NOTREACHED*/
59310535SVikram.Hegde@Sun.COM }
59410535SVikram.Hegde@Sun.COM
59510535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_Lint1Pass = deventry->idev_Lint1Pass;
59610535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_Lint0Pass = deventry->idev_Lint0Pass;
59710535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_SysMgt = deventry->idev_SysMgt;
59810535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_NMIPass = deventry->idev_NMIPass;
59910535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_ExtIntPass = deventry->idev_ExtIntPass;
60010535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_INITPass = deventry->idev_INITPass;
60110535SVikram.Hegde@Sun.COM
60210535SVikram.Hegde@Sun.COM
60310535SVikram.Hegde@Sun.COM /* extended data */
60410535SVikram.Hegde@Sun.COM if (acpi_ivhdp->ach_dev_type == DEVENTRY_EXTENDED_SELECT ||
60510535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_dev_type == DEVENTRY_EXTENDED_RANGE) {
60610535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_AtsDisabled = deventry->idev_AtsDisabled;
60710535SVikram.Hegde@Sun.COM }
60810535SVikram.Hegde@Sun.COM
60910535SVikram.Hegde@Sun.COM /*
61010535SVikram.Hegde@Sun.COM * Now add it to the hash
61110535SVikram.Hegde@Sun.COM */
61210535SVikram.Hegde@Sun.COM ASSERT(hash[idx] != acpi_ivhdp);
61310535SVikram.Hegde@Sun.COM acpi_ivhdp->ach_next = hash[idx];
61410535SVikram.Hegde@Sun.COM hash[idx] = acpi_ivhdp;
61510535SVikram.Hegde@Sun.COM }
61610535SVikram.Hegde@Sun.COM
617*12203SJerry.Gilliam@Sun.COM /*
618*12203SJerry.Gilliam@Sun.COM * A device entry may be declared implicitly as a source device ID
619*12203SJerry.Gilliam@Sun.COM * in an alias entry. This routine adds it to the hash
620*12203SJerry.Gilliam@Sun.COM */
621*12203SJerry.Gilliam@Sun.COM static void
add_implicit_deventry(ivhd_container_t * ivhdcp,amd_iommu_acpi_ivhd_t ** hash)622*12203SJerry.Gilliam@Sun.COM add_implicit_deventry(ivhd_container_t *ivhdcp, amd_iommu_acpi_ivhd_t **hash)
623*12203SJerry.Gilliam@Sun.COM {
624*12203SJerry.Gilliam@Sun.COM ivhd_deventry_t *d;
625*12203SJerry.Gilliam@Sun.COM int deviceid;
626*12203SJerry.Gilliam@Sun.COM
627*12203SJerry.Gilliam@Sun.COM for (d = ivhdcp->ivhdc_first_deventry; d; d = d->idev_next) {
628*12203SJerry.Gilliam@Sun.COM
629*12203SJerry.Gilliam@Sun.COM if ((d->idev_type != DEVENTRY_ALIAS_SELECT) &&
630*12203SJerry.Gilliam@Sun.COM (d->idev_type != DEVENTRY_ALIAS_RANGE))
631*12203SJerry.Gilliam@Sun.COM continue;
632*12203SJerry.Gilliam@Sun.COM
633*12203SJerry.Gilliam@Sun.COM deviceid = d->idev_src_deviceid;
634*12203SJerry.Gilliam@Sun.COM
635*12203SJerry.Gilliam@Sun.COM if (amd_iommu_lookup_ivhd(deviceid) == NULL) {
636*12203SJerry.Gilliam@Sun.COM ivhd_deventry_t deventry;
637*12203SJerry.Gilliam@Sun.COM
638*12203SJerry.Gilliam@Sun.COM /* Fake a SELECT entry */
639*12203SJerry.Gilliam@Sun.COM deventry.idev_type = DEVENTRY_SELECT;
640*12203SJerry.Gilliam@Sun.COM deventry.idev_len = 4;
641*12203SJerry.Gilliam@Sun.COM deventry.idev_deviceid = deviceid;
642*12203SJerry.Gilliam@Sun.COM deventry.idev_src_deviceid = -1;
643*12203SJerry.Gilliam@Sun.COM
644*12203SJerry.Gilliam@Sun.COM deventry.idev_Lint1Pass = d->idev_Lint1Pass;
645*12203SJerry.Gilliam@Sun.COM deventry.idev_Lint0Pass = d->idev_Lint0Pass;
646*12203SJerry.Gilliam@Sun.COM deventry.idev_SysMgt = d->idev_SysMgt;
647*12203SJerry.Gilliam@Sun.COM deventry.idev_NMIPass = d->idev_NMIPass;
648*12203SJerry.Gilliam@Sun.COM deventry.idev_ExtIntPass = d->idev_ExtIntPass;
649*12203SJerry.Gilliam@Sun.COM deventry.idev_INITPass = d->idev_INITPass;
650*12203SJerry.Gilliam@Sun.COM
651*12203SJerry.Gilliam@Sun.COM add_deventry_info(ivhdcp->ivhdc_ivhd, &deventry, hash);
652*12203SJerry.Gilliam@Sun.COM
653*12203SJerry.Gilliam@Sun.COM if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
654*12203SJerry.Gilliam@Sun.COM cmn_err(CE_NOTE, "Added implicit IVHD entry "
655*12203SJerry.Gilliam@Sun.COM "for: deviceid = %u", deviceid);
656*12203SJerry.Gilliam@Sun.COM }
657*12203SJerry.Gilliam@Sun.COM }
658*12203SJerry.Gilliam@Sun.COM }
659*12203SJerry.Gilliam@Sun.COM }
660*12203SJerry.Gilliam@Sun.COM
66110535SVikram.Hegde@Sun.COM static void
add_ivhdc_info(ivhd_container_t * ivhdcp,amd_iommu_acpi_ivhd_t ** hash)66210535SVikram.Hegde@Sun.COM add_ivhdc_info(ivhd_container_t *ivhdcp, amd_iommu_acpi_ivhd_t **hash)
66310535SVikram.Hegde@Sun.COM {
66410535SVikram.Hegde@Sun.COM ivhd_deventry_t *deventry;
66510535SVikram.Hegde@Sun.COM ivhd_t *ivhdp = ivhdcp->ivhdc_ivhd;
66610535SVikram.Hegde@Sun.COM
66710535SVikram.Hegde@Sun.COM for (deventry = ivhdcp->ivhdc_first_deventry; deventry;
66810535SVikram.Hegde@Sun.COM deventry = deventry->idev_next) {
66910535SVikram.Hegde@Sun.COM add_deventry_info(ivhdp, deventry, hash);
67010535SVikram.Hegde@Sun.COM }
671*12203SJerry.Gilliam@Sun.COM
672*12203SJerry.Gilliam@Sun.COM add_implicit_deventry(ivhdcp, hash);
673*12203SJerry.Gilliam@Sun.COM
67410535SVikram.Hegde@Sun.COM }
67510535SVikram.Hegde@Sun.COM
67610535SVikram.Hegde@Sun.COM static void
add_ivhd_info(amd_iommu_acpi_t * acpi,amd_iommu_acpi_ivhd_t ** hash)67710535SVikram.Hegde@Sun.COM add_ivhd_info(amd_iommu_acpi_t *acpi, amd_iommu_acpi_ivhd_t **hash)
67810535SVikram.Hegde@Sun.COM {
67910535SVikram.Hegde@Sun.COM ivhd_container_t *ivhdcp;
68010535SVikram.Hegde@Sun.COM
68110535SVikram.Hegde@Sun.COM for (ivhdcp = acpi->acp_first_ivhdc; ivhdcp;
68210535SVikram.Hegde@Sun.COM ivhdcp = ivhdcp->ivhdc_next) {
68310535SVikram.Hegde@Sun.COM add_ivhdc_info(ivhdcp, hash);
68410535SVikram.Hegde@Sun.COM }
68510535SVikram.Hegde@Sun.COM }
68610535SVikram.Hegde@Sun.COM
68710535SVikram.Hegde@Sun.COM static void
set_ivmd_info(ivmd_t * ivmdp,amd_iommu_acpi_ivmd_t ** hash)68810535SVikram.Hegde@Sun.COM set_ivmd_info(ivmd_t *ivmdp, amd_iommu_acpi_ivmd_t **hash)
68910535SVikram.Hegde@Sun.COM {
69010535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivmd_t *acpi_ivmdp;
69110535SVikram.Hegde@Sun.COM uint8_t uint8_flags;
69210535SVikram.Hegde@Sun.COM uint16_t idx;
69310535SVikram.Hegde@Sun.COM
69410535SVikram.Hegde@Sun.COM uint8_flags = ivmdp->ivmd_flags;
69510535SVikram.Hegde@Sun.COM
69610535SVikram.Hegde@Sun.COM acpi_ivmdp = kmem_zalloc(sizeof (*acpi_ivmdp), KM_SLEEP);
69710535SVikram.Hegde@Sun.COM
69810535SVikram.Hegde@Sun.COM switch (ivmdp->ivmd_type) {
69910535SVikram.Hegde@Sun.COM case 0x20:
70010535SVikram.Hegde@Sun.COM acpi_ivmdp->acm_deviceid_start = 0;
70110535SVikram.Hegde@Sun.COM acpi_ivmdp->acm_deviceid_end = (uint16_t)-1;
70210535SVikram.Hegde@Sun.COM acpi_ivmdp->acm_dev_type = IVMD_DEVICEID_ALL;
70310535SVikram.Hegde@Sun.COM idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
70410535SVikram.Hegde@Sun.COM break;
70510535SVikram.Hegde@Sun.COM case 0x21:
70610535SVikram.Hegde@Sun.COM acpi_ivmdp->acm_deviceid_start = ivmdp->ivmd_deviceid;
70710535SVikram.Hegde@Sun.COM acpi_ivmdp->acm_deviceid_end = ivmdp->ivmd_deviceid;
70810535SVikram.Hegde@Sun.COM acpi_ivmdp->acm_dev_type = IVMD_DEVICEID_SELECT;
70910535SVikram.Hegde@Sun.COM idx = deviceid_hashfn(ivmdp->ivmd_deviceid);
71010535SVikram.Hegde@Sun.COM break;
71110535SVikram.Hegde@Sun.COM case 0x22:
71210535SVikram.Hegde@Sun.COM acpi_ivmdp->acm_deviceid_start = ivmdp->ivmd_deviceid;
71310535SVikram.Hegde@Sun.COM acpi_ivmdp->acm_deviceid_end = ivmdp->ivmd_auxdata;
71410535SVikram.Hegde@Sun.COM acpi_ivmdp->acm_dev_type = IVMD_DEVICEID_RANGE;
71510535SVikram.Hegde@Sun.COM idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
71610535SVikram.Hegde@Sun.COM break;
71710535SVikram.Hegde@Sun.COM default:
71810535SVikram.Hegde@Sun.COM cmn_err(CE_PANIC, "Unknown AMD IOMMU ACPI IVMD deviceid type: "
71910535SVikram.Hegde@Sun.COM "%x", ivmdp->ivmd_type);
72010535SVikram.Hegde@Sun.COM /*NOTREACHED*/
72110535SVikram.Hegde@Sun.COM }
72210535SVikram.Hegde@Sun.COM
72310535SVikram.Hegde@Sun.COM ASSERT(AMD_IOMMU_REG_GET8(&uint8_flags,
72410535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_IVMD_RSV) == 0);
72510535SVikram.Hegde@Sun.COM
72610535SVikram.Hegde@Sun.COM acpi_ivmdp->acm_ExclRange = AMD_IOMMU_REG_GET8(&uint8_flags,
72710535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_IVMD_EXCL_RANGE);
72810535SVikram.Hegde@Sun.COM acpi_ivmdp->acm_IW = AMD_IOMMU_REG_GET8(&uint8_flags,
72910535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_IVMD_IW);
73010535SVikram.Hegde@Sun.COM acpi_ivmdp->acm_IR = AMD_IOMMU_REG_GET8(&uint8_flags,
73110535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_IVMD_IR);
73210535SVikram.Hegde@Sun.COM acpi_ivmdp->acm_Unity = AMD_IOMMU_REG_GET8(&uint8_flags,
73310535SVikram.Hegde@Sun.COM AMD_IOMMU_ACPI_IVMD_UNITY);
73410535SVikram.Hegde@Sun.COM
73510535SVikram.Hegde@Sun.COM acpi_ivmdp->acm_ivmd_phys_start = ivmdp->ivmd_phys_start;
73610535SVikram.Hegde@Sun.COM acpi_ivmdp->acm_ivmd_phys_len = ivmdp->ivmd_phys_len;
73710535SVikram.Hegde@Sun.COM
73810535SVikram.Hegde@Sun.COM acpi_ivmdp->acm_next = hash[idx];
73910535SVikram.Hegde@Sun.COM hash[idx] = acpi_ivmdp;
74010535SVikram.Hegde@Sun.COM }
74110535SVikram.Hegde@Sun.COM
74210535SVikram.Hegde@Sun.COM static void
add_ivmdc_info(ivmd_container_t * ivmdcp,amd_iommu_acpi_ivmd_t ** hash)74310535SVikram.Hegde@Sun.COM add_ivmdc_info(ivmd_container_t *ivmdcp, amd_iommu_acpi_ivmd_t **hash)
74410535SVikram.Hegde@Sun.COM {
74510535SVikram.Hegde@Sun.COM set_ivmd_info(ivmdcp->ivmdc_ivmd, hash);
74610535SVikram.Hegde@Sun.COM }
74710535SVikram.Hegde@Sun.COM
74810535SVikram.Hegde@Sun.COM static void
add_ivmd_info(amd_iommu_acpi_t * acpi,amd_iommu_acpi_ivmd_t ** hash)74910535SVikram.Hegde@Sun.COM add_ivmd_info(amd_iommu_acpi_t *acpi, amd_iommu_acpi_ivmd_t **hash)
75010535SVikram.Hegde@Sun.COM {
75110535SVikram.Hegde@Sun.COM ivmd_container_t *ivmdcp;
75210535SVikram.Hegde@Sun.COM
75310535SVikram.Hegde@Sun.COM for (ivmdcp = acpi->acp_first_ivmdc; ivmdcp;
75410535SVikram.Hegde@Sun.COM ivmdcp = ivmdcp->ivmdc_next) {
75510535SVikram.Hegde@Sun.COM add_ivmdc_info(ivmdcp, hash);
75610535SVikram.Hegde@Sun.COM }
75710535SVikram.Hegde@Sun.COM }
75810535SVikram.Hegde@Sun.COM
75910535SVikram.Hegde@Sun.COM static void
add_global_info(amd_iommu_acpi_t * acpi,amd_iommu_acpi_global_t * global)76010535SVikram.Hegde@Sun.COM add_global_info(amd_iommu_acpi_t *acpi, amd_iommu_acpi_global_t *global)
76110535SVikram.Hegde@Sun.COM {
76210535SVikram.Hegde@Sun.COM uint32_t ivrs_ivinfo = acpi->acp_ivrs->ivrs_ivinfo;
76310535SVikram.Hegde@Sun.COM
76410535SVikram.Hegde@Sun.COM global->acg_HtAtsResv =
76510535SVikram.Hegde@Sun.COM AMD_IOMMU_REG_GET32(&ivrs_ivinfo, AMD_IOMMU_ACPI_HT_ATSRSV);
76610535SVikram.Hegde@Sun.COM global->acg_VAsize =
76710535SVikram.Hegde@Sun.COM AMD_IOMMU_REG_GET32(&ivrs_ivinfo, AMD_IOMMU_ACPI_VA_SIZE);
76810535SVikram.Hegde@Sun.COM global->acg_PAsize =
76910535SVikram.Hegde@Sun.COM AMD_IOMMU_REG_GET32(&ivrs_ivinfo, AMD_IOMMU_ACPI_PA_SIZE);
77010535SVikram.Hegde@Sun.COM }
77110535SVikram.Hegde@Sun.COM
77210535SVikram.Hegde@Sun.COM static int
create_acpi_hash(amd_iommu_acpi_t * acpi)77310535SVikram.Hegde@Sun.COM create_acpi_hash(amd_iommu_acpi_t *acpi)
77410535SVikram.Hegde@Sun.COM {
77510535SVikram.Hegde@Sun.COM /* Last hash entry is for deviceid ranges including "all" */
77610535SVikram.Hegde@Sun.COM
77710535SVikram.Hegde@Sun.COM amd_iommu_acpi_global = kmem_zalloc(sizeof (amd_iommu_acpi_global_t),
77810535SVikram.Hegde@Sun.COM KM_SLEEP);
77910535SVikram.Hegde@Sun.COM
78010535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivhd_hash = kmem_zalloc(sizeof (amd_iommu_acpi_ivhd_t *)
78110535SVikram.Hegde@Sun.COM * (AMD_IOMMU_ACPI_INFO_HASH_SZ + 1), KM_SLEEP);
78210535SVikram.Hegde@Sun.COM
78310535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivmd_hash = kmem_zalloc(sizeof (amd_iommu_acpi_ivmd_t *)
78410535SVikram.Hegde@Sun.COM * (AMD_IOMMU_ACPI_INFO_HASH_SZ + 1), KM_SLEEP);
78510535SVikram.Hegde@Sun.COM
78610535SVikram.Hegde@Sun.COM add_global_info(acpi, amd_iommu_acpi_global);
78710535SVikram.Hegde@Sun.COM
78810535SVikram.Hegde@Sun.COM add_ivhd_info(acpi, amd_iommu_acpi_ivhd_hash);
78910535SVikram.Hegde@Sun.COM
79010535SVikram.Hegde@Sun.COM add_ivmd_info(acpi, amd_iommu_acpi_ivmd_hash);
79110535SVikram.Hegde@Sun.COM
79210535SVikram.Hegde@Sun.COM return (DDI_SUCCESS);
79310535SVikram.Hegde@Sun.COM }
79410535SVikram.Hegde@Sun.COM
795*12203SJerry.Gilliam@Sun.COM static void
set_deventry(amd_iommu_t * iommu,int entry,amd_iommu_acpi_ivhd_t * hinfop)796*12203SJerry.Gilliam@Sun.COM set_deventry(amd_iommu_t *iommu, int entry, amd_iommu_acpi_ivhd_t *hinfop)
797*12203SJerry.Gilliam@Sun.COM {
798*12203SJerry.Gilliam@Sun.COM uint64_t *dentry;
799*12203SJerry.Gilliam@Sun.COM
800*12203SJerry.Gilliam@Sun.COM dentry = (uint64_t *)(intptr_t)
801*12203SJerry.Gilliam@Sun.COM &iommu->aiomt_devtbl[entry * AMD_IOMMU_DEVTBL_ENTRY_SZ];
802*12203SJerry.Gilliam@Sun.COM
803*12203SJerry.Gilliam@Sun.COM AMD_IOMMU_REG_SET64(&(dentry[1]), AMD_IOMMU_DEVTBL_SYSMGT,
804*12203SJerry.Gilliam@Sun.COM hinfop->ach_SysMgt);
805*12203SJerry.Gilliam@Sun.COM }
806*12203SJerry.Gilliam@Sun.COM
807*12203SJerry.Gilliam@Sun.COM /* Initialize device table according to IVHD */
808*12203SJerry.Gilliam@Sun.COM int
amd_iommu_acpi_init_devtbl(amd_iommu_t * iommu)809*12203SJerry.Gilliam@Sun.COM amd_iommu_acpi_init_devtbl(amd_iommu_t *iommu)
810*12203SJerry.Gilliam@Sun.COM {
811*12203SJerry.Gilliam@Sun.COM int i, j;
812*12203SJerry.Gilliam@Sun.COM amd_iommu_acpi_ivhd_t *hinfop;
813*12203SJerry.Gilliam@Sun.COM
814*12203SJerry.Gilliam@Sun.COM for (i = 0; i <= AMD_IOMMU_ACPI_INFO_HASH_SZ; i++) {
815*12203SJerry.Gilliam@Sun.COM for (hinfop = amd_iommu_acpi_ivhd_hash[i];
816*12203SJerry.Gilliam@Sun.COM hinfop; hinfop = hinfop->ach_next) {
817*12203SJerry.Gilliam@Sun.COM
818*12203SJerry.Gilliam@Sun.COM if (hinfop->ach_IOMMU_deviceid != iommu->aiomt_bdf)
819*12203SJerry.Gilliam@Sun.COM continue;
820*12203SJerry.Gilliam@Sun.COM
821*12203SJerry.Gilliam@Sun.COM switch (hinfop->ach_dev_type) {
822*12203SJerry.Gilliam@Sun.COM case DEVENTRY_ALL:
823*12203SJerry.Gilliam@Sun.COM for (j = 0; j < AMD_IOMMU_MAX_DEVICEID; j++)
824*12203SJerry.Gilliam@Sun.COM set_deventry(iommu, j, hinfop);
825*12203SJerry.Gilliam@Sun.COM break;
826*12203SJerry.Gilliam@Sun.COM case DEVENTRY_SELECT:
827*12203SJerry.Gilliam@Sun.COM case DEVENTRY_EXTENDED_SELECT:
828*12203SJerry.Gilliam@Sun.COM set_deventry(iommu,
829*12203SJerry.Gilliam@Sun.COM hinfop->ach_deviceid_start,
830*12203SJerry.Gilliam@Sun.COM hinfop);
831*12203SJerry.Gilliam@Sun.COM break;
832*12203SJerry.Gilliam@Sun.COM case DEVENTRY_RANGE:
833*12203SJerry.Gilliam@Sun.COM case DEVENTRY_EXTENDED_RANGE:
834*12203SJerry.Gilliam@Sun.COM for (j = hinfop->ach_deviceid_start;
835*12203SJerry.Gilliam@Sun.COM j <= hinfop->ach_deviceid_end;
836*12203SJerry.Gilliam@Sun.COM j++)
837*12203SJerry.Gilliam@Sun.COM set_deventry(iommu, j, hinfop);
838*12203SJerry.Gilliam@Sun.COM break;
839*12203SJerry.Gilliam@Sun.COM case DEVENTRY_ALIAS_SELECT:
840*12203SJerry.Gilliam@Sun.COM case DEVENTRY_ALIAS_RANGE:
841*12203SJerry.Gilliam@Sun.COM case DEVENTRY_SPECIAL_DEVICE:
842*12203SJerry.Gilliam@Sun.COM set_deventry(iommu,
843*12203SJerry.Gilliam@Sun.COM hinfop->ach_src_deviceid,
844*12203SJerry.Gilliam@Sun.COM hinfop);
845*12203SJerry.Gilliam@Sun.COM break;
846*12203SJerry.Gilliam@Sun.COM default:
847*12203SJerry.Gilliam@Sun.COM cmn_err(CE_WARN,
848*12203SJerry.Gilliam@Sun.COM "%s: Unknown deventry type",
849*12203SJerry.Gilliam@Sun.COM amd_iommu_modname);
850*12203SJerry.Gilliam@Sun.COM return (DDI_FAILURE);
851*12203SJerry.Gilliam@Sun.COM }
852*12203SJerry.Gilliam@Sun.COM }
853*12203SJerry.Gilliam@Sun.COM }
854*12203SJerry.Gilliam@Sun.COM
855*12203SJerry.Gilliam@Sun.COM return (DDI_SUCCESS);
856*12203SJerry.Gilliam@Sun.COM }
857*12203SJerry.Gilliam@Sun.COM
85810535SVikram.Hegde@Sun.COM amd_iommu_acpi_global_t *
amd_iommu_lookup_acpi_global(void)85910535SVikram.Hegde@Sun.COM amd_iommu_lookup_acpi_global(void)
86010535SVikram.Hegde@Sun.COM {
86110535SVikram.Hegde@Sun.COM ASSERT(amd_iommu_acpi_global);
86210535SVikram.Hegde@Sun.COM
86310535SVikram.Hegde@Sun.COM return (amd_iommu_acpi_global);
86410535SVikram.Hegde@Sun.COM }
86510535SVikram.Hegde@Sun.COM
86610535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivhd_t *
amd_iommu_lookup_all_ivhd(void)86710535SVikram.Hegde@Sun.COM amd_iommu_lookup_all_ivhd(void)
86810535SVikram.Hegde@Sun.COM {
86910535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivhd_t *hinfop;
87010535SVikram.Hegde@Sun.COM
87110535SVikram.Hegde@Sun.COM hinfop = amd_iommu_acpi_ivhd_hash[AMD_IOMMU_ACPI_INFO_HASH_SZ];
87210535SVikram.Hegde@Sun.COM for (; hinfop; hinfop = hinfop->ach_next) {
87310535SVikram.Hegde@Sun.COM if (hinfop->ach_deviceid_start == 0 &&
87410535SVikram.Hegde@Sun.COM hinfop->ach_deviceid_end == (uint16_t)-1) {
87510535SVikram.Hegde@Sun.COM break;
87610535SVikram.Hegde@Sun.COM }
87710535SVikram.Hegde@Sun.COM }
87810535SVikram.Hegde@Sun.COM
87910535SVikram.Hegde@Sun.COM return (hinfop);
88010535SVikram.Hegde@Sun.COM }
88110535SVikram.Hegde@Sun.COM
88210535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivmd_t *
amd_iommu_lookup_all_ivmd(void)88310535SVikram.Hegde@Sun.COM amd_iommu_lookup_all_ivmd(void)
88410535SVikram.Hegde@Sun.COM {
88510535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivmd_t *minfop;
88610535SVikram.Hegde@Sun.COM
88710535SVikram.Hegde@Sun.COM minfop = amd_iommu_acpi_ivmd_hash[AMD_IOMMU_ACPI_INFO_HASH_SZ];
88810535SVikram.Hegde@Sun.COM for (; minfop; minfop = minfop->acm_next) {
88910535SVikram.Hegde@Sun.COM if (minfop->acm_deviceid_start == 0 &&
89010535SVikram.Hegde@Sun.COM minfop->acm_deviceid_end == (uint16_t)-1) {
89110535SVikram.Hegde@Sun.COM break;
89210535SVikram.Hegde@Sun.COM }
89310535SVikram.Hegde@Sun.COM }
89410535SVikram.Hegde@Sun.COM
89510535SVikram.Hegde@Sun.COM return (minfop);
89610535SVikram.Hegde@Sun.COM }
89710535SVikram.Hegde@Sun.COM
89810535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivhd_t *
amd_iommu_lookup_any_ivhd(amd_iommu_t * iommu)899*12203SJerry.Gilliam@Sun.COM amd_iommu_lookup_any_ivhd(amd_iommu_t *iommu)
90010535SVikram.Hegde@Sun.COM {
90110535SVikram.Hegde@Sun.COM int i;
90210535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivhd_t *hinfop;
90310535SVikram.Hegde@Sun.COM
90410535SVikram.Hegde@Sun.COM for (i = AMD_IOMMU_ACPI_INFO_HASH_SZ; i >= 0; i--) {
905*12203SJerry.Gilliam@Sun.COM hinfop = amd_iommu_acpi_ivhd_hash[i];
906*12203SJerry.Gilliam@Sun.COM if ((hinfop != NULL) &&
907*12203SJerry.Gilliam@Sun.COM hinfop->ach_IOMMU_deviceid == iommu->aiomt_bdf)
90810535SVikram.Hegde@Sun.COM break;
90910535SVikram.Hegde@Sun.COM }
91010535SVikram.Hegde@Sun.COM
91110535SVikram.Hegde@Sun.COM return (hinfop);
91210535SVikram.Hegde@Sun.COM }
91310535SVikram.Hegde@Sun.COM
91410535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivmd_t *
amd_iommu_lookup_any_ivmd(void)91510535SVikram.Hegde@Sun.COM amd_iommu_lookup_any_ivmd(void)
91610535SVikram.Hegde@Sun.COM {
91710535SVikram.Hegde@Sun.COM int i;
91810535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivmd_t *minfop;
91910535SVikram.Hegde@Sun.COM
92010535SVikram.Hegde@Sun.COM for (i = AMD_IOMMU_ACPI_INFO_HASH_SZ; i >= 0; i--) {
921*12203SJerry.Gilliam@Sun.COM if ((minfop = amd_iommu_acpi_ivmd_hash[i]) != NULL)
92210535SVikram.Hegde@Sun.COM break;
92310535SVikram.Hegde@Sun.COM }
92410535SVikram.Hegde@Sun.COM
92510535SVikram.Hegde@Sun.COM return (minfop);
92610535SVikram.Hegde@Sun.COM }
92710535SVikram.Hegde@Sun.COM
92810535SVikram.Hegde@Sun.COM static void
dump_acpi_aliases(void)92910535SVikram.Hegde@Sun.COM dump_acpi_aliases(void)
93010535SVikram.Hegde@Sun.COM {
93110535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivhd_t *hinfop;
93210535SVikram.Hegde@Sun.COM uint16_t idx;
93310535SVikram.Hegde@Sun.COM
93410535SVikram.Hegde@Sun.COM for (idx = 0; idx <= AMD_IOMMU_ACPI_INFO_HASH_SZ; idx++) {
93510535SVikram.Hegde@Sun.COM hinfop = amd_iommu_acpi_ivhd_hash[idx];
93610535SVikram.Hegde@Sun.COM for (; hinfop; hinfop = hinfop->ach_next) {
93710535SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "start=%d, end=%d, src_bdf=%d",
93810535SVikram.Hegde@Sun.COM hinfop->ach_deviceid_start,
93910535SVikram.Hegde@Sun.COM hinfop->ach_deviceid_end,
94010535SVikram.Hegde@Sun.COM hinfop->ach_src_deviceid);
94110535SVikram.Hegde@Sun.COM }
94210535SVikram.Hegde@Sun.COM }
94310535SVikram.Hegde@Sun.COM }
94410535SVikram.Hegde@Sun.COM
94510535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivhd_t *
amd_iommu_lookup_ivhd(int32_t deviceid)94610535SVikram.Hegde@Sun.COM amd_iommu_lookup_ivhd(int32_t deviceid)
94710535SVikram.Hegde@Sun.COM {
94810535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivhd_t *hinfop;
94910535SVikram.Hegde@Sun.COM uint16_t idx;
95010535SVikram.Hegde@Sun.COM
951*12203SJerry.Gilliam@Sun.COM if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
95210535SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "Attempting to get ACPI IVHD info "
95310535SVikram.Hegde@Sun.COM "for deviceid: %d", deviceid);
95410535SVikram.Hegde@Sun.COM }
95510535SVikram.Hegde@Sun.COM
95610535SVikram.Hegde@Sun.COM ASSERT(amd_iommu_acpi_ivhd_hash);
95710535SVikram.Hegde@Sun.COM
95810535SVikram.Hegde@Sun.COM /* check if special device */
95910535SVikram.Hegde@Sun.COM if (deviceid == -1) {
96010535SVikram.Hegde@Sun.COM hinfop = amd_iommu_acpi_ivhd_hash[AMD_IOMMU_ACPI_INFO_HASH_SZ];
96110535SVikram.Hegde@Sun.COM for (; hinfop; hinfop = hinfop->ach_next) {
96210535SVikram.Hegde@Sun.COM if (hinfop->ach_deviceid_start == -1 &&
96310535SVikram.Hegde@Sun.COM hinfop->ach_deviceid_end == -1) {
96410535SVikram.Hegde@Sun.COM break;
96510535SVikram.Hegde@Sun.COM }
96610535SVikram.Hegde@Sun.COM }
96710535SVikram.Hegde@Sun.COM return (hinfop);
96810535SVikram.Hegde@Sun.COM }
96910535SVikram.Hegde@Sun.COM
97010535SVikram.Hegde@Sun.COM /* First search for an exact match */
97110535SVikram.Hegde@Sun.COM
97210535SVikram.Hegde@Sun.COM idx = deviceid_hashfn(deviceid);
97310535SVikram.Hegde@Sun.COM
97410535SVikram.Hegde@Sun.COM
97510535SVikram.Hegde@Sun.COM range:
97610535SVikram.Hegde@Sun.COM hinfop = amd_iommu_acpi_ivhd_hash[idx];
97710535SVikram.Hegde@Sun.COM
97810535SVikram.Hegde@Sun.COM for (; hinfop; hinfop = hinfop->ach_next) {
97910535SVikram.Hegde@Sun.COM if (deviceid < hinfop->ach_deviceid_start ||
98010535SVikram.Hegde@Sun.COM deviceid > hinfop->ach_deviceid_end)
98110535SVikram.Hegde@Sun.COM continue;
98210535SVikram.Hegde@Sun.COM
983*12203SJerry.Gilliam@Sun.COM if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
98410535SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "Found ACPI IVHD match: %p, "
98510535SVikram.Hegde@Sun.COM "actual deviceid = %u, start = %u, end = %u",
98610535SVikram.Hegde@Sun.COM (void *)hinfop, deviceid,
98710535SVikram.Hegde@Sun.COM hinfop->ach_deviceid_start,
98810535SVikram.Hegde@Sun.COM hinfop->ach_deviceid_end);
98910535SVikram.Hegde@Sun.COM }
99010535SVikram.Hegde@Sun.COM goto out;
99110535SVikram.Hegde@Sun.COM }
99210535SVikram.Hegde@Sun.COM
99310535SVikram.Hegde@Sun.COM if (idx != AMD_IOMMU_ACPI_INFO_HASH_SZ) {
99410535SVikram.Hegde@Sun.COM idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
99510535SVikram.Hegde@Sun.COM goto range;
99610535SVikram.Hegde@Sun.COM }
99710535SVikram.Hegde@Sun.COM
99810535SVikram.Hegde@Sun.COM out:
999*12203SJerry.Gilliam@Sun.COM if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
100010535SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "%u: %s ACPI IVHD %p", deviceid,
100110535SVikram.Hegde@Sun.COM hinfop ? "GOT" : "Did NOT get", (void *)hinfop);
100210535SVikram.Hegde@Sun.COM }
100310535SVikram.Hegde@Sun.COM
100410535SVikram.Hegde@Sun.COM return (hinfop);
100510535SVikram.Hegde@Sun.COM }
100610535SVikram.Hegde@Sun.COM
100710535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivmd_t *
amd_iommu_lookup_ivmd(int32_t deviceid)100810535SVikram.Hegde@Sun.COM amd_iommu_lookup_ivmd(int32_t deviceid)
100910535SVikram.Hegde@Sun.COM {
101010535SVikram.Hegde@Sun.COM amd_iommu_acpi_ivmd_t *minfop;
101110535SVikram.Hegde@Sun.COM uint16_t idx;
101210535SVikram.Hegde@Sun.COM
1013*12203SJerry.Gilliam@Sun.COM if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
101410535SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "Attempting to get ACPI IVMD info "
101510535SVikram.Hegde@Sun.COM "for deviceid: %u", deviceid);
101610535SVikram.Hegde@Sun.COM }
101710535SVikram.Hegde@Sun.COM
101810535SVikram.Hegde@Sun.COM ASSERT(amd_iommu_acpi_ivmd_hash);
101910535SVikram.Hegde@Sun.COM
102010535SVikram.Hegde@Sun.COM /* First search for an exact match */
102110535SVikram.Hegde@Sun.COM
102210535SVikram.Hegde@Sun.COM idx = deviceid_hashfn(deviceid);
102310535SVikram.Hegde@Sun.COM
102410535SVikram.Hegde@Sun.COM range:
102510535SVikram.Hegde@Sun.COM minfop = amd_iommu_acpi_ivmd_hash[idx];
102610535SVikram.Hegde@Sun.COM
102710535SVikram.Hegde@Sun.COM for (; minfop; minfop = minfop->acm_next) {
102810535SVikram.Hegde@Sun.COM if (deviceid < minfop->acm_deviceid_start &&
102910535SVikram.Hegde@Sun.COM deviceid > minfop->acm_deviceid_end)
103010535SVikram.Hegde@Sun.COM continue;
103110535SVikram.Hegde@Sun.COM
1032*12203SJerry.Gilliam@Sun.COM if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
103310535SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "Found ACPI IVMD match: %p, "
103410535SVikram.Hegde@Sun.COM "actual deviceid = %u, start = %u, end = %u",
103510535SVikram.Hegde@Sun.COM (void *)minfop, deviceid,
103610535SVikram.Hegde@Sun.COM minfop->acm_deviceid_start,
103710535SVikram.Hegde@Sun.COM minfop->acm_deviceid_end);
103810535SVikram.Hegde@Sun.COM }
103910535SVikram.Hegde@Sun.COM
104010535SVikram.Hegde@Sun.COM goto out;
104110535SVikram.Hegde@Sun.COM }
104210535SVikram.Hegde@Sun.COM
104310535SVikram.Hegde@Sun.COM if (idx != AMD_IOMMU_ACPI_INFO_HASH_SZ) {
104410535SVikram.Hegde@Sun.COM idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
104510535SVikram.Hegde@Sun.COM goto range;
104610535SVikram.Hegde@Sun.COM }
104710535SVikram.Hegde@Sun.COM
104810535SVikram.Hegde@Sun.COM out:
1049*12203SJerry.Gilliam@Sun.COM if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
105010535SVikram.Hegde@Sun.COM cmn_err(CE_NOTE, "%u: %s ACPI IVMD info %p", deviceid,
105110535SVikram.Hegde@Sun.COM minfop ? "GOT" : "Did NOT get", (void *)minfop);
105210535SVikram.Hegde@Sun.COM }
105310535SVikram.Hegde@Sun.COM
105410535SVikram.Hegde@Sun.COM return (minfop);
105510535SVikram.Hegde@Sun.COM }
1056