diff options
-rw-r--r-- | core/ipmi.c | 40 | ||||
-rw-r--r-- | hw/bt.c | 6 | ||||
-rw-r--r-- | include/ipmi.h | 15 |
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 */ @@ -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); |