On arm64 systems, IPMI can actually attach using mmio. The diff below implements this. It also sets the IPMI revision based on the _SRV method if present.
I can't actually test this properly. The firmware I'm using on my od1000 has the IPMI device in its ACPI tables. But I'm 99% certain there isn't an actual BMC in the machine. There should be on in the od3000 though. Anyway, with my diff I get: ipmi0 at acpi0: version 2.0 interface KCS membase 0xe0010000/8 spacing 4 instead of: ipmi0 at acpi0ipmi0: Unexpected resource #0 type 134 ipmi0: Unexpected resource #1 type 134 ipmi0: invalid resource #2 type 137 (ift 1) ipmi0: incomplete resources (ift 1) which looks correct, but then I get: ipmi0: sendcmd fails ipmi0: get header fails ipmi0: no SDRs IPMI disabled Which is expected if there is no BMC. Would be good to have this tested on an x86 where IPMI attaches through ACPI. ok? Index: dev/acpi/ipmi_acpi.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/ipmi_acpi.c,v retrieving revision 1.2 diff -u -p -r1.2 ipmi_acpi.c --- dev/acpi/ipmi_acpi.c 13 Aug 2019 18:31:23 -0000 1.2 +++ dev/acpi/ipmi_acpi.c 21 Dec 2019 11:30:22 -0000 @@ -46,8 +46,8 @@ struct ipmi_acpi_softc { struct aml_node *sc_devnode; int sc_ift; + int sc_srv; - bus_space_tag_t sc_iot; bus_size_t sc_iobase; int sc_iospacing; char sc_iotype; @@ -76,7 +76,7 @@ ipmi_acpi_attach(struct device *parent, struct acpi_attach_args *aa = aux; struct ipmi_attach_args ia; struct aml_value res; - int64_t ift; + int64_t ift, srv = 0; int rc; sc->sc_acpi = (struct acpi_softc *)parent; @@ -89,6 +89,9 @@ ipmi_acpi_attach(struct device *parent, } sc->sc_ift = ift; + aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "_SRV", 0, NULL, &srv); + sc->sc_srv = srv; + if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_CRS", 0, NULL, &res)) { printf(": no _CRS method\n"); return; @@ -103,17 +106,17 @@ ipmi_acpi_attach(struct device *parent, aml_parse_resource(&res, ipmi_acpi_parse_crs, sc); aml_freevalue(&res); - if (sc->sc_iot == NULL) { + if (sc->sc_iotype == 0) { printf("%s: incomplete resources (ift %d)\n", DEVNAME(sc), sc->sc_ift); return; } memset(&ia, 0, sizeof(ia)); - ia.iaa_iot = sc->sc_iot; - ia.iaa_memt = sc->sc_iot; + ia.iaa_iot = sc->sc_acpi->sc_iot; + ia.iaa_memt = sc->sc_acpi->sc_memt; ia.iaa_if_type = sc->sc_ift; - ia.iaa_if_rev = 0; + ia.iaa_if_rev = (sc->sc_srv >> 4); ia.iaa_if_irq = -1; ia.iaa_if_irqlvl = 0; ia.iaa_if_iospacing = sc->sc_iospacing; @@ -128,32 +131,52 @@ ipmi_acpi_parse_crs(int crsidx, union ac { struct ipmi_acpi_softc *sc = arg; int type = AML_CRSTYPE(crs); + bus_size_t addr; + char iotype; + + switch (type) { + case SR_IOPORT: + addr = crs->sr_ioport._max; + iotype = 'i'; + break; + case LR_MEM32FIXED: + addr = crs->lr_m32fixed._bas; + iotype = 'm'; + break; + case LR_EXTIRQ: + /* Ignore for now. */ + return 0; + default: + printf("\n%s: unexpected resource #%d type %d", + DEVNAME(sc), crsidx, type); + sc->sc_iotype = 0; + return -1; + } switch (crsidx) { case 0: - if (type != SR_IOPORT) { - printf("%s: Unexpected resource #%d type %d\n", - DEVNAME(sc), crsidx, type); - break; - } - sc->sc_iot = sc->sc_acpi->sc_iot; - sc->sc_iobase = crs->sr_ioport._max; + sc->sc_iobase = addr; sc->sc_iospacing = 1; - sc->sc_iotype = 'i'; + sc->sc_iotype = iotype; break; case 1: - if (type != SR_IOPORT) { - printf("%s: Unexpected resource #%d type %d\n", + if (sc->sc_iotype != iotype) { + printf("\n%s: unexpected resource #%d type %d\n", DEVNAME(sc), crsidx, type); - break; + sc->sc_iotype = 0; + return -1; + } + if (addr <= sc->sc_iobase) { + sc->sc_iotype = 0; + return -1; } - if (crs->sr_ioport._max <= sc->sc_iobase) - break; - sc->sc_iospacing = crs->sr_ioport._max - sc->sc_iobase; + sc->sc_iospacing = addr - sc->sc_iobase; break; default: - printf("%s: invalid resource #%d type %d (ift %d)\n", + printf("\n%s: invalid resource #%d type %d (ift %d)", DEVNAME(sc), crsidx, type, sc->sc_ift); + sc->sc_iotype = 0; + return -1; } return 0;