> Perhaps acpiec should use aml_parse_resource() instead of the hand-crafted
> parsing it does right now? That would solve the second problem, at
> least.
Like this?
To the OP can you please test this diff on your system and let me know
if it fixes things?
I will move on to adding support for hardware reduced machines once this
diff is in and I see an actual ACPI dump that has GPIO AML code.
Index: acpidev.h
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpidev.h,v
retrieving revision 1.38
diff -u -p -u -p -r1.38 acpidev.h
--- acpidev.h 12 Aug 2015 05:59:54 -0000 1.38
+++ acpidev.h 18 Oct 2016 10:22:41 -0000
@@ -323,10 +323,12 @@ struct acpiec_softc {
int sc_ecbusy;
/* command/status register */
+ bus_size_t sc_ec_sc;
bus_space_tag_t sc_cmd_bt;
bus_space_handle_t sc_cmd_bh;
/* data register */
+ bus_size_t sc_ec_data;
bus_space_tag_t sc_data_bt;
bus_space_handle_t sc_data_bh;
Index: acpiec.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpiec.c,v
retrieving revision 1.54
diff -u -p -u -p -r1.54 acpiec.c
--- acpiec.c 23 Aug 2016 18:26:21 -0000 1.54
+++ acpiec.c 18 Oct 2016 10:22:41 -0000
@@ -407,13 +407,53 @@ acpiec_getregister(const u_int8_t *buf,
}
int
+acpiec_parse_resources(union acpi_resource *crs, void *arg)
+{
+ struct acpiec_softc *sc = arg;
+ int type = AML_CRSTYPE(crs);
+
+ static int argno = 0;
+
+ switch (argno) {
+ case 1:
+ if (type != SR_IOPORT) {
+ printf("%s: Unexpected resource #%d type %d\n",
+ DEVNAME(sc), argno, type);
+ break;
+ }
+ sc->sc_data_bt = sc->sc_acpi->sc_iot;
+ sc->sc_ec_data = crs->sr_ioport._max;
+ break;
+ case 2:
+ if (type != SR_IOPORT) {
+ printf("%s: Unexpected resource #%d type %d\n",
+ DEVNAME(sc), argno, type);
+ break;
+ }
+ sc->sc_cmd_bt = sc->sc_acpi->sc_iot;
+ sc->sc_ec_sc = crs->sr_ioport._max;
+ break;
+ case 3:
+ if (!sc->sc_acpi->sc_hw_reduced) {
+ printf("%s: Not running on HW-Reduced ACPI type %d\n",
+ DEVNAME(sc), type);
+ break;
+ }
+ /* XXX: handle SCI GPIO */
+ break;
+ default:
+ printf("%s: invalid resource #%d type %d\n",
+ DEVNAME(sc), argno, type);
+ }
+
+ argno++;
+ 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;
@@ -423,11 +463,17 @@ acpiec_getcrs(struct acpiec_softc *sc, s
/* 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;
+ if (ecdt->ec_control.address_space_id == GAS_SYSTEM_IOSPACE)
+ sc->sc_cmd_bt = sc->sc_acpi->sc_iot;
+ else
+ sc->sc_cmd_bt = sc->sc_acpi->sc_memt;
+ sc->sc_ec_sc = ecdt->ec_control.address;
+
+ if (ecdt->ec_data.address_space_id == GAS_SYSTEM_IOSPACE)
+ sc->sc_data_bt = sc->sc_acpi->sc_iot;
+ else
+ sc->sc_data_bt = sc->sc_acpi->sc_memt;
+ sc->sc_ec_data = ecdt->ec_data.address;
/* Get devnode from header */
sc->sc_devnode = aml_searchname(&aml_root, ecdt->ec_id);
@@ -456,60 +502,24 @@ acpiec_getcrs(struct acpiec_softc *sc, s
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);
+ aml_parse_resource(&res, acpiec_parse_resources, sc);
+ aml_freevalue(&res);
+ if (sc->sc_ec_data == 0 || sc->sc_ec_sc == 0) {
+ printf("%s: failed to read from _CRS\n", DEVNAME(sc));
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);
+ DEVNAME(sc), sc->sc_ec_data, sc->sc_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)) {
+ if (bus_space_map(sc->sc_cmd_bt, sc->sc_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)) {
+ if (bus_space_map(sc->sc_data_bt, sc->sc_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);