The branch stable/13 has been updated by ae:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=53380074a162833e2fdca11908e702ea7b7541f2

commit 53380074a162833e2fdca11908e702ea7b7541f2
Author:     Andrey V. Elsukov <a...@freebsd.org>
AuthorDate: 2023-06-07 09:30:47 +0000
Commit:     Andrey V. Elsukov <a...@freebsd.org>
CommitDate: 2023-06-25 18:34:28 +0000

    ipmi: add Block Transfer interface support
    
    Reviewed by:    ambrisko
    Obtained from:  Yandex LLC
    Sponsored by:   Yandex LLC
    Differential Revision:  https://reviews.freebsd.org/D40421
    
    (cherry picked from commit 1f166509895dd90fcaaa08b557f9bc106e3f7e71)
---
 sys/conf/files.arm64       |   1 +
 sys/conf/files.x86         |   1 +
 sys/dev/ipmi/ipmi_acpi.c   |  19 +--
 sys/dev/ipmi/ipmi_bt.c     | 296 +++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/ipmi/ipmi_isa.c    |  19 +--
 sys/dev/ipmi/ipmi_pci.c    |  28 +++--
 sys/dev/ipmi/ipmi_smbios.c |   1 +
 sys/dev/ipmi/ipmivars.h    |  19 ++-
 sys/modules/ipmi/Makefile  |   2 +-
 9 files changed, 353 insertions(+), 33 deletions(-)

diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index 6b96de28128d..df7bbe002f5c 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -259,6 +259,7 @@ dev/iicbus/twsi/twsi.c                              
optional twsi fdt
 
 dev/ipmi/ipmi.c                                        optional ipmi
 dev/ipmi/ipmi_acpi.c                           optional ipmi acpi
+dev/ipmi/ipmi_bt.c                             optional ipmi
 dev/ipmi/ipmi_kcs.c                            optional ipmi
 dev/ipmi/ipmi_smic.c                           optional ipmi
 
diff --git a/sys/conf/files.x86 b/sys/conf/files.x86
index 07ecb9fe1e01..bc7dbccaf16d 100644
--- a/sys/conf/files.x86
+++ b/sys/conf/files.x86
@@ -171,6 +171,7 @@ dev/iommu/iommu_gas.c               optional        acpi 
iommu pci
 dev/ipmi/ipmi.c                        optional        ipmi
 dev/ipmi/ipmi_acpi.c           optional        ipmi acpi
 dev/ipmi/ipmi_isa.c            optional        ipmi isa
+dev/ipmi/ipmi_bt.c             optional        ipmi
 dev/ipmi/ipmi_kcs.c            optional        ipmi
 dev/ipmi/ipmi_smic.c           optional        ipmi
 dev/ipmi/ipmi_smbus.c          optional        ipmi smbus
diff --git a/sys/dev/ipmi/ipmi_acpi.c b/sys/dev/ipmi/ipmi_acpi.c
index 7c34f49075af..9d92608e8f1d 100644
--- a/sys/dev/ipmi/ipmi_acpi.c
+++ b/sys/dev/ipmi/ipmi_acpi.c
@@ -95,16 +95,17 @@ ipmi_acpi_attach(device_t dev)
 
        switch (interface_type) {
        case KCS_MODE:
-               count = 2;
+               count = IPMI_IF_KCS_NRES;
                mode = "KCS";
                break;
        case SMIC_MODE:
-               count = 3;
+               count = IPMI_IF_SMIC_NRES;
                mode = "SMIC";
                break;
        case BT_MODE:
-               device_printf(dev, "BT interface not supported\n");
-               return (ENXIO);
+               count = IPMI_IF_BT_NRES;
+               mode = "BT";
+               break;
        case SSIF_MODE:
                if (ACPI_FAILURE(acpi_GetInteger(devh, "_ADR", &flags)))
                        return (ENXIO);
@@ -174,18 +175,20 @@ ipmi_acpi_attach(device_t dev)
         * We assume an alignment of 1 byte as currently the IPMI spec
         * doesn't provide any way to determine the alignment via ACPI.
         */
+       error = ENXIO;
        switch (interface_type) {
        case KCS_MODE:
                error = ipmi_kcs_attach(sc);
-               if (error)
-                       goto bad;
                break;
        case SMIC_MODE:
                error = ipmi_smic_attach(sc);
-               if (error)
-                       goto bad;
+               break;
+       case BT_MODE:
+               error = ipmi_bt_attach(sc);
                break;
        }
+       if (error)
+               goto bad;
        error = ipmi_attach(dev);
        if (error)
                goto bad;
diff --git a/sys/dev/ipmi/ipmi_bt.c b/sys/dev/ipmi/ipmi_bt.c
new file mode 100644
index 000000000000..0f970d966731
--- /dev/null
+++ b/sys/dev/ipmi/ipmi_bt.c
@@ -0,0 +1,296 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Yandex LLC
+ * Copyright (c) 2023 Andrey V. Elsukov <a...@freebsd.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/eventhandler.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/selinfo.h>
+#include <machine/bus.h>
+
+#include <sys/ipmi.h>
+#include <dev/ipmi/ipmivars.h>
+
+/*
+ * BT interface
+ */
+
+#define        DMSG0(sc, fmt, ...)     do {                            \
+       device_printf((sc)->ipmi_dev, "BT: %s: " fmt "\n",      \
+           __func__, ## __VA_ARGS__);                          \
+} while (0)
+
+#define        DMSGV(...)              if (bootverbose) {              \
+       DMSG0(__VA_ARGS__);                                     \
+}
+
+#ifdef IPMI_BT_DEBUG
+#define        DMSG(...)               DMSG0(__VA_ARGS__)
+#else
+#define        DMSG(...)
+#endif
+
+#define        BT_IO_BASE              0xe4
+
+#define        BT_CTRL_REG             0
+#define          BT_C_CLR_WR_PTR       (1L << 0)
+#define          BT_C_CLR_RD_PTR       (1L << 1)
+#define          BT_C_H2B_ATN          (1L << 2)
+#define          BT_C_B2H_ATN          (1L << 3)
+#define          BT_C_SMS_ATN          (1L << 4)
+#define          BT_C_OEM0             (1L << 5)
+#define          BT_C_H_BUSY           (1L << 6)
+#define          BT_C_B_BUSY           (1L << 7)
+
+#define        BT_CTRL_BITS            
"\20\01CLR_WR_PTR\02CLR_RD_PTR\03H2B_ATN\04B2H_ATN"\
+                               "\05SMS_ATN\06OEM0\07H_BUSY\010B_BUSY"
+
+#define        BT_DATA_REG             1
+#define         BTMSG_REQLEN           3
+#define         BTMSG_REPLEN           4
+
+#define        BT_INTMASK_REG          2
+#define         BT_IM_B2H_IRQ_EN       (1L << 0)
+#define         BT_IM_B2H_IRQ          (1L << 1)
+#define         BT_IM_BMC_HWRST        (1L << 7)
+
+static int bt_polled_request(struct ipmi_softc *, struct ipmi_request *);
+static int bt_driver_request(struct ipmi_softc *, struct ipmi_request *, int);
+static int bt_wait(struct ipmi_softc *, uint8_t, uint8_t);
+static int bt_reset(struct ipmi_softc *);
+
+static void bt_loop(void *);
+static int bt_startup(struct ipmi_softc *);
+
+#define        BT_DELAY_MIN    1
+#define        BT_DELAY_MAX    256
+
+static int
+bt_wait(struct ipmi_softc *sc, uint8_t mask, uint8_t wanted)
+{
+       volatile uint8_t value;
+       int delay = BT_DELAY_MIN;
+       int count = 20000; /* about 5 seconds */
+
+       while (count--) {
+               value = INB(sc, BT_CTRL_REG);
+               if ((value & mask) == wanted)
+                       return (value);
+               /*
+                * The wait delay is increased exponentially to avoid putting
+                * significant load on I/O bus.
+                */
+               DELAY(delay);
+               if (delay < BT_DELAY_MAX)
+                       delay <<= 1;
+       }
+       DMSGV(sc, "failed: m=%b w=%b v=0x%02x\n",
+           mask, BT_CTRL_BITS, wanted, BT_CTRL_BITS, value);
+       return (-1);
+
+}
+
+static int
+bt_reset(struct ipmi_softc *sc)
+{
+       uint8_t v;
+
+       v = INB(sc, BT_CTRL_REG);
+       DMSG(sc, "ctrl: %b", v, BT_CTRL_BITS);
+       v &= BT_C_H_BUSY; /* clear H_BUSY iff it set */
+       v |= BT_C_CLR_WR_PTR | BT_C_CLR_RD_PTR | BT_C_B2H_ATN | BT_C_H2B_ATN;
+
+       bt_wait(sc, BT_C_B_BUSY, 0);
+       OUTB(sc, BT_CTRL_REG, v);
+
+       v = BT_IM_B2H_IRQ | BT_IM_BMC_HWRST;
+       OUTB(sc, BT_INTMASK_REG, v);
+
+       return (0);
+}
+
+/*
+ * Send a request message and collect the reply. Returns 1 if we
+ * succeed.
+ */
+static int
+bt_polled_request(struct ipmi_softc *sc, struct ipmi_request *req)
+{
+       uint8_t addr, cmd, seq, v;
+       int i;
+
+       IPMI_IO_LOCK(sc);
+
+       /*
+        * Send the request:
+        *
+        * Byte 1 | Byte 2    | Byte 3 | Byte 4 | Byte 5:N
+        * -------+-----------+--------+--------+---------
+        * Length | NetFn/LUN | Seq    | Cmd    | Data
+        */
+
+       if (bt_wait(sc, BT_C_B_BUSY | BT_C_H2B_ATN, 0) < 0) {
+               DMSG(sc, "failed to start write transfer");
+               goto fail;
+       }
+       DMSG(sc, "request: length=%d, addr=0x%02x, seq=%u, cmd=0x%02x",
+           (int)req->ir_requestlen, req->ir_addr, sc->ipmi_bt_seq, 
req->ir_command);
+       OUTB(sc, BT_CTRL_REG, BT_C_CLR_WR_PTR);
+       OUTB(sc, BT_DATA_REG, req->ir_requestlen + BTMSG_REQLEN);
+       OUTB(sc, BT_DATA_REG, req->ir_addr);
+       OUTB(sc, BT_DATA_REG, sc->ipmi_bt_seq);
+       OUTB(sc, BT_DATA_REG, req->ir_command);
+       for (i = 0; i < req->ir_requestlen; i++)
+               OUTB(sc, BT_DATA_REG, req->ir_request[i]);
+       OUTB(sc, BT_CTRL_REG, BT_C_H2B_ATN);
+
+       if (bt_wait(sc, BT_C_B_BUSY | BT_C_H2B_ATN, 0) < 0) {
+               DMSG(sc, "failed to finish write transfer");
+               goto fail;
+       }
+
+       /*
+        * Read the reply:
+        *
+        * Byte 1 | Byte 2    | Byte 3 | Byte 4 | Byte 5          | Byte 6:N
+        * -------+-----------+--------+--------+-----------------+---------
+        * Length | NetFn/LUN | Seq    | Cmd    | Completion code | Data
+        */
+       if (bt_wait(sc, BT_C_B2H_ATN, BT_C_B2H_ATN) < 0) {
+               DMSG(sc, "got no reply from BMC");
+               goto fail;
+       }
+       OUTB(sc, BT_CTRL_REG, BT_C_H_BUSY);
+       OUTB(sc, BT_CTRL_REG, BT_C_B2H_ATN);
+       OUTB(sc, BT_CTRL_REG, BT_C_CLR_RD_PTR);
+
+       i = INB(sc, BT_DATA_REG);
+       if (i < BTMSG_REPLEN) {
+               DMSG(sc, "wrong data length: %d", i);
+               goto fail;
+       }
+       req->ir_replylen = i - BTMSG_REPLEN;
+       DMSG(sc, "data length: %d, frame length: %d", req->ir_replylen, i);
+
+       addr = INB(sc, BT_DATA_REG);
+       if (addr != IPMI_REPLY_ADDR(req->ir_addr)) {
+               DMSGV(sc, "address doesn't match: addr=0x%02x vs. 0x%02x",
+                   req->ir_addr, addr);
+       }
+
+       seq = INB(sc, BT_DATA_REG);
+       if (seq != sc->ipmi_bt_seq) {
+               DMSGV(sc, "seq number doesn't match: seq=0x%02x vs. 0x%02x",
+                   sc->ipmi_bt_seq, seq);
+       }
+
+       cmd = INB(sc, BT_DATA_REG);
+       if (cmd != req->ir_command) {
+               DMSGV(sc, "command doesn't match: cmd=0x%02x vs. 0x%02x",
+                   req->ir_command, cmd);
+       }
+
+       req->ir_compcode = INB(sc, BT_DATA_REG);
+       for (i = 0; i < req->ir_replylen; i++) {
+               v = INB(sc, BT_DATA_REG);
+               if (i < req->ir_replybuflen)
+                       req->ir_reply[i] = v;
+       }
+
+       OUTB(sc, BT_CTRL_REG, BT_C_H_BUSY);
+       IPMI_IO_UNLOCK(sc);
+       DMSG(sc, "reply: length=%d, addr=0x%02x, seq=%u, cmd=0x%02x, 
code=0x%02x",
+           (int)req->ir_replylen, addr, seq, req->ir_command, 
req->ir_compcode);
+       return (1);
+fail:
+       bt_reset(sc);
+       IPMI_IO_UNLOCK(sc);
+       return (0);
+}
+
+static void
+bt_loop(void *arg)
+{
+       struct ipmi_softc *sc = arg;
+       struct ipmi_request *req;
+
+       IPMI_LOCK(sc);
+       while ((req = ipmi_dequeue_request(sc)) != NULL) {
+               IPMI_UNLOCK(sc);
+               (void)bt_driver_request(sc, req, 0);
+               IPMI_LOCK(sc);
+               sc->ipmi_bt_seq++;
+               ipmi_complete_request(sc, req);
+       }
+       IPMI_UNLOCK(sc);
+       kproc_exit(0);
+}
+
+static int
+bt_startup(struct ipmi_softc *sc)
+{
+
+       return (kproc_create(bt_loop, sc, &sc->ipmi_kthread, 0, 0, "%s: bt",
+           device_get_nameunit(sc->ipmi_dev)));
+}
+
+static int
+bt_driver_request(struct ipmi_softc *sc, struct ipmi_request *req, int timo 
__unused)
+{
+       int i, ok;
+
+       ok = 0;
+       for (i = 0; i < 3 && !ok; i++)
+               ok = bt_polled_request(sc, req);
+       if (ok)
+               req->ir_error = 0;
+       else
+               req->ir_error = EIO;
+       return (req->ir_error);
+}
+
+int
+ipmi_bt_attach(struct ipmi_softc *sc)
+{
+       /* Setup function pointers. */
+       sc->ipmi_startup = bt_startup;
+       sc->ipmi_enqueue_request = ipmi_polled_enqueue_request;
+       sc->ipmi_driver_request = bt_driver_request;
+       sc->ipmi_driver_requests_polled = 1;
+       sc->ipmi_bt_seq = 1;
+
+       return (bt_reset(sc));
+}
diff --git a/sys/dev/ipmi/ipmi_isa.c b/sys/dev/ipmi/ipmi_isa.c
index de21b59692e1..9abe697c23fc 100644
--- a/sys/dev/ipmi/ipmi_isa.c
+++ b/sys/dev/ipmi/ipmi_isa.c
@@ -188,16 +188,17 @@ ipmi_isa_attach(device_t dev)
 
        switch (info.iface_type) {
        case KCS_MODE:
-               count = 2;
+               count = IPMI_IF_KCS_NRES;
                mode = "KCS";
                break;
        case SMIC_MODE:
-               count = 3;
+               count = IPMI_IF_SMIC_NRES;
                mode = "SMIC";
                break;
        case BT_MODE:
-               device_printf(dev, "BT mode is unsupported\n");
-               return (ENXIO);
+               count = IPMI_IF_BT_NRES;
+               mode = "BT";
+               break;
        default:
                return (ENXIO);
        }
@@ -248,19 +249,21 @@ ipmi_isa_attach(device_t dev)
                    RF_SHAREABLE | RF_ACTIVE);
        }
 
+       error = ENXIO;
        switch (info.iface_type) {
        case KCS_MODE:
                error = ipmi_kcs_attach(sc);
-               if (error)
-                       goto bad;
                break;
        case SMIC_MODE:
                error = ipmi_smic_attach(sc);
-               if (error)
-                       goto bad;
+               break;
+       case BT_MODE:
+               error = ipmi_bt_attach(sc);
                break;
        }
 
+       if (error)
+               goto bad;
        error = ipmi_attach(dev);
        if (error)
                goto bad;
diff --git a/sys/dev/ipmi/ipmi_pci.c b/sys/dev/ipmi/ipmi_pci.c
index 13ac4f4b5ede..76b9832c8db1 100644
--- a/sys/dev/ipmi/ipmi_pci.c
+++ b/sys/dev/ipmi/ipmi_pci.c
@@ -112,8 +112,8 @@ ipmi_pci_attach(device_t dev)
                mode = "SMIC";
                break;
        case BT_MODE:
-               device_printf(dev, "BT mode is unsupported\n");
-               return (ENXIO);
+               mode = "BT";
+               break;
        default:
                device_printf(dev, "No IPMI interface found\n");
                return (ENXIO);
@@ -143,18 +143,20 @@ ipmi_pci_attach(device_t dev)
        sc->ipmi_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
            &sc->ipmi_irq_rid, RF_SHAREABLE | RF_ACTIVE);
 
+       error = ENXIO;
        switch (info.iface_type) {
        case KCS_MODE:
                error = ipmi_kcs_attach(sc);
-               if (error)
-                       goto bad;
                break;
        case SMIC_MODE:
                error = ipmi_smic_attach(sc);
-               if (error)
-                       goto bad;
+               break;
+       case BT_MODE:
+               error = ipmi_bt_attach(sc);
                break;
        }
+       if (error)
+               goto bad;
        error = ipmi_attach(dev);
        if (error)
                goto bad;
@@ -215,8 +217,7 @@ ipmi2_pci_attach(device_t dev)
                break;
        case PCIP_SERIALBUS_IPMI_BT:
                iface = BT_MODE;
-               device_printf(dev, "BT interface unsupported\n");
-               return (ENXIO);
+               break;
        default:
                device_printf(dev, "Unsupported interface: %d\n",
                    pci_get_progif(dev));
@@ -242,6 +243,7 @@ ipmi2_pci_attach(device_t dev)
        sc->ipmi_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
            &sc->ipmi_irq_rid, RF_SHAREABLE | RF_ACTIVE);
 
+       error = ENXIO;
        switch (iface) {
        case KCS_MODE:
                device_printf(dev, "using KSC interface\n");
@@ -252,7 +254,6 @@ ipmi2_pci_attach(device_t dev)
                 */
                if (!ipmi_kcs_probe_align(sc)) {
                        device_printf(dev, "Unable to determine alignment\n");
-                       error = ENXIO;
                        goto bad;
                }
 
@@ -262,12 +263,15 @@ ipmi2_pci_attach(device_t dev)
                break;
        case SMIC_MODE:
                device_printf(dev, "using SMIC interface\n");
-
                error = ipmi_smic_attach(sc);
-               if (error)
-                       goto bad;
+               break;
+       case BT_MODE:
+               device_printf(dev, "using BT interface\n");
+               error = ipmi_bt_attach(sc);
                break;
        }
+       if (error)
+               goto bad;
        error = ipmi_attach(dev);
        if (error)
                goto bad;
diff --git a/sys/dev/ipmi/ipmi_smbios.c b/sys/dev/ipmi/ipmi_smbios.c
index e26b6f2956ad..7917464d7d32 100644
--- a/sys/dev/ipmi/ipmi_smbios.c
+++ b/sys/dev/ipmi/ipmi_smbios.c
@@ -104,6 +104,7 @@ smbios_ipmi_info(struct smbios_structure_header *h, void 
*arg)
        switch (s->interface_type) {
        case KCS_MODE:
        case SMIC_MODE:
+       case BT_MODE:
                info->address = IPMI_BAR_ADDR(s->base_address) |
                    IPMI_BAM_ADDR_LSB(s->base_address_modifier);
                info->io_mode = IPMI_BAR_MODE(s->base_address);
diff --git a/sys/dev/ipmi/ipmivars.h b/sys/dev/ipmi/ipmivars.h
index 8c6a716adb9c..73b1073e5e16 100644
--- a/sys/dev/ipmi/ipmivars.h
+++ b/sys/dev/ipmi/ipmivars.h
@@ -59,6 +59,10 @@ struct ipmi_request {
        uint8_t         ir_ipmb_command;
 };
 
+#define        IPMI_IF_KCS_NRES                2
+#define        IPMI_IF_SMIC_NRES               3
+#define        IPMI_IF_BT_NRES                 3
+
 #define        MAX_RES                         3
 #define KCS_DATA                       0
 #define KCS_CTL_STS                    1
@@ -80,6 +84,10 @@ struct ipmi_device {
        u_char                  ipmi_lun;
 };
 
+struct ipmi_bt {
+       uint8_t seq;
+};
+
 struct ipmi_kcs {
 };
 
@@ -94,6 +102,7 @@ struct ipmi_ssif {
 struct ipmi_softc {
        device_t                ipmi_dev;
        union {
+               struct ipmi_bt bt;
                struct ipmi_kcs kcs;
                struct ipmi_smic smic;
                struct ipmi_ssif ssif;
@@ -130,11 +139,12 @@ struct ipmi_softc {
 
 #define        ipmi_ssif_smbus_address         _iface.ssif.smbus_address
 #define        ipmi_ssif_smbus                 _iface.ssif.smbus
+#define        ipmi_bt_seq                     _iface.bt.seq
 
-#define KCS_MODE               0x01
-#define SMIC_MODE              0x02
-#define        BT_MODE                 0x03
-#define SSIF_MODE              0x04
+#define        KCS_MODE                        0x01
+#define        SMIC_MODE                       0x02
+#define        BT_MODE                         0x03
+#define        SSIF_MODE                       0x04
 
 /* KCS status flags */
 #define KCS_STATUS_OBF                 0x01 /* Data Out ready from BMC */
@@ -250,6 +260,7 @@ const char *ipmi_pci_match(uint16_t, uint16_t);
 int    ipmi_kcs_attach(struct ipmi_softc *);
 int    ipmi_kcs_probe_align(struct ipmi_softc *);
 int    ipmi_smic_attach(struct ipmi_softc *);
+int    ipmi_bt_attach(struct ipmi_softc *);
 int    ipmi_ssif_attach(struct ipmi_softc *, device_t, int);
 
 extern devclass_t ipmi_devclass;
diff --git a/sys/modules/ipmi/Makefile b/sys/modules/ipmi/Makefile
index 733ac6f30222..3d0414fc3807 100644
--- a/sys/modules/ipmi/Makefile
+++ b/sys/modules/ipmi/Makefile
@@ -10,7 +10,7 @@ SRCS+=        bus_if.h device_if.h
 
 .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" || \
     ${MACHINE_CPUARCH} == "aarch64"
-SRCS+= ipmi_kcs.c ipmi_smic.c
+SRCS+= ipmi_kcs.c ipmi_smic.c ipmi_bt.c
 SRCS+= ipmi_acpi.c
 SRCS+= opt_acpi.h
 SRCS+= acpi_if.h

Reply via email to