diff options
Diffstat (limited to 'hw/i386/acpi-build.c')
-rw-r--r-- | hw/i386/acpi-build.c | 120 |
1 files changed, 22 insertions, 98 deletions
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 5d4bd2b..4967aa7 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -724,120 +724,44 @@ static Aml *aml_pci_pdsm(void) return method; } -/** - * build_prt_entry: - * @link_name: link name for PCI route entry - * - * build AML package containing a PCI route entry for @link_name - */ -static Aml *build_prt_entry(const char *link_name) -{ - Aml *a_zero = aml_int(0); - Aml *pkg = aml_package(4); - aml_append(pkg, a_zero); - aml_append(pkg, a_zero); - aml_append(pkg, aml_name("%s", link_name)); - aml_append(pkg, a_zero); - return pkg; -} - /* - * initialize_route - Initialize the interrupt routing rule - * through a specific LINK: - * if (lnk_idx == idx) - * route using link 'link_name' - */ -static Aml *initialize_route(Aml *route, const char *link_name, - Aml *lnk_idx, int idx) -{ - Aml *if_ctx = aml_if(aml_equal(lnk_idx, aml_int(idx))); - Aml *pkg = build_prt_entry(link_name); - - aml_append(if_ctx, aml_store(pkg, route)); - - return if_ctx; -} - -/* - * build_prt - Define interrupt rounting rules + * build_prt - Define interrupt routing rules * * Returns an array of 128 routes, one for each device, * based on device location. * The main goal is to equally distribute the interrupts * over the 4 existing ACPI links (works only for i440fx). - * The hash function is (slot + pin) & 3 -> "LNK[D|A|B|C]". + * The hash function is: (slot + pin) & 3 -> "LNK[D|A|B|C]". * */ static Aml *build_prt(bool is_pci0_prt) { - Aml *method, *while_ctx, *pin, *res; + const int nroutes = 128; + Aml *rt_pkg, *method; + int pin; method = aml_method("_PRT", 0, AML_NOTSERIALIZED); - res = aml_local(0); - pin = aml_local(1); - aml_append(method, aml_store(aml_package(128), res)); - aml_append(method, aml_store(aml_int(0), pin)); + rt_pkg = aml_varpackage(nroutes); - /* while (pin < 128) */ - while_ctx = aml_while(aml_lless(pin, aml_int(128))); - { - Aml *slot = aml_local(2); - Aml *lnk_idx = aml_local(3); - Aml *route = aml_local(4); - - /* slot = pin >> 2 */ - aml_append(while_ctx, - aml_store(aml_shiftright(pin, aml_int(2), NULL), slot)); - /* lnk_idx = (slot + pin) & 3 */ - aml_append(while_ctx, - aml_store(aml_and(aml_add(pin, slot, NULL), aml_int(3), NULL), - lnk_idx)); - - /* route[2] = "LNK[D|A|B|C]", selection based on pin % 3 */ - aml_append(while_ctx, initialize_route(route, "LNKD", lnk_idx, 0)); - if (is_pci0_prt) { - Aml *if_device_1, *if_pin_4, *else_pin_4; - - /* device 1 is the power-management device, needs SCI */ - if_device_1 = aml_if(aml_equal(lnk_idx, aml_int(1))); - { - if_pin_4 = aml_if(aml_equal(pin, aml_int(4))); - { - aml_append(if_pin_4, - aml_store(build_prt_entry("LNKS"), route)); - } - aml_append(if_device_1, if_pin_4); - else_pin_4 = aml_else(); - { - aml_append(else_pin_4, - aml_store(build_prt_entry("LNKA"), route)); - } - aml_append(if_device_1, else_pin_4); - } - aml_append(while_ctx, if_device_1); + for (pin = 0; pin < nroutes; pin++) { + Aml *pkg = aml_package(4); + int slot = pin >> 2; + + aml_append(pkg, aml_int((slot << 16) | 0xFFFF)); + aml_append(pkg, aml_int(pin & 3)); + /* device 1 is the power-management device, needs SCI */ + if (is_pci0_prt && pin == 4) { + aml_append(pkg, aml_name("%s", "LNKS")); } else { - aml_append(while_ctx, initialize_route(route, "LNKA", lnk_idx, 1)); + static const char link_name[][5] = {"LNKD", "LNKA", "LNKB", "LNKC"}; + int hash = (slot + pin) & 3; + aml_append(pkg, aml_name("%s", link_name[hash])); } - aml_append(while_ctx, initialize_route(route, "LNKB", lnk_idx, 2)); - aml_append(while_ctx, initialize_route(route, "LNKC", lnk_idx, 3)); - - /* route[0] = 0x[slot]FFFF */ - aml_append(while_ctx, - aml_store(aml_or(aml_shiftleft(slot, aml_int(16)), aml_int(0xFFFF), - NULL), - aml_index(route, aml_int(0)))); - /* route[1] = pin & 3 */ - aml_append(while_ctx, - aml_store(aml_and(pin, aml_int(3), NULL), - aml_index(route, aml_int(1)))); - /* res[pin] = route */ - aml_append(while_ctx, aml_store(route, aml_index(res, pin))); - /* pin++ */ - aml_append(while_ctx, aml_increment(pin)); + aml_append(pkg, aml_int(0)); + aml_append(rt_pkg, pkg); } - aml_append(method, while_ctx); - /* return res*/ - aml_append(method, aml_return(res)); + + aml_append(method, aml_return(rt_pkg)); return method; } |