mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'ipmi-for-qemu-10.0' of https://github.com/cminyard/qemu into staging
Some minor fixes for various things # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCgAdFiEE/Q1c5nzg9ZpmiCaGYfOMkJGb/4EFAmgAQuQACgkQYfOMkJGb # /4G9EQ//do2GgBjj2NChR7G8CV7DyAA7rnhYx1txD8I4F1cyvMAW0flc8qE5MaC8 # pJpfvQwYJs60WQbg5RELEEPFubtMPz/OPgfZfpGsXBRwqbpl2c3JGrEpVnDpsqdW # VXd24gFEuHyFKLoa4VMeJ40TvCsHsndkFTb7v12mneiH52YJyYDdb6ywkbeJS34F # 1sX745LtgQbC/piFzcuwX/NvSPlk3O9FT84k4AdfUPpBJNicQ6aKeQB/kuXmecEU # 6i6j8E/oCzZM9yLXWFFg3Fit5F24CBK9uDpFLE1ctoOW0lsVaQ+e8ogprvY7KMlO # zZVu2CPOZPf6IwUC/nmvWukey1BHpJSpEwZPZJao3Bt+qxK3hEl2FNPQIBVLNsJ9 # /6f6VtdgYSkkMed3G11eVS+p5QwX+4GEg+rhV8HDMYPecpaSePR3DIomAUKTc9je # t89ooW3iy6egONcbZSlFILPRmfRHv2h6aLOSMAAFXgx4aKt1I9b0EpjqBvDgTIxZ # 3ehn2jnwG8jTYaJdkiXFvvYNn2A8qEJc1Hifud1skJchqFXn7e6mjneLuOWO4uYZ # /VnOljqu+KwyDWxCnMfkLuOd+PNnHvB9fctqRvYJpsyc+WyjmRhH+YlbG2yt/FZj # fmCjZWKrZR2e6GaUPQSTEpahbuySf4QV4B9sP+YOcSQFy3N8ocU= # =V8+d # -----END PGP SIGNATURE----- # gpg: Signature made Wed 16 Apr 2025 19:53:08 EDT # gpg: using RSA key FD0D5CE67CE0F59A6688268661F38C90919BFF81 # gpg: Good signature from "Corey Minyard <cminyard@mvista.com>" [unknown] # gpg: aka "Corey Minyard <corey@minyard.net>" [unknown] # gpg: aka "Corey Minyard <minyard@mvista.com>" [unknown] # gpg: aka "Corey Minyard <minyard@acm.org>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: FD0D 5CE6 7CE0 F59A 6688 2686 61F3 8C90 919B FF81 * tag 'ipmi-for-qemu-10.0' of https://github.com/cminyard/qemu: ipmi/bmc-sim: add error handling for 'Set BMC Global Enables' command ipmi/bmc-sim: implement watchdog dont log flag ipmi/bmc-sim: Add 'Get Channel Info' command ipmi: add fwinfo to pci ipmi devices ipmi/pci-ipmi-bt: Rename copy-paste variables hw/ipmi: Move vmsd registration to device class Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
+2
-1
@@ -55,7 +55,8 @@ static Aml *aml_ipmi_crs(IPMIFwInfo *info)
|
||||
abort();
|
||||
}
|
||||
|
||||
if (info->interrupt_number) {
|
||||
/* Should PCI interrupts also be appended? */
|
||||
if (info->irq_source == IPMI_ISA_IRQ && info->interrupt_number) {
|
||||
aml_append(crs, aml_irq_no_flags(info->interrupt_number));
|
||||
}
|
||||
|
||||
|
||||
@@ -497,8 +497,6 @@ static void ipmi_bmc_extern_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
qemu_chr_fe_set_handlers(&ibe->chr, can_receive, receive,
|
||||
chr_event, NULL, ibe, NULL, true);
|
||||
|
||||
vmstate_register(NULL, 0, &vmstate_ipmi_bmc_extern, ibe);
|
||||
}
|
||||
|
||||
static void ipmi_bmc_extern_init(Object *obj)
|
||||
@@ -528,6 +526,7 @@ static void ipmi_bmc_extern_class_init(ObjectClass *oc, void *data)
|
||||
bk->handle_reset = ipmi_bmc_extern_handle_reset;
|
||||
dc->hotpluggable = false;
|
||||
dc->realize = ipmi_bmc_extern_realize;
|
||||
dc->vmsd = &vmstate_ipmi_bmc_extern;
|
||||
device_class_set_props(dc, ipmi_bmc_extern_properties);
|
||||
}
|
||||
|
||||
|
||||
+93
-14
@@ -70,6 +70,7 @@
|
||||
#define IPMI_CMD_GET_MSG 0x33
|
||||
#define IPMI_CMD_SEND_MSG 0x34
|
||||
#define IPMI_CMD_READ_EVT_MSG_BUF 0x35
|
||||
#define IPMI_CMD_GET_CHANNEL_INFO 0x42
|
||||
|
||||
#define IPMI_NETFN_STORAGE 0x0a
|
||||
|
||||
@@ -234,6 +235,7 @@ struct IPMIBmcSim {
|
||||
#define IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(s) \
|
||||
(IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE & (s)->msg_flags)
|
||||
|
||||
#define IPMI_BMC_GLOBAL_ENABLES_SUPPORTED 0x0f
|
||||
#define IPMI_BMC_RCV_MSG_QUEUE_INT_BIT 0
|
||||
#define IPMI_BMC_EVBUF_FULL_INT_BIT 1
|
||||
#define IPMI_BMC_EVENT_MSG_BUF_BIT 2
|
||||
@@ -513,7 +515,8 @@ static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert,
|
||||
|
||||
static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
|
||||
unsigned int bit, unsigned int val,
|
||||
uint8_t evd1, uint8_t evd2, uint8_t evd3)
|
||||
uint8_t evd1, uint8_t evd2, uint8_t evd3,
|
||||
bool do_log)
|
||||
{
|
||||
IPMISensor *sens;
|
||||
uint16_t mask;
|
||||
@@ -533,7 +536,7 @@ static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
|
||||
return; /* Already asserted */
|
||||
}
|
||||
sens->assert_states |= mask & sens->assert_suppt;
|
||||
if (sens->assert_enable & mask & sens->assert_states) {
|
||||
if (do_log && (sens->assert_enable & mask & sens->assert_states)) {
|
||||
/* Send an event on assert */
|
||||
gen_event(ibs, sensor, 0, evd1, evd2, evd3);
|
||||
}
|
||||
@@ -543,7 +546,7 @@ static void sensor_set_discrete_bit(IPMIBmcSim *ibs, unsigned int sensor,
|
||||
return; /* Already deasserted */
|
||||
}
|
||||
sens->deassert_states |= mask & sens->deassert_suppt;
|
||||
if (sens->deassert_enable & mask & sens->deassert_states) {
|
||||
if (do_log && (sens->deassert_enable & mask & sens->deassert_states)) {
|
||||
/* Send an event on deassert */
|
||||
gen_event(ibs, sensor, 1, evd1, evd2, evd3);
|
||||
}
|
||||
@@ -699,6 +702,7 @@ static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
|
||||
{
|
||||
IPMIInterface *s = ibs->parent.intf;
|
||||
IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
|
||||
bool do_log = !IPMI_BMC_WATCHDOG_GET_DONT_LOG(ibs);
|
||||
|
||||
if (!ibs->watchdog_running) {
|
||||
goto out;
|
||||
@@ -710,14 +714,16 @@ static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
|
||||
ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
|
||||
k->do_hw_op(s, IPMI_SEND_NMI, 0);
|
||||
sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
|
||||
0xc8, (2 << 4) | 0xf, 0xff);
|
||||
0xc8, (2 << 4) | 0xf, 0xff,
|
||||
do_log);
|
||||
break;
|
||||
|
||||
case IPMI_BMC_WATCHDOG_PRE_MSG_INT:
|
||||
ibs->msg_flags |= IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK;
|
||||
k->set_atn(s, 1, attn_irq_enabled(ibs));
|
||||
sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 8, 1,
|
||||
0xc8, (3 << 4) | 0xf, 0xff);
|
||||
0xc8, (3 << 4) | 0xf, 0xff,
|
||||
do_log);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -737,24 +743,28 @@ static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
|
||||
switch (IPMI_BMC_WATCHDOG_GET_ACTION(ibs)) {
|
||||
case IPMI_BMC_WATCHDOG_ACTION_NONE:
|
||||
sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 0, 1,
|
||||
0xc0, ibs->watchdog_use & 0xf, 0xff);
|
||||
0xc0, ibs->watchdog_use & 0xf, 0xff,
|
||||
do_log);
|
||||
break;
|
||||
|
||||
case IPMI_BMC_WATCHDOG_ACTION_RESET:
|
||||
sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 1, 1,
|
||||
0xc1, ibs->watchdog_use & 0xf, 0xff);
|
||||
0xc1, ibs->watchdog_use & 0xf, 0xff,
|
||||
do_log);
|
||||
k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
|
||||
break;
|
||||
|
||||
case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
|
||||
sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
|
||||
0xc2, ibs->watchdog_use & 0xf, 0xff);
|
||||
0xc2, ibs->watchdog_use & 0xf, 0xff,
|
||||
do_log);
|
||||
k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
|
||||
break;
|
||||
|
||||
case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
|
||||
sensor_set_discrete_bit(ibs, IPMI_WATCHDOG_SENSOR, 2, 1,
|
||||
0xc3, ibs->watchdog_use & 0xf, 0xff);
|
||||
0xc3, ibs->watchdog_use & 0xf, 0xff,
|
||||
do_log);
|
||||
k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
|
||||
break;
|
||||
}
|
||||
@@ -925,7 +935,14 @@ static void set_bmc_global_enables(IPMIBmcSim *ibs,
|
||||
uint8_t *cmd, unsigned int cmd_len,
|
||||
RspBuffer *rsp)
|
||||
{
|
||||
set_global_enables(ibs, cmd[2]);
|
||||
uint8_t val = cmd[2];
|
||||
|
||||
if (val & ~IPMI_BMC_GLOBAL_ENABLES_SUPPORTED) {
|
||||
rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
|
||||
return;
|
||||
}
|
||||
|
||||
set_global_enables(ibs, val);
|
||||
}
|
||||
|
||||
static void get_bmc_global_enables(IPMIBmcSim *ibs,
|
||||
@@ -1020,8 +1037,8 @@ static void send_msg(IPMIBmcSim *ibs,
|
||||
uint8_t *buf;
|
||||
uint8_t netfn, rqLun, rsLun, rqSeq;
|
||||
|
||||
if (cmd[2] != 0) {
|
||||
/* We only handle channel 0 with no options */
|
||||
if (cmd[2] != IPMI_CHANNEL_IPMB) {
|
||||
/* We only handle channel 0h (IPMB) with no options */
|
||||
rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
|
||||
return;
|
||||
}
|
||||
@@ -1219,6 +1236,68 @@ static void get_watchdog_timer(IPMIBmcSim *ibs,
|
||||
}
|
||||
}
|
||||
|
||||
static void get_channel_info(IPMIBmcSim *ibs,
|
||||
uint8_t *cmd, unsigned int cmd_len,
|
||||
RspBuffer *rsp)
|
||||
{
|
||||
IPMIInterface *s = ibs->parent.intf;
|
||||
IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
|
||||
IPMIFwInfo info = {};
|
||||
uint8_t ch = cmd[2] & 0x0f;
|
||||
|
||||
/* Only define channel 0h (IPMB) and Fh (system interface) */
|
||||
|
||||
if (ch == 0x0e) { /* "This channel" */
|
||||
ch = IPMI_CHANNEL_SYSTEM;
|
||||
}
|
||||
rsp_buffer_push(rsp, ch);
|
||||
|
||||
if (ch != IPMI_CHANNEL_IPMB && ch != IPMI_CHANNEL_SYSTEM) {
|
||||
/* Not a supported channel */
|
||||
rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
|
||||
return;
|
||||
}
|
||||
|
||||
if (k->get_fwinfo) {
|
||||
k->get_fwinfo(s, &info);
|
||||
}
|
||||
|
||||
if (ch == IPMI_CHANNEL_IPMB) {
|
||||
rsp_buffer_push(rsp, IPMI_CHANNEL_MEDIUM_IPMB);
|
||||
rsp_buffer_push(rsp, IPMI_CHANNEL_PROTOCOL_IPMB);
|
||||
} else { /* IPMI_CHANNEL_SYSTEM */
|
||||
rsp_buffer_push(rsp, IPMI_CHANNEL_MEDIUM_SYSTEM);
|
||||
rsp_buffer_push(rsp, info.ipmi_channel_protocol);
|
||||
}
|
||||
|
||||
rsp_buffer_push(rsp, 0x00); /* Session-less */
|
||||
|
||||
/* IPMI Enterprise Number for Vendor ID */
|
||||
rsp_buffer_push(rsp, 0xf2);
|
||||
rsp_buffer_push(rsp, 0x1b);
|
||||
rsp_buffer_push(rsp, 0x00);
|
||||
|
||||
if (ch == IPMI_CHANNEL_SYSTEM) {
|
||||
uint8_t irq;
|
||||
|
||||
if (info.irq_source == IPMI_ISA_IRQ) {
|
||||
irq = info.interrupt_number;
|
||||
} else if (info.irq_source == IPMI_PCI_IRQ) {
|
||||
irq = 0x10 + info.interrupt_number;
|
||||
} else {
|
||||
irq = 0xff; /* no interrupt / unspecified */
|
||||
}
|
||||
|
||||
/* Both interrupts use the same irq number */
|
||||
rsp_buffer_push(rsp, irq);
|
||||
rsp_buffer_push(rsp, irq);
|
||||
} else {
|
||||
/* Reserved */
|
||||
rsp_buffer_push(rsp, 0x00);
|
||||
rsp_buffer_push(rsp, 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
static void get_sdr_rep_info(IPMIBmcSim *ibs,
|
||||
uint8_t *cmd, unsigned int cmd_len,
|
||||
RspBuffer *rsp)
|
||||
@@ -2015,6 +2094,7 @@ static const IPMICmdHandler app_cmds[] = {
|
||||
[IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
|
||||
[IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
|
||||
[IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
|
||||
[IPMI_CMD_GET_CHANNEL_INFO] = { get_channel_info, 3 },
|
||||
};
|
||||
static const IPMINetfn app_netfn = {
|
||||
.cmd_nums = ARRAY_SIZE(app_cmds),
|
||||
@@ -2187,8 +2267,6 @@ static void ipmi_sim_realize(DeviceState *dev, Error **errp)
|
||||
register_cmds(ibs);
|
||||
|
||||
ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
|
||||
|
||||
vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
|
||||
}
|
||||
|
||||
static const Property ipmi_sim_properties[] = {
|
||||
@@ -2212,6 +2290,7 @@ static void ipmi_sim_class_init(ObjectClass *oc, void *data)
|
||||
|
||||
dc->hotpluggable = false;
|
||||
dc->realize = ipmi_sim_realize;
|
||||
dc->vmsd = &vmstate_ipmi_sim;
|
||||
device_class_set_props(dc, ipmi_sim_properties);
|
||||
bk->handle_command = ipmi_sim_handle_command;
|
||||
}
|
||||
|
||||
@@ -419,6 +419,8 @@ void ipmi_bt_get_fwinfo(struct IPMIBT *ib, IPMIFwInfo *info)
|
||||
info->interface_type = IPMI_SMBIOS_BT;
|
||||
info->ipmi_spec_major_revision = 2;
|
||||
info->ipmi_spec_minor_revision = 0;
|
||||
/* BT System Interface Format, IPMI v1.5 */
|
||||
info->ipmi_channel_protocol = IPMI_CHANNEL_PROTOCOL_BT_15;
|
||||
info->base_address = ib->io_base;
|
||||
info->register_length = ib->io_length;
|
||||
info->register_spacing = 1;
|
||||
|
||||
@@ -405,6 +405,7 @@ void ipmi_kcs_get_fwinfo(IPMIKCS *ik, IPMIFwInfo *info)
|
||||
info->interface_type = IPMI_SMBIOS_KCS;
|
||||
info->ipmi_spec_major_revision = 2;
|
||||
info->ipmi_spec_minor_revision = 0;
|
||||
info->ipmi_channel_protocol = IPMI_CHANNEL_PROTOCOL_KCS;
|
||||
info->base_address = ik->io_base;
|
||||
info->i2c_slave_address = ik->bmc->slave_addr;
|
||||
info->register_length = ik->io_length;
|
||||
|
||||
@@ -49,6 +49,7 @@ static void isa_ipmi_bt_get_fwinfo(struct IPMIInterface *ii, IPMIFwInfo *info)
|
||||
ISAIPMIBTDevice *iib = ISA_IPMI_BT(ii);
|
||||
|
||||
ipmi_bt_get_fwinfo(&iib->bt, info);
|
||||
info->irq_source = IPMI_ISA_IRQ;
|
||||
info->interrupt_number = iib->isairq;
|
||||
info->i2c_slave_address = iib->bt.bmc->slave_addr;
|
||||
info->uuid = iib->uuid;
|
||||
@@ -117,8 +118,6 @@ static void isa_ipmi_bt_realize(DeviceState *dev, Error **errp)
|
||||
qdev_set_legacy_instance_id(dev, iib->bt.io_base, iib->bt.io_length);
|
||||
|
||||
isa_register_ioport(isadev, &iib->bt.io, iib->bt.io_base);
|
||||
|
||||
vmstate_register(NULL, 0, &vmstate_ISAIPMIBTDevice, dev);
|
||||
}
|
||||
|
||||
static void isa_ipmi_bt_init(Object *obj)
|
||||
@@ -147,6 +146,7 @@ static void isa_ipmi_bt_class_init(ObjectClass *oc, void *data)
|
||||
AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(oc);
|
||||
|
||||
dc->realize = isa_ipmi_bt_realize;
|
||||
dc->vmsd = &vmstate_ISAIPMIBTDevice;
|
||||
device_class_set_props(dc, ipmi_isa_properties);
|
||||
|
||||
iic->get_backend_data = isa_ipmi_bt_get_backend_data;
|
||||
|
||||
@@ -49,6 +49,7 @@ static void isa_ipmi_kcs_get_fwinfo(IPMIInterface *ii, IPMIFwInfo *info)
|
||||
ISAIPMIKCSDevice *iik = ISA_IPMI_KCS(ii);
|
||||
|
||||
ipmi_kcs_get_fwinfo(&iik->kcs, info);
|
||||
info->irq_source = IPMI_ISA_IRQ;
|
||||
info->interrupt_number = iik->isairq;
|
||||
info->uuid = iik->uuid;
|
||||
}
|
||||
@@ -72,6 +73,10 @@ static bool vmstate_kcs_before_version2(void *opaque, int version)
|
||||
return version <= 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Version 1 had an incorrect name, it clashed with the BT IPMI
|
||||
* device, so receive it, but transmit a different version.
|
||||
*/
|
||||
static const VMStateDescription vmstate_ISAIPMIKCSDevice = {
|
||||
.name = TYPE_IPMI_INTERFACE,
|
||||
.version_id = 2,
|
||||
@@ -119,13 +124,6 @@ static void ipmi_isa_realize(DeviceState *dev, Error **errp)
|
||||
qdev_set_legacy_instance_id(dev, iik->kcs.io_base, iik->kcs.io_length);
|
||||
|
||||
isa_register_ioport(isadev, &iik->kcs.io, iik->kcs.io_base);
|
||||
|
||||
/*
|
||||
* Version 1 had an incorrect name, it clashed with the BT
|
||||
* IPMI device, so receive it, but transmit a different
|
||||
* version.
|
||||
*/
|
||||
vmstate_register(NULL, 0, &vmstate_ISAIPMIKCSDevice, iik);
|
||||
}
|
||||
|
||||
static void isa_ipmi_kcs_init(Object *obj)
|
||||
@@ -154,6 +152,7 @@ static void isa_ipmi_kcs_class_init(ObjectClass *oc, void *data)
|
||||
AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(oc);
|
||||
|
||||
dc->realize = ipmi_isa_realize;
|
||||
dc->vmsd = &vmstate_ISAIPMIKCSDevice;
|
||||
device_class_set_props(dc, ipmi_isa_properties);
|
||||
|
||||
iic->get_backend_data = isa_ipmi_kcs_get_backend_data;
|
||||
|
||||
+31
-19
@@ -38,49 +38,60 @@ struct PCIIPMIBTDevice {
|
||||
uint32_t uuid;
|
||||
};
|
||||
|
||||
static void pci_ipmi_raise_irq(IPMIBT *ik)
|
||||
static void pci_ipmi_bt_get_fwinfo(struct IPMIInterface *ii, IPMIFwInfo *info)
|
||||
{
|
||||
PCIIPMIBTDevice *pik = ik->opaque;
|
||||
PCIIPMIBTDevice *pib = PCI_IPMI_BT(ii);
|
||||
|
||||
pci_set_irq(&pik->dev, true);
|
||||
ipmi_bt_get_fwinfo(&pib->bt, info);
|
||||
info->irq_source = IPMI_PCI_IRQ;
|
||||
info->interrupt_number = pci_intx(&pib->dev);
|
||||
info->i2c_slave_address = pib->bt.bmc->slave_addr;
|
||||
info->uuid = pib->uuid;
|
||||
}
|
||||
|
||||
static void pci_ipmi_lower_irq(IPMIBT *ik)
|
||||
static void pci_ipmi_raise_irq(IPMIBT *ib)
|
||||
{
|
||||
PCIIPMIBTDevice *pik = ik->opaque;
|
||||
PCIIPMIBTDevice *pib = ib->opaque;
|
||||
|
||||
pci_set_irq(&pik->dev, false);
|
||||
pci_set_irq(&pib->dev, true);
|
||||
}
|
||||
|
||||
static void pci_ipmi_lower_irq(IPMIBT *ib)
|
||||
{
|
||||
PCIIPMIBTDevice *pib = ib->opaque;
|
||||
|
||||
pci_set_irq(&pib->dev, false);
|
||||
}
|
||||
|
||||
static void pci_ipmi_bt_realize(PCIDevice *pd, Error **errp)
|
||||
{
|
||||
Error *err = NULL;
|
||||
PCIIPMIBTDevice *pik = PCI_IPMI_BT(pd);
|
||||
PCIIPMIBTDevice *pib = PCI_IPMI_BT(pd);
|
||||
IPMIInterface *ii = IPMI_INTERFACE(pd);
|
||||
IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
|
||||
|
||||
if (!pik->bt.bmc) {
|
||||
if (!pib->bt.bmc) {
|
||||
error_setg(errp, "IPMI device requires a bmc attribute to be set");
|
||||
return;
|
||||
}
|
||||
|
||||
pik->uuid = ipmi_next_uuid();
|
||||
pib->uuid = ipmi_next_uuid();
|
||||
|
||||
pik->bt.bmc->intf = ii;
|
||||
pik->bt.opaque = pik;
|
||||
pib->bt.bmc->intf = ii;
|
||||
pib->bt.opaque = pib;
|
||||
|
||||
pci_config_set_prog_interface(pd->config, 0x02); /* BT */
|
||||
pci_config_set_interrupt_pin(pd->config, 0x01);
|
||||
pik->bt.use_irq = 1;
|
||||
pik->bt.raise_irq = pci_ipmi_raise_irq;
|
||||
pik->bt.lower_irq = pci_ipmi_lower_irq;
|
||||
pib->bt.use_irq = 1;
|
||||
pib->bt.raise_irq = pci_ipmi_raise_irq;
|
||||
pib->bt.lower_irq = pci_ipmi_lower_irq;
|
||||
|
||||
iic->init(ii, 8, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
pci_register_bar(pd, 0, PCI_BASE_ADDRESS_SPACE_IO, &pik->bt.io);
|
||||
pci_register_bar(pd, 0, PCI_BASE_ADDRESS_SPACE_IO, &pib->bt.io);
|
||||
}
|
||||
|
||||
const VMStateDescription vmstate_PCIIPMIBTDevice = {
|
||||
@@ -96,16 +107,16 @@ const VMStateDescription vmstate_PCIIPMIBTDevice = {
|
||||
|
||||
static void pci_ipmi_bt_instance_init(Object *obj)
|
||||
{
|
||||
PCIIPMIBTDevice *pik = PCI_IPMI_BT(obj);
|
||||
PCIIPMIBTDevice *pib = PCI_IPMI_BT(obj);
|
||||
|
||||
ipmi_bmc_find_and_link(obj, (Object **) &pik->bt.bmc);
|
||||
ipmi_bmc_find_and_link(obj, (Object **) &pib->bt.bmc);
|
||||
}
|
||||
|
||||
static void *pci_ipmi_bt_get_backend_data(IPMIInterface *ii)
|
||||
{
|
||||
PCIIPMIBTDevice *pik = PCI_IPMI_BT(ii);
|
||||
PCIIPMIBTDevice *pib = PCI_IPMI_BT(ii);
|
||||
|
||||
return &pik->bt;
|
||||
return &pib->bt;
|
||||
}
|
||||
|
||||
static void pci_ipmi_bt_class_init(ObjectClass *oc, void *data)
|
||||
@@ -125,6 +136,7 @@ static void pci_ipmi_bt_class_init(ObjectClass *oc, void *data)
|
||||
|
||||
iic->get_backend_data = pci_ipmi_bt_get_backend_data;
|
||||
ipmi_bt_class_init(iic);
|
||||
iic->get_fwinfo = pci_ipmi_bt_get_fwinfo;
|
||||
}
|
||||
|
||||
static const TypeInfo pci_ipmi_bt_info = {
|
||||
|
||||
@@ -38,6 +38,16 @@ struct PCIIPMIKCSDevice {
|
||||
uint32_t uuid;
|
||||
};
|
||||
|
||||
static void pci_ipmi_kcs_get_fwinfo(struct IPMIInterface *ii, IPMIFwInfo *info)
|
||||
{
|
||||
PCIIPMIKCSDevice *pik = PCI_IPMI_KCS(ii);
|
||||
|
||||
ipmi_kcs_get_fwinfo(&pik->kcs, info);
|
||||
info->irq_source = IPMI_PCI_IRQ;
|
||||
info->interrupt_number = pci_intx(&pik->dev);
|
||||
info->uuid = pik->uuid;
|
||||
}
|
||||
|
||||
static void pci_ipmi_raise_irq(IPMIKCS *ik)
|
||||
{
|
||||
PCIIPMIKCSDevice *pik = ik->opaque;
|
||||
@@ -125,6 +135,7 @@ static void pci_ipmi_kcs_class_init(ObjectClass *oc, void *data)
|
||||
|
||||
iic->get_backend_data = pci_ipmi_kcs_get_backend_data;
|
||||
ipmi_kcs_class_init(iic);
|
||||
iic->get_fwinfo = pci_ipmi_kcs_get_fwinfo;
|
||||
}
|
||||
|
||||
static const TypeInfo pci_ipmi_kcs_info = {
|
||||
|
||||
@@ -72,7 +72,12 @@ static void smbios_build_one_type_38(IPMIFwInfo *info)
|
||||
" SMBIOS, ignoring this entry.", info->register_spacing);
|
||||
return;
|
||||
}
|
||||
t->interrupt_number = info->interrupt_number;
|
||||
if (info->irq_source == IPMI_ISA_IRQ) {
|
||||
t->interrupt_number = info->interrupt_number;
|
||||
} else {
|
||||
/* TODO: How to handle PCI? */
|
||||
t->interrupt_number = 0;
|
||||
}
|
||||
|
||||
SMBIOS_BUILD_TABLE_POST;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,15 @@ enum ipmi_op {
|
||||
IPMI_SEND_NMI
|
||||
};
|
||||
|
||||
/* Channel properties */
|
||||
#define IPMI_CHANNEL_IPMB 0x00
|
||||
#define IPMI_CHANNEL_SYSTEM 0x0f
|
||||
#define IPMI_CHANNEL_MEDIUM_IPMB 0x01
|
||||
#define IPMI_CHANNEL_MEDIUM_SYSTEM 0x0c
|
||||
#define IPMI_CHANNEL_PROTOCOL_IPMB 0x01
|
||||
#define IPMI_CHANNEL_PROTOCOL_KCS 0x05
|
||||
#define IPMI_CHANNEL_PROTOCOL_BT_15 0x08
|
||||
|
||||
#define IPMI_CC_INVALID_CMD 0xc1
|
||||
#define IPMI_CC_COMMAND_INVALID_FOR_LUN 0xc2
|
||||
#define IPMI_CC_TIMEOUT 0xc3
|
||||
@@ -76,6 +85,7 @@ typedef struct IPMIFwInfo {
|
||||
int interface_type;
|
||||
uint8_t ipmi_spec_major_revision;
|
||||
uint8_t ipmi_spec_minor_revision;
|
||||
uint8_t ipmi_channel_protocol;
|
||||
uint8_t i2c_slave_address;
|
||||
uint32_t uuid;
|
||||
|
||||
@@ -90,6 +100,11 @@ typedef struct IPMIFwInfo {
|
||||
} memspace;
|
||||
|
||||
int interrupt_number;
|
||||
enum {
|
||||
IPMI_NO_IRQ = 0,
|
||||
IPMI_ISA_IRQ,
|
||||
IPMI_PCI_IRQ,
|
||||
} irq_source;
|
||||
enum {
|
||||
IPMI_LEVEL_IRQ,
|
||||
IPMI_EDGE_IRQ
|
||||
|
||||
Reference in New Issue
Block a user