+}
+#endif
+
+void ipmb_invalid(struct ipmb_resp *resp)
+{
+#if 1
+ static const unsigned char cmd_invalid[] PROGMEM = {IPMB_CC_INVALID};
+
+ ipmb_send(resp, cmd_invalid, sizeof(cmd_invalid));
+#endif
+}
+
+void ipmb_cmd(struct ipmb_req *req)
+{
+ struct ipmb_resp resp;
+ static const unsigned char get_devid[] PROGMEM =
+ {IPMB_CC_NORMALLY, 0x42, 0x42, 0x01, 0x01, 0x51, 0xff /* Add. Dev. Supp */, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const unsigned char get_wd_timer[] PROGMEM =
+ {IPMB_CC_NORMALLY, 0x42, 0x00, 0x00, 0x04, 0xff, 0xff, 0xfe, 0xfe};
+ static const unsigned char cc_normal[] PROGMEM =
+ {IPMB_CC_NORMALLY};
+ static const unsigned char sel_info[] PROGMEM =
+ {IPMB_CC_NORMALLY, 0x51, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00};
+ static const unsigned char sel_alloc_info[] PROGMEM =
+ {IPMB_CC_NORMALLY, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ static const unsigned char sel_entry[] PROGMEM =
+ {IPMB_CC_ERROR};
+ static const unsigned char sel_timestamp[] PROGMEM =
+ {IPMB_CC_NORMALLY, 0x00, 0x00, 0x00, 0x00};
+ static const unsigned char chassis_status[] PROGMEM =
+ {IPMB_CC_NORMALLY, 0x60, 0x10, 0x00, 0x00};
+ static const unsigned char reserve_sdr[] PROGMEM =
+ {IPMB_CC_NORMALLY, 0x00, 0x00};
+ static const unsigned char get_sdr[] PROGMEM =
+ {IPMB_CC_NORMALLY, 0xff, 0xff};
+
+ resp.rqSA = req->rqSA;
+ resp.netFn = req->netFn+1;
+ resp.rqLUN = req->rqLUN;
+ resp.rsSA = req->rsSA;
+ resp.rqSEQ = req->rqSEQ;
+ resp.rsLUN = req->rsLUN;
+ resp.cmd = req->cmd;
+
+ switch (req->netFn) {
+ case IPMB_NETFN_CHASSIS:
+ switch (req->cmd) {
+ case IPMB_CHASSIS_GET_STATUS:
+ ipmb_send(&resp, chassis_status, sizeof(chassis_status));
+ break;
+ case IPMB_CHASSIS_CONTROL:
+ chassis_control(*(req->data));
+ ipmb_send(&resp, cc_normal, sizeof(cc_normal));
+ break;
+ default:
+#ifdef DEBUG
+ printf("Unknown chassis cmd 0x%02x\n", req->cmd);
+ ipmb_dump_req(req);
+#endif
+ ipmb_invalid(&resp);
+ break;
+ }
+ break;
+
+ case IPMB_NETFN_SENSOR_EVENT:
+ switch (req->cmd) {
+ case IPMB_SE_PLATFORM_EVENT:
+ /*
+ * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+ * Connection Header:
+ * rs Slave Addr.: 0x24
+ * netFn: 0x04, LUN: 0x00
+ * Data:
+ * rq Slave Addr.: 0x28
+ * rqSeq: 0x03, rqLUN: 0x00
+ * cmd: 0x02
+ * Data: 0x03 0xc8 0x00 0x6f 0x61 0x8f 0x03
+ * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ * data[0] - EvMRev: 0x03
+ * data[1] - Sensor Type: 0xc8
+ * data[2] - Sensor #: 0x00
+ * data[3] - Event Dir(1)|Event Type(7): 0x6f: 0x0|0x6f (assert, discrete)
+ * data[4] - Event Data: 0x61
+ * data[5] - Event Data: 0x8f
+ * data[6] - Event Data: 0x03
+ */
+ ipmb_send(&resp, cc_normal, sizeof(cc_normal));
+ break;
+
+
+ default:
+#ifdef DEBUG
+ printf("Unknown sensor cmd 0x%02x\n", req->cmd);
+ ipmb_dump_req(req);
+#endif
+ ipmb_invalid(&resp);
+ break;
+ }
+ break;
+
+ case IPMB_NETFN_APP:
+ switch (req->cmd) {
+ case IPMB_APP_GET_DEVICE_ID:
+ ipmb_send(&resp, get_devid, sizeof(get_devid));
+ break;
+
+ case IPMB_APP_GET_WATCHDOG_TIMER:
+ ipmb_send(&resp, get_wd_timer, sizeof(get_wd_timer));
+ break;
+
+ default:
+#ifdef DEBUG
+ printf("Unknown app cmd 0x%02x\n", req->cmd);
+ ipmb_dump_req(req);
+#endif
+ ipmb_invalid(&resp);
+ break;
+ }
+ break;
+
+ case IPMB_NETFN_STORAGE:
+ switch (req->cmd) {
+ case IPMB_STORAGE_RESERVE_SDR:
+ ipmb_send(&resp, reserve_sdr, sizeof(reserve_sdr));
+ break;
+ case IPMB_STORAGE_GET_SDR:
+ ipmb_send(&resp, get_sdr, sizeof(get_sdr));
+ break;
+ case IPMB_STORAGE_GET_SEL_INFO:
+ ipmb_send(&resp, sel_info, sizeof(sel_info));
+ break;
+ case IPMB_STORAGE_GET_SEL_ALLOCATION:
+ ipmb_send(&resp, sel_alloc_info, sizeof(sel_alloc_info));
+ break;
+ case IPMB_STORAGE_GET_SEL_ENTRY:
+ ipmb_send(&resp, sel_entry, sizeof(sel_entry));
+ break;
+ case IPMB_STORAGE_GET_SEL_TIME:
+ ipmb_send(&resp, sel_timestamp, sizeof(sel_timestamp));
+ break;
+ default:
+#ifdef DEBUG
+ printf("Unknown storage cmd 0x%02x\n", req->cmd);
+ ipmb_dump_req(req);
+#endif
+ ipmb_invalid(&resp);
+ break;
+ }
+ break;
+
+ default:
+#ifdef DEBUG
+ printf("Unknown netFn 0x%02x\n", req->netFn);
+ ipmb_dump_req(req);
+#endif
+ ipmb_invalid(&resp);
+ break;
+ }
+}
+
+void decode_ipmb_pkt(unsigned char *buf, int len)
+{
+ struct ipmb_req req;