cleanup
[linux-2.4.21-pre4.git] / drivers / char / ipmi / ipmi_kcs_sm.c
1 /*
2  * ipmi_kcs_sm.c
3  *
4  * State machine for handling IPMI KCS interfaces.
5  *
6  * Author: MontaVista Software, Inc.
7  *         Corey Minyard <minyard@mvista.com>
8  *         source@mvista.com
9  *
10  * Copyright 2002 MontaVista Software Inc.
11  *
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.
16  *
17  *
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.
28  *
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.
32  */
33
34 /*
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
37  * that document.
38  */
39
40 #include <asm/io.h>
41 #include <asm/string.h>         /* Gets rid of memcpy warning */
42
43 #include "ipmi_kcs_sm.h"
44
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
48
49 /* Print the state machine state on entry every time. */
50 #undef DEBUG_STATE
51
52 /* The states the KCS driver may be in. */
53 enum kcs_states {
54         KCS_IDLE,               /* The KCS interface is currently
55                                    doing nothing. */
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
63                                    interface. */
64         KCS_WAIT_WRITE,         /* We are writing bytes to the
65                                    interface. */
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
70                                    the interface. */
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
79                                    respond. */
80         KCS_ERROR3,             /* We wrote some data to the
81                                    interface, wait for it to switch to
82                                    read mode. */
83         KCS_HOSED               /* The hardware failed to follow the
84                                    state machine. */
85 };
86
87 #define MAX_KCS_READ_SIZE 80
88 #define MAX_KCS_WRITE_SIZE 80
89
90 /* Timeouts in microseconds. */
91 #define IBF_RETRY_TIMEOUT 1000000
92 #define OBF_RETRY_TIMEOUT 1000000
93 #define MAX_ERROR_RETRIES 10
94
95 #define IPMI_ERR_MSG_TRUNCATED  0xc6
96
97 struct kcs_data
98 {
99         enum kcs_states state;
100         unsigned int    port;
101         unsigned char   *addr;
102         unsigned char   write_data[MAX_KCS_WRITE_SIZE];
103         int             write_pos;
104         int             write_count;
105         int             orig_write_count;
106         unsigned char   read_data[MAX_KCS_READ_SIZE];
107         int             read_pos;
108         int             truncated;
109
110         unsigned int  error_retries;
111         long          ibf_timeout;
112         long          obf_timeout;
113 };
114
115 void init_kcs_data(struct kcs_data *kcs, unsigned int port, unsigned char *addr)
116 {
117         kcs->state = KCS_IDLE;
118         kcs->port = port;
119         kcs->addr = addr;
120         kcs->write_pos = 0;
121         kcs->write_count = 0;
122         kcs->orig_write_count = 0;
123         kcs->read_pos = 0;
124         kcs->error_retries = 0;
125         kcs->truncated = 0;
126         kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
127         kcs->obf_timeout = OBF_RETRY_TIMEOUT;
128 }
129
130 /* Remember, init_one_kcs() insured port and addr can't both be set */
131
132 static inline unsigned char read_status(struct kcs_data *kcs)
133 {
134         if (kcs->port)
135                 return inb(kcs->port + 1);
136         else
137                 return readb(kcs->addr + 1);
138 }
139
140 static inline unsigned char read_data(struct kcs_data *kcs)
141 {
142         if (kcs->port)
143                 return inb(kcs->port + 0);
144         else
145                 return readb(kcs->addr + 0);
146 }
147
148 static inline void write_cmd(struct kcs_data *kcs, unsigned char data)
149 {
150         if (kcs->port)
151                 outb(data, kcs->port + 1);
152         else
153                 writeb(data, kcs->addr + 1);
154 }
155
156 static inline void write_data(struct kcs_data *kcs, unsigned char data)
157 {
158         if (kcs->port)
159                 outb(data, kcs->port + 0);
160         else
161                 writeb(data, kcs->addr + 0);
162 }
163
164 /* Control codes. */
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
169
170 /* Status bits. */
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)
179
180
181 static inline void write_next_byte(struct kcs_data *kcs)
182 {
183         write_data(kcs, kcs->write_data[kcs->write_pos]);
184         (kcs->write_pos)++;
185         (kcs->write_count)--;
186 }
187
188 static inline void start_error_recovery(struct kcs_data *kcs, char *reason)
189 {
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);
194 #endif
195                 kcs->state = KCS_HOSED;
196         } else {
197                 kcs->state = KCS_ERROR0;
198         }
199 }
200
201 static inline void read_next_byte(struct kcs_data *kcs)
202 {
203         if (kcs->read_pos >= MAX_KCS_READ_SIZE) {
204                 /* Throw the data away and mark it truncated. */
205                 read_data(kcs);
206                 kcs->truncated = 1;
207         } else {
208                 kcs->read_data[kcs->read_pos] = read_data(kcs);
209                 (kcs->read_pos)++;
210         }
211         write_data(kcs, KCS_READ_BYTE);
212 }
213
214 static inline int check_ibf(struct kcs_data *kcs,
215                             unsigned char   status,
216                             long            time)
217 {
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");
222                         return 1;
223                 }
224                 return 0;
225         }
226         kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
227         return 1;
228 }
229
230 static inline int check_obf(struct kcs_data *kcs,
231                             unsigned char   status,
232                             long            time)
233 {
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");
238                     return 1;
239                 }
240                 return 0;
241         }
242         kcs->obf_timeout = OBF_RETRY_TIMEOUT;
243         return 1;
244 }
245
246 static void clear_obf(struct kcs_data *kcs, unsigned char status)
247 {
248         if (GET_STATUS_OBF(status))
249                 read_data(kcs);
250 }
251
252 static void restart_kcs_transaction(struct kcs_data *kcs)
253 {
254         kcs->write_count = kcs->orig_write_count;
255         kcs->write_pos = 0;
256         kcs->read_pos = 0;
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);
261 }
262
263 int start_kcs_transaction(struct kcs_data *kcs, char *data, unsigned int size)
264 {
265         if ((size < 2) || (size > MAX_KCS_WRITE_SIZE)) {
266                 return -1;
267         }
268
269         if ((kcs->state != KCS_IDLE) && (kcs->state != KCS_HOSED)) {
270                 return -2;
271         }
272
273         kcs->error_retries = 0;
274         memcpy(kcs->write_data, data, size);
275         kcs->write_count = size;
276         kcs->orig_write_count = size;
277         kcs->write_pos = 0;
278         kcs->read_pos = 0;
279         kcs->state = KCS_START_OP;
280         kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
281         kcs->obf_timeout = OBF_RETRY_TIMEOUT;
282         return 0;
283 }
284
285 int kcs_get_result(struct kcs_data *kcs, unsigned char *data, int length)
286 {
287         if (length < kcs->read_pos) {
288                 kcs->read_pos = length;
289                 kcs->truncated = 1;
290         }
291
292         memcpy(data, kcs->read_data, kcs->read_pos);
293
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;
299                 kcs->truncated = 0;
300         }
301
302         return kcs->read_pos;
303 }
304
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)
309 {
310         unsigned char status;
311         unsigned char state;
312
313         status = read_status(kcs);
314
315 #ifdef DEBUG_STATE
316         printk("  State = %d, %x\n", kcs->state, status);
317 #endif
318         /* All states wait for ibf, so just do it here. */
319         if (!check_ibf(kcs, status, time))
320                 return KCS_CALL_WITH_DELAY;
321
322         /* Just about everything looks at the KCS state, so grab that, too. */
323         state = GET_STATUS_STATE(status);
324
325         switch (kcs->state) {
326         case KCS_IDLE:
327                 if (GET_STATUS_ATN(status))
328                         return KCS_ATTN;
329                 else
330                         return KCS_SM_IDLE;
331
332         case KCS_START_OP:
333                 if (state != KCS_IDLE) {
334                         start_error_recovery(kcs,
335                                              "State machine not idle at start");
336                         break;
337                 }
338
339                 clear_obf(kcs, status);
340                 write_cmd(kcs, KCS_WRITE_START);
341                 kcs->state = KCS_WAIT_WRITE_START;
342                 break;
343
344         case KCS_WAIT_WRITE_START:
345                 if (state != KCS_WRITE_STATE) {
346                         start_error_recovery(
347                                 kcs,
348                                 "Not in write state at write start");
349                         break;
350                 }
351                 read_data(kcs);
352                 if (kcs->write_count == 1) {
353                         write_cmd(kcs, KCS_WRITE_END);
354                         kcs->state = KCS_WAIT_WRITE_END;
355                 } else {
356                         write_next_byte(kcs);
357                         kcs->state = KCS_WAIT_WRITE;
358                 }
359                 break;
360
361         case KCS_WAIT_WRITE:
362                 if (state != KCS_WRITE_STATE) {
363                         start_error_recovery(kcs,
364                                              "Not in write state for write");
365                         break;
366                 }
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;
371                 } else {
372                         write_next_byte(kcs);
373                 }
374                 break;
375                 
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");
380                         break;
381                 }
382                 clear_obf(kcs, status);
383                 write_next_byte(kcs);
384                 kcs->state = KCS_WAIT_READ;
385                 break;
386
387         case KCS_WAIT_READ:
388                 if ((state != KCS_READ_STATE) && (state != KCS_IDLE_STATE)) {
389                         start_error_recovery(
390                                 kcs,
391                                 "Not in read or idle in read state");
392                         break;
393                 }
394                 if (! check_obf(kcs, status, time))
395                         return KCS_CALL_WITH_DELAY;
396
397                 if (state == KCS_READ_STATE) {
398                         read_next_byte(kcs);
399                 } else {
400                         read_data(kcs);
401                         kcs->orig_write_count = 0;
402                         kcs->state = KCS_IDLE;
403                         return KCS_TRANSACTION_COMPLETE;
404                 }
405                 break;
406
407         case KCS_ERROR0:
408                 clear_obf(kcs, status);
409                 write_cmd(kcs, KCS_GET_STATUS_ABORT);
410                 kcs->state = KCS_ERROR1;
411                 break;
412
413         case KCS_ERROR1:
414                 clear_obf(kcs, status);
415                 write_data(kcs, 0);
416                 kcs->state = KCS_ERROR2;
417                 break;
418                 
419         case KCS_ERROR2:
420                 if (state != KCS_READ_STATE) {
421                         start_error_recovery(kcs,
422                                              "Not in read state for error2");
423                         break;
424                 }
425                 if (! check_obf(kcs, status, time))
426                         return KCS_CALL_WITH_DELAY;
427
428                 clear_obf(kcs, status);
429                 write_data(kcs, KCS_READ_BYTE);
430                 kcs->state = KCS_ERROR3;
431                 break;
432                 
433         case KCS_ERROR3:
434                 if (state != KCS_IDLE_STATE) {
435                         start_error_recovery(kcs,
436                                              "Not in idle state for error3");
437                         break;
438                 }
439
440                 if (! check_obf(kcs, status, time))
441                         return KCS_CALL_WITH_DELAY;
442
443                 clear_obf(kcs, status);
444                 if (kcs->orig_write_count) {
445                         restart_kcs_transaction(kcs);
446                 } else {
447                         kcs->state = KCS_IDLE;
448                         return KCS_TRANSACTION_COMPLETE;
449                 }
450                 break;
451                         
452         case KCS_HOSED:
453                 return KCS_SM_HOSED;
454         }
455
456         if (kcs->state == KCS_HOSED) {
457                 init_kcs_data(kcs, kcs->port, kcs->addr);
458                 return KCS_SM_HOSED;
459         }
460
461         return KCS_CALL_WITHOUT_DELAY;
462 }
463
464 int kcs_size(void)
465 {
466         return sizeof(struct kcs_data);
467 }