]>
Commit | Line | Data |
---|---|---|
da7751cb | 1 | #include <string.h> |
d5193055 MG |
2 | #include <stdio.h> |
3 | ||
da7751cb MG |
4 | #include "i2c.h" |
5 | #include "chassis.h" | |
d5193055 MG |
6 | #include "ipmb.h" |
7 | ||
8 | uint8_t ipmb_csum(unsigned char *buf, int len) | |
9 | { | |
10 | uint8_t csum = 0x00; | |
11 | int i; | |
12 | ||
13 | for(i = 0; i < len; i++) { | |
14 | csum += buf[i]; | |
15 | } | |
16 | ||
17 | return -csum; | |
18 | } | |
19 | ||
67a9a9e8 | 20 | void ipmb_send(struct ipmb_resp *resp, unsigned char *data, uint8_t datalen) |
d5193055 | 21 | { |
da7751cb MG |
22 | unsigned char buf[24]; |
23 | int len; | |
24 | #ifdef DEBUG | |
d5193055 | 25 | int i; |
da7751cb | 26 | #endif |
d5193055 | 27 | |
da7751cb MG |
28 | buf[0] = resp->rqSA; |
29 | buf[1] = ((resp->netFn)<<2) | (resp->rqLUN & 0x3); | |
30 | buf[2] = ipmb_csum(buf, 2); | |
31 | buf[3] = resp->rsSA; | |
32 | buf[4] = ((resp->rqSEQ)<<2) | (resp->rsLUN & 0x3); | |
33 | buf[5] = resp->cmd; | |
67a9a9e8 MG |
34 | memcpy(buf+6, data, datalen); |
35 | len = datalen + 7; | |
da7751cb MG |
36 | buf[len-1] = ipmb_csum(buf+3, len - 4); |
37 | ||
38 | #ifdef DEBUG | |
39 | printf("Sending: "); | |
40 | for(i = 0; i < len; i++) { | |
41 | printf("0x%02x ", buf[i]); | |
42 | } | |
43 | printf("\n"); | |
44 | #endif | |
45 | ||
46 | i2c_send(buf, len); | |
47 | ||
48 | } | |
49 | ||
50 | #ifdef DEBUG | |
51 | void ipmb_dump_req(struct ipmb_req *req) | |
52 | { | |
53 | int i; | |
d5193055 MG |
54 | |
55 | printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); | |
56 | printf("Connection Header:\n"); | |
da7751cb MG |
57 | printf("\trs Slave Addr.: 0x%02x\n", req->rsSA); |
58 | printf("\tnetFn: 0x%02x, LUN: 0x%02x\n", req->netFn, req->rsLUN); | |
d5193055 | 59 | printf("Data:\n"); |
da7751cb MG |
60 | printf("\trq Slave Addr.: 0x%02x\n", req->rqSA); |
61 | printf("\trqSeq: 0x%02x, rqLUN: 0x%02x\n", req->rqSEQ, req->rqLUN); | |
62 | printf("\tcmd: 0x%02x\n", req->cmd); | |
d5193055 | 63 | printf("\tData: "); |
da7751cb MG |
64 | for(i = 0; i < req->datalen; i++) { |
65 | printf("0x%02x ", req->data[i]); | |
d5193055 MG |
66 | } |
67 | printf("\n"); | |
d5193055 | 68 | printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); |
da7751cb MG |
69 | } |
70 | #endif | |
71 | ||
72 | void ipmb_invalid(struct ipmb_resp *resp) | |
73 | { | |
67a9a9e8 MG |
74 | #if 1 |
75 | static unsigned char cmd_invalid[] = {IPMB_CC_INVALID}; | |
da7751cb | 76 | |
67a9a9e8 | 77 | ipmb_send(resp, cmd_invalid, sizeof(cmd_invalid)); |
da7751cb MG |
78 | #endif |
79 | } | |
80 | ||
81 | void ipmb_cmd(struct ipmb_req *req) | |
82 | { | |
83 | struct ipmb_resp resp; | |
84 | static unsigned char get_devid[] = | |
85 | {IPMB_CC_NORMALLY, 0x42, 0x42, 0x01, 0x01, 0x51, 0xff /* Add. Dev. Supp */, 0x00, 0x00, 0x00, 0x00, 0x00 }; | |
86 | static unsigned char get_wd_timer[] = | |
87 | {IPMB_CC_NORMALLY, 0x42, 0x00, 0x00, 0x04, 0xff, 0xff, 0xfe, 0xfe}; | |
88 | static unsigned char cc_normal[] = | |
89 | {IPMB_CC_NORMALLY}; | |
67a9a9e8 MG |
90 | static unsigned char sel_info[] = |
91 | {IPMB_CC_NORMALLY, 0x51, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
92 | static unsigned char sel_alloc_info[] = | |
93 | {IPMB_CC_NORMALLY, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
94 | static unsigned char sel_entry[] = | |
95 | {IPMB_CC_ERROR}; | |
96 | static unsigned char sel_timestamp[] = | |
97 | {IPMB_CC_NORMALLY, 0x00, 0x00, 0x00, 0x00}; | |
98 | static unsigned char chassis_status[] = | |
99 | {IPMB_CC_NORMALLY, 0x60, 0x10, 0x00, 0x00}; | |
100 | static unsigned char reserve_sdr[] = | |
101 | {IPMB_CC_NORMALLY, 0x00, 0x00}; | |
102 | static unsigned char get_sdr[] = | |
103 | {IPMB_CC_NORMALLY, 0xff, 0xff}; | |
da7751cb MG |
104 | |
105 | resp.rqSA = req->rqSA; | |
106 | resp.netFn = req->netFn+1; | |
107 | resp.rqLUN = req->rqLUN; | |
108 | resp.rsSA = req->rsSA; | |
109 | resp.rqSEQ = req->rqSEQ; | |
110 | resp.rsLUN = req->rsLUN; | |
111 | resp.cmd = req->cmd; | |
112 | ||
113 | switch (req->netFn) { | |
114 | case IPMB_NETFN_CHASSIS: | |
115 | switch (req->cmd) { | |
67a9a9e8 MG |
116 | case IPMB_CHASSIS_GET_STATUS: |
117 | ipmb_send(&resp, chassis_status, sizeof(chassis_status)); | |
118 | break; | |
da7751cb MG |
119 | case IPMB_CHASSIS_CONTROL: |
120 | chassis_control(*(req->data)); | |
67a9a9e8 | 121 | ipmb_send(&resp, cc_normal, sizeof(cc_normal)); |
da7751cb MG |
122 | break; |
123 | default: | |
124 | #ifdef DEBUG | |
125 | printf("Unknown chassis cmd 0x%02x\n", req->cmd); | |
126 | ipmb_dump_req(req); | |
127 | #endif | |
128 | ipmb_invalid(&resp); | |
129 | break; | |
130 | } | |
131 | break; | |
132 | ||
133 | case IPMB_NETFN_SENSOR_EVENT: | |
134 | switch (req->cmd) { | |
4f3bb118 MG |
135 | case IPMB_SE_PLATFORM_EVENT: |
136 | /* | |
137 | * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> | |
138 | * Connection Header: | |
139 | * rs Slave Addr.: 0x24 | |
140 | * netFn: 0x04, LUN: 0x00 | |
141 | * Data: | |
142 | * rq Slave Addr.: 0x28 | |
143 | * rqSeq: 0x03, rqLUN: 0x00 | |
144 | * cmd: 0x02 | |
145 | * Data: 0x03 0xc8 0x00 0x6f 0x61 0x8f 0x03 | |
146 | * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
147 | * data[0] - EvMRev: 0x03 | |
148 | * data[1] - Sensor Type: 0xc8 | |
149 | * data[2] - Sensor #: 0x00 | |
150 | * data[3] - Event Dir(1)|Event Type(7): 0x6f: 0x0|0x6f (assert, discrete) | |
151 | * data[4] - Event Data: 0x61 | |
152 | * data[5] - Event Data: 0x8f | |
153 | * data[6] - Event Data: 0x03 | |
154 | */ | |
67a9a9e8 | 155 | ipmb_send(&resp, cc_normal, sizeof(cc_normal)); |
4f3bb118 MG |
156 | break; |
157 | ||
158 | ||
da7751cb MG |
159 | default: |
160 | #ifdef DEBUG | |
161 | printf("Unknown sensor cmd 0x%02x\n", req->cmd); | |
162 | ipmb_dump_req(req); | |
163 | #endif | |
164 | ipmb_invalid(&resp); | |
165 | break; | |
166 | } | |
167 | break; | |
168 | ||
169 | case IPMB_NETFN_APP: | |
170 | switch (req->cmd) { | |
171 | case IPMB_APP_GET_DEVICE_ID: | |
67a9a9e8 | 172 | ipmb_send(&resp, get_devid, sizeof(get_devid)); |
da7751cb MG |
173 | break; |
174 | ||
175 | case IPMB_APP_GET_WATCHDOG_TIMER: | |
67a9a9e8 | 176 | ipmb_send(&resp, get_wd_timer, sizeof(get_wd_timer)); |
da7751cb MG |
177 | break; |
178 | ||
179 | default: | |
180 | #ifdef DEBUG | |
181 | printf("Unknown app cmd 0x%02x\n", req->cmd); | |
182 | ipmb_dump_req(req); | |
183 | #endif | |
184 | ipmb_invalid(&resp); | |
185 | break; | |
186 | } | |
187 | break; | |
188 | ||
189 | case IPMB_NETFN_STORAGE: | |
190 | switch (req->cmd) { | |
67a9a9e8 MG |
191 | case IPMB_STORAGE_RESERVE_SDR: |
192 | ipmb_send(&resp, reserve_sdr, sizeof(reserve_sdr)); | |
193 | break; | |
194 | case IPMB_STORAGE_GET_SDR: | |
195 | ipmb_send(&resp, get_sdr, sizeof(get_sdr)); | |
196 | break; | |
197 | case IPMB_STORAGE_GET_SEL_INFO: | |
198 | ipmb_send(&resp, sel_info, sizeof(sel_info)); | |
199 | break; | |
200 | case IPMB_STORAGE_GET_SEL_ALLOCATION: | |
201 | ipmb_send(&resp, sel_alloc_info, sizeof(sel_alloc_info)); | |
202 | break; | |
203 | case IPMB_STORAGE_GET_SEL_ENTRY: | |
204 | ipmb_send(&resp, sel_entry, sizeof(sel_entry)); | |
205 | break; | |
206 | case IPMB_STORAGE_GET_SEL_TIME: | |
207 | ipmb_send(&resp, sel_timestamp, sizeof(sel_timestamp)); | |
208 | break; | |
da7751cb MG |
209 | default: |
210 | #ifdef DEBUG | |
211 | printf("Unknown storage cmd 0x%02x\n", req->cmd); | |
212 | ipmb_dump_req(req); | |
213 | #endif | |
214 | ipmb_invalid(&resp); | |
215 | break; | |
216 | } | |
217 | break; | |
218 | ||
219 | default: | |
220 | #ifdef DEBUG | |
221 | printf("Unknown netFn 0x%02x\n", req->netFn); | |
222 | ipmb_dump_req(req); | |
223 | #endif | |
224 | ipmb_invalid(&resp); | |
225 | break; | |
226 | } | |
227 | } | |
228 | ||
229 | void decode_ipmb_pkt(unsigned char *buf, int len) | |
230 | { | |
231 | struct ipmb_req req; | |
d5193055 MG |
232 | |
233 | if ((buf[2] != ipmb_csum(buf, 2)) || | |
da7751cb | 234 | (buf[len-1] != ipmb_csum(buf+3, len-4))) |
d5193055 MG |
235 | return; /* Checksum wrong */ |
236 | ||
da7751cb MG |
237 | req.rsSA = buf[0]; |
238 | req.netFn = (buf[1]>>2)&0x3f; | |
239 | req.rsLUN = (buf[1] & 0x03); | |
240 | req.rqSA = buf[3]; | |
241 | req.rqSEQ = (buf[4]>>2)&0x3f; | |
242 | req.rqLUN = (buf[4] & 0x03); | |
243 | req.cmd = buf[5]; | |
244 | req.data = buf+6; | |
245 | req.datalen = len - 6 - 1; | |
246 | ||
247 | ipmb_cmd(&req); | |
d5193055 | 248 | } |