aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/ipmi.c40
-rw-r--r--hw/bt.c6
-rw-r--r--include/ipmi.h15
3 files changed, 61 insertions, 0 deletions
diff --git a/core/ipmi.c b/core/ipmi.c
index 941cf52..04c381a 100644
--- a/core/ipmi.c
+++ b/core/ipmi.c
@@ -137,6 +137,46 @@ void ipmi_queue_msg_sync(struct ipmi_msg *msg)
unlock(&sync_lock);
}
+static void ipmi_read_event_complete(struct ipmi_msg *msg)
+{
+ prlog(PR_DEBUG, "IPMI read event %02x complete: %d bytes. cc: %02x\n",
+ msg->cmd, msg->resp_size, msg->cc);
+
+ /* TODO: Handle power control & PNOR handshake events */
+
+ ipmi_free_msg(msg);
+}
+
+static void ipmi_get_message_flags_complete(struct ipmi_msg *msg)
+{
+ uint8_t flags = msg->data[0];
+
+ ipmi_free_msg(msg);
+
+ prlog(PR_DEBUG, "IPMI Get Message Flags: %02x\n", flags);
+
+ /* Message available in the event buffer? Queue a Read Event command
+ * to retrieve it. The flag is cleared by performing a read */
+ if (flags & IPMI_MESSAGE_FLAGS_EVENT_BUFFER) {
+ msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_READ_EVENT,
+ ipmi_read_event_complete, NULL, NULL, 0, 16);
+ ipmi_queue_msg(msg);
+ }
+}
+
+void ipmi_sms_attention(void)
+{
+ struct ipmi_msg *msg;
+
+ /* todo: when we handle multiple IPMI interfaces, we'll need to
+ * ensure that this message is associated with the appropriate
+ * backend. */
+ msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_GET_MESSAGE_FLAGS,
+ ipmi_get_message_flags_complete, NULL, NULL, 0, 1);
+
+ ipmi_queue_msg(msg);
+}
+
void ipmi_register_backend(struct ipmi_backend *backend)
{
/* We only support one backend at the moment */
diff --git a/hw/bt.c b/hw/bt.c
index afdd5df..d5c71a8 100644
--- a/hw/bt.c
+++ b/hw/bt.c
@@ -418,12 +418,18 @@ static int bt_add_ipmi_msg(struct ipmi_msg *ipmi_msg)
void bt_irq(void)
{
uint8_t ireg = bt_inb(BT_INTMASK);
+ uint8_t ctrl = bt_inb(BT_CTRL);
bt.irq_ok = true;
if (ireg & BT_INTMASK_B2H_IRQ) {
bt_outb(BT_INTMASK_B2H_IRQ | BT_INTMASK_B2H_IRQEN, BT_INTMASK);
bt_poll(NULL, NULL);
}
+
+ if (ctrl & BT_CTRL_SMS_ATN) {
+ bt_outb(BT_CTRL_SMS_ATN, BT_CTRL);
+ ipmi_sms_attention();
+ }
}
/*
diff --git a/include/ipmi.h b/include/ipmi.h
index 5660704..9f9cfbb 100644
--- a/include/ipmi.h
+++ b/include/ipmi.h
@@ -76,6 +76,14 @@
#define IPMI_PWR_SYS_UNKNOWN 0x2a
#define IPMI_PWR_NOCHANGE 0x7f
+/* 22.{3,4} Clear / Get message flags */
+#define IPMI_MESSAGE_FLAGS_RX_MESSAGE_QUEUE (1<<0)
+#define IPMI_MESSAGE_FLAGS_EVENT_BUFFER (1<<1)
+#define IPMI_MESSAGE_FLAGS_WATCHDOG_PRE_TIMEOUT (1<<3)
+#define IPMI_MESSAGE_FLAGS_OEM0 (1<<5)
+#define IPMI_MESSAGE_FLAGS_OEM1 (1<<6)
+#define IPMI_MESSAGE_FLAGS_OEM2 (1<<7)
+
#define IPMI_CODE(netfn, cmd) ((netfn) << 8 | (cmd))
#define IPMI_CMD(code) ((code) & 0xff)
#define IPMI_NETFN(code) ((code) >> 8 & 0xff)
@@ -93,6 +101,10 @@
#define IPMI_CHASSIS_CONTROL IPMI_CODE(IPMI_NETFN_CHASSIS, 0x02)
#define IPMI_SET_POWER_STATE IPMI_CODE(IPMI_NETFN_APP, 0x06)
#define IPMI_GET_POWER_STATE IPMI_CODE(IPMI_NETFN_APP, 0x07)
+#define IPMI_CLEAR_MESSAGE_FLAGS IPMI_CODE(IPMI_NETFN_APP, 0x30)
+#define IPMI_GET_MESSAGE_FLAGS IPMI_CODE(IPMI_NETFN_APP, 0x31)
+#define IPMI_GET_MESSAGE IPMI_CODE(IPMI_NETFN_APP, 0x33)
+#define IPMI_READ_EVENT IPMI_CODE(IPMI_NETFN_APP, 0x35)
#define IPMI_PARTIAL_ADD_ESEL IPMI_CODE(IPMI_NETFN_OEM, 0xf0)
@@ -170,6 +182,9 @@ void ipmi_init_msg(struct ipmi_msg *msg, int interface,
uint32_t code, void (*complete)(struct ipmi_msg *),
void *user_data, size_t req_size, size_t resp_size);
+/* called by backend code to indicate a SMS_ATN event */
+void ipmi_sms_attention(void);
+
/* Add an ipmi message to the queue */
int ipmi_queue_msg(struct ipmi_msg *msg);