X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/rsbs2/blobdiff_plain/d51930558a73dd1083b924159971d4c77df411e6..67a9a9e866d0ff3c40dc2a4a5df32c6e39e9747f:/bmc/ipmb.c diff --git a/bmc/ipmb.c b/bmc/ipmb.c index 7d272fb..fa057c9 100644 --- a/bmc/ipmb.c +++ b/bmc/ipmb.c @@ -1,5 +1,8 @@ +#include #include +#include "i2c.h" +#include "chassis.h" #include "ipmb.h" uint8_t ipmb_csum(unsigned char *buf, int len) @@ -14,43 +17,232 @@ uint8_t ipmb_csum(unsigned char *buf, int len) return -csum; } -void decode_ipmb_pkt(unsigned char *buf, int len) +void ipmb_send(struct ipmb_resp *resp, unsigned char *data, uint8_t datalen) { + unsigned char buf[24]; + int len; +#ifdef DEBUG int i; - struct ipmb_req req; +#endif - req.rsSA = buf[0]; - req.netFn = (buf[1]>>2)&0x3f; - req.rsLUN = (buf[1] & 0x03); - req.rqSA = buf[3]; - req.rqSEQ = (buf[4]>>2)&0x3f; - req.rqLUN = (buf[4] & 0x03); - req.cmd = buf[5]; - req.data = buf+6; - req.datalen = len - 6 - 1; + buf[0] = resp->rqSA; + buf[1] = ((resp->netFn)<<2) | (resp->rqLUN & 0x3); + buf[2] = ipmb_csum(buf, 2); + buf[3] = resp->rsSA; + buf[4] = ((resp->rqSEQ)<<2) | (resp->rsLUN & 0x3); + buf[5] = resp->cmd; + memcpy(buf+6, data, datalen); + len = datalen + 7; + buf[len-1] = ipmb_csum(buf+3, len - 4); + +#ifdef DEBUG + printf("Sending: "); + for(i = 0; i < len; i++) { + printf("0x%02x ", buf[i]); + } + printf("\n"); +#endif + + i2c_send(buf, len); + +} + +#ifdef DEBUG +void ipmb_dump_req(struct ipmb_req *req) +{ + int i; printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); printf("Connection Header:\n"); - printf("\trs Slave Addr.: 0x%02x\n", req.rsSA); - printf("\tnetFn: 0x%02x, LUN: 0x%02x\n", req.netFn, req.rsLUN); - printf("\tChecksum: 0x%02x (%s)\n", buf[2], - (buf[2] == ipmb_csum(buf, 2)) ? "OK" : "Wrong"); + printf("\trs Slave Addr.: 0x%02x\n", req->rsSA); + printf("\tnetFn: 0x%02x, LUN: 0x%02x\n", req->netFn, req->rsLUN); printf("Data:\n"); - printf("\trq Slave Addr.: 0x%02x\n", req.rqSA); - printf("\trqSeq: 0x%02x, rqLUN: 0x%02x\n", req.rqSEQ, req.rqLUN); - printf("\tcmd: 0x%02x\n", req.cmd); + printf("\trq Slave Addr.: 0x%02x\n", req->rqSA); + printf("\trqSeq: 0x%02x, rqLUN: 0x%02x\n", req->rqSEQ, req->rqLUN); + printf("\tcmd: 0x%02x\n", req->cmd); printf("\tData: "); - for(i = 0; i < req.datalen; i++) { - printf("0x%02x ", req.data[i]); + for(i = 0; i < req->datalen; i++) { + printf("0x%02x ", req->data[i]); } printf("\n"); - printf("\tChecksum: 0x%02x (%s)\n", buf[len-1], - (buf[len-1] == ipmb_csum(buf+3, len-4)) ? "OK" : "Wrong"); printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); +} +#endif + +void ipmb_invalid(struct ipmb_resp *resp) +{ +#if 1 + static unsigned char cmd_invalid[] = {IPMB_CC_INVALID}; + + ipmb_send(resp, cmd_invalid, sizeof(cmd_invalid)); +#endif +} + +void ipmb_cmd(struct ipmb_req *req) +{ + struct ipmb_resp resp; + static unsigned char get_devid[] = + {IPMB_CC_NORMALLY, 0x42, 0x42, 0x01, 0x01, 0x51, 0xff /* Add. Dev. Supp */, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static unsigned char get_wd_timer[] = + {IPMB_CC_NORMALLY, 0x42, 0x00, 0x00, 0x04, 0xff, 0xff, 0xfe, 0xfe}; + static unsigned char cc_normal[] = + {IPMB_CC_NORMALLY}; + static unsigned char sel_info[] = + {IPMB_CC_NORMALLY, 0x51, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00}; + static unsigned char sel_alloc_info[] = + {IPMB_CC_NORMALLY, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + static unsigned char sel_entry[] = + {IPMB_CC_ERROR}; + static unsigned char sel_timestamp[] = + {IPMB_CC_NORMALLY, 0x00, 0x00, 0x00, 0x00}; + static unsigned char chassis_status[] = + {IPMB_CC_NORMALLY, 0x60, 0x10, 0x00, 0x00}; + static unsigned char reserve_sdr[] = + {IPMB_CC_NORMALLY, 0x00, 0x00}; + static unsigned char get_sdr[] = + {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; if ((buf[2] != ipmb_csum(buf, 2)) || - (buf[len-1] == ipmb_csum(buf+3, len-4))) + (buf[len-1] != ipmb_csum(buf+3, len-4))) return; /* Checksum wrong */ - //i2c_send((unsigned char*)"\x28\x00",1); + req.rsSA = buf[0]; + req.netFn = (buf[1]>>2)&0x3f; + req.rsLUN = (buf[1] & 0x03); + req.rqSA = buf[3]; + req.rqSEQ = (buf[4]>>2)&0x3f; + req.rqLUN = (buf[4] & 0x03); + req.cmd = buf[5]; + req.data = buf+6; + req.datalen = len - 6 - 1; + + ipmb_cmd(&req); }