]>
Commit | Line | Data |
---|---|---|
1 | #include <string.h> | |
2 | #include <stdio.h> | |
3 | ||
4 | #include "i2c.h" | |
5 | #include "chassis.h" | |
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 | ||
20 | void ipmb_send(struct ipmb_resp *resp) | |
21 | { | |
22 | unsigned char buf[24]; | |
23 | int len; | |
24 | #ifdef DEBUG | |
25 | int i; | |
26 | #endif | |
27 | ||
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; | |
34 | memcpy(buf+6, resp->data, resp->datalen); | |
35 | len = resp->datalen + 7; | |
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; | |
54 | ||
55 | printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); | |
56 | printf("Connection Header:\n"); | |
57 | printf("\trs Slave Addr.: 0x%02x\n", req->rsSA); | |
58 | printf("\tnetFn: 0x%02x, LUN: 0x%02x\n", req->netFn, req->rsLUN); | |
59 | printf("Data:\n"); | |
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); | |
63 | printf("\tData: "); | |
64 | for(i = 0; i < req->datalen; i++) { | |
65 | printf("0x%02x ", req->data[i]); | |
66 | } | |
67 | printf("\n"); | |
68 | printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); | |
69 | } | |
70 | #endif | |
71 | ||
72 | void ipmb_invalid(struct ipmb_resp *resp) | |
73 | { | |
74 | #if 0 | |
75 | static unsigned char cmd_invalid[] = {0xc2}; | |
76 | ||
77 | resp->data = cmd_invalid; | |
78 | resp->datalen = sizeof(cmd_invalid); | |
79 | ipmb_send(resp); | |
80 | #endif | |
81 | } | |
82 | ||
83 | void ipmb_cmd(struct ipmb_req *req) | |
84 | { | |
85 | struct ipmb_resp resp; | |
86 | static unsigned char get_devid[] = | |
87 | {IPMB_CC_NORMALLY, 0x42, 0x42, 0x01, 0x01, 0x51, 0xff /* Add. Dev. Supp */, 0x00, 0x00, 0x00, 0x00, 0x00 }; | |
88 | static unsigned char get_wd_timer[] = | |
89 | {IPMB_CC_NORMALLY, 0x42, 0x00, 0x00, 0x04, 0xff, 0xff, 0xfe, 0xfe}; | |
90 | static unsigned char cc_normal[] = | |
91 | {IPMB_CC_NORMALLY}; | |
92 | ||
93 | resp.rqSA = req->rqSA; | |
94 | resp.netFn = req->netFn+1; | |
95 | resp.rqLUN = req->rqLUN; | |
96 | resp.rsSA = req->rsSA; | |
97 | resp.rqSEQ = req->rqSEQ; | |
98 | resp.rsLUN = req->rsLUN; | |
99 | resp.cmd = req->cmd; | |
100 | ||
101 | switch (req->netFn) { | |
102 | case IPMB_NETFN_CHASSIS: | |
103 | switch (req->cmd) { | |
104 | case IPMB_CHASSIS_CONTROL: | |
105 | chassis_control(*(req->data)); | |
106 | resp.data = cc_normal; | |
107 | resp.datalen = sizeof(cc_normal); | |
108 | ipmb_send(&resp); | |
109 | break; | |
110 | default: | |
111 | #ifdef DEBUG | |
112 | printf("Unknown chassis cmd 0x%02x\n", req->cmd); | |
113 | ipmb_dump_req(req); | |
114 | #endif | |
115 | ipmb_invalid(&resp); | |
116 | break; | |
117 | } | |
118 | break; | |
119 | ||
120 | case IPMB_NETFN_SENSOR_EVENT: | |
121 | switch (req->cmd) { | |
122 | case IPMB_SE_PLATFORM_EVENT: | |
123 | /* | |
124 | * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> | |
125 | * Connection Header: | |
126 | * rs Slave Addr.: 0x24 | |
127 | * netFn: 0x04, LUN: 0x00 | |
128 | * Data: | |
129 | * rq Slave Addr.: 0x28 | |
130 | * rqSeq: 0x03, rqLUN: 0x00 | |
131 | * cmd: 0x02 | |
132 | * Data: 0x03 0xc8 0x00 0x6f 0x61 0x8f 0x03 | |
133 | * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
134 | * data[0] - EvMRev: 0x03 | |
135 | * data[1] - Sensor Type: 0xc8 | |
136 | * data[2] - Sensor #: 0x00 | |
137 | * data[3] - Event Dir(1)|Event Type(7): 0x6f: 0x0|0x6f (assert, discrete) | |
138 | * data[4] - Event Data: 0x61 | |
139 | * data[5] - Event Data: 0x8f | |
140 | * data[6] - Event Data: 0x03 | |
141 | */ | |
142 | resp.data = cc_normal; | |
143 | resp.datalen = sizeof(cc_normal); | |
144 | ipmb_send(&resp); | |
145 | break; | |
146 | ||
147 | ||
148 | default: | |
149 | #ifdef DEBUG | |
150 | printf("Unknown sensor cmd 0x%02x\n", req->cmd); | |
151 | ipmb_dump_req(req); | |
152 | #endif | |
153 | ipmb_invalid(&resp); | |
154 | break; | |
155 | } | |
156 | break; | |
157 | ||
158 | case IPMB_NETFN_APP: | |
159 | switch (req->cmd) { | |
160 | case IPMB_APP_GET_DEVICE_ID: | |
161 | resp.data = get_devid; | |
162 | resp.datalen = sizeof(get_devid); | |
163 | ipmb_send(&resp); | |
164 | break; | |
165 | ||
166 | case IPMB_APP_GET_WATCHDOG_TIMER: | |
167 | resp.data = get_wd_timer; | |
168 | resp.datalen = sizeof(get_wd_timer); | |
169 | ipmb_send(&resp); | |
170 | break; | |
171 | ||
172 | default: | |
173 | #ifdef DEBUG | |
174 | printf("Unknown app cmd 0x%02x\n", req->cmd); | |
175 | ipmb_dump_req(req); | |
176 | #endif | |
177 | ipmb_invalid(&resp); | |
178 | break; | |
179 | } | |
180 | break; | |
181 | ||
182 | case IPMB_NETFN_STORAGE: | |
183 | switch (req->cmd) { | |
184 | default: | |
185 | #ifdef DEBUG | |
186 | printf("Unknown storage cmd 0x%02x\n", req->cmd); | |
187 | ipmb_dump_req(req); | |
188 | #endif | |
189 | ipmb_invalid(&resp); | |
190 | break; | |
191 | } | |
192 | break; | |
193 | ||
194 | default: | |
195 | #ifdef DEBUG | |
196 | printf("Unknown netFn 0x%02x\n", req->netFn); | |
197 | ipmb_dump_req(req); | |
198 | #endif | |
199 | ipmb_invalid(&resp); | |
200 | break; | |
201 | } | |
202 | } | |
203 | ||
204 | void decode_ipmb_pkt(unsigned char *buf, int len) | |
205 | { | |
206 | struct ipmb_req req; | |
207 | ||
208 | if ((buf[2] != ipmb_csum(buf, 2)) || | |
209 | (buf[len-1] != ipmb_csum(buf+3, len-4))) | |
210 | return; /* Checksum wrong */ | |
211 | ||
212 | req.rsSA = buf[0]; | |
213 | req.netFn = (buf[1]>>2)&0x3f; | |
214 | req.rsLUN = (buf[1] & 0x03); | |
215 | req.rqSA = buf[3]; | |
216 | req.rqSEQ = (buf[4]>>2)&0x3f; | |
217 | req.rqLUN = (buf[4] & 0x03); | |
218 | req.cmd = buf[5]; | |
219 | req.data = buf+6; | |
220 | req.datalen = len - 6 - 1; | |
221 | ||
222 | ipmb_cmd(&req); | |
223 | } |