On Wed, Mar 14, 2018 at 02:58:14PM +0100, Patrick Wildt wrote:
> Hi,
> 
> I have some hardware where IPMI is not found using the SMBIOS table
> anymore but using ACPI.  These show up in the dmesg as
> 
> "IPI0001" at acpi0 not configured
> 
> The driver basically reads the information out of ACPI and then runs
> the normal IPMI attach code.  It's an attachment driver, no magic.
> 
> This is so far tested with the KSC interface type, I don't have any
> hardware (that I know of) with the other interface types.  But it
> should complain if things don't work.
> 
> With this I get proper sensor data out of IPMI.
> 
> Comments?
> 
> Patrick
> 
> diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC
> index f76f70697c2..0f9dbedfc71 100644
> --- a/sys/arch/amd64/conf/GENERIC
> +++ b/sys/arch/amd64/conf/GENERIC
> @@ -66,6 +66,7 @@ acpicbkbd*  at acpi?
>  acpials*     at acpi?
>  tpm*         at acpi?
>  acpihve*     at acpi?
> +ipmi*                at acpi? disable

This should be ipmi0, otherwise on machines where IPMI is defined in
both tables it tries to attach twice and will fail.  With ipmi0 there
can only be one.  Verified on some other hardware I found.

Found thanks to jsg@.

>  
>  mpbios0              at bios0
>  
> diff --git a/sys/dev/acpi/acpireg.h b/sys/dev/acpi/acpireg.h
> index 130df5c97b2..2c6612d2b3f 100644
> --- a/sys/dev/acpi/acpireg.h
> +++ b/sys/dev/acpi/acpireg.h
> @@ -760,5 +760,6 @@ struct acpi_ivrs {
>  #define ACPI_DEV_IOSA        "ACPI000B"      /* IO SAPIC Device */
>  #define ACPI_DEV_THZ "THERMALZONE"   /* Thermal Zone */
>  #define ACPI_DEV_FFB "FIXEDBUTTON"   /* Fixed Feature Button */
> +#define ACPI_DEV_IPMI        "IPI0001"       /* IPMI */
>  
>  #endif       /* !_DEV_ACPI_ACPIREG_H_ */
> diff --git a/sys/dev/acpi/files.acpi b/sys/dev/acpi/files.acpi
> index 44edff19d6f..e22d64673ec 100644
> --- a/sys/dev/acpi/files.acpi
> +++ b/sys/dev/acpi/files.acpi
> @@ -154,3 +154,7 @@ file      dev/acpi/acpihve.c              acpihve
>  device       acpisbs
>  attach       acpisbs at acpi
>  file dev/acpi/acpisbs.c              acpisbs
> +
> +# IPMI
> +attach       ipmi at acpi with ipmi_acpi
> +file dev/acpi/ipmi_acpi.c            ipmi_acpi
> diff --git a/sys/dev/acpi/ipmi_acpi.c b/sys/dev/acpi/ipmi_acpi.c
> new file mode 100644
> index 00000000000..df5a7bbf06e
> --- /dev/null
> +++ b/sys/dev/acpi/ipmi_acpi.c
> @@ -0,0 +1,161 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2018 Patrick Wildt <patr...@blueri.se>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/param.h>
> +#include <sys/signalvar.h>
> +#include <sys/systm.h>
> +#include <sys/device.h>
> +#include <sys/malloc.h>
> +
> +#include <machine/bus.h>
> +#include <machine/apmvar.h>
> +
> +#include <dev/acpi/acpireg.h>
> +#include <dev/acpi/acpivar.h>
> +#include <dev/acpi/acpidev.h>
> +#include <dev/acpi/amltypes.h>
> +#include <dev/acpi/dsdt.h>
> +#undef DEVNAME
> +
> +#include <dev/ipmivar.h>
> +
> +#define DEVNAME(s)           ((s)->sc.sc_dev.dv_xname)
> +
> +int  ipmi_acpi_match(struct device *, void *, void *);
> +void ipmi_acpi_attach(struct device *, struct device *, void *);
> +int  ipmi_acpi_parse_crs(int, union acpi_resource *, void *);
> +
> +extern void ipmi_attach(struct device *, struct device *, void *);
> +
> +struct ipmi_acpi_softc {
> +     struct ipmi_softc        sc;
> +
> +     struct acpi_softc       *sc_acpi;
> +     struct aml_node         *sc_devnode;
> +
> +     int                      sc_ift;
> +
> +     bus_space_tag_t          sc_iot;
> +     bus_size_t               sc_iobase;
> +     int                      sc_iospacing;
> +     char                     sc_iotype;
> +};
> +
> +struct cfattach ipmi_acpi_ca = {
> +     sizeof(struct ipmi_acpi_softc), ipmi_acpi_match, ipmi_acpi_attach,
> +};
> +
> +const char *ipmi_acpi_hids[] = { ACPI_DEV_IPMI, NULL };
> +
> +int
> +ipmi_acpi_match(struct device *parent, void *match, void *aux)
> +{
> +     struct acpi_attach_args *aa = aux;
> +     struct cfdata *cf = match;
> +
> +     /* sanity */
> +     return (acpi_matchhids(aa, ipmi_acpi_hids, cf->cf_driver->cd_name));
> +}
> +
> +void
> +ipmi_acpi_attach(struct device *parent, struct device *self, void *aux)
> +{
> +     struct ipmi_acpi_softc *sc = (struct ipmi_acpi_softc *)self;
> +     struct acpi_attach_args *aa = aux;
> +     struct ipmi_attach_args ia;
> +     struct aml_value res;
> +     int64_t ift;
> +     int rc;
> +
> +     sc->sc_acpi = (struct acpi_softc *)parent;
> +     sc->sc_devnode = aa->aaa_node;
> +
> +     rc = aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "_IFT", 0, NULL, 
> &ift);
> +     if (rc) {
> +             printf(": no _IFT\n");
> +             return;
> +     }
> +     sc->sc_ift = ift;
> +
> +     if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_CRS", 0, NULL, &res)) {
> +             printf(": no _CRS method\n");
> +             return;
> +     }
> +     if (res.type != AML_OBJTYPE_BUFFER) {
> +             printf(": invalid _CRS object (type %d len %d)\n",
> +                 res.type, res.length);
> +             aml_freevalue(&res);
> +             return;
> +     }
> +
> +     aml_parse_resource(&res, ipmi_acpi_parse_crs, sc);
> +     aml_freevalue(&res);
> +
> +     if (sc->sc_iot == NULL) {
> +             printf("%s: incomplete resources (ift %d)\n",
> +                 DEVNAME(sc), sc->sc_ift);
> +             return;
> +     }
> +
> +     ia.iaa_iot = sc->sc_iot;
> +     ia.iaa_memt = sc->sc_iot;
> +     ia.iaa_if_type = sc->sc_ift;
> +     ia.iaa_if_rev = 0;
> +     ia.iaa_if_irq = -1;
> +     ia.iaa_if_irqlvl = 0;
> +     ia.iaa_if_iospacing = sc->sc_iospacing;
> +     ia.iaa_if_iobase = sc->sc_iobase;
> +     ia.iaa_if_iotype = sc->sc_iotype;
> +
> +     ipmi_attach(parent, self, &ia);
> +}
> +
> +int
> +ipmi_acpi_parse_crs(int crsidx, union acpi_resource *crs, void *arg)
> +{
> +     struct ipmi_acpi_softc *sc = arg;
> +     int type = AML_CRSTYPE(crs);
> +
> +     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_iospacing = 1;
> +             sc->sc_iotype = 'i';
> +             break;
> +     case 1:
> +             if (type != SR_IOPORT) {
> +                     printf("%s: Unexpected resource #%d type %d\n",
> +                         DEVNAME(sc), crsidx, type);
> +                     break;
> +             }
> +             if (crs->sr_ioport._max <= sc->sc_iobase)
> +                     break;
> +             sc->sc_iospacing = crs->sr_ioport._max - sc->sc_iobase;
> +             break;
> +     default:
> +             printf("%s: invalid resource #%d type %d (ift %d)\n",
> +                 DEVNAME(sc), crsidx, type, sc->sc_ift);
> +     }
> +
> +     return 0;
> +}

Reply via email to