qemu/hw/ipmi/isa_ipmi_kcs.c
<<
>>
Prefs
   1/*
   2 * QEMU ISA IPMI KCS emulation
   3 *
   4 * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining a copy
   7 * of this software and associated documentation files (the "Software"), to deal
   8 * in the Software without restriction, including without limitation the rights
   9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 * copies of the Software, and to permit persons to whom the Software is
  11 * furnished to do so, subject to the following conditions:
  12 *
  13 * The above copyright notice and this permission notice shall be included in
  14 * all copies or substantial portions of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 * THE SOFTWARE.
  23 */
  24
  25#include "qemu/osdep.h"
  26#include "qemu/log.h"
  27#include "qemu/module.h"
  28#include "qapi/error.h"
  29#include "hw/hw.h"
  30#include "hw/ipmi/ipmi.h"
  31#include "hw/isa/isa.h"
  32
  33#define IPMI_KCS_OBF_BIT        0
  34#define IPMI_KCS_IBF_BIT        1
  35#define IPMI_KCS_SMS_ATN_BIT    2
  36#define IPMI_KCS_CD_BIT         3
  37
  38#define IPMI_KCS_OBF_MASK          (1 << IPMI_KCS_OBF_BIT)
  39#define IPMI_KCS_GET_OBF(d)        (((d) >> IPMI_KCS_OBF_BIT) & 0x1)
  40#define IPMI_KCS_SET_OBF(d, v)     (d) = (((d) & ~IPMI_KCS_OBF_MASK) | \
  41                                       (((v) & 1) << IPMI_KCS_OBF_BIT))
  42#define IPMI_KCS_IBF_MASK          (1 << IPMI_KCS_IBF_BIT)
  43#define IPMI_KCS_GET_IBF(d)        (((d) >> IPMI_KCS_IBF_BIT) & 0x1)
  44#define IPMI_KCS_SET_IBF(d, v)     (d) = (((d) & ~IPMI_KCS_IBF_MASK) | \
  45                                       (((v) & 1) << IPMI_KCS_IBF_BIT))
  46#define IPMI_KCS_SMS_ATN_MASK      (1 << IPMI_KCS_SMS_ATN_BIT)
  47#define IPMI_KCS_GET_SMS_ATN(d)    (((d) >> IPMI_KCS_SMS_ATN_BIT) & 0x1)
  48#define IPMI_KCS_SET_SMS_ATN(d, v) (d) = (((d) & ~IPMI_KCS_SMS_ATN_MASK) | \
  49                                       (((v) & 1) << IPMI_KCS_SMS_ATN_BIT))
  50#define IPMI_KCS_CD_MASK           (1 << IPMI_KCS_CD_BIT)
  51#define IPMI_KCS_GET_CD(d)         (((d) >> IPMI_KCS_CD_BIT) & 0x1)
  52#define IPMI_KCS_SET_CD(d, v)      (d) = (((d) & ~IPMI_KCS_CD_MASK) | \
  53                                       (((v) & 1) << IPMI_KCS_CD_BIT))
  54
  55#define IPMI_KCS_IDLE_STATE        0
  56#define IPMI_KCS_READ_STATE        1
  57#define IPMI_KCS_WRITE_STATE       2
  58#define IPMI_KCS_ERROR_STATE       3
  59
  60#define IPMI_KCS_GET_STATE(d)    (((d) >> 6) & 0x3)
  61#define IPMI_KCS_SET_STATE(d, v) ((d) = ((d) & ~0xc0) | (((v) & 0x3) << 6))
  62
  63#define IPMI_KCS_ABORT_STATUS_CMD       0x60
  64#define IPMI_KCS_WRITE_START_CMD        0x61
  65#define IPMI_KCS_WRITE_END_CMD          0x62
  66#define IPMI_KCS_READ_CMD               0x68
  67
  68#define IPMI_KCS_STATUS_NO_ERR          0x00
  69#define IPMI_KCS_STATUS_ABORTED_ERR     0x01
  70#define IPMI_KCS_STATUS_BAD_CC_ERR      0x02
  71#define IPMI_KCS_STATUS_LENGTH_ERR      0x06
  72
  73typedef struct IPMIKCS {
  74    IPMIBmc *bmc;
  75
  76    bool do_wake;
  77
  78    qemu_irq irq;
  79
  80    uint32_t io_base;
  81    unsigned long io_length;
  82    MemoryRegion io;
  83
  84    bool obf_irq_set;
  85    bool atn_irq_set;
  86    bool use_irq;
  87    bool irqs_enabled;
  88
  89    uint8_t outmsg[MAX_IPMI_MSG_SIZE];
  90    uint32_t outpos;
  91    uint32_t outlen;
  92
  93    uint8_t inmsg[MAX_IPMI_MSG_SIZE];
  94    uint32_t inlen;
  95    bool write_end;
  96
  97    uint8_t status_reg;
  98    uint8_t data_out_reg;
  99
 100    int16_t data_in_reg; /* -1 means not written */
 101    int16_t cmd_reg;
 102
 103    /*
 104     * This is a response number that we send with the command to make
 105     * sure that the response matches the command.
 106     */
 107    uint8_t waiting_rsp;
 108} IPMIKCS;
 109
 110#define SET_OBF() \
 111    do {                                                                      \
 112        IPMI_KCS_SET_OBF(ik->status_reg, 1);                                  \
 113        if (ik->use_irq && ik->irqs_enabled && !ik->obf_irq_set) {            \
 114            ik->obf_irq_set = 1;                                              \
 115            if (!ik->atn_irq_set) {                                           \
 116                qemu_irq_raise(ik->irq);                                      \
 117            }                                                                 \
 118        }                                                                     \
 119    } while (0)
 120
 121static void ipmi_kcs_signal(IPMIKCS *ik, IPMIInterface *ii)
 122{
 123    IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
 124
 125    ik->do_wake = 1;
 126    while (ik->do_wake) {
 127        ik->do_wake = 0;
 128        iic->handle_if_event(ii);
 129    }
 130}
 131
 132static void ipmi_kcs_handle_event(IPMIInterface *ii)
 133{
 134    IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
 135    IPMIKCS *ik = iic->get_backend_data(ii);
 136
 137    if (ik->cmd_reg == IPMI_KCS_ABORT_STATUS_CMD) {
 138        if (IPMI_KCS_GET_STATE(ik->status_reg) != IPMI_KCS_ERROR_STATE) {
 139            ik->waiting_rsp++; /* Invalidate the message */
 140            ik->outmsg[0] = IPMI_KCS_STATUS_ABORTED_ERR;
 141            ik->outlen = 1;
 142            ik->outpos = 0;
 143            IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_ERROR_STATE);
 144            SET_OBF();
 145        }
 146        goto out;
 147    }
 148
 149    switch (IPMI_KCS_GET_STATE(ik->status_reg)) {
 150    case IPMI_KCS_IDLE_STATE:
 151        if (ik->cmd_reg == IPMI_KCS_WRITE_START_CMD) {
 152            IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_WRITE_STATE);
 153            ik->cmd_reg = -1;
 154            ik->write_end = 0;
 155            ik->inlen = 0;
 156            SET_OBF();
 157        }
 158        break;
 159
 160    case IPMI_KCS_READ_STATE:
 161    handle_read:
 162        if (ik->outpos >= ik->outlen) {
 163            IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_IDLE_STATE);
 164            SET_OBF();
 165        } else if (ik->data_in_reg == IPMI_KCS_READ_CMD) {
 166            ik->data_out_reg = ik->outmsg[ik->outpos];
 167            ik->outpos++;
 168            SET_OBF();
 169        } else {
 170            ik->outmsg[0] = IPMI_KCS_STATUS_BAD_CC_ERR;
 171            ik->outlen = 1;
 172            ik->outpos = 0;
 173            IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_ERROR_STATE);
 174            SET_OBF();
 175            goto out;
 176        }
 177        break;
 178
 179    case IPMI_KCS_WRITE_STATE:
 180        if (ik->data_in_reg != -1) {
 181            /*
 182             * Don't worry about input overrun here, that will be
 183             * handled in the BMC.
 184             */
 185            if (ik->inlen < sizeof(ik->inmsg)) {
 186                ik->inmsg[ik->inlen] = ik->data_in_reg;
 187            }
 188            ik->inlen++;
 189        }
 190        if (ik->write_end) {
 191            IPMIBmcClass *bk = IPMI_BMC_GET_CLASS(ik->bmc);
 192            ik->outlen = 0;
 193            ik->write_end = 0;
 194            ik->outpos = 0;
 195            bk->handle_command(ik->bmc, ik->inmsg, ik->inlen, sizeof(ik->inmsg),
 196                               ik->waiting_rsp);
 197            goto out_noibf;
 198        } else if (ik->cmd_reg == IPMI_KCS_WRITE_END_CMD) {
 199            ik->cmd_reg = -1;
 200            ik->write_end = 1;
 201        }
 202        SET_OBF();
 203        break;
 204
 205    case IPMI_KCS_ERROR_STATE:
 206        if (ik->data_in_reg != -1) {
 207            IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_READ_STATE);
 208            ik->data_in_reg = IPMI_KCS_READ_CMD;
 209            goto handle_read;
 210        }
 211        break;
 212    }
 213
 214    if (ik->cmd_reg != -1) {
 215        /* Got an invalid command */
 216        ik->outmsg[0] = IPMI_KCS_STATUS_BAD_CC_ERR;
 217        ik->outlen = 1;
 218        ik->outpos = 0;
 219        IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_ERROR_STATE);
 220    }
 221
 222 out:
 223    ik->cmd_reg = -1;
 224    ik->data_in_reg = -1;
 225    IPMI_KCS_SET_IBF(ik->status_reg, 0);
 226 out_noibf:
 227    return;
 228}
 229
 230static void ipmi_kcs_handle_rsp(IPMIInterface *ii, uint8_t msg_id,
 231                                unsigned char *rsp, unsigned int rsp_len)
 232{
 233    IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
 234    IPMIKCS *ik = iic->get_backend_data(ii);
 235
 236    if (ik->waiting_rsp == msg_id) {
 237        ik->waiting_rsp++;
 238        if (rsp_len > sizeof(ik->outmsg)) {
 239            ik->outmsg[0] = rsp[0];
 240            ik->outmsg[1] = rsp[1];
 241            ik->outmsg[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
 242            ik->outlen = 3;
 243        } else {
 244            memcpy(ik->outmsg, rsp, rsp_len);
 245            ik->outlen = rsp_len;
 246        }
 247        IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_READ_STATE);
 248        ik->data_in_reg = IPMI_KCS_READ_CMD;
 249        ipmi_kcs_signal(ik, ii);
 250    }
 251}
 252
 253
 254static uint64_t ipmi_kcs_ioport_read(void *opaque, hwaddr addr, unsigned size)
 255{
 256    IPMIInterface *ii = opaque;
 257    IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
 258    IPMIKCS *ik = iic->get_backend_data(ii);
 259    uint32_t ret;
 260
 261    switch (addr & 1) {
 262    case 0:
 263        ret = ik->data_out_reg;
 264        IPMI_KCS_SET_OBF(ik->status_reg, 0);
 265        if (ik->obf_irq_set) {
 266            ik->obf_irq_set = 0;
 267            if (!ik->atn_irq_set) {
 268                qemu_irq_lower(ik->irq);
 269            }
 270        }
 271        break;
 272    case 1:
 273        ret = ik->status_reg;
 274        if (ik->atn_irq_set) {
 275            ik->atn_irq_set = 0;
 276            if (!ik->obf_irq_set) {
 277                qemu_irq_lower(ik->irq);
 278            }
 279        }
 280        break;
 281    }
 282    return ret;
 283}
 284
 285static void ipmi_kcs_ioport_write(void *opaque, hwaddr addr, uint64_t val,
 286                                  unsigned size)
 287{
 288    IPMIInterface *ii = opaque;
 289    IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
 290    IPMIKCS *ik = iic->get_backend_data(ii);
 291
 292    if (IPMI_KCS_GET_IBF(ik->status_reg)) {
 293        return;
 294    }
 295
 296    switch (addr & 1) {
 297    case 0:
 298        ik->data_in_reg = val;
 299        break;
 300
 301    case 1:
 302        ik->cmd_reg = val;
 303        break;
 304    }
 305    IPMI_KCS_SET_IBF(ik->status_reg, 1);
 306    ipmi_kcs_signal(ik, ii);
 307}
 308
 309const MemoryRegionOps ipmi_kcs_io_ops = {
 310    .read = ipmi_kcs_ioport_read,
 311    .write = ipmi_kcs_ioport_write,
 312    .impl = {
 313        .min_access_size = 1,
 314        .max_access_size = 1,
 315    },
 316    .endianness = DEVICE_LITTLE_ENDIAN,
 317};
 318
 319static void ipmi_kcs_set_atn(IPMIInterface *ii, int val, int irq)
 320{
 321    IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
 322    IPMIKCS *ik = iic->get_backend_data(ii);
 323
 324    IPMI_KCS_SET_SMS_ATN(ik->status_reg, val);
 325    if (val) {
 326        if (irq && !ik->atn_irq_set && ik->use_irq && ik->irqs_enabled) {
 327            ik->atn_irq_set = 1;
 328            if (!ik->obf_irq_set) {
 329                qemu_irq_raise(ik->irq);
 330            }
 331        }
 332    } else {
 333        if (ik->atn_irq_set) {
 334            ik->atn_irq_set = 0;
 335            if (!ik->obf_irq_set) {
 336                qemu_irq_lower(ik->irq);
 337            }
 338        }
 339    }
 340}
 341
 342static void ipmi_kcs_set_irq_enable(IPMIInterface *ii, int val)
 343{
 344    IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
 345    IPMIKCS *ik = iic->get_backend_data(ii);
 346
 347    ik->irqs_enabled = val;
 348}
 349
 350static void ipmi_kcs_init(IPMIInterface *ii, Error **errp)
 351{
 352    IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
 353    IPMIKCS *ik = iic->get_backend_data(ii);
 354
 355    ik->io_length = 2;
 356    memory_region_init_io(&ik->io, NULL, &ipmi_kcs_io_ops, ii, "ipmi-kcs", 2);
 357}
 358
 359#define TYPE_ISA_IPMI_KCS "isa-ipmi-kcs"
 360#define ISA_IPMI_KCS(obj) OBJECT_CHECK(ISAIPMIKCSDevice, (obj), \
 361                                       TYPE_ISA_IPMI_KCS)
 362
 363typedef struct ISAIPMIKCSDevice {
 364    ISADevice dev;
 365    int32_t isairq;
 366    IPMIKCS kcs;
 367    uint32_t uuid;
 368} ISAIPMIKCSDevice;
 369
 370static void ipmi_kcs_get_fwinfo(IPMIInterface *ii, IPMIFwInfo *info)
 371{
 372    ISAIPMIKCSDevice *iik = ISA_IPMI_KCS(ii);
 373
 374    info->interface_name = "kcs";
 375    info->interface_type = IPMI_SMBIOS_KCS;
 376    info->ipmi_spec_major_revision = 2;
 377    info->ipmi_spec_minor_revision = 0;
 378    info->base_address = iik->kcs.io_base;
 379    info->i2c_slave_address = iik->kcs.bmc->slave_addr;
 380    info->register_length = iik->kcs.io_length;
 381    info->register_spacing = 1;
 382    info->memspace = IPMI_MEMSPACE_IO;
 383    info->irq_type = IPMI_LEVEL_IRQ;
 384    info->interrupt_number = iik->isairq;
 385    info->uuid = iik->uuid;
 386}
 387
 388static void ipmi_kcs_class_init(IPMIInterfaceClass *iic)
 389{
 390    iic->init = ipmi_kcs_init;
 391    iic->set_atn = ipmi_kcs_set_atn;
 392    iic->handle_rsp = ipmi_kcs_handle_rsp;
 393    iic->handle_if_event = ipmi_kcs_handle_event;
 394    iic->set_irq_enable = ipmi_kcs_set_irq_enable;
 395    iic->get_fwinfo = ipmi_kcs_get_fwinfo;
 396}
 397
 398static void ipmi_isa_realize(DeviceState *dev, Error **errp)
 399{
 400    ISADevice *isadev = ISA_DEVICE(dev);
 401    ISAIPMIKCSDevice *iik = ISA_IPMI_KCS(dev);
 402    IPMIInterface *ii = IPMI_INTERFACE(dev);
 403    IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
 404
 405    if (!iik->kcs.bmc) {
 406        error_setg(errp, "IPMI device requires a bmc attribute to be set");
 407        return;
 408    }
 409
 410    iik->uuid = ipmi_next_uuid();
 411
 412    iik->kcs.bmc->intf = ii;
 413
 414    iic->init(ii, errp);
 415    if (*errp)
 416        return;
 417
 418    if (iik->isairq > 0) {
 419        isa_init_irq(isadev, &iik->kcs.irq, iik->isairq);
 420        iik->kcs.use_irq = 1;
 421    }
 422
 423    qdev_set_legacy_instance_id(dev, iik->kcs.io_base, iik->kcs.io_length);
 424
 425    isa_register_ioport(isadev, &iik->kcs.io, iik->kcs.io_base);
 426}
 427
 428static int ipmi_kcs_vmstate_post_load(void *opaque, int version)
 429{
 430    IPMIKCS *ik = opaque;
 431
 432    /* Make sure all the values are sane. */
 433    if (ik->outpos >= MAX_IPMI_MSG_SIZE || ik->outlen >= MAX_IPMI_MSG_SIZE ||
 434        ik->outpos >= ik->outlen) {
 435        qemu_log_mask(LOG_GUEST_ERROR,
 436                      "ipmi:kcs: vmstate transfer received bad out values: %d %d\n",
 437                      ik->outpos, ik->outlen);
 438        ik->outpos = 0;
 439        ik->outlen = 0;
 440    }
 441
 442    if (ik->inlen >= MAX_IPMI_MSG_SIZE) {
 443        qemu_log_mask(LOG_GUEST_ERROR,
 444                      "ipmi:kcs: vmstate transfer received bad in value: %d\n",
 445                      ik->inlen);
 446        ik->inlen = 0;
 447    }
 448
 449    return 0;
 450}
 451
 452static bool vmstate_kcs_before_version2(void *opaque, int version)
 453{
 454    return version <= 1;
 455}
 456
 457static const VMStateDescription vmstate_IPMIKCS = {
 458    .name = TYPE_IPMI_INTERFACE_PREFIX "kcs",
 459    .version_id = 2,
 460    .minimum_version_id = 1,
 461    .post_load = ipmi_kcs_vmstate_post_load,
 462    .fields      = (VMStateField[]) {
 463        VMSTATE_BOOL(obf_irq_set, IPMIKCS),
 464        VMSTATE_BOOL(atn_irq_set, IPMIKCS),
 465        VMSTATE_UNUSED_TEST(vmstate_kcs_before_version2, 1), /* Was use_irq */
 466        VMSTATE_BOOL(irqs_enabled, IPMIKCS),
 467        VMSTATE_UINT32(outpos, IPMIKCS),
 468        VMSTATE_UINT32_V(outlen, IPMIKCS, 2),
 469        VMSTATE_UINT8_ARRAY(outmsg, IPMIKCS, MAX_IPMI_MSG_SIZE),
 470        VMSTATE_UINT32_V(inlen, IPMIKCS, 2),
 471        VMSTATE_UINT8_ARRAY(inmsg, IPMIKCS, MAX_IPMI_MSG_SIZE),
 472        VMSTATE_BOOL(write_end, IPMIKCS),
 473        VMSTATE_UINT8(status_reg, IPMIKCS),
 474        VMSTATE_UINT8(data_out_reg, IPMIKCS),
 475        VMSTATE_INT16(data_in_reg, IPMIKCS),
 476        VMSTATE_INT16(cmd_reg, IPMIKCS),
 477        VMSTATE_UINT8(waiting_rsp, IPMIKCS),
 478        VMSTATE_END_OF_LIST()
 479    }
 480};
 481
 482static const VMStateDescription vmstate_ISAIPMIKCSDevice = {
 483    .name = TYPE_IPMI_INTERFACE,
 484    .version_id = 2,
 485    .minimum_version_id = 1,
 486    .fields      = (VMStateField[]) {
 487        VMSTATE_VSTRUCT_TEST(kcs, ISAIPMIKCSDevice, vmstate_kcs_before_version2,
 488                             0, vmstate_IPMIKCS, IPMIKCS, 1),
 489        VMSTATE_VSTRUCT_V(kcs, ISAIPMIKCSDevice, 2, vmstate_IPMIKCS,
 490                          IPMIKCS, 2),
 491        VMSTATE_END_OF_LIST()
 492    }
 493};
 494
 495static void isa_ipmi_kcs_init(Object *obj)
 496{
 497    ISAIPMIKCSDevice *iik = ISA_IPMI_KCS(obj);
 498
 499    ipmi_bmc_find_and_link(obj, (Object **) &iik->kcs.bmc);
 500
 501    /*
 502     * Version 1 had an incorrect name, it clashed with the BT
 503     * IPMI device, so receive it, but transmit a different
 504     * version.
 505     */
 506    vmstate_register(NULL, 0, &vmstate_ISAIPMIKCSDevice, iik);
 507}
 508
 509static void *isa_ipmi_kcs_get_backend_data(IPMIInterface *ii)
 510{
 511    ISAIPMIKCSDevice *iik = ISA_IPMI_KCS(ii);
 512
 513    return &iik->kcs;
 514}
 515
 516static Property ipmi_isa_properties[] = {
 517    DEFINE_PROP_UINT32("ioport", ISAIPMIKCSDevice, kcs.io_base,  0xca2),
 518    DEFINE_PROP_INT32("irq",   ISAIPMIKCSDevice, isairq,  5),
 519    DEFINE_PROP_END_OF_LIST(),
 520};
 521
 522static void isa_ipmi_kcs_class_init(ObjectClass *oc, void *data)
 523{
 524    DeviceClass *dc = DEVICE_CLASS(oc);
 525    IPMIInterfaceClass *iic = IPMI_INTERFACE_CLASS(oc);
 526
 527    dc->realize = ipmi_isa_realize;
 528    dc->props = ipmi_isa_properties;
 529
 530    iic->get_backend_data = isa_ipmi_kcs_get_backend_data;
 531    ipmi_kcs_class_init(iic);
 532}
 533
 534static const TypeInfo isa_ipmi_kcs_info = {
 535    .name          = TYPE_ISA_IPMI_KCS,
 536    .parent        = TYPE_ISA_DEVICE,
 537    .instance_size = sizeof(ISAIPMIKCSDevice),
 538    .instance_init = isa_ipmi_kcs_init,
 539    .class_init    = isa_ipmi_kcs_class_init,
 540    .interfaces = (InterfaceInfo[]) {
 541        { TYPE_IPMI_INTERFACE },
 542        { }
 543    }
 544};
 545
 546static void ipmi_register_types(void)
 547{
 548    type_register_static(&isa_ipmi_kcs_info);
 549}
 550
 551type_init(ipmi_register_types)
 552