110394SMichael.Corcoran@Sun.COM /*
210394SMichael.Corcoran@Sun.COM * CDDL HEADER START
310394SMichael.Corcoran@Sun.COM *
410394SMichael.Corcoran@Sun.COM * The contents of this file are subject to the terms of the
510394SMichael.Corcoran@Sun.COM * Common Development and Distribution License (the "License").
610394SMichael.Corcoran@Sun.COM * You may not use this file except in compliance with the License.
710394SMichael.Corcoran@Sun.COM *
810394SMichael.Corcoran@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910394SMichael.Corcoran@Sun.COM * or http://www.opensolaris.org/os/licensing.
1010394SMichael.Corcoran@Sun.COM * See the License for the specific language governing permissions
1110394SMichael.Corcoran@Sun.COM * and limitations under the License.
1210394SMichael.Corcoran@Sun.COM *
1310394SMichael.Corcoran@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1410394SMichael.Corcoran@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510394SMichael.Corcoran@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1610394SMichael.Corcoran@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1710394SMichael.Corcoran@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1810394SMichael.Corcoran@Sun.COM *
1910394SMichael.Corcoran@Sun.COM * CDDL HEADER END
2010394SMichael.Corcoran@Sun.COM */
2110394SMichael.Corcoran@Sun.COM /*
2211225SDana.Myers@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2311225SDana.Myers@Sun.COM * Use is subject to license terms.
2411225SDana.Myers@Sun.COM */
2511225SDana.Myers@Sun.COM /*
26*12004Sjiang.liu@intel.com * Copyright (c) 2009-2010, Intel Corporation.
2710394SMichael.Corcoran@Sun.COM * All rights reserved.
2810394SMichael.Corcoran@Sun.COM */
2910394SMichael.Corcoran@Sun.COM
3010394SMichael.Corcoran@Sun.COM #include <sys/types.h>
3110394SMichael.Corcoran@Sun.COM #include <sys/cmn_err.h>
3210394SMichael.Corcoran@Sun.COM #include <sys/sysmacros.h>
3310394SMichael.Corcoran@Sun.COM #include <sys/sunddi.h>
3410394SMichael.Corcoran@Sun.COM #include <sys/sunndi.h>
3510394SMichael.Corcoran@Sun.COM #include <sys/acpi/acpi.h>
3610394SMichael.Corcoran@Sun.COM #include <sys/acpica.h>
3710394SMichael.Corcoran@Sun.COM #include <sys/acpidev.h>
3810394SMichael.Corcoran@Sun.COM #include <sys/acpidev_rsc.h>
3910394SMichael.Corcoran@Sun.COM #include <sys/acpidev_impl.h>
4010394SMichael.Corcoran@Sun.COM
4110394SMichael.Corcoran@Sun.COM #define ACPIDEV_RES_INIT_ITEMS 8
4210394SMichael.Corcoran@Sun.COM #define ACPIDEV_RES_INCR_ITEMS 8
4310394SMichael.Corcoran@Sun.COM
4410394SMichael.Corcoran@Sun.COM /* Data structure to hold parsed resources during walking. */
4510394SMichael.Corcoran@Sun.COM struct acpidev_resource_handle {
4610394SMichael.Corcoran@Sun.COM boolean_t acpidev_consumer;
4710394SMichael.Corcoran@Sun.COM int acpidev_reg_count;
4810394SMichael.Corcoran@Sun.COM int acpidev_reg_max;
4910394SMichael.Corcoran@Sun.COM acpidev_phys_spec_t *acpidev_regp;
5010394SMichael.Corcoran@Sun.COM acpidev_phys_spec_t acpidev_regs[ACPIDEV_RES_INIT_ITEMS];
5110394SMichael.Corcoran@Sun.COM int acpidev_range_count;
5210394SMichael.Corcoran@Sun.COM int acpidev_range_max;
5310394SMichael.Corcoran@Sun.COM acpidev_ranges_t *acpidev_rangep;
5410394SMichael.Corcoran@Sun.COM acpidev_ranges_t acpidev_ranges[ACPIDEV_RES_INIT_ITEMS];
5510394SMichael.Corcoran@Sun.COM int acpidev_bus_count;
5610394SMichael.Corcoran@Sun.COM int acpidev_bus_max;
5710394SMichael.Corcoran@Sun.COM acpidev_bus_range_t *acpidev_busp;
5810394SMichael.Corcoran@Sun.COM acpidev_bus_range_t acpidev_buses[ACPIDEV_RES_INIT_ITEMS];
5910394SMichael.Corcoran@Sun.COM int acpidev_irq_count;
6010394SMichael.Corcoran@Sun.COM int acpidev_irqp[ACPIDEV_RES_IRQ_MAX];
6110394SMichael.Corcoran@Sun.COM int acpidev_dma_count;
6210394SMichael.Corcoran@Sun.COM int acpidev_dmap[ACPIDEV_RES_DMA_MAX];
6310394SMichael.Corcoran@Sun.COM };
6410394SMichael.Corcoran@Sun.COM
6510394SMichael.Corcoran@Sun.COM acpidev_resource_handle_t
acpidev_resource_handle_alloc(boolean_t consumer)6610394SMichael.Corcoran@Sun.COM acpidev_resource_handle_alloc(boolean_t consumer)
6710394SMichael.Corcoran@Sun.COM {
6810394SMichael.Corcoran@Sun.COM acpidev_resource_handle_t rhdl;
6910394SMichael.Corcoran@Sun.COM
7010394SMichael.Corcoran@Sun.COM rhdl = kmem_zalloc(sizeof (*rhdl), KM_SLEEP);
7110394SMichael.Corcoran@Sun.COM rhdl->acpidev_consumer = consumer;
7210394SMichael.Corcoran@Sun.COM rhdl->acpidev_reg_max = ACPIDEV_RES_INIT_ITEMS;
7310394SMichael.Corcoran@Sun.COM rhdl->acpidev_regp = rhdl->acpidev_regs;
7410394SMichael.Corcoran@Sun.COM rhdl->acpidev_range_max = ACPIDEV_RES_INIT_ITEMS;
7510394SMichael.Corcoran@Sun.COM rhdl->acpidev_rangep = rhdl->acpidev_ranges;
7610394SMichael.Corcoran@Sun.COM rhdl->acpidev_bus_max = ACPIDEV_RES_INIT_ITEMS;
7710394SMichael.Corcoran@Sun.COM rhdl->acpidev_busp = rhdl->acpidev_buses;
7810394SMichael.Corcoran@Sun.COM
7910394SMichael.Corcoran@Sun.COM return (rhdl);
8010394SMichael.Corcoran@Sun.COM }
8110394SMichael.Corcoran@Sun.COM
8210394SMichael.Corcoran@Sun.COM void
acpidev_resource_handle_free(acpidev_resource_handle_t rhdl)8310394SMichael.Corcoran@Sun.COM acpidev_resource_handle_free(acpidev_resource_handle_t rhdl)
8410394SMichael.Corcoran@Sun.COM {
8510394SMichael.Corcoran@Sun.COM size_t sz;
8610394SMichael.Corcoran@Sun.COM
8710394SMichael.Corcoran@Sun.COM ASSERT(rhdl != NULL);
8810394SMichael.Corcoran@Sun.COM if (rhdl != NULL) {
8910394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_regp != rhdl->acpidev_regs) {
9010394SMichael.Corcoran@Sun.COM sz = sizeof (acpidev_phys_spec_t) *
9110394SMichael.Corcoran@Sun.COM rhdl->acpidev_reg_max;
9210394SMichael.Corcoran@Sun.COM kmem_free(rhdl->acpidev_regp, sz);
9310394SMichael.Corcoran@Sun.COM }
9410394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_rangep != rhdl->acpidev_ranges) {
9510394SMichael.Corcoran@Sun.COM sz = sizeof (acpidev_ranges_t) *
9610394SMichael.Corcoran@Sun.COM rhdl->acpidev_range_max;
9710394SMichael.Corcoran@Sun.COM kmem_free(rhdl->acpidev_rangep, sz);
9810394SMichael.Corcoran@Sun.COM }
9910394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_busp != rhdl->acpidev_buses) {
10010394SMichael.Corcoran@Sun.COM sz = sizeof (acpidev_bus_range_t) *
10110394SMichael.Corcoran@Sun.COM rhdl->acpidev_bus_max;
10210394SMichael.Corcoran@Sun.COM kmem_free(rhdl->acpidev_busp, sz);
10310394SMichael.Corcoran@Sun.COM }
10410394SMichael.Corcoran@Sun.COM kmem_free(rhdl, sizeof (struct acpidev_resource_handle));
10510394SMichael.Corcoran@Sun.COM }
10610394SMichael.Corcoran@Sun.COM }
10710394SMichael.Corcoran@Sun.COM
10810394SMichael.Corcoran@Sun.COM static void
acpidev_resource_handle_grow(acpidev_resource_handle_t rhdl)10910394SMichael.Corcoran@Sun.COM acpidev_resource_handle_grow(acpidev_resource_handle_t rhdl)
11010394SMichael.Corcoran@Sun.COM {
11110394SMichael.Corcoran@Sun.COM size_t sz;
11210394SMichael.Corcoran@Sun.COM
11310394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_reg_count == rhdl->acpidev_reg_max) {
11410394SMichael.Corcoran@Sun.COM acpidev_phys_spec_t *regp;
11510394SMichael.Corcoran@Sun.COM
11610394SMichael.Corcoran@Sun.COM /* Prefer linear incremental here. */
11710394SMichael.Corcoran@Sun.COM rhdl->acpidev_reg_max += ACPIDEV_RES_INCR_ITEMS;
11810394SMichael.Corcoran@Sun.COM sz = sizeof (*regp) * rhdl->acpidev_reg_max;
11910394SMichael.Corcoran@Sun.COM regp = kmem_zalloc(sz, KM_SLEEP);
12010394SMichael.Corcoran@Sun.COM sz = sizeof (*regp) * rhdl->acpidev_reg_count;
12110394SMichael.Corcoran@Sun.COM bcopy(rhdl->acpidev_regp, regp, sz);
12210394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_regp != rhdl->acpidev_regs) {
12310394SMichael.Corcoran@Sun.COM kmem_free(rhdl->acpidev_regp, sz);
12410394SMichael.Corcoran@Sun.COM }
12510394SMichael.Corcoran@Sun.COM rhdl->acpidev_regp = regp;
12610394SMichael.Corcoran@Sun.COM }
12710394SMichael.Corcoran@Sun.COM
12810394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_range_count == rhdl->acpidev_range_max) {
12910394SMichael.Corcoran@Sun.COM acpidev_ranges_t *rngp;
13010394SMichael.Corcoran@Sun.COM
13110394SMichael.Corcoran@Sun.COM /* Prefer linear incremental here. */
13210394SMichael.Corcoran@Sun.COM rhdl->acpidev_range_max += ACPIDEV_RES_INCR_ITEMS;
13310394SMichael.Corcoran@Sun.COM sz = sizeof (*rngp) * rhdl->acpidev_range_max;
13410394SMichael.Corcoran@Sun.COM rngp = kmem_zalloc(sz, KM_SLEEP);
13510394SMichael.Corcoran@Sun.COM sz = sizeof (*rngp) * rhdl->acpidev_range_count;
13610394SMichael.Corcoran@Sun.COM bcopy(rhdl->acpidev_rangep, rngp, sz);
13710394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_rangep != rhdl->acpidev_ranges) {
13810394SMichael.Corcoran@Sun.COM kmem_free(rhdl->acpidev_rangep, sz);
13910394SMichael.Corcoran@Sun.COM }
14010394SMichael.Corcoran@Sun.COM rhdl->acpidev_rangep = rngp;
14110394SMichael.Corcoran@Sun.COM }
14210394SMichael.Corcoran@Sun.COM
14310394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_bus_count == rhdl->acpidev_bus_max) {
14410394SMichael.Corcoran@Sun.COM acpidev_bus_range_t *busp;
14510394SMichael.Corcoran@Sun.COM
14610394SMichael.Corcoran@Sun.COM /* Prefer linear incremental here. */
14710394SMichael.Corcoran@Sun.COM rhdl->acpidev_bus_max += ACPIDEV_RES_INCR_ITEMS;
14810394SMichael.Corcoran@Sun.COM sz = sizeof (*busp) * rhdl->acpidev_bus_max;
14910394SMichael.Corcoran@Sun.COM busp = kmem_zalloc(sz, KM_SLEEP);
15010394SMichael.Corcoran@Sun.COM sz = sizeof (*busp) * rhdl->acpidev_bus_count;
15110394SMichael.Corcoran@Sun.COM bcopy(rhdl->acpidev_busp, busp, sz);
15210394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_busp != rhdl->acpidev_buses) {
15310394SMichael.Corcoran@Sun.COM kmem_free(rhdl->acpidev_busp, sz);
15410394SMichael.Corcoran@Sun.COM }
15510394SMichael.Corcoran@Sun.COM rhdl->acpidev_busp = busp;
15610394SMichael.Corcoran@Sun.COM }
15710394SMichael.Corcoran@Sun.COM }
15810394SMichael.Corcoran@Sun.COM
15910394SMichael.Corcoran@Sun.COM ACPI_STATUS
acpidev_resource_insert_reg(acpidev_resource_handle_t rhdl,acpidev_regspec_t * regp)16010394SMichael.Corcoran@Sun.COM acpidev_resource_insert_reg(acpidev_resource_handle_t rhdl,
16110394SMichael.Corcoran@Sun.COM acpidev_regspec_t *regp)
16210394SMichael.Corcoran@Sun.COM {
16310394SMichael.Corcoran@Sun.COM ASSERT(rhdl != NULL);
16410394SMichael.Corcoran@Sun.COM ASSERT(regp != NULL);
16510394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_reg_count >= rhdl->acpidev_reg_max) {
16610394SMichael.Corcoran@Sun.COM acpidev_resource_handle_grow(rhdl);
16710394SMichael.Corcoran@Sun.COM }
16810394SMichael.Corcoran@Sun.COM ASSERT(rhdl->acpidev_reg_count < rhdl->acpidev_reg_max);
16910394SMichael.Corcoran@Sun.COM rhdl->acpidev_regp[rhdl->acpidev_reg_count] = *regp;
17010394SMichael.Corcoran@Sun.COM rhdl->acpidev_reg_count++;
17110394SMichael.Corcoran@Sun.COM
17210394SMichael.Corcoran@Sun.COM return (AE_OK);
17310394SMichael.Corcoran@Sun.COM }
17410394SMichael.Corcoran@Sun.COM
17510394SMichael.Corcoran@Sun.COM ACPI_STATUS
acpidev_resource_get_regs(acpidev_resource_handle_t rhdl,uint_t mask,uint_t value,acpidev_regspec_t * regp,uint_t * cntp)17610394SMichael.Corcoran@Sun.COM acpidev_resource_get_regs(acpidev_resource_handle_t rhdl,
17710394SMichael.Corcoran@Sun.COM uint_t mask, uint_t value, acpidev_regspec_t *regp, uint_t *cntp)
17810394SMichael.Corcoran@Sun.COM {
17910394SMichael.Corcoran@Sun.COM uint_t i, j;
18010394SMichael.Corcoran@Sun.COM
18110394SMichael.Corcoran@Sun.COM ASSERT(rhdl != NULL);
18210394SMichael.Corcoran@Sun.COM ASSERT(cntp != NULL);
18310394SMichael.Corcoran@Sun.COM if (rhdl == NULL || cntp == NULL || (regp == NULL && *cntp != 0)) {
18410394SMichael.Corcoran@Sun.COM return (AE_BAD_PARAMETER);
18510394SMichael.Corcoran@Sun.COM }
18610394SMichael.Corcoran@Sun.COM for (i = 0, j = 0; i < rhdl->acpidev_reg_count; i++) {
18710394SMichael.Corcoran@Sun.COM if ((rhdl->acpidev_regp[i].phys_hi & mask) == value) {
18810394SMichael.Corcoran@Sun.COM if (j < *cntp) {
18910394SMichael.Corcoran@Sun.COM regp[j] = rhdl->acpidev_regp[i];
19010394SMichael.Corcoran@Sun.COM }
19110394SMichael.Corcoran@Sun.COM j++;
19210394SMichael.Corcoran@Sun.COM }
19310394SMichael.Corcoran@Sun.COM }
19410394SMichael.Corcoran@Sun.COM if (j >= *cntp) {
19510394SMichael.Corcoran@Sun.COM *cntp = j;
19610394SMichael.Corcoran@Sun.COM return (AE_LIMIT);
19710394SMichael.Corcoran@Sun.COM } else {
19810394SMichael.Corcoran@Sun.COM *cntp = j;
19910394SMichael.Corcoran@Sun.COM return (AE_OK);
20010394SMichael.Corcoran@Sun.COM }
20110394SMichael.Corcoran@Sun.COM }
20210394SMichael.Corcoran@Sun.COM
20310394SMichael.Corcoran@Sun.COM uint_t
acpidev_resource_get_reg_count(acpidev_resource_handle_t rhdl,uint_t mask,uint_t value)20410394SMichael.Corcoran@Sun.COM acpidev_resource_get_reg_count(acpidev_resource_handle_t rhdl,
20510394SMichael.Corcoran@Sun.COM uint_t mask, uint_t value)
20610394SMichael.Corcoran@Sun.COM {
20710394SMichael.Corcoran@Sun.COM uint_t i, j;
20810394SMichael.Corcoran@Sun.COM
20910394SMichael.Corcoran@Sun.COM ASSERT(rhdl != NULL);
21010394SMichael.Corcoran@Sun.COM for (i = 0, j = 0; i < rhdl->acpidev_reg_count; i++) {
21110394SMichael.Corcoran@Sun.COM if ((rhdl->acpidev_regp[i].phys_hi & mask) == value) {
21210394SMichael.Corcoran@Sun.COM j++;
21310394SMichael.Corcoran@Sun.COM }
21410394SMichael.Corcoran@Sun.COM }
21510394SMichael.Corcoran@Sun.COM
21610394SMichael.Corcoran@Sun.COM return (j);
21710394SMichael.Corcoran@Sun.COM }
21810394SMichael.Corcoran@Sun.COM
21910394SMichael.Corcoran@Sun.COM ACPI_STATUS
acpidev_resource_insert_range(acpidev_resource_handle_t rhdl,acpidev_ranges_t * rangep)22010394SMichael.Corcoran@Sun.COM acpidev_resource_insert_range(acpidev_resource_handle_t rhdl,
22110394SMichael.Corcoran@Sun.COM acpidev_ranges_t *rangep)
22210394SMichael.Corcoran@Sun.COM {
22310394SMichael.Corcoran@Sun.COM ASSERT(rhdl != NULL);
22410394SMichael.Corcoran@Sun.COM ASSERT(rangep != NULL);
22510394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_range_count >= rhdl->acpidev_range_max) {
22610394SMichael.Corcoran@Sun.COM acpidev_resource_handle_grow(rhdl);
22710394SMichael.Corcoran@Sun.COM }
22810394SMichael.Corcoran@Sun.COM ASSERT(rhdl->acpidev_range_count < rhdl->acpidev_range_max);
22910394SMichael.Corcoran@Sun.COM rhdl->acpidev_rangep[rhdl->acpidev_range_count] = *rangep;
23010394SMichael.Corcoran@Sun.COM rhdl->acpidev_range_count++;
23110394SMichael.Corcoran@Sun.COM
23210394SMichael.Corcoran@Sun.COM return (AE_OK);
23310394SMichael.Corcoran@Sun.COM }
23410394SMichael.Corcoran@Sun.COM
23510394SMichael.Corcoran@Sun.COM ACPI_STATUS
acpidev_resource_get_ranges(acpidev_resource_handle_t rhdl,uint_t mask,uint_t value,acpidev_ranges_t * rangep,uint_t * cntp)23610394SMichael.Corcoran@Sun.COM acpidev_resource_get_ranges(acpidev_resource_handle_t rhdl,
23710394SMichael.Corcoran@Sun.COM uint_t mask, uint_t value, acpidev_ranges_t *rangep, uint_t *cntp)
23810394SMichael.Corcoran@Sun.COM {
23910394SMichael.Corcoran@Sun.COM uint_t i, j;
24010394SMichael.Corcoran@Sun.COM
24110394SMichael.Corcoran@Sun.COM ASSERT(rhdl != NULL);
24210394SMichael.Corcoran@Sun.COM ASSERT(cntp != NULL);
24310394SMichael.Corcoran@Sun.COM if (rhdl == NULL || cntp == NULL || (rangep == NULL && *cntp != 0)) {
24410394SMichael.Corcoran@Sun.COM return (AE_BAD_PARAMETER);
24510394SMichael.Corcoran@Sun.COM }
24610394SMichael.Corcoran@Sun.COM for (i = 0, j = 0; i < rhdl->acpidev_range_count; i++) {
24710394SMichael.Corcoran@Sun.COM if ((rhdl->acpidev_rangep[i].child_hi & mask) == value) {
24810394SMichael.Corcoran@Sun.COM if (j < *cntp) {
24910394SMichael.Corcoran@Sun.COM rangep[j] = rhdl->acpidev_rangep[i];
25010394SMichael.Corcoran@Sun.COM }
25110394SMichael.Corcoran@Sun.COM j++;
25210394SMichael.Corcoran@Sun.COM }
25310394SMichael.Corcoran@Sun.COM }
25410394SMichael.Corcoran@Sun.COM if (j >= *cntp) {
25510394SMichael.Corcoran@Sun.COM *cntp = j;
25610394SMichael.Corcoran@Sun.COM return (AE_LIMIT);
25710394SMichael.Corcoran@Sun.COM } else {
25810394SMichael.Corcoran@Sun.COM *cntp = j;
25910394SMichael.Corcoran@Sun.COM return (AE_OK);
26010394SMichael.Corcoran@Sun.COM }
26110394SMichael.Corcoran@Sun.COM }
26210394SMichael.Corcoran@Sun.COM
26310394SMichael.Corcoran@Sun.COM uint_t
acpidev_resource_get_range_count(acpidev_resource_handle_t rhdl,uint_t mask,uint_t value)26410394SMichael.Corcoran@Sun.COM acpidev_resource_get_range_count(acpidev_resource_handle_t rhdl,
26510394SMichael.Corcoran@Sun.COM uint_t mask, uint_t value)
26610394SMichael.Corcoran@Sun.COM {
26710394SMichael.Corcoran@Sun.COM uint_t i, j;
26810394SMichael.Corcoran@Sun.COM
26910394SMichael.Corcoran@Sun.COM ASSERT(rhdl != NULL);
27010394SMichael.Corcoran@Sun.COM for (i = 0, j = 0; i < rhdl->acpidev_range_count; i++) {
27110394SMichael.Corcoran@Sun.COM if ((rhdl->acpidev_rangep[i].child_hi & mask) == value) {
27210394SMichael.Corcoran@Sun.COM j++;
27310394SMichael.Corcoran@Sun.COM }
27410394SMichael.Corcoran@Sun.COM }
27510394SMichael.Corcoran@Sun.COM
27610394SMichael.Corcoran@Sun.COM return (j);
27710394SMichael.Corcoran@Sun.COM }
27810394SMichael.Corcoran@Sun.COM
27910394SMichael.Corcoran@Sun.COM ACPI_STATUS
acpidev_resource_insert_bus(acpidev_resource_handle_t rhdl,acpidev_bus_range_t * busp)28010394SMichael.Corcoran@Sun.COM acpidev_resource_insert_bus(acpidev_resource_handle_t rhdl,
28110394SMichael.Corcoran@Sun.COM acpidev_bus_range_t *busp)
28210394SMichael.Corcoran@Sun.COM {
28310394SMichael.Corcoran@Sun.COM ASSERT(rhdl != NULL);
28410394SMichael.Corcoran@Sun.COM ASSERT(busp != NULL);
28510394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_bus_count >= rhdl->acpidev_bus_max) {
28610394SMichael.Corcoran@Sun.COM acpidev_resource_handle_grow(rhdl);
28710394SMichael.Corcoran@Sun.COM }
28810394SMichael.Corcoran@Sun.COM ASSERT(rhdl->acpidev_bus_count < rhdl->acpidev_bus_max);
28910394SMichael.Corcoran@Sun.COM rhdl->acpidev_busp[rhdl->acpidev_bus_count] = *busp;
29010394SMichael.Corcoran@Sun.COM rhdl->acpidev_bus_count++;
29110394SMichael.Corcoran@Sun.COM
29210394SMichael.Corcoran@Sun.COM return (AE_OK);
29310394SMichael.Corcoran@Sun.COM }
29410394SMichael.Corcoran@Sun.COM
29510394SMichael.Corcoran@Sun.COM ACPI_STATUS
acpidev_resource_get_buses(acpidev_resource_handle_t rhdl,acpidev_bus_range_t * busp,uint_t * cntp)29610394SMichael.Corcoran@Sun.COM acpidev_resource_get_buses(acpidev_resource_handle_t rhdl,
29710394SMichael.Corcoran@Sun.COM acpidev_bus_range_t *busp, uint_t *cntp)
29810394SMichael.Corcoran@Sun.COM {
29910394SMichael.Corcoran@Sun.COM uint_t i, j;
30010394SMichael.Corcoran@Sun.COM
30110394SMichael.Corcoran@Sun.COM ASSERT(rhdl != NULL);
30210394SMichael.Corcoran@Sun.COM ASSERT(cntp != NULL);
30310394SMichael.Corcoran@Sun.COM if (rhdl == NULL || cntp == NULL || (busp == NULL && *cntp != 0)) {
30410394SMichael.Corcoran@Sun.COM return (AE_BAD_PARAMETER);
30510394SMichael.Corcoran@Sun.COM }
30610394SMichael.Corcoran@Sun.COM for (i = 0, j = 0; i < rhdl->acpidev_bus_count; i++) {
30710394SMichael.Corcoran@Sun.COM if (j < *cntp) {
30810394SMichael.Corcoran@Sun.COM busp[j] = rhdl->acpidev_busp[i];
30910394SMichael.Corcoran@Sun.COM }
31010394SMichael.Corcoran@Sun.COM j++;
31110394SMichael.Corcoran@Sun.COM }
31210394SMichael.Corcoran@Sun.COM if (j >= *cntp) {
31310394SMichael.Corcoran@Sun.COM *cntp = j;
31410394SMichael.Corcoran@Sun.COM return (AE_LIMIT);
31510394SMichael.Corcoran@Sun.COM } else {
31610394SMichael.Corcoran@Sun.COM *cntp = j;
31710394SMichael.Corcoran@Sun.COM return (AE_OK);
31810394SMichael.Corcoran@Sun.COM }
31910394SMichael.Corcoran@Sun.COM }
32010394SMichael.Corcoran@Sun.COM
32110394SMichael.Corcoran@Sun.COM uint_t
acpidev_resource_get_bus_count(acpidev_resource_handle_t rhdl)32210394SMichael.Corcoran@Sun.COM acpidev_resource_get_bus_count(acpidev_resource_handle_t rhdl)
32310394SMichael.Corcoran@Sun.COM {
32410394SMichael.Corcoran@Sun.COM ASSERT(rhdl != NULL);
32510394SMichael.Corcoran@Sun.COM return (rhdl->acpidev_bus_count);
32610394SMichael.Corcoran@Sun.COM }
32710394SMichael.Corcoran@Sun.COM
32810394SMichael.Corcoran@Sun.COM ACPI_STATUS
acpidev_resource_insert_dma(acpidev_resource_handle_t rhdl,int dma)32910394SMichael.Corcoran@Sun.COM acpidev_resource_insert_dma(acpidev_resource_handle_t rhdl, int dma)
33010394SMichael.Corcoran@Sun.COM {
33110394SMichael.Corcoran@Sun.COM ASSERT(rhdl != NULL);
33210394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_dma_count >= ACPIDEV_RES_DMA_MAX) {
33310394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_WARN,
334*12004Sjiang.liu@intel.com "!acpidev: too many DMA resources, max %u.",
33510394SMichael.Corcoran@Sun.COM ACPIDEV_RES_DMA_MAX);
33610394SMichael.Corcoran@Sun.COM return (AE_LIMIT);
33710394SMichael.Corcoran@Sun.COM }
33810394SMichael.Corcoran@Sun.COM rhdl->acpidev_dmap[rhdl->acpidev_dma_count] = dma;
33910394SMichael.Corcoran@Sun.COM rhdl->acpidev_dma_count++;
34010394SMichael.Corcoran@Sun.COM
34110394SMichael.Corcoran@Sun.COM return (AE_OK);
34210394SMichael.Corcoran@Sun.COM }
34310394SMichael.Corcoran@Sun.COM
34410394SMichael.Corcoran@Sun.COM ACPI_STATUS
acpidev_resource_get_dmas(acpidev_resource_handle_t rhdl,uint_t * dmap,uint_t * cntp)34510394SMichael.Corcoran@Sun.COM acpidev_resource_get_dmas(acpidev_resource_handle_t rhdl,
34610394SMichael.Corcoran@Sun.COM uint_t *dmap, uint_t *cntp)
34710394SMichael.Corcoran@Sun.COM {
34810394SMichael.Corcoran@Sun.COM uint_t i, j;
34910394SMichael.Corcoran@Sun.COM
35010394SMichael.Corcoran@Sun.COM ASSERT(rhdl != NULL);
35110394SMichael.Corcoran@Sun.COM ASSERT(cntp != NULL);
35210394SMichael.Corcoran@Sun.COM if (rhdl == NULL || cntp == NULL || (dmap == NULL && *cntp != 0)) {
35310394SMichael.Corcoran@Sun.COM return (AE_BAD_PARAMETER);
35410394SMichael.Corcoran@Sun.COM }
35510394SMichael.Corcoran@Sun.COM for (i = 0, j = 0; i < rhdl->acpidev_dma_count; i++) {
35610394SMichael.Corcoran@Sun.COM if (j < *cntp) {
35710394SMichael.Corcoran@Sun.COM dmap[j] = rhdl->acpidev_dmap[i];
35810394SMichael.Corcoran@Sun.COM }
35910394SMichael.Corcoran@Sun.COM j++;
36010394SMichael.Corcoran@Sun.COM }
36110394SMichael.Corcoran@Sun.COM if (j >= *cntp) {
36210394SMichael.Corcoran@Sun.COM *cntp = j;
36310394SMichael.Corcoran@Sun.COM return (AE_LIMIT);
36410394SMichael.Corcoran@Sun.COM } else {
36510394SMichael.Corcoran@Sun.COM *cntp = j;
36610394SMichael.Corcoran@Sun.COM return (AE_OK);
36710394SMichael.Corcoran@Sun.COM }
36810394SMichael.Corcoran@Sun.COM }
36910394SMichael.Corcoran@Sun.COM
37010394SMichael.Corcoran@Sun.COM uint_t
acpidev_resource_get_dma_count(acpidev_resource_handle_t rhdl)37110394SMichael.Corcoran@Sun.COM acpidev_resource_get_dma_count(acpidev_resource_handle_t rhdl)
37210394SMichael.Corcoran@Sun.COM {
37310394SMichael.Corcoran@Sun.COM ASSERT(rhdl != NULL);
37410394SMichael.Corcoran@Sun.COM return (rhdl->acpidev_dma_count);
37510394SMichael.Corcoran@Sun.COM }
37610394SMichael.Corcoran@Sun.COM
37710394SMichael.Corcoran@Sun.COM ACPI_STATUS
acpidev_resource_insert_irq(acpidev_resource_handle_t rhdl,int irq)37810394SMichael.Corcoran@Sun.COM acpidev_resource_insert_irq(acpidev_resource_handle_t rhdl, int irq)
37910394SMichael.Corcoran@Sun.COM {
38010394SMichael.Corcoran@Sun.COM ASSERT(rhdl != NULL);
38110394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_irq_count >= ACPIDEV_RES_IRQ_MAX) {
38210394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_WARN,
383*12004Sjiang.liu@intel.com "!acpidev: too many IRQ resources, max %u.",
38410394SMichael.Corcoran@Sun.COM ACPIDEV_RES_IRQ_MAX);
38510394SMichael.Corcoran@Sun.COM return (AE_LIMIT);
38610394SMichael.Corcoran@Sun.COM }
38710394SMichael.Corcoran@Sun.COM rhdl->acpidev_irqp[rhdl->acpidev_irq_count] = irq;
38810394SMichael.Corcoran@Sun.COM rhdl->acpidev_irq_count++;
38910394SMichael.Corcoran@Sun.COM
39010394SMichael.Corcoran@Sun.COM return (AE_OK);
39110394SMichael.Corcoran@Sun.COM }
39210394SMichael.Corcoran@Sun.COM
39310394SMichael.Corcoran@Sun.COM ACPI_STATUS
acpidev_resource_get_irqs(acpidev_resource_handle_t rhdl,uint_t * irqp,uint_t * cntp)39410394SMichael.Corcoran@Sun.COM acpidev_resource_get_irqs(acpidev_resource_handle_t rhdl,
39510394SMichael.Corcoran@Sun.COM uint_t *irqp, uint_t *cntp)
39610394SMichael.Corcoran@Sun.COM {
39710394SMichael.Corcoran@Sun.COM uint_t i, j;
39810394SMichael.Corcoran@Sun.COM
39910394SMichael.Corcoran@Sun.COM ASSERT(rhdl != NULL);
40010394SMichael.Corcoran@Sun.COM ASSERT(cntp != NULL);
40110394SMichael.Corcoran@Sun.COM if (rhdl == NULL || cntp == NULL || (irqp == NULL && *cntp != 0)) {
40210394SMichael.Corcoran@Sun.COM return (AE_BAD_PARAMETER);
40310394SMichael.Corcoran@Sun.COM }
40410394SMichael.Corcoran@Sun.COM for (i = 0, j = 0; i < rhdl->acpidev_irq_count; i++) {
40510394SMichael.Corcoran@Sun.COM if (j < *cntp) {
40610394SMichael.Corcoran@Sun.COM irqp[j] = rhdl->acpidev_irqp[i];
40710394SMichael.Corcoran@Sun.COM }
40810394SMichael.Corcoran@Sun.COM j++;
40910394SMichael.Corcoran@Sun.COM }
41010394SMichael.Corcoran@Sun.COM if (j >= *cntp) {
41110394SMichael.Corcoran@Sun.COM *cntp = j;
41210394SMichael.Corcoran@Sun.COM return (AE_LIMIT);
41310394SMichael.Corcoran@Sun.COM } else {
41410394SMichael.Corcoran@Sun.COM *cntp = j;
41510394SMichael.Corcoran@Sun.COM return (AE_OK);
41610394SMichael.Corcoran@Sun.COM }
41710394SMichael.Corcoran@Sun.COM }
41810394SMichael.Corcoran@Sun.COM
41910394SMichael.Corcoran@Sun.COM uint_t
acpidev_resource_get_irq_count(acpidev_resource_handle_t rhdl)42010394SMichael.Corcoran@Sun.COM acpidev_resource_get_irq_count(acpidev_resource_handle_t rhdl)
42110394SMichael.Corcoran@Sun.COM {
42210394SMichael.Corcoran@Sun.COM ASSERT(rhdl != NULL);
42310394SMichael.Corcoran@Sun.COM return (rhdl->acpidev_irq_count);
42410394SMichael.Corcoran@Sun.COM }
42510394SMichael.Corcoran@Sun.COM
42610394SMichael.Corcoran@Sun.COM static ACPI_STATUS
acpidev_resource_address64(acpidev_resource_handle_t rhdl,ACPI_RESOURCE_ADDRESS64 * addrp)42710394SMichael.Corcoran@Sun.COM acpidev_resource_address64(acpidev_resource_handle_t rhdl,
42810394SMichael.Corcoran@Sun.COM ACPI_RESOURCE_ADDRESS64 *addrp)
42910394SMichael.Corcoran@Sun.COM {
43010394SMichael.Corcoran@Sun.COM ACPI_STATUS rc = AE_OK;
43110394SMichael.Corcoran@Sun.COM uint_t high;
43210394SMichael.Corcoran@Sun.COM
43310394SMichael.Corcoran@Sun.COM ASSERT(addrp != NULL && rhdl != NULL);
43410394SMichael.Corcoran@Sun.COM if (addrp->AddressLength == 0) {
43510394SMichael.Corcoran@Sun.COM return (AE_OK);
43610394SMichael.Corcoran@Sun.COM }
43710394SMichael.Corcoran@Sun.COM
43810394SMichael.Corcoran@Sun.COM switch (addrp->ResourceType) {
43910394SMichael.Corcoran@Sun.COM case ACPI_MEMORY_RANGE:
44010394SMichael.Corcoran@Sun.COM high = ACPIDEV_REG_TYPE_MEMORY;
44110394SMichael.Corcoran@Sun.COM if (addrp->Decode == ACPI_SUB_DECODE) {
44210394SMichael.Corcoran@Sun.COM high |= ACPIDEV_REG_SUB_DEC;
44310394SMichael.Corcoran@Sun.COM }
44410394SMichael.Corcoran@Sun.COM if (addrp->Info.Mem.Translation) {
44510394SMichael.Corcoran@Sun.COM high |= ACPIDEV_REG_TRANSLATED;
44610394SMichael.Corcoran@Sun.COM }
44710394SMichael.Corcoran@Sun.COM if (addrp->Info.Mem.Caching == ACPI_NON_CACHEABLE_MEMORY) {
44810394SMichael.Corcoran@Sun.COM high |= ACPIDEV_REG_MEM_COHERENT_NC;
44910394SMichael.Corcoran@Sun.COM } else if (addrp->Info.Mem.Caching == ACPI_CACHABLE_MEMORY) {
45010394SMichael.Corcoran@Sun.COM high |= ACPIDEV_REG_MEM_COHERENT_CA;
45110394SMichael.Corcoran@Sun.COM } else if (addrp->Info.Mem.Caching ==
45210394SMichael.Corcoran@Sun.COM ACPI_WRITE_COMBINING_MEMORY) {
45310394SMichael.Corcoran@Sun.COM high |= ACPIDEV_REG_MEM_COHERENT_WC;
45410394SMichael.Corcoran@Sun.COM } else if (addrp->Info.Mem.Caching ==
45510394SMichael.Corcoran@Sun.COM ACPI_PREFETCHABLE_MEMORY) {
45610394SMichael.Corcoran@Sun.COM high |= ACPIDEV_REG_MEM_COHERENT_PF;
45710394SMichael.Corcoran@Sun.COM } else {
45810394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_WARN,
459*12004Sjiang.liu@intel.com "!acpidev: unknown memory caching type %u.",
46010394SMichael.Corcoran@Sun.COM addrp->Info.Mem.Caching);
46110394SMichael.Corcoran@Sun.COM rc = AE_ERROR;
46210394SMichael.Corcoran@Sun.COM break;
46310394SMichael.Corcoran@Sun.COM }
46410394SMichael.Corcoran@Sun.COM if (addrp->Info.Mem.WriteProtect == ACPI_READ_WRITE_MEMORY) {
46510394SMichael.Corcoran@Sun.COM high |= ACPIDEV_REG_MEM_WRITABLE;
46610394SMichael.Corcoran@Sun.COM }
46710394SMichael.Corcoran@Sun.COM
46810394SMichael.Corcoran@Sun.COM /* Generate 'reg' for producer. */
46910394SMichael.Corcoran@Sun.COM if (addrp->ProducerConsumer == ACPI_CONSUMER &&
47010394SMichael.Corcoran@Sun.COM rhdl->acpidev_consumer == B_TRUE) {
47110394SMichael.Corcoran@Sun.COM acpidev_regspec_t reg;
47210394SMichael.Corcoran@Sun.COM
47310394SMichael.Corcoran@Sun.COM reg.phys_hi = high;
47410394SMichael.Corcoran@Sun.COM reg.phys_mid = addrp->Minimum >> 32;
47510394SMichael.Corcoran@Sun.COM reg.phys_low = addrp->Minimum & 0xFFFFFFFF;
47610394SMichael.Corcoran@Sun.COM reg.size_hi = addrp->AddressLength >> 32;
47710394SMichael.Corcoran@Sun.COM reg.size_low = addrp->AddressLength & 0xFFFFFFFF;
47810394SMichael.Corcoran@Sun.COM rc = acpidev_resource_insert_reg(rhdl, ®);
47910394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(rc)) {
480*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
48110394SMichael.Corcoran@Sun.COM "insert regspec into resource handle.");
48210394SMichael.Corcoran@Sun.COM }
48310394SMichael.Corcoran@Sun.COM /* Generate 'ranges' for producer. */
48410394SMichael.Corcoran@Sun.COM } else if (addrp->ProducerConsumer == ACPI_PRODUCER &&
48510394SMichael.Corcoran@Sun.COM rhdl->acpidev_consumer == B_FALSE) {
48610394SMichael.Corcoran@Sun.COM uint64_t paddr;
48710394SMichael.Corcoran@Sun.COM acpidev_ranges_t range;
48810394SMichael.Corcoran@Sun.COM
48910394SMichael.Corcoran@Sun.COM range.child_hi = high;
49010394SMichael.Corcoran@Sun.COM range.child_mid = addrp->Minimum >> 32;
49110394SMichael.Corcoran@Sun.COM range.child_low = addrp->Minimum & 0xFFFFFFFF;
49210394SMichael.Corcoran@Sun.COM /* It's IO on parent side if Translation is true. */
49310394SMichael.Corcoran@Sun.COM if (addrp->Info.Mem.Translation) {
49410394SMichael.Corcoran@Sun.COM range.parent_hi = ACPIDEV_REG_TYPE_IO;
49510394SMichael.Corcoran@Sun.COM } else {
49610394SMichael.Corcoran@Sun.COM range.parent_hi = high;
49710394SMichael.Corcoran@Sun.COM }
49810394SMichael.Corcoran@Sun.COM paddr = addrp->Minimum + addrp->TranslationOffset;
49910394SMichael.Corcoran@Sun.COM range.parent_mid = paddr >> 32;
50010394SMichael.Corcoran@Sun.COM range.parent_low = paddr & 0xFFFFFFFF;
50110394SMichael.Corcoran@Sun.COM range.size_hi = addrp->AddressLength >> 32;
50210394SMichael.Corcoran@Sun.COM range.size_low = addrp->AddressLength & 0xFFFFFFFF;
50310394SMichael.Corcoran@Sun.COM rc = acpidev_resource_insert_range(rhdl, &range);
50410394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(rc)) {
505*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
50610394SMichael.Corcoran@Sun.COM "insert range into resource handle.");
50710394SMichael.Corcoran@Sun.COM }
50810394SMichael.Corcoran@Sun.COM }
50910394SMichael.Corcoran@Sun.COM break;
51010394SMichael.Corcoran@Sun.COM
51110394SMichael.Corcoran@Sun.COM case ACPI_IO_RANGE:
51210394SMichael.Corcoran@Sun.COM high = ACPIDEV_REG_TYPE_IO;
51310394SMichael.Corcoran@Sun.COM if (addrp->Decode == ACPI_SUB_DECODE) {
51410394SMichael.Corcoran@Sun.COM high |= ACPIDEV_REG_SUB_DEC;
51510394SMichael.Corcoran@Sun.COM }
51610394SMichael.Corcoran@Sun.COM if (addrp->Info.Io.Translation) {
51710394SMichael.Corcoran@Sun.COM high |= ACPIDEV_REG_TRANSLATED;
51810394SMichael.Corcoran@Sun.COM }
51910394SMichael.Corcoran@Sun.COM if (addrp->Info.Io.RangeType == ACPI_NON_ISA_ONLY_RANGES) {
52010394SMichael.Corcoran@Sun.COM high |= ACPIDEV_REG_IO_RANGE_NONISA;
52110394SMichael.Corcoran@Sun.COM } else if (addrp->Info.Io.RangeType == ACPI_ISA_ONLY_RANGES) {
52210394SMichael.Corcoran@Sun.COM high |= ACPIDEV_REG_IO_RANGE_ISA;
52310394SMichael.Corcoran@Sun.COM } else if (addrp->Info.Io.RangeType == ACPI_ENTIRE_RANGE) {
52410394SMichael.Corcoran@Sun.COM high |= ACPIDEV_REG_IO_RANGE_FULL;
52510394SMichael.Corcoran@Sun.COM } else {
52610394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_WARN,
527*12004Sjiang.liu@intel.com "!acpidev: unknown IO range type %u.",
52810394SMichael.Corcoran@Sun.COM addrp->Info.Io.RangeType);
52910394SMichael.Corcoran@Sun.COM rc = AE_ERROR;
53010394SMichael.Corcoran@Sun.COM break;
53110394SMichael.Corcoran@Sun.COM }
53210394SMichael.Corcoran@Sun.COM if (addrp->Info.Io.TranslationType == ACPI_SPARSE_TRANSLATION) {
53310394SMichael.Corcoran@Sun.COM high |= ACPIDEV_REG_IO_SPARSE;
53410394SMichael.Corcoran@Sun.COM }
53510394SMichael.Corcoran@Sun.COM
53610394SMichael.Corcoran@Sun.COM /* Generate 'reg' for producer. */
53710394SMichael.Corcoran@Sun.COM if (addrp->ProducerConsumer == ACPI_CONSUMER &&
53810394SMichael.Corcoran@Sun.COM rhdl->acpidev_consumer == B_TRUE) {
53910394SMichael.Corcoran@Sun.COM acpidev_regspec_t reg;
54010394SMichael.Corcoran@Sun.COM
54110394SMichael.Corcoran@Sun.COM reg.phys_hi = high;
54210394SMichael.Corcoran@Sun.COM reg.phys_mid = addrp->Minimum >> 32;
54310394SMichael.Corcoran@Sun.COM reg.phys_low = addrp->Minimum & 0xFFFFFFFF;
54410394SMichael.Corcoran@Sun.COM reg.size_hi = addrp->AddressLength >> 32;
54510394SMichael.Corcoran@Sun.COM reg.size_low = addrp->AddressLength & 0xFFFFFFFF;
54610394SMichael.Corcoran@Sun.COM rc = acpidev_resource_insert_reg(rhdl, ®);
54710394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(rc)) {
548*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
54910394SMichael.Corcoran@Sun.COM "insert regspec into resource handle.");
55010394SMichael.Corcoran@Sun.COM }
55110394SMichael.Corcoran@Sun.COM /* Generate 'ranges' for producer. */
55210394SMichael.Corcoran@Sun.COM } else if (addrp->ProducerConsumer == ACPI_PRODUCER &&
55310394SMichael.Corcoran@Sun.COM rhdl->acpidev_consumer == B_FALSE) {
55410394SMichael.Corcoran@Sun.COM uint64_t paddr;
55510394SMichael.Corcoran@Sun.COM acpidev_ranges_t range;
55610394SMichael.Corcoran@Sun.COM
55710394SMichael.Corcoran@Sun.COM range.child_hi = high;
55810394SMichael.Corcoran@Sun.COM range.child_mid = addrp->Minimum >> 32;
55910394SMichael.Corcoran@Sun.COM range.child_low = addrp->Minimum & 0xFFFFFFFF;
56010394SMichael.Corcoran@Sun.COM /* It's Memory on parent side if Translation is true. */
56110394SMichael.Corcoran@Sun.COM if (addrp->Info.Io.Translation) {
56210394SMichael.Corcoran@Sun.COM range.parent_hi = ACPIDEV_REG_TYPE_MEMORY;
56310394SMichael.Corcoran@Sun.COM } else {
56410394SMichael.Corcoran@Sun.COM range.parent_hi = high;
56510394SMichael.Corcoran@Sun.COM }
56610394SMichael.Corcoran@Sun.COM paddr = addrp->Minimum + addrp->TranslationOffset;
56710394SMichael.Corcoran@Sun.COM range.parent_mid = paddr >> 32;
56810394SMichael.Corcoran@Sun.COM range.parent_low = paddr & 0xFFFFFFFF;
56910394SMichael.Corcoran@Sun.COM range.size_hi = addrp->AddressLength >> 32;
57010394SMichael.Corcoran@Sun.COM range.size_low = addrp->AddressLength & 0xFFFFFFFF;
57110394SMichael.Corcoran@Sun.COM rc = acpidev_resource_insert_range(rhdl, &range);
57210394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(rc)) {
573*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
57410394SMichael.Corcoran@Sun.COM "insert range into resource handle.");
57510394SMichael.Corcoran@Sun.COM }
57610394SMichael.Corcoran@Sun.COM }
57710394SMichael.Corcoran@Sun.COM break;
57810394SMichael.Corcoran@Sun.COM
57910394SMichael.Corcoran@Sun.COM case ACPI_BUS_NUMBER_RANGE:
58010394SMichael.Corcoran@Sun.COM /* Only support producer of BUS. */
58110394SMichael.Corcoran@Sun.COM if (addrp->ProducerConsumer == ACPI_PRODUCER &&
58210394SMichael.Corcoran@Sun.COM rhdl->acpidev_consumer == B_FALSE) {
58310394SMichael.Corcoran@Sun.COM uint64_t end;
58410394SMichael.Corcoran@Sun.COM acpidev_bus_range_t bus;
58510394SMichael.Corcoran@Sun.COM
58610394SMichael.Corcoran@Sun.COM end = addrp->Minimum + addrp->AddressLength;
58710394SMichael.Corcoran@Sun.COM if (end < addrp->Minimum || end > UINT_MAX) {
588*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: bus range "
58910394SMichael.Corcoran@Sun.COM "in ADDRESS64 is invalid.");
59010394SMichael.Corcoran@Sun.COM rc = AE_ERROR;
59110394SMichael.Corcoran@Sun.COM break;
59210394SMichael.Corcoran@Sun.COM }
59310394SMichael.Corcoran@Sun.COM bus.bus_start = addrp->Minimum & 0xFFFFFFFF;
59410394SMichael.Corcoran@Sun.COM bus.bus_end = end & 0xFFFFFFFF;
59510394SMichael.Corcoran@Sun.COM ASSERT(bus.bus_start <= bus.bus_end);
59610394SMichael.Corcoran@Sun.COM rc = acpidev_resource_insert_bus(rhdl, &bus);
59710394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(rc)) {
598*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
59910394SMichael.Corcoran@Sun.COM "insert bus range into resource handle.");
60010394SMichael.Corcoran@Sun.COM }
60110394SMichael.Corcoran@Sun.COM }
60210394SMichael.Corcoran@Sun.COM break;
60310394SMichael.Corcoran@Sun.COM
60410394SMichael.Corcoran@Sun.COM default:
60510394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_WARN,
606*12004Sjiang.liu@intel.com "!acpidev: unknown resource type %u in ADDRESS64.",
60710394SMichael.Corcoran@Sun.COM addrp->ResourceType);
60810394SMichael.Corcoran@Sun.COM rc = AE_BAD_PARAMETER;
60910394SMichael.Corcoran@Sun.COM }
61010394SMichael.Corcoran@Sun.COM
61110394SMichael.Corcoran@Sun.COM return (rc);
61210394SMichael.Corcoran@Sun.COM }
61310394SMichael.Corcoran@Sun.COM
61410394SMichael.Corcoran@Sun.COM static ACPI_STATUS
acpidev_resource_walk_producer(ACPI_RESOURCE * rscp,void * ctxp)61510394SMichael.Corcoran@Sun.COM acpidev_resource_walk_producer(ACPI_RESOURCE *rscp, void *ctxp)
61610394SMichael.Corcoran@Sun.COM {
61710394SMichael.Corcoran@Sun.COM ACPI_STATUS rc = AE_OK;
61810394SMichael.Corcoran@Sun.COM acpidev_resource_handle_t rhdl;
61910394SMichael.Corcoran@Sun.COM
62010394SMichael.Corcoran@Sun.COM ASSERT(ctxp != NULL);
62110394SMichael.Corcoran@Sun.COM rhdl = (acpidev_resource_handle_t)ctxp;
62210394SMichael.Corcoran@Sun.COM ASSERT(rhdl->acpidev_consumer == B_FALSE);
62310394SMichael.Corcoran@Sun.COM
62410394SMichael.Corcoran@Sun.COM switch (rscp->Type) {
62510394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_DMA:
62610394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_IRQ:
62710394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
62810394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_FIXED_IO:
62910394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_MEMORY24:
63010394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_MEMORY32:
63110394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
63210394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
63310394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_VENDOR:
63410394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_NOTE,
635*12004Sjiang.liu@intel.com "!acpidev: unsupported producer resource type %u, ignored.",
63610394SMichael.Corcoran@Sun.COM rscp->Type);
63710394SMichael.Corcoran@Sun.COM break;
63810394SMichael.Corcoran@Sun.COM
63910394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_IO:
64010394SMichael.Corcoran@Sun.COM {
64110394SMichael.Corcoran@Sun.COM acpidev_ranges_t range;
64210394SMichael.Corcoran@Sun.COM
64310394SMichael.Corcoran@Sun.COM range.child_hi = ACPIDEV_REG_TYPE_IO;
64410394SMichael.Corcoran@Sun.COM range.child_hi |= ACPIDEV_REG_IO_RANGE_FULL;
64510394SMichael.Corcoran@Sun.COM if (rscp->Data.Io.IoDecode == ACPI_DECODE_16) {
64610394SMichael.Corcoran@Sun.COM range.child_hi |= ACPIDEV_REG_IO_DECODE16;
64710394SMichael.Corcoran@Sun.COM }
64810394SMichael.Corcoran@Sun.COM range.parent_hi = range.child_hi;
64910394SMichael.Corcoran@Sun.COM range.parent_mid = range.child_mid = 0;
65010394SMichael.Corcoran@Sun.COM range.parent_low = range.child_low = rscp->Data.Io.Minimum;
65110394SMichael.Corcoran@Sun.COM range.size_hi = 0;
65210394SMichael.Corcoran@Sun.COM range.size_low = rscp->Data.Io.AddressLength;
65310394SMichael.Corcoran@Sun.COM if ((uint64_t)range.child_low + range.size_low > UINT16_MAX) {
654*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid IO record, "
65510394SMichael.Corcoran@Sun.COM "IO max is out of range.");
65610394SMichael.Corcoran@Sun.COM rc = AE_ERROR;
65710394SMichael.Corcoran@Sun.COM } else if (range.size_low != 0) {
65810394SMichael.Corcoran@Sun.COM rc = acpidev_resource_insert_range(rhdl, &range);
65910394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(rc)) {
660*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
66110394SMichael.Corcoran@Sun.COM "insert range into resource handle.");
66210394SMichael.Corcoran@Sun.COM }
66310394SMichael.Corcoran@Sun.COM }
66410394SMichael.Corcoran@Sun.COM break;
66510394SMichael.Corcoran@Sun.COM }
66610394SMichael.Corcoran@Sun.COM
66710394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_ADDRESS16:
66810394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_ADDRESS32:
66910394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_ADDRESS64:
67010394SMichael.Corcoran@Sun.COM {
67110394SMichael.Corcoran@Sun.COM ACPI_RESOURCE_ADDRESS64 addr64;
67210394SMichael.Corcoran@Sun.COM
67310394SMichael.Corcoran@Sun.COM if (rscp->Data.Address.ProducerConsumer != ACPI_PRODUCER) {
674*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_NOTE, "!acpidev: producer encountered "
67510394SMichael.Corcoran@Sun.COM "a CONSUMER resource, ignored.");
67610394SMichael.Corcoran@Sun.COM } else if (ACPI_FAILURE(AcpiResourceToAddress64(rscp,
67710394SMichael.Corcoran@Sun.COM &addr64))) {
67810394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_WARN,
679*12004Sjiang.liu@intel.com "!acpidev: failed to convert resource to ADDR64.");
68010394SMichael.Corcoran@Sun.COM } else if (ACPI_FAILURE(rc = acpidev_resource_address64(rhdl,
68110394SMichael.Corcoran@Sun.COM &addr64))) {
68210394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_WARN,
683*12004Sjiang.liu@intel.com "!acpidev: failed to handle ADDRESS resource.");
68410394SMichael.Corcoran@Sun.COM }
68510394SMichael.Corcoran@Sun.COM break;
68610394SMichael.Corcoran@Sun.COM }
68710394SMichael.Corcoran@Sun.COM
68810394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
68910394SMichael.Corcoran@Sun.COM {
69010394SMichael.Corcoran@Sun.COM ACPI_RESOURCE_ADDRESS64 addr64;
69110394SMichael.Corcoran@Sun.COM
69210394SMichael.Corcoran@Sun.COM if (rscp->Data.ExtAddress64.ProducerConsumer != ACPI_PRODUCER) {
693*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_NOTE, "!acpidev: producer encountered "
69410394SMichael.Corcoran@Sun.COM "a CONSUMER resource, ignored.");
69510394SMichael.Corcoran@Sun.COM break;
69610394SMichael.Corcoran@Sun.COM }
69710394SMichael.Corcoran@Sun.COM
69810394SMichael.Corcoran@Sun.COM *(ACPI_RESOURCE_ADDRESS *)&addr64 = rscp->Data.Address;
69910394SMichael.Corcoran@Sun.COM addr64.Granularity = rscp->Data.ExtAddress64.Granularity;
70010394SMichael.Corcoran@Sun.COM addr64.Minimum = rscp->Data.ExtAddress64.Minimum;
70110394SMichael.Corcoran@Sun.COM addr64.Maximum = rscp->Data.ExtAddress64.Maximum;
70210394SMichael.Corcoran@Sun.COM addr64.TranslationOffset =
70310394SMichael.Corcoran@Sun.COM rscp->Data.ExtAddress64.TranslationOffset;
70410394SMichael.Corcoran@Sun.COM addr64.AddressLength = rscp->Data.ExtAddress64.AddressLength;
70510394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(rc = acpidev_resource_address64(rhdl,
70610394SMichael.Corcoran@Sun.COM &addr64))) {
70710394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_WARN,
708*12004Sjiang.liu@intel.com "!acpidev: failed to handle EXTADDRESS resource.");
70910394SMichael.Corcoran@Sun.COM }
71010394SMichael.Corcoran@Sun.COM break;
71110394SMichael.Corcoran@Sun.COM }
71210394SMichael.Corcoran@Sun.COM
71310394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_START_DEPENDENT:
71410394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_END_DEPENDENT:
715*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_NOTE, "!acpidev: producer encountered "
71610394SMichael.Corcoran@Sun.COM "START_DEPENDENT or END_DEPENDENT tag, ignored.");
71710394SMichael.Corcoran@Sun.COM break;
71810394SMichael.Corcoran@Sun.COM
71910394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_END_TAG:
72010394SMichael.Corcoran@Sun.COM /* Finish walking when we encounter END_TAG. */
72110394SMichael.Corcoran@Sun.COM rc = AE_CTRL_TERMINATE;
72210394SMichael.Corcoran@Sun.COM break;
72310394SMichael.Corcoran@Sun.COM
72410394SMichael.Corcoran@Sun.COM default:
72510394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_NOTE,
726*12004Sjiang.liu@intel.com "!acpidev: unknown ACPI resource type %u, ignored.",
72710394SMichael.Corcoran@Sun.COM rscp->Type);
72810394SMichael.Corcoran@Sun.COM break;
72910394SMichael.Corcoran@Sun.COM }
73010394SMichael.Corcoran@Sun.COM
73110394SMichael.Corcoran@Sun.COM return (rc);
73210394SMichael.Corcoran@Sun.COM }
73310394SMichael.Corcoran@Sun.COM
73410394SMichael.Corcoran@Sun.COM static ACPI_STATUS
acpidev_resource_walk_consumer(ACPI_RESOURCE * rscp,void * ctxp)73510394SMichael.Corcoran@Sun.COM acpidev_resource_walk_consumer(ACPI_RESOURCE *rscp, void *ctxp)
73610394SMichael.Corcoran@Sun.COM {
73710394SMichael.Corcoran@Sun.COM ACPI_STATUS rc = AE_OK;
73810394SMichael.Corcoran@Sun.COM acpidev_resource_handle_t rhdl;
73910394SMichael.Corcoran@Sun.COM
74010394SMichael.Corcoran@Sun.COM ASSERT(ctxp != NULL);
74110394SMichael.Corcoran@Sun.COM rhdl = (acpidev_resource_handle_t)ctxp;
74210394SMichael.Corcoran@Sun.COM ASSERT(rhdl->acpidev_consumer == B_TRUE);
74310394SMichael.Corcoran@Sun.COM
74410394SMichael.Corcoran@Sun.COM switch (rscp->Type) {
74510394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_MEMORY24:
74610394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
74710394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_VENDOR:
74810394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_NOTE,
749*12004Sjiang.liu@intel.com "!acpidev: unsupported consumer resource type %u, ignored.",
75010394SMichael.Corcoran@Sun.COM rscp->Type);
75110394SMichael.Corcoran@Sun.COM break;
75210394SMichael.Corcoran@Sun.COM
75310394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
75410394SMichael.Corcoran@Sun.COM {
75510394SMichael.Corcoran@Sun.COM int i;
75610394SMichael.Corcoran@Sun.COM
75710394SMichael.Corcoran@Sun.COM if (rscp->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) {
758*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_NOTE, "!acpidev: consumer encountered "
75910394SMichael.Corcoran@Sun.COM "a PRODUCER resource, ignored.");
76010394SMichael.Corcoran@Sun.COM break;
76110394SMichael.Corcoran@Sun.COM }
76210394SMichael.Corcoran@Sun.COM for (i = 0; i < rscp->Data.ExtendedIrq.InterruptCount; i++) {
76310394SMichael.Corcoran@Sun.COM if (ACPI_SUCCESS(acpidev_resource_insert_irq(rhdl,
76410394SMichael.Corcoran@Sun.COM rscp->Data.ExtendedIrq.Interrupts[i]))) {
76510394SMichael.Corcoran@Sun.COM continue;
76610394SMichael.Corcoran@Sun.COM }
767*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to insert"
76810394SMichael.Corcoran@Sun.COM "Extended IRQ into resource handle.");
76910394SMichael.Corcoran@Sun.COM rc = AE_ERROR;
77010394SMichael.Corcoran@Sun.COM break;
77110394SMichael.Corcoran@Sun.COM }
77210394SMichael.Corcoran@Sun.COM break;
77310394SMichael.Corcoran@Sun.COM }
77410394SMichael.Corcoran@Sun.COM
77510394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_IRQ:
77610394SMichael.Corcoran@Sun.COM {
77710394SMichael.Corcoran@Sun.COM int i;
77810394SMichael.Corcoran@Sun.COM
77910394SMichael.Corcoran@Sun.COM for (i = 0; i < rscp->Data.Irq.InterruptCount; i++) {
78010394SMichael.Corcoran@Sun.COM if (ACPI_SUCCESS(acpidev_resource_insert_irq(rhdl,
78110394SMichael.Corcoran@Sun.COM rscp->Data.Irq.Interrupts[i]))) {
78210394SMichael.Corcoran@Sun.COM continue;
78310394SMichael.Corcoran@Sun.COM }
784*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to insert"
78510394SMichael.Corcoran@Sun.COM "IRQ into resource handle.");
78610394SMichael.Corcoran@Sun.COM rc = AE_ERROR;
78710394SMichael.Corcoran@Sun.COM break;
78810394SMichael.Corcoran@Sun.COM }
78910394SMichael.Corcoran@Sun.COM break;
79010394SMichael.Corcoran@Sun.COM }
79110394SMichael.Corcoran@Sun.COM
79210394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_DMA:
79310394SMichael.Corcoran@Sun.COM {
79410394SMichael.Corcoran@Sun.COM int i;
79510394SMichael.Corcoran@Sun.COM
79610394SMichael.Corcoran@Sun.COM for (i = 0; i < rscp->Data.Dma.ChannelCount; i++) {
79710394SMichael.Corcoran@Sun.COM if (ACPI_SUCCESS(acpidev_resource_insert_dma(rhdl,
79810394SMichael.Corcoran@Sun.COM rscp->Data.Dma.Channels[i]))) {
79910394SMichael.Corcoran@Sun.COM continue;
80010394SMichael.Corcoran@Sun.COM }
801*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to insert"
80210394SMichael.Corcoran@Sun.COM "dma into resource handle.");
80310394SMichael.Corcoran@Sun.COM rc = AE_ERROR;
80410394SMichael.Corcoran@Sun.COM break;
80510394SMichael.Corcoran@Sun.COM }
80610394SMichael.Corcoran@Sun.COM break;
80710394SMichael.Corcoran@Sun.COM }
80810394SMichael.Corcoran@Sun.COM
80910394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_IO:
81010394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_FIXED_IO:
81110394SMichael.Corcoran@Sun.COM {
81210394SMichael.Corcoran@Sun.COM acpidev_regspec_t reg;
81310394SMichael.Corcoran@Sun.COM
81410394SMichael.Corcoran@Sun.COM reg.phys_hi = ACPIDEV_REG_TYPE_IO;
81510394SMichael.Corcoran@Sun.COM reg.phys_hi |= ACPIDEV_REG_IO_RANGE_FULL;
81610394SMichael.Corcoran@Sun.COM if (rscp->Type == ACPI_RESOURCE_TYPE_IO) {
81710394SMichael.Corcoran@Sun.COM if (rscp->Data.Io.IoDecode == ACPI_DECODE_16) {
81810394SMichael.Corcoran@Sun.COM reg.phys_hi |= ACPIDEV_REG_IO_DECODE16;
81910394SMichael.Corcoran@Sun.COM }
82010394SMichael.Corcoran@Sun.COM reg.phys_low = rscp->Data.Io.Minimum;
82110394SMichael.Corcoran@Sun.COM reg.size_low = rscp->Data.Io.AddressLength;
82210394SMichael.Corcoran@Sun.COM } else {
82310394SMichael.Corcoran@Sun.COM reg.phys_hi |= ACPIDEV_REG_IO_DECODE16;
82410394SMichael.Corcoran@Sun.COM reg.phys_low = rscp->Data.FixedIo.Address;
82510394SMichael.Corcoran@Sun.COM reg.size_low = rscp->Data.FixedIo.AddressLength;
82610394SMichael.Corcoran@Sun.COM }
82710394SMichael.Corcoran@Sun.COM reg.phys_mid = 0;
82810394SMichael.Corcoran@Sun.COM reg.size_hi = 0;
82910394SMichael.Corcoran@Sun.COM if ((uint64_t)reg.phys_low + reg.size_low > UINT16_MAX) {
830*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid IO/FIXEDIO "
83110394SMichael.Corcoran@Sun.COM "record, IO max is out of range.");
83210394SMichael.Corcoran@Sun.COM rc = AE_ERROR;
83310394SMichael.Corcoran@Sun.COM } else if (reg.size_low != 0) {
83410394SMichael.Corcoran@Sun.COM rc = acpidev_resource_insert_reg(rhdl, ®);
83510394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(rc)) {
836*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
83710394SMichael.Corcoran@Sun.COM "insert reg into resource handle.");
83810394SMichael.Corcoran@Sun.COM }
83910394SMichael.Corcoran@Sun.COM }
84010394SMichael.Corcoran@Sun.COM break;
84110394SMichael.Corcoran@Sun.COM }
84210394SMichael.Corcoran@Sun.COM
84310394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_MEMORY32:
84410394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
84510394SMichael.Corcoran@Sun.COM {
84610394SMichael.Corcoran@Sun.COM acpidev_regspec_t reg;
84710394SMichael.Corcoran@Sun.COM
84810394SMichael.Corcoran@Sun.COM reg.phys_hi = ACPIDEV_REG_TYPE_MEMORY;
84910394SMichael.Corcoran@Sun.COM reg.phys_hi |= ACPIDEV_REG_MEM_COHERENT_CA;
85010394SMichael.Corcoran@Sun.COM if (rscp->Type == ACPI_RESOURCE_TYPE_MEMORY32) {
85110394SMichael.Corcoran@Sun.COM if (rscp->Data.Memory32.WriteProtect ==
85210394SMichael.Corcoran@Sun.COM ACPI_READ_WRITE_MEMORY) {
85310394SMichael.Corcoran@Sun.COM reg.phys_hi |= ACPIDEV_REG_MEM_WRITABLE;
85410394SMichael.Corcoran@Sun.COM }
85510394SMichael.Corcoran@Sun.COM reg.phys_low = rscp->Data.Memory32.Minimum;
85610394SMichael.Corcoran@Sun.COM reg.size_low = rscp->Data.Memory32.AddressLength;
85710394SMichael.Corcoran@Sun.COM } else {
85810394SMichael.Corcoran@Sun.COM if (rscp->Data.FixedMemory32.WriteProtect ==
85910394SMichael.Corcoran@Sun.COM ACPI_READ_WRITE_MEMORY) {
86010394SMichael.Corcoran@Sun.COM reg.phys_hi |= ACPIDEV_REG_MEM_WRITABLE;
86110394SMichael.Corcoran@Sun.COM }
86210394SMichael.Corcoran@Sun.COM reg.phys_low = rscp->Data.FixedMemory32.Address;
86310394SMichael.Corcoran@Sun.COM reg.size_low = rscp->Data.FixedMemory32.AddressLength;
86410394SMichael.Corcoran@Sun.COM }
86510394SMichael.Corcoran@Sun.COM reg.phys_mid = 0;
86610394SMichael.Corcoran@Sun.COM reg.size_hi = 0;
86710394SMichael.Corcoran@Sun.COM if ((uint64_t)reg.phys_low + reg.size_low > UINT32_MAX) {
86810394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_WARN,
869*12004Sjiang.liu@intel.com "!acpidev: invalid MEMORY32/FIXEDMEMORY32 record, "
87010394SMichael.Corcoran@Sun.COM "memory max is out of range.");
87110394SMichael.Corcoran@Sun.COM rc = AE_ERROR;
87210394SMichael.Corcoran@Sun.COM } else if (reg.size_low != 0) {
87310394SMichael.Corcoran@Sun.COM rc = acpidev_resource_insert_reg(rhdl, ®);
87410394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(rc)) {
875*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
87610394SMichael.Corcoran@Sun.COM "insert reg into resource handle.");
87710394SMichael.Corcoran@Sun.COM }
87810394SMichael.Corcoran@Sun.COM }
87910394SMichael.Corcoran@Sun.COM break;
88010394SMichael.Corcoran@Sun.COM }
88110394SMichael.Corcoran@Sun.COM
88210394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_ADDRESS16:
88310394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_ADDRESS32:
88410394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_ADDRESS64:
88510394SMichael.Corcoran@Sun.COM {
88610394SMichael.Corcoran@Sun.COM ACPI_RESOURCE_ADDRESS64 addr64;
88710394SMichael.Corcoran@Sun.COM
88810394SMichael.Corcoran@Sun.COM if (rscp->Data.Address.ProducerConsumer != ACPI_CONSUMER) {
889*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_NOTE, "!acpidev: consumer encountered "
89010394SMichael.Corcoran@Sun.COM "a PRODUCER resource, ignored.");
89110394SMichael.Corcoran@Sun.COM } else if (ACPI_FAILURE(AcpiResourceToAddress64(rscp,
89210394SMichael.Corcoran@Sun.COM &addr64))) {
89310394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_WARN,
894*12004Sjiang.liu@intel.com "!acpidev: failed to convert resource to ADDR64.");
89510394SMichael.Corcoran@Sun.COM } else if (ACPI_FAILURE(rc = acpidev_resource_address64(rhdl,
89610394SMichael.Corcoran@Sun.COM &addr64))) {
89710394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_WARN,
898*12004Sjiang.liu@intel.com "!acpidev: failed to handle ADDRESS resource.");
89910394SMichael.Corcoran@Sun.COM }
90010394SMichael.Corcoran@Sun.COM break;
90110394SMichael.Corcoran@Sun.COM }
90210394SMichael.Corcoran@Sun.COM
90310394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
90410394SMichael.Corcoran@Sun.COM {
90510394SMichael.Corcoran@Sun.COM ACPI_RESOURCE_ADDRESS64 addr64;
90610394SMichael.Corcoran@Sun.COM
90710394SMichael.Corcoran@Sun.COM if (rscp->Data.ExtAddress64.ProducerConsumer != ACPI_CONSUMER) {
908*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_NOTE, "!acpidev: consumer encountered "
90910394SMichael.Corcoran@Sun.COM "a PRODUCER resource, ignored.");
91010394SMichael.Corcoran@Sun.COM break;
91110394SMichael.Corcoran@Sun.COM }
91210394SMichael.Corcoran@Sun.COM
91310394SMichael.Corcoran@Sun.COM *(ACPI_RESOURCE_ADDRESS *)&addr64 = rscp->Data.Address;
91410394SMichael.Corcoran@Sun.COM addr64.Granularity = rscp->Data.ExtAddress64.Granularity;
91510394SMichael.Corcoran@Sun.COM addr64.Minimum = rscp->Data.ExtAddress64.Minimum;
91610394SMichael.Corcoran@Sun.COM addr64.Maximum = rscp->Data.ExtAddress64.Maximum;
91710394SMichael.Corcoran@Sun.COM addr64.TranslationOffset =
91810394SMichael.Corcoran@Sun.COM rscp->Data.ExtAddress64.TranslationOffset;
91910394SMichael.Corcoran@Sun.COM addr64.AddressLength = rscp->Data.ExtAddress64.AddressLength;
92010394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(rc = acpidev_resource_address64(rhdl,
92110394SMichael.Corcoran@Sun.COM &addr64))) {
92210394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_WARN,
923*12004Sjiang.liu@intel.com "!acpidev: failed to handle EXTADDRESS resource.");
92410394SMichael.Corcoran@Sun.COM }
92510394SMichael.Corcoran@Sun.COM break;
92610394SMichael.Corcoran@Sun.COM }
92710394SMichael.Corcoran@Sun.COM
92810394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_START_DEPENDENT:
92910394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_END_DEPENDENT:
930*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_NOTE, "!acpidev: consumer encountered "
93110394SMichael.Corcoran@Sun.COM "START_DEPENDENT or END_DEPENDENT tag, ignored.");
93210394SMichael.Corcoran@Sun.COM break;
93310394SMichael.Corcoran@Sun.COM
93410394SMichael.Corcoran@Sun.COM case ACPI_RESOURCE_TYPE_END_TAG:
93510394SMichael.Corcoran@Sun.COM /* Finish walking when we encounter END_TAG. */
93610394SMichael.Corcoran@Sun.COM rc = AE_CTRL_TERMINATE;
93710394SMichael.Corcoran@Sun.COM break;
93810394SMichael.Corcoran@Sun.COM
93910394SMichael.Corcoran@Sun.COM default:
94010394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_NOTE,
941*12004Sjiang.liu@intel.com "!acpidev: unknown ACPI resource type %u, ignored.",
94210394SMichael.Corcoran@Sun.COM rscp->Type);
94310394SMichael.Corcoran@Sun.COM break;
94410394SMichael.Corcoran@Sun.COM }
94510394SMichael.Corcoran@Sun.COM
94610394SMichael.Corcoran@Sun.COM return (rc);
94710394SMichael.Corcoran@Sun.COM }
94810394SMichael.Corcoran@Sun.COM
94910394SMichael.Corcoran@Sun.COM ACPI_STATUS
acpidev_resource_walk(ACPI_HANDLE hdl,char * method,boolean_t consumer,acpidev_resource_handle_t * rhdlp)95010394SMichael.Corcoran@Sun.COM acpidev_resource_walk(ACPI_HANDLE hdl, char *method,
95110394SMichael.Corcoran@Sun.COM boolean_t consumer, acpidev_resource_handle_t *rhdlp)
95210394SMichael.Corcoran@Sun.COM {
95310394SMichael.Corcoran@Sun.COM ACPI_STATUS rc = AE_OK;
95410394SMichael.Corcoran@Sun.COM ACPI_HANDLE mhdl = NULL;
95510394SMichael.Corcoran@Sun.COM acpidev_resource_handle_t rhdl = NULL;
95610394SMichael.Corcoran@Sun.COM
95710394SMichael.Corcoran@Sun.COM ASSERT(hdl != NULL);
95810394SMichael.Corcoran@Sun.COM ASSERT(method != NULL);
95910394SMichael.Corcoran@Sun.COM ASSERT(rhdlp != NULL);
96010394SMichael.Corcoran@Sun.COM if (hdl == NULL) {
96110394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_WARN,
962*12004Sjiang.liu@intel.com "!acpidev: hdl is NULL in acpidev_resource_walk().");
96310394SMichael.Corcoran@Sun.COM return (AE_BAD_PARAMETER);
96410394SMichael.Corcoran@Sun.COM } else if (method == NULL) {
96510394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_WARN,
966*12004Sjiang.liu@intel.com "!acpidev: method is NULL in acpidev_resource_walk().");
96710394SMichael.Corcoran@Sun.COM return (AE_BAD_PARAMETER);
96810394SMichael.Corcoran@Sun.COM } else if (rhdlp == NULL) {
969*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: resource handle ptr is NULL "
97010394SMichael.Corcoran@Sun.COM "in acpidev_resource_walk().");
97110394SMichael.Corcoran@Sun.COM return (AE_BAD_PARAMETER);
97210394SMichael.Corcoran@Sun.COM }
97310394SMichael.Corcoran@Sun.COM
97410394SMichael.Corcoran@Sun.COM /* Check whether method exists under object. */
97510394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(AcpiGetHandle(hdl, method, &mhdl))) {
97610394SMichael.Corcoran@Sun.COM char *objname = acpidev_get_object_name(hdl);
97710394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_NOTE,
978*12004Sjiang.liu@intel.com "!acpidev: method %s doesn't exist under %s",
97910394SMichael.Corcoran@Sun.COM method, objname);
98011225SDana.Myers@Sun.COM acpidev_free_object_name(objname);
98110394SMichael.Corcoran@Sun.COM return (AE_NOT_FOUND);
98210394SMichael.Corcoran@Sun.COM }
98310394SMichael.Corcoran@Sun.COM
98410394SMichael.Corcoran@Sun.COM /* Walk all resources. */
98510394SMichael.Corcoran@Sun.COM rhdl = acpidev_resource_handle_alloc(consumer);
98610394SMichael.Corcoran@Sun.COM if (consumer) {
98710394SMichael.Corcoran@Sun.COM rc = AcpiWalkResources(hdl, method,
98810394SMichael.Corcoran@Sun.COM acpidev_resource_walk_consumer, rhdl);
98910394SMichael.Corcoran@Sun.COM } else {
99010394SMichael.Corcoran@Sun.COM rc = AcpiWalkResources(hdl, method,
99110394SMichael.Corcoran@Sun.COM acpidev_resource_walk_producer, rhdl);
99210394SMichael.Corcoran@Sun.COM }
99310394SMichael.Corcoran@Sun.COM if (ACPI_SUCCESS(rc)) {
99410394SMichael.Corcoran@Sun.COM *rhdlp = rhdl;
99510394SMichael.Corcoran@Sun.COM } else {
99610394SMichael.Corcoran@Sun.COM acpidev_resource_handle_free(rhdl);
99710394SMichael.Corcoran@Sun.COM }
99810394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(rc)) {
99910394SMichael.Corcoran@Sun.COM char *objname = acpidev_get_object_name(hdl);
1000*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to walk resource from "
1001*12004Sjiang.liu@intel.com "method %s under %s.", method, objname);
100211225SDana.Myers@Sun.COM acpidev_free_object_name(objname);
100310394SMichael.Corcoran@Sun.COM }
100410394SMichael.Corcoran@Sun.COM
100510394SMichael.Corcoran@Sun.COM return (rc);
100610394SMichael.Corcoran@Sun.COM }
100710394SMichael.Corcoran@Sun.COM
100810394SMichael.Corcoran@Sun.COM ACPI_STATUS
acpidev_resource_process(acpidev_walk_info_t * infop,boolean_t consumer)100910394SMichael.Corcoran@Sun.COM acpidev_resource_process(acpidev_walk_info_t *infop, boolean_t consumer)
101010394SMichael.Corcoran@Sun.COM {
101110394SMichael.Corcoran@Sun.COM ACPI_STATUS rc;
101210394SMichael.Corcoran@Sun.COM char path[MAXPATHLEN];
101310394SMichael.Corcoran@Sun.COM acpidev_resource_handle_t rhdl = NULL;
101410394SMichael.Corcoran@Sun.COM
101510394SMichael.Corcoran@Sun.COM ASSERT(infop != NULL);
101610394SMichael.Corcoran@Sun.COM if (infop == NULL) {
1017*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameter "
101810394SMichael.Corcoran@Sun.COM "in acpidev_resource_process().");
101910394SMichael.Corcoran@Sun.COM return (AE_BAD_PARAMETER);
102010394SMichael.Corcoran@Sun.COM }
102110394SMichael.Corcoran@Sun.COM
102210394SMichael.Corcoran@Sun.COM /* Walk all resources. */
102310394SMichael.Corcoran@Sun.COM (void) ddi_pathname(infop->awi_dip, path);
102410394SMichael.Corcoran@Sun.COM rc = acpidev_resource_walk(infop->awi_hdl, METHOD_NAME__CRS,
102510394SMichael.Corcoran@Sun.COM consumer, &rhdl);
102610394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(rc)) {
102710394SMichael.Corcoran@Sun.COM ACPIDEV_DEBUG(CE_WARN,
1028*12004Sjiang.liu@intel.com "!acpidev: failed to walk ACPI resources of %s(%s).",
102910394SMichael.Corcoran@Sun.COM path, infop->awi_name);
103010394SMichael.Corcoran@Sun.COM return (rc);
103110394SMichael.Corcoran@Sun.COM }
103210394SMichael.Corcoran@Sun.COM
103310394SMichael.Corcoran@Sun.COM if (consumer) {
103410394SMichael.Corcoran@Sun.COM /* Create device properties for consumer. */
103510394SMichael.Corcoran@Sun.COM
103610394SMichael.Corcoran@Sun.COM /* Create 'reg' and 'assigned-addresses' properties. */
103710394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_reg_count > 0 &&
103810394SMichael.Corcoran@Sun.COM ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
103910394SMichael.Corcoran@Sun.COM "reg", (int *)rhdl->acpidev_regp,
104010394SMichael.Corcoran@Sun.COM rhdl->acpidev_reg_count * sizeof (acpidev_regspec_t) /
104110394SMichael.Corcoran@Sun.COM sizeof (int)) != NDI_SUCCESS) {
1042*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
104310394SMichael.Corcoran@Sun.COM "'reg' property for %s.", path);
104410394SMichael.Corcoran@Sun.COM rc = AE_ERROR;
104510394SMichael.Corcoran@Sun.COM goto out;
104610394SMichael.Corcoran@Sun.COM }
104710394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_reg_count > 0 &&
104810394SMichael.Corcoran@Sun.COM ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
104910394SMichael.Corcoran@Sun.COM "assigned-addresses", (int *)rhdl->acpidev_regp,
105010394SMichael.Corcoran@Sun.COM rhdl->acpidev_reg_count * sizeof (acpidev_regspec_t) /
105110394SMichael.Corcoran@Sun.COM sizeof (int)) != NDI_SUCCESS) {
1052*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
105310394SMichael.Corcoran@Sun.COM "'assigned-addresses' property for %s.", path);
105410394SMichael.Corcoran@Sun.COM rc = AE_ERROR;
105510394SMichael.Corcoran@Sun.COM goto out;
105610394SMichael.Corcoran@Sun.COM }
105710394SMichael.Corcoran@Sun.COM
105810394SMichael.Corcoran@Sun.COM /* Create 'interrupts' property. */
105910394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_irq_count > 0 &&
106010394SMichael.Corcoran@Sun.COM ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
106110394SMichael.Corcoran@Sun.COM "interrupts", (int *)rhdl->acpidev_irqp,
106210394SMichael.Corcoran@Sun.COM rhdl->acpidev_irq_count) != NDI_SUCCESS) {
1063*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
106410394SMichael.Corcoran@Sun.COM "'interrupts' property for %s.", path);
106510394SMichael.Corcoran@Sun.COM rc = AE_ERROR;
106610394SMichael.Corcoran@Sun.COM goto out;
106710394SMichael.Corcoran@Sun.COM }
106810394SMichael.Corcoran@Sun.COM
106910394SMichael.Corcoran@Sun.COM /* Create 'dma-channels' property. */
107010394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_dma_count > 0 &&
107110394SMichael.Corcoran@Sun.COM ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
107210394SMichael.Corcoran@Sun.COM "dma-channels", (int *)rhdl->acpidev_dmap,
107310394SMichael.Corcoran@Sun.COM rhdl->acpidev_dma_count) != NDI_SUCCESS) {
1074*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
107510394SMichael.Corcoran@Sun.COM "'dma-channels' property for %s.", path);
107610394SMichael.Corcoran@Sun.COM rc = AE_ERROR;
107710394SMichael.Corcoran@Sun.COM goto out;
107810394SMichael.Corcoran@Sun.COM }
107910394SMichael.Corcoran@Sun.COM
108010394SMichael.Corcoran@Sun.COM } else {
108110394SMichael.Corcoran@Sun.COM /* Create device properties for producer. */
108210394SMichael.Corcoran@Sun.COM
108310394SMichael.Corcoran@Sun.COM /* Create 'ranges' property. */
108410394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_range_count > 0 &&
108510394SMichael.Corcoran@Sun.COM ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
108610394SMichael.Corcoran@Sun.COM "ranges", (int *)rhdl->acpidev_rangep,
108710394SMichael.Corcoran@Sun.COM rhdl->acpidev_range_count * sizeof (acpidev_ranges_t) /
108810394SMichael.Corcoran@Sun.COM sizeof (int)) != NDI_SUCCESS) {
1089*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
109010394SMichael.Corcoran@Sun.COM "'ranges' property for %s.", path);
109110394SMichael.Corcoran@Sun.COM rc = AE_ERROR;
109210394SMichael.Corcoran@Sun.COM goto out;
109310394SMichael.Corcoran@Sun.COM }
109410394SMichael.Corcoran@Sun.COM
109510394SMichael.Corcoran@Sun.COM /* Create 'bus-range' property. */
109610394SMichael.Corcoran@Sun.COM if (rhdl->acpidev_bus_count > 0 &&
109710394SMichael.Corcoran@Sun.COM ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
109810394SMichael.Corcoran@Sun.COM "bus-range", (int *)rhdl->acpidev_busp,
109910394SMichael.Corcoran@Sun.COM rhdl->acpidev_bus_count * sizeof (acpidev_bus_range_t) /
110010394SMichael.Corcoran@Sun.COM sizeof (int)) != NDI_SUCCESS) {
1101*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
110210394SMichael.Corcoran@Sun.COM "'bus-range' property for %s.", path);
110310394SMichael.Corcoran@Sun.COM rc = AE_ERROR;
110410394SMichael.Corcoran@Sun.COM goto out;
110510394SMichael.Corcoran@Sun.COM }
110610394SMichael.Corcoran@Sun.COM }
110710394SMichael.Corcoran@Sun.COM
110810394SMichael.Corcoran@Sun.COM out:
110910394SMichael.Corcoran@Sun.COM /* Free resources allocated by acpidev_resource_walk. */
111010394SMichael.Corcoran@Sun.COM acpidev_resource_handle_free(rhdl);
111110394SMichael.Corcoran@Sun.COM
111210394SMichael.Corcoran@Sun.COM return (rc);
111310394SMichael.Corcoran@Sun.COM }
1114