4 * State machine for handling IPMI KCS interfaces.
6 * Author: MontaVista Software, Inc.
7 * Corey Minyard <minyard@mvista.com>
10 * Copyright 2002 MontaVista Software Inc.
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * You should have received a copy of the GNU General Public License along
30 * with this program; if not, write to the Free Software Foundation, Inc.,
31 * 675 Mass Ave, Cambridge, MA 02139, USA.
35 * This state machine is taken from the state machine in the IPMI spec,
36 * pretty much verbatim. If you have questions about the states, see
41 #include <asm/string.h> /* Gets rid of memcpy warning */
43 #include "ipmi_kcs_sm.h"
45 /* Set this if you want a printout of why the state machine was hosed
46 when it gets hosed. */
47 #define DEBUG_HOSED_REASON
49 /* Print the state machine state on entry every time. */
52 /* The states the KCS driver may be in. */
54 KCS_IDLE, /* The KCS interface is currently
56 KCS_START_OP, /* We are starting an operation. The
57 data is in the output buffer, but
58 nothing has been done to the
59 interface yet. This was added to
60 the state machine in the spec to
61 wait for the initial IBF. */
62 KCS_WAIT_WRITE_START, /* We have written a write cmd to the
64 KCS_WAIT_WRITE, /* We are writing bytes to the
66 KCS_WAIT_WRITE_END, /* We have written the write end cmd
67 to the interface, and still need to
68 write the last byte. */
69 KCS_WAIT_READ, /* We are waiting to read data from
71 KCS_ERROR0, /* State to transition to the error
72 handler, this was added to the
73 state machine in the spec to be
74 sure IBF was there. */
75 KCS_ERROR1, /* First stage error handler, wait for
76 the interface to respond. */
77 KCS_ERROR2, /* The abort cmd has been written,
78 wait for the interface to
80 KCS_ERROR3, /* We wrote some data to the
81 interface, wait for it to switch to
83 KCS_HOSED /* The hardware failed to follow the
87 #define MAX_KCS_READ_SIZE 80
88 #define MAX_KCS_WRITE_SIZE 80
90 /* Timeouts in microseconds. */
91 #define IBF_RETRY_TIMEOUT 1000000
92 #define OBF_RETRY_TIMEOUT 1000000
93 #define MAX_ERROR_RETRIES 10
95 #define IPMI_ERR_MSG_TRUNCATED 0xc6
99 enum kcs_states state;
102 unsigned char write_data[MAX_KCS_WRITE_SIZE];
105 int orig_write_count;
106 unsigned char read_data[MAX_KCS_READ_SIZE];
110 unsigned int error_retries;
115 void init_kcs_data(struct kcs_data *kcs, unsigned int port, unsigned char *addr)
117 kcs->state = KCS_IDLE;
121 kcs->write_count = 0;
122 kcs->orig_write_count = 0;
124 kcs->error_retries = 0;
126 kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
127 kcs->obf_timeout = OBF_RETRY_TIMEOUT;
130 /* Remember, init_one_kcs() insured port and addr can't both be set */
132 static inline unsigned char read_status(struct kcs_data *kcs)
135 return inb(kcs->port + 1);
137 return readb(kcs->addr + 1);
140 static inline unsigned char read_data(struct kcs_data *kcs)
143 return inb(kcs->port + 0);
145 return readb(kcs->addr + 0);
148 static inline void write_cmd(struct kcs_data *kcs, unsigned char data)
151 outb(data, kcs->port + 1);
153 writeb(data, kcs->addr + 1);
156 static inline void write_data(struct kcs_data *kcs, unsigned char data)
159 outb(data, kcs->port + 0);
161 writeb(data, kcs->addr + 0);
165 #define KCS_GET_STATUS_ABORT 0x60
166 #define KCS_WRITE_START 0x61
167 #define KCS_WRITE_END 0x62
168 #define KCS_READ_BYTE 0x68
171 #define GET_STATUS_STATE(status) (((status) >> 6) & 0x03)
172 #define KCS_IDLE_STATE 0
173 #define KCS_READ_STATE 1
174 #define KCS_WRITE_STATE 2
175 #define KCS_ERROR_STATE 3
176 #define GET_STATUS_ATN(status) ((status) & 0x04)
177 #define GET_STATUS_IBF(status) ((status) & 0x02)
178 #define GET_STATUS_OBF(status) ((status) & 0x01)
181 static inline void write_next_byte(struct kcs_data *kcs)
183 write_data(kcs, kcs->write_data[kcs->write_pos]);
185 (kcs->write_count)--;
188 static inline void start_error_recovery(struct kcs_data *kcs, char *reason)
190 (kcs->error_retries)++;
191 if (kcs->error_retries > MAX_ERROR_RETRIES) {
192 #ifdef DEBUG_HOSED_REASON
193 printk("ipmi_kcs_sm: kcs hosed: %s\n", reason);
195 kcs->state = KCS_HOSED;
197 kcs->state = KCS_ERROR0;
201 static inline void read_next_byte(struct kcs_data *kcs)
203 if (kcs->read_pos >= MAX_KCS_READ_SIZE) {
204 /* Throw the data away and mark it truncated. */
208 kcs->read_data[kcs->read_pos] = read_data(kcs);
211 write_data(kcs, KCS_READ_BYTE);
214 static inline int check_ibf(struct kcs_data *kcs,
215 unsigned char status,
218 if (GET_STATUS_IBF(status)) {
219 kcs->ibf_timeout -= time;
220 if (kcs->ibf_timeout < 0) {
221 start_error_recovery(kcs, "IBF not ready in time");
226 kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
230 static inline int check_obf(struct kcs_data *kcs,
231 unsigned char status,
234 if (! GET_STATUS_OBF(status)) {
235 kcs->obf_timeout -= time;
236 if (kcs->obf_timeout < 0) {
237 start_error_recovery(kcs, "OBF not ready in time");
242 kcs->obf_timeout = OBF_RETRY_TIMEOUT;
246 static void clear_obf(struct kcs_data *kcs, unsigned char status)
248 if (GET_STATUS_OBF(status))
252 static void restart_kcs_transaction(struct kcs_data *kcs)
254 kcs->write_count = kcs->orig_write_count;
257 kcs->state = KCS_WAIT_WRITE_START;
258 kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
259 kcs->obf_timeout = OBF_RETRY_TIMEOUT;
260 write_cmd(kcs, KCS_WRITE_START);
263 int start_kcs_transaction(struct kcs_data *kcs, char *data, unsigned int size)
265 if ((size < 2) || (size > MAX_KCS_WRITE_SIZE)) {
269 if ((kcs->state != KCS_IDLE) && (kcs->state != KCS_HOSED)) {
273 kcs->error_retries = 0;
274 memcpy(kcs->write_data, data, size);
275 kcs->write_count = size;
276 kcs->orig_write_count = size;
279 kcs->state = KCS_START_OP;
280 kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
281 kcs->obf_timeout = OBF_RETRY_TIMEOUT;
285 int kcs_get_result(struct kcs_data *kcs, unsigned char *data, int length)
287 if (length < kcs->read_pos) {
288 kcs->read_pos = length;
292 memcpy(data, kcs->read_data, kcs->read_pos);
294 if (kcs->truncated) {
295 /* Report a truncated error. We might overwrite
296 another error, but that's too bad, the user needs
297 to know it was truncated. */
298 data[2] = IPMI_ERR_MSG_TRUNCATED;
302 return kcs->read_pos;
305 /* This implements the state machine defined in the IPMI manual, see
306 that for details on how this works. Divide that flowchart into
307 sections delimited by "Wait for IBF" and this will become clear. */
308 enum kcs_result kcs_event(struct kcs_data *kcs, long time)
310 unsigned char status;
313 status = read_status(kcs);
316 printk(" State = %d, %x\n", kcs->state, status);
318 /* All states wait for ibf, so just do it here. */
319 if (!check_ibf(kcs, status, time))
320 return KCS_CALL_WITH_DELAY;
322 /* Just about everything looks at the KCS state, so grab that, too. */
323 state = GET_STATUS_STATE(status);
325 switch (kcs->state) {
327 if (GET_STATUS_ATN(status))
333 if (state != KCS_IDLE) {
334 start_error_recovery(kcs,
335 "State machine not idle at start");
339 clear_obf(kcs, status);
340 write_cmd(kcs, KCS_WRITE_START);
341 kcs->state = KCS_WAIT_WRITE_START;
344 case KCS_WAIT_WRITE_START:
345 if (state != KCS_WRITE_STATE) {
346 start_error_recovery(
348 "Not in write state at write start");
352 if (kcs->write_count == 1) {
353 write_cmd(kcs, KCS_WRITE_END);
354 kcs->state = KCS_WAIT_WRITE_END;
356 write_next_byte(kcs);
357 kcs->state = KCS_WAIT_WRITE;
362 if (state != KCS_WRITE_STATE) {
363 start_error_recovery(kcs,
364 "Not in write state for write");
367 clear_obf(kcs, status);
368 if (kcs->write_count == 1) {
369 write_cmd(kcs, KCS_WRITE_END);
370 kcs->state = KCS_WAIT_WRITE_END;
372 write_next_byte(kcs);
376 case KCS_WAIT_WRITE_END:
377 if (state != KCS_WRITE_STATE) {
378 start_error_recovery(kcs,
379 "Not in write state for write end");
382 clear_obf(kcs, status);
383 write_next_byte(kcs);
384 kcs->state = KCS_WAIT_READ;
388 if ((state != KCS_READ_STATE) && (state != KCS_IDLE_STATE)) {
389 start_error_recovery(
391 "Not in read or idle in read state");
394 if (! check_obf(kcs, status, time))
395 return KCS_CALL_WITH_DELAY;
397 if (state == KCS_READ_STATE) {
401 kcs->orig_write_count = 0;
402 kcs->state = KCS_IDLE;
403 return KCS_TRANSACTION_COMPLETE;
408 clear_obf(kcs, status);
409 write_cmd(kcs, KCS_GET_STATUS_ABORT);
410 kcs->state = KCS_ERROR1;
414 clear_obf(kcs, status);
416 kcs->state = KCS_ERROR2;
420 if (state != KCS_READ_STATE) {
421 start_error_recovery(kcs,
422 "Not in read state for error2");
425 if (! check_obf(kcs, status, time))
426 return KCS_CALL_WITH_DELAY;
428 clear_obf(kcs, status);
429 write_data(kcs, KCS_READ_BYTE);
430 kcs->state = KCS_ERROR3;
434 if (state != KCS_IDLE_STATE) {
435 start_error_recovery(kcs,
436 "Not in idle state for error3");
440 if (! check_obf(kcs, status, time))
441 return KCS_CALL_WITH_DELAY;
443 clear_obf(kcs, status);
444 if (kcs->orig_write_count) {
445 restart_kcs_transaction(kcs);
447 kcs->state = KCS_IDLE;
448 return KCS_TRANSACTION_COMPLETE;
456 if (kcs->state == KCS_HOSED) {
457 init_kcs_data(kcs, kcs->port, kcs->addr);
461 return KCS_CALL_WITHOUT_DELAY;
466 return sizeof(struct kcs_data);