]>
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 | ||
da7751cb | 20 | void ipmb_send(struct ipmb_resp *resp) |
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; | |
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; | |
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 | { | |
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 | default: | |
123 | #ifdef DEBUG | |
124 | printf("Unknown sensor cmd 0x%02x\n", req->cmd); | |
125 | ipmb_dump_req(req); | |
126 | #endif | |
127 | ipmb_invalid(&resp); | |
128 | break; | |
129 | } | |
130 | break; | |
131 | ||
132 | case IPMB_NETFN_APP: | |
133 | switch (req->cmd) { | |
134 | case IPMB_APP_GET_DEVICE_ID: | |
135 | resp.data = get_devid; | |
136 | resp.datalen = sizeof(get_devid); | |
137 | ipmb_send(&resp); | |
138 | break; | |
139 | ||
140 | case IPMB_APP_GET_WATCHDOG_TIMER: | |
141 | resp.data = get_wd_timer; | |
142 | resp.datalen = sizeof(get_wd_timer); | |
143 | ipmb_send(&resp); | |
144 | break; | |
145 | ||
146 | default: | |
147 | #ifdef DEBUG | |
148 | printf("Unknown app cmd 0x%02x\n", req->cmd); | |
149 | ipmb_dump_req(req); | |
150 | #endif | |
151 | ipmb_invalid(&resp); | |
152 | break; | |
153 | } | |
154 | break; | |
155 | ||
156 | case IPMB_NETFN_STORAGE: | |
157 | switch (req->cmd) { | |
158 | default: | |
159 | #ifdef DEBUG | |
160 | printf("Unknown storage cmd 0x%02x\n", req->cmd); | |
161 | ipmb_dump_req(req); | |
162 | #endif | |
163 | ipmb_invalid(&resp); | |
164 | break; | |
165 | } | |
166 | break; | |
167 | ||
168 | default: | |
169 | #ifdef DEBUG | |
170 | printf("Unknown netFn 0x%02x\n", req->netFn); | |
171 | ipmb_dump_req(req); | |
172 | #endif | |
173 | ipmb_invalid(&resp); | |
174 | break; | |
175 | } | |
176 | } | |
177 | ||
178 | void decode_ipmb_pkt(unsigned char *buf, int len) | |
179 | { | |
180 | struct ipmb_req req; | |
d5193055 MG |
181 | |
182 | if ((buf[2] != ipmb_csum(buf, 2)) || | |
da7751cb | 183 | (buf[len-1] != ipmb_csum(buf+3, len-4))) |
d5193055 MG |
184 | return; /* Checksum wrong */ |
185 | ||
da7751cb MG |
186 | req.rsSA = buf[0]; |
187 | req.netFn = (buf[1]>>2)&0x3f; | |
188 | req.rsLUN = (buf[1] & 0x03); | |
189 | req.rqSA = buf[3]; | |
190 | req.rqSEQ = (buf[4]>>2)&0x3f; | |
191 | req.rqLUN = (buf[4] & 0x03); | |
192 | req.cmd = buf[5]; | |
193 | req.data = buf+6; | |
194 | req.datalen = len - 6 - 1; | |
195 | ||
196 | ipmb_cmd(&req); | |
d5193055 | 197 | } |