linux/drivers/char/ipmi/ipmi_smic_sm.c
<<
>>
Prefs
   1/*
   2 * ipmi_smic_sm.c
   3 *
   4 * The state-machine driver for an IPMI SMIC driver
   5 *
   6 * It started as a copy of Corey Minyard's driver for the KSC interface
   7 * and the kernel patch "mmcdev-patch-245" by HP
   8 *
   9 * modified by: Hannes Schulz <schulz@schwaar.com>
  10 *              ipmi@schwaar.com
  11 *
  12 *
  13 * Corey Minyard's driver for the KSC interface has the following
  14 * copyright notice:
  15 *   Copyright 2002 MontaVista Software Inc.
  16 *
  17 * the kernel patch "mmcdev-patch-245" by HP has the following
  18 * copyright notice:
  19 * (c) Copyright 2001 Grant Grundler (c) Copyright
  20 * 2001 Hewlett-Packard Company
  21 *
  22 *
  23 *  This program is free software; you can redistribute it and/or modify it
  24 *  under the terms of the GNU General Public License as published by the
  25 *  Free Software Foundation; either version 2 of the License, or (at your
  26 *  option) any later version.
  27 *
  28 *
  29 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  30 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  31 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  32 *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  33 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  34 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  35 *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  36 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  37 *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  38 *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  39 *
  40 *  You should have received a copy of the GNU General Public License along
  41 *  with this program; if not, write to the Free Software Foundation, Inc.,
  42 *  675 Mass Ave, Cambridge, MA 02139, USA.  */
  43
  44#include <linux/kernel.h> /* For printk. */
  45#include <linux/string.h>
  46#include <linux/module.h>
  47#include <linux/moduleparam.h>
  48#include <linux/ipmi_msgdefs.h>         /* for completion codes */
  49#include "ipmi_si_sm.h"
  50
  51/* smic_debug is a bit-field
  52 *      SMIC_DEBUG_ENABLE -     turned on for now
  53 *      SMIC_DEBUG_MSG -        commands and their responses
  54 *      SMIC_DEBUG_STATES -     state machine
  55*/
  56#define SMIC_DEBUG_STATES       4
  57#define SMIC_DEBUG_MSG          2
  58#define SMIC_DEBUG_ENABLE       1
  59
  60static int smic_debug = 1;
  61module_param(smic_debug, int, 0644);
  62MODULE_PARM_DESC(smic_debug, "debug bitmask, 1=enable, 2=messages, 4=states");
  63
  64enum smic_states {
  65        SMIC_IDLE,
  66        SMIC_START_OP,
  67        SMIC_OP_OK,
  68        SMIC_WRITE_START,
  69        SMIC_WRITE_NEXT,
  70        SMIC_WRITE_END,
  71        SMIC_WRITE2READ,
  72        SMIC_READ_START,
  73        SMIC_READ_NEXT,
  74        SMIC_READ_END,
  75        SMIC_HOSED
  76};
  77
  78#define MAX_SMIC_READ_SIZE 80
  79#define MAX_SMIC_WRITE_SIZE 80
  80#define SMIC_MAX_ERROR_RETRIES 3
  81
  82/* Timeouts in microseconds. */
  83#define SMIC_RETRY_TIMEOUT 2000000
  84
  85/* SMIC Flags Register Bits */
  86#define SMIC_RX_DATA_READY      0x80
  87#define SMIC_TX_DATA_READY      0x40
  88
  89/*
  90 * SMIC_SMI and SMIC_EVM_DATA_AVAIL are only used by
  91 * a few systems, and then only by Systems Management
  92 * Interrupts, not by the OS.  Always ignore these bits.
  93 *
  94 */
  95#define SMIC_SMI                0x10
  96#define SMIC_EVM_DATA_AVAIL     0x08
  97#define SMIC_SMS_DATA_AVAIL     0x04
  98#define SMIC_FLAG_BSY           0x01
  99
 100/* SMIC Error Codes */
 101#define EC_NO_ERROR             0x00
 102#define EC_ABORTED              0x01
 103#define EC_ILLEGAL_CONTROL      0x02
 104#define EC_NO_RESPONSE          0x03
 105#define EC_ILLEGAL_COMMAND      0x04
 106#define EC_BUFFER_FULL          0x05
 107
 108struct si_sm_data {
 109        enum smic_states state;
 110        struct si_sm_io *io;
 111        unsigned char    write_data[MAX_SMIC_WRITE_SIZE];
 112        int              write_pos;
 113        int              write_count;
 114        int              orig_write_count;
 115        unsigned char    read_data[MAX_SMIC_READ_SIZE];
 116        int              read_pos;
 117        int              truncated;
 118        unsigned int     error_retries;
 119        long             smic_timeout;
 120};
 121
 122static unsigned int init_smic_data(struct si_sm_data *smic,
 123                                   struct si_sm_io *io)
 124{
 125        smic->state = SMIC_IDLE;
 126        smic->io = io;
 127        smic->write_pos = 0;
 128        smic->write_count = 0;
 129        smic->orig_write_count = 0;
 130        smic->read_pos = 0;
 131        smic->error_retries = 0;
 132        smic->truncated = 0;
 133        smic->smic_timeout = SMIC_RETRY_TIMEOUT;
 134
 135        /* We use 3 bytes of I/O. */
 136        return 3;
 137}
 138
 139static int start_smic_transaction(struct si_sm_data *smic,
 140                                  unsigned char *data, unsigned int size)
 141{
 142        unsigned int i;
 143
 144        if (size < 2)
 145                return IPMI_REQ_LEN_INVALID_ERR;
 146        if (size > MAX_SMIC_WRITE_SIZE)
 147                return IPMI_REQ_LEN_EXCEEDED_ERR;
 148
 149        if ((smic->state != SMIC_IDLE) && (smic->state != SMIC_HOSED))
 150                return IPMI_NOT_IN_MY_STATE_ERR;
 151
 152        if (smic_debug & SMIC_DEBUG_MSG) {
 153                printk(KERN_DEBUG "start_smic_transaction -");
 154                for (i = 0; i < size; i++)
 155                        printk(" %02x", (unsigned char) data[i]);
 156                printk("\n");
 157        }
 158        smic->error_retries = 0;
 159        memcpy(smic->write_data, data, size);
 160        smic->write_count = size;
 161        smic->orig_write_count = size;
 162        smic->write_pos = 0;
 163        smic->read_pos = 0;
 164        smic->state = SMIC_START_OP;
 165        smic->smic_timeout = SMIC_RETRY_TIMEOUT;
 166        return 0;
 167}
 168
 169static int smic_get_result(struct si_sm_data *smic,
 170                           unsigned char *data, unsigned int length)
 171{
 172        int i;
 173
 174        if (smic_debug & SMIC_DEBUG_MSG) {
 175                printk(KERN_DEBUG "smic_get result -");
 176                for (i = 0; i < smic->read_pos; i++)
 177                        printk(" %02x", smic->read_data[i]);
 178                printk("\n");
 179        }
 180        if (length < smic->read_pos) {
 181                smic->read_pos = length;
 182                smic->truncated = 1;
 183        }
 184        memcpy(data, smic->read_data, smic->read_pos);
 185
 186        if ((length >= 3) && (smic->read_pos < 3)) {
 187                data[2] = IPMI_ERR_UNSPECIFIED;
 188                smic->read_pos = 3;
 189        }
 190        if (smic->truncated) {
 191                data[2] = IPMI_ERR_MSG_TRUNCATED;
 192                smic->truncated = 0;
 193        }
 194        return smic->read_pos;
 195}
 196
 197static inline unsigned char read_smic_flags(struct si_sm_data *smic)
 198{
 199        return smic->io->inputb(smic->io, 2);
 200}
 201
 202static inline unsigned char read_smic_status(struct si_sm_data *smic)
 203{
 204        return smic->io->inputb(smic->io, 1);
 205}
 206
 207static inline unsigned char read_smic_data(struct si_sm_data *smic)
 208{
 209        return smic->io->inputb(smic->io, 0);
 210}
 211
 212static inline void write_smic_flags(struct si_sm_data *smic,
 213                                    unsigned char   flags)
 214{
 215        smic->io->outputb(smic->io, 2, flags);
 216}
 217
 218static inline void write_smic_control(struct si_sm_data *smic,
 219                                      unsigned char   control)
 220{
 221        smic->io->outputb(smic->io, 1, control);
 222}
 223
 224static inline void write_si_sm_data(struct si_sm_data *smic,
 225                                    unsigned char   data)
 226{
 227        smic->io->outputb(smic->io, 0, data);
 228}
 229
 230static inline void start_error_recovery(struct si_sm_data *smic, char *reason)
 231{
 232        (smic->error_retries)++;
 233        if (smic->error_retries > SMIC_MAX_ERROR_RETRIES) {
 234                if (smic_debug & SMIC_DEBUG_ENABLE)
 235                        printk(KERN_WARNING
 236                               "ipmi_smic_drv: smic hosed: %s\n", reason);
 237                smic->state = SMIC_HOSED;
 238        } else {
 239                smic->write_count = smic->orig_write_count;
 240                smic->write_pos = 0;
 241                smic->read_pos = 0;
 242                smic->state = SMIC_START_OP;
 243                smic->smic_timeout = SMIC_RETRY_TIMEOUT;
 244        }
 245}
 246
 247static inline void write_next_byte(struct si_sm_data *smic)
 248{
 249        write_si_sm_data(smic, smic->write_data[smic->write_pos]);
 250        (smic->write_pos)++;
 251        (smic->write_count)--;
 252}
 253
 254static inline void read_next_byte(struct si_sm_data *smic)
 255{
 256        if (smic->read_pos >= MAX_SMIC_READ_SIZE) {
 257                read_smic_data(smic);
 258                smic->truncated = 1;
 259        } else {
 260                smic->read_data[smic->read_pos] = read_smic_data(smic);
 261                smic->read_pos++;
 262        }
 263}
 264
 265/*  SMIC Control/Status Code Components */
 266#define SMIC_GET_STATUS         0x00    /* Control form's name */
 267#define SMIC_READY              0x00    /* Status  form's name */
 268#define SMIC_WR_START           0x01    /* Unified Control/Status names... */
 269#define SMIC_WR_NEXT            0x02
 270#define SMIC_WR_END             0x03
 271#define SMIC_RD_START           0x04
 272#define SMIC_RD_NEXT            0x05
 273#define SMIC_RD_END             0x06
 274#define SMIC_CODE_MASK          0x0f
 275
 276#define SMIC_CONTROL            0x00
 277#define SMIC_STATUS             0x80
 278#define SMIC_CS_MASK            0x80
 279
 280#define SMIC_SMS                0x40
 281#define SMIC_SMM                0x60
 282#define SMIC_STREAM_MASK        0x60
 283
 284/*  SMIC Control Codes */
 285#define SMIC_CC_SMS_GET_STATUS  (SMIC_CONTROL|SMIC_SMS|SMIC_GET_STATUS)
 286#define SMIC_CC_SMS_WR_START    (SMIC_CONTROL|SMIC_SMS|SMIC_WR_START)
 287#define SMIC_CC_SMS_WR_NEXT     (SMIC_CONTROL|SMIC_SMS|SMIC_WR_NEXT)
 288#define SMIC_CC_SMS_WR_END      (SMIC_CONTROL|SMIC_SMS|SMIC_WR_END)
 289#define SMIC_CC_SMS_RD_START    (SMIC_CONTROL|SMIC_SMS|SMIC_RD_START)
 290#define SMIC_CC_SMS_RD_NEXT     (SMIC_CONTROL|SMIC_SMS|SMIC_RD_NEXT)
 291#define SMIC_CC_SMS_RD_END      (SMIC_CONTROL|SMIC_SMS|SMIC_RD_END)
 292
 293#define SMIC_CC_SMM_GET_STATUS  (SMIC_CONTROL|SMIC_SMM|SMIC_GET_STATUS)
 294#define SMIC_CC_SMM_WR_START    (SMIC_CONTROL|SMIC_SMM|SMIC_WR_START)
 295#define SMIC_CC_SMM_WR_NEXT     (SMIC_CONTROL|SMIC_SMM|SMIC_WR_NEXT)
 296#define SMIC_CC_SMM_WR_END      (SMIC_CONTROL|SMIC_SMM|SMIC_WR_END)
 297#define SMIC_CC_SMM_RD_START    (SMIC_CONTROL|SMIC_SMM|SMIC_RD_START)
 298#define SMIC_CC_SMM_RD_NEXT     (SMIC_CONTROL|SMIC_SMM|SMIC_RD_NEXT)
 299#define SMIC_CC_SMM_RD_END      (SMIC_CONTROL|SMIC_SMM|SMIC_RD_END)
 300
 301/*  SMIC Status Codes */
 302#define SMIC_SC_SMS_READY       (SMIC_STATUS|SMIC_SMS|SMIC_READY)
 303#define SMIC_SC_SMS_WR_START    (SMIC_STATUS|SMIC_SMS|SMIC_WR_START)
 304#define SMIC_SC_SMS_WR_NEXT     (SMIC_STATUS|SMIC_SMS|SMIC_WR_NEXT)
 305#define SMIC_SC_SMS_WR_END      (SMIC_STATUS|SMIC_SMS|SMIC_WR_END)
 306#define SMIC_SC_SMS_RD_START    (SMIC_STATUS|SMIC_SMS|SMIC_RD_START)
 307#define SMIC_SC_SMS_RD_NEXT     (SMIC_STATUS|SMIC_SMS|SMIC_RD_NEXT)
 308#define SMIC_SC_SMS_RD_END      (SMIC_STATUS|SMIC_SMS|SMIC_RD_END)
 309
 310#define SMIC_SC_SMM_READY       (SMIC_STATUS|SMIC_SMM|SMIC_READY)
 311#define SMIC_SC_SMM_WR_START    (SMIC_STATUS|SMIC_SMM|SMIC_WR_START)
 312#define SMIC_SC_SMM_WR_NEXT     (SMIC_STATUS|SMIC_SMM|SMIC_WR_NEXT)
 313#define SMIC_SC_SMM_WR_END      (SMIC_STATUS|SMIC_SMM|SMIC_WR_END)
 314#define SMIC_SC_SMM_RD_START    (SMIC_STATUS|SMIC_SMM|SMIC_RD_START)
 315#define SMIC_SC_SMM_RD_NEXT     (SMIC_STATUS|SMIC_SMM|SMIC_RD_NEXT)
 316#define SMIC_SC_SMM_RD_END      (SMIC_STATUS|SMIC_SMM|SMIC_RD_END)
 317
 318/* these are the control/status codes we actually use
 319        SMIC_CC_SMS_GET_STATUS  0x40
 320        SMIC_CC_SMS_WR_START    0x41
 321        SMIC_CC_SMS_WR_NEXT     0x42
 322        SMIC_CC_SMS_WR_END      0x43
 323        SMIC_CC_SMS_RD_START    0x44
 324        SMIC_CC_SMS_RD_NEXT     0x45
 325        SMIC_CC_SMS_RD_END      0x46
 326
 327        SMIC_SC_SMS_READY       0xC0
 328        SMIC_SC_SMS_WR_START    0xC1
 329        SMIC_SC_SMS_WR_NEXT     0xC2
 330        SMIC_SC_SMS_WR_END      0xC3
 331        SMIC_SC_SMS_RD_START    0xC4
 332        SMIC_SC_SMS_RD_NEXT     0xC5
 333        SMIC_SC_SMS_RD_END      0xC6
 334*/
 335
 336static enum si_sm_result smic_event(struct si_sm_data *smic, long time)
 337{
 338        unsigned char status;
 339        unsigned char flags;
 340        unsigned char data;
 341
 342        if (smic->state == SMIC_HOSED) {
 343                init_smic_data(smic, smic->io);
 344                return SI_SM_HOSED;
 345        }
 346        if (smic->state != SMIC_IDLE) {
 347                if (smic_debug & SMIC_DEBUG_STATES)
 348                        printk(KERN_DEBUG
 349                               "smic_event - smic->smic_timeout = %ld,"
 350                               " time = %ld\n",
 351                               smic->smic_timeout, time);
 352                /*
 353                 * FIXME: smic_event is sometimes called with time >
 354                 * SMIC_RETRY_TIMEOUT
 355                 */
 356                if (time < SMIC_RETRY_TIMEOUT) {
 357                        smic->smic_timeout -= time;
 358                        if (smic->smic_timeout < 0) {
 359                                start_error_recovery(smic, "smic timed out.");
 360                                return SI_SM_CALL_WITH_DELAY;
 361                        }
 362                }
 363        }
 364        flags = read_smic_flags(smic);
 365        if (flags & SMIC_FLAG_BSY)
 366                return SI_SM_CALL_WITH_DELAY;
 367
 368        status = read_smic_status(smic);
 369        if (smic_debug & SMIC_DEBUG_STATES)
 370                printk(KERN_DEBUG
 371                       "smic_event - state = %d, flags = 0x%02x,"
 372                       " status = 0x%02x\n",
 373                       smic->state, flags, status);
 374
 375        switch (smic->state) {
 376        case SMIC_IDLE:
 377                /* in IDLE we check for available messages */
 378                if (flags & SMIC_SMS_DATA_AVAIL)
 379                        return SI_SM_ATTN;
 380                return SI_SM_IDLE;
 381
 382        case SMIC_START_OP:
 383                /* sanity check whether smic is really idle */
 384                write_smic_control(smic, SMIC_CC_SMS_GET_STATUS);
 385                write_smic_flags(smic, flags | SMIC_FLAG_BSY);
 386                smic->state = SMIC_OP_OK;
 387                break;
 388
 389        case SMIC_OP_OK:
 390                if (status != SMIC_SC_SMS_READY) {
 391                        /* this should not happen */
 392                        start_error_recovery(smic,
 393                                             "state = SMIC_OP_OK,"
 394                                             " status != SMIC_SC_SMS_READY");
 395                        return SI_SM_CALL_WITH_DELAY;
 396                }
 397                /* OK so far; smic is idle let us start ... */
 398                write_smic_control(smic, SMIC_CC_SMS_WR_START);
 399                write_next_byte(smic);
 400                write_smic_flags(smic, flags | SMIC_FLAG_BSY);
 401                smic->state = SMIC_WRITE_START;
 402                break;
 403
 404        case SMIC_WRITE_START:
 405                if (status != SMIC_SC_SMS_WR_START) {
 406                        start_error_recovery(smic,
 407                                             "state = SMIC_WRITE_START, "
 408                                             "status != SMIC_SC_SMS_WR_START");
 409                        return SI_SM_CALL_WITH_DELAY;
 410                }
 411                /*
 412                 * we must not issue WR_(NEXT|END) unless
 413                 * TX_DATA_READY is set
 414                 * */
 415                if (flags & SMIC_TX_DATA_READY) {
 416                        if (smic->write_count == 1) {
 417                                /* last byte */
 418                                write_smic_control(smic, SMIC_CC_SMS_WR_END);
 419                                smic->state = SMIC_WRITE_END;
 420                        } else {
 421                                write_smic_control(smic, SMIC_CC_SMS_WR_NEXT);
 422                                smic->state = SMIC_WRITE_NEXT;
 423                        }
 424                        write_next_byte(smic);
 425                        write_smic_flags(smic, flags | SMIC_FLAG_BSY);
 426                } else
 427                        return SI_SM_CALL_WITH_DELAY;
 428                break;
 429
 430        case SMIC_WRITE_NEXT:
 431                if (status != SMIC_SC_SMS_WR_NEXT) {
 432                        start_error_recovery(smic,
 433                                             "state = SMIC_WRITE_NEXT, "
 434                                             "status != SMIC_SC_SMS_WR_NEXT");
 435                        return SI_SM_CALL_WITH_DELAY;
 436                }
 437                /* this is the same code as in SMIC_WRITE_START */
 438                if (flags & SMIC_TX_DATA_READY) {
 439                        if (smic->write_count == 1) {
 440                                write_smic_control(smic, SMIC_CC_SMS_WR_END);
 441                                smic->state = SMIC_WRITE_END;
 442                        } else {
 443                                write_smic_control(smic, SMIC_CC_SMS_WR_NEXT);
 444                                smic->state = SMIC_WRITE_NEXT;
 445                        }
 446                        write_next_byte(smic);
 447                        write_smic_flags(smic, flags | SMIC_FLAG_BSY);
 448                } else
 449                        return SI_SM_CALL_WITH_DELAY;
 450                break;
 451
 452        case SMIC_WRITE_END:
 453                if (status != SMIC_SC_SMS_WR_END) {
 454                        start_error_recovery(smic,
 455                                             "state = SMIC_WRITE_END, "
 456                                             "status != SMIC_SC_SMS_WR_END");
 457                        return SI_SM_CALL_WITH_DELAY;
 458                }
 459                /* data register holds an error code */
 460                data = read_smic_data(smic);
 461                if (data != 0) {
 462                        if (smic_debug & SMIC_DEBUG_ENABLE)
 463                                printk(KERN_DEBUG
 464                                       "SMIC_WRITE_END: data = %02x\n", data);
 465                        start_error_recovery(smic,
 466                                             "state = SMIC_WRITE_END, "
 467                                             "data != SUCCESS");
 468                        return SI_SM_CALL_WITH_DELAY;
 469                } else
 470                        smic->state = SMIC_WRITE2READ;
 471                break;
 472
 473        case SMIC_WRITE2READ:
 474                /*
 475                 * we must wait for RX_DATA_READY to be set before we
 476                 * can continue
 477                 */
 478                if (flags & SMIC_RX_DATA_READY) {
 479                        write_smic_control(smic, SMIC_CC_SMS_RD_START);
 480                        write_smic_flags(smic, flags | SMIC_FLAG_BSY);
 481                        smic->state = SMIC_READ_START;
 482                } else
 483                        return SI_SM_CALL_WITH_DELAY;
 484                break;
 485
 486        case SMIC_READ_START:
 487                if (status != SMIC_SC_SMS_RD_START) {
 488                        start_error_recovery(smic,
 489                                             "state = SMIC_READ_START, "
 490                                             "status != SMIC_SC_SMS_RD_START");
 491                        return SI_SM_CALL_WITH_DELAY;
 492                }
 493                if (flags & SMIC_RX_DATA_READY) {
 494                        read_next_byte(smic);
 495                        write_smic_control(smic, SMIC_CC_SMS_RD_NEXT);
 496                        write_smic_flags(smic, flags | SMIC_FLAG_BSY);
 497                        smic->state = SMIC_READ_NEXT;
 498                } else
 499                        return SI_SM_CALL_WITH_DELAY;
 500                break;
 501
 502        case SMIC_READ_NEXT:
 503                switch (status) {
 504                /*
 505                 * smic tells us that this is the last byte to be read
 506                 * --> clean up
 507                 */
 508                case SMIC_SC_SMS_RD_END:
 509                        read_next_byte(smic);
 510                        write_smic_control(smic, SMIC_CC_SMS_RD_END);
 511                        write_smic_flags(smic, flags | SMIC_FLAG_BSY);
 512                        smic->state = SMIC_READ_END;
 513                        break;
 514                case SMIC_SC_SMS_RD_NEXT:
 515                        if (flags & SMIC_RX_DATA_READY) {
 516                                read_next_byte(smic);
 517                                write_smic_control(smic, SMIC_CC_SMS_RD_NEXT);
 518                                write_smic_flags(smic, flags | SMIC_FLAG_BSY);
 519                                smic->state = SMIC_READ_NEXT;
 520                        } else
 521                                return SI_SM_CALL_WITH_DELAY;
 522                        break;
 523                default:
 524                        start_error_recovery(
 525                                smic,
 526                                "state = SMIC_READ_NEXT, "
 527                                "status != SMIC_SC_SMS_RD_(NEXT|END)");
 528                        return SI_SM_CALL_WITH_DELAY;
 529                }
 530                break;
 531
 532        case SMIC_READ_END:
 533                if (status != SMIC_SC_SMS_READY) {
 534                        start_error_recovery(smic,
 535                                             "state = SMIC_READ_END, "
 536                                             "status != SMIC_SC_SMS_READY");
 537                        return SI_SM_CALL_WITH_DELAY;
 538                }
 539                data = read_smic_data(smic);
 540                /* data register holds an error code */
 541                if (data != 0) {
 542                        if (smic_debug & SMIC_DEBUG_ENABLE)
 543                                printk(KERN_DEBUG
 544                                       "SMIC_READ_END: data = %02x\n", data);
 545                        start_error_recovery(smic,
 546                                             "state = SMIC_READ_END, "
 547                                             "data != SUCCESS");
 548                        return SI_SM_CALL_WITH_DELAY;
 549                } else {
 550                        smic->state = SMIC_IDLE;
 551                        return SI_SM_TRANSACTION_COMPLETE;
 552                }
 553
 554        case SMIC_HOSED:
 555                init_smic_data(smic, smic->io);
 556                return SI_SM_HOSED;
 557
 558        default:
 559                if (smic_debug & SMIC_DEBUG_ENABLE) {
 560                        printk(KERN_DEBUG "smic->state = %d\n", smic->state);
 561                        start_error_recovery(smic, "state = UNKNOWN");
 562                        return SI_SM_CALL_WITH_DELAY;
 563                }
 564        }
 565        smic->smic_timeout = SMIC_RETRY_TIMEOUT;
 566        return SI_SM_CALL_WITHOUT_DELAY;
 567}
 568
 569static int smic_detect(struct si_sm_data *smic)
 570{
 571        /*
 572         * It's impossible for the SMIC fnags register to be all 1's,
 573         * (assuming a properly functioning, self-initialized BMC)
 574         * but that's what you get from reading a bogus address, so we
 575         * test that first.
 576         */
 577        if (read_smic_flags(smic) == 0xff)
 578                return 1;
 579
 580        return 0;
 581}
 582
 583static void smic_cleanup(struct si_sm_data *kcs)
 584{
 585}
 586
 587static int smic_size(void)
 588{
 589        return sizeof(struct si_sm_data);
 590}
 591
 592struct si_sm_handlers smic_smi_handlers = {
 593        .init_data         = init_smic_data,
 594        .start_transaction = start_smic_transaction,
 595        .get_result        = smic_get_result,
 596        .event             = smic_event,
 597        .detect            = smic_detect,
 598        .cleanup           = smic_cleanup,
 599        .size              = smic_size,
 600};
 601