int acpiec_getcrs(struct acpiec_softc *sc, struct acpi_attach_args *aa) { struct aml_value res; bus_size_t ec_sc, ec_data; int type1, type2; char *buf; int size, ret; if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_GPE", 0, NULL, &res)) { dnprintf(10, "%s: no _GPE\n", DEVNAME(sc)); return (1); } sc->sc_gpe = aml_val2int(&res); aml_freevalue(&res); if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_CRS", 0, NULL, &res)) { dnprintf(10, "%s: no _CRS\n", DEVNAME(sc)); return (1); } /* Parse CRS to get control and data registers */ if (res.type != AML_OBJTYPE_BUFFER) { dnprintf(10, "%s: unknown _CRS type %d\n", DEVNAME(sc), res.type); aml_freevalue(&res); return (1); } size = res.length; buf = res.v_buffer; ret = acpiec_getregister(buf, size, &type1, &ec_data); if (ret <= 0) { dnprintf(10, "%s: failed to read DATA from _CRS\n", DEVNAME(sc)); aml_freevalue(&res); return (1); } buf += ret; size -= ret; ret = acpiec_getregister(buf, size, &type2, &ec_sc); if (ret <= 0) { dnprintf(10, "%s: failed to read S/C from _CRS\n", DEVNAME(sc)); aml_freevalue(&res); return (1); } buf += ret; size -= ret; if (size != 2 || *buf != RES_TYPE_ENDTAG) { dnprintf(10, "%s: no _CRS end tag\n", DEVNAME(sc)); aml_freevalue(&res); return (1); } aml_freevalue(&res); /* XXX: todo - validate _CRS checksum? */ dnprintf(10, "%s: Data: 0x%x, S/C: 0x%x\n", DEVNAME(sc), ec_data, ec_sc); if (type1 == GAS_SYSTEM_IOSPACE) sc->sc_cmd_bt = aa->aaa_iot; else sc->sc_cmd_bt = aa->aaa_memt; if (bus_space_map(sc->sc_cmd_bt, ec_sc, 1, 0, &sc->sc_cmd_bh)) { dnprintf(10, "%s: failed to map S/C reg.\n", DEVNAME(sc)); return (1); } if (type2 == GAS_SYSTEM_IOSPACE) sc->sc_data_bt = aa->aaa_iot; else sc->sc_data_bt = aa->aaa_memt; if (bus_space_map(sc->sc_data_bt, ec_data, 1, 0, &sc->sc_data_bh)) { dnprintf(10, "%s: failed to map DATA reg.\n", DEVNAME(sc)); bus_space_unmap(sc->sc_cmd_bt, sc->sc_cmd_bh, 1); return (1); } return (0); }
int acpiec_getcrs(struct acpiec_softc *sc, struct acpi_attach_args *aa) { struct aml_value res; bus_size_t ec_sc, ec_data; int dtype, ctype; char *buf; int size, ret; int64_t gpe; struct acpi_ecdt *ecdt = aa->aaa_table; extern struct aml_node aml_root; /* Check if this is ECDT initialization */ if (ecdt) { /* Get GPE, Data and Control segments */ sc->sc_gpe = ecdt->gpe_bit; ctype = ecdt->ec_control.address_space_id; ec_sc = ecdt->ec_control.address; dtype = ecdt->ec_data.address_space_id; ec_data = ecdt->ec_data.address; /* Get devnode from header */ sc->sc_devnode = aml_searchname(&aml_root, ecdt->ec_id); goto ecdtdone; } if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "_GPE", 0, NULL, &gpe)) { dnprintf(10, "%s: no _GPE\n", DEVNAME(sc)); return (1); } sc->sc_gpe = gpe; if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_CRS", 0, NULL, &res)) { dnprintf(10, "%s: no _CRS\n", DEVNAME(sc)); return (1); } /* Parse CRS to get control and data registers */ if (res.type != AML_OBJTYPE_BUFFER) { dnprintf(10, "%s: unknown _CRS type %d\n", DEVNAME(sc), res.type); aml_freevalue(&res); return (1); } size = res.length; buf = res.v_buffer; ret = acpiec_getregister(buf, size, &dtype, &ec_data); if (ret <= 0) { dnprintf(10, "%s: failed to read DATA from _CRS\n", DEVNAME(sc)); aml_freevalue(&res); return (1); } buf += ret; size -= ret; ret = acpiec_getregister(buf, size, &ctype, &ec_sc); if (ret <= 0) { dnprintf(10, "%s: failed to read S/C from _CRS\n", DEVNAME(sc)); aml_freevalue(&res); return (1); } buf += ret; size -= ret; if (size != 2 || *buf != RES_TYPE_ENDTAG) { dnprintf(10, "%s: no _CRS end tag\n", DEVNAME(sc)); aml_freevalue(&res); return (1); } aml_freevalue(&res); /* XXX: todo - validate _CRS checksum? */ ecdtdone: dnprintf(10, "%s: Data: 0x%lx, S/C: 0x%lx\n", DEVNAME(sc), ec_data, ec_sc); if (ctype == GAS_SYSTEM_IOSPACE) sc->sc_cmd_bt = aa->aaa_iot; else sc->sc_cmd_bt = aa->aaa_memt; if (bus_space_map(sc->sc_cmd_bt, ec_sc, 1, 0, &sc->sc_cmd_bh)) { dnprintf(10, "%s: failed to map S/C reg.\n", DEVNAME(sc)); return (1); } if (dtype == GAS_SYSTEM_IOSPACE) sc->sc_data_bt = aa->aaa_iot; else sc->sc_data_bt = aa->aaa_memt; if (bus_space_map(sc->sc_data_bt, ec_data, 1, 0, &sc->sc_data_bh)) { dnprintf(10, "%s: failed to map DATA reg.\n", DEVNAME(sc)); bus_space_unmap(sc->sc_cmd_bt, sc->sc_cmd_bh, 1); return (1); } return (0); }