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;

Reply via email to