📄 ipmi_smic_sm.c
字号:
/* * ipmi_smic_sm.c * * The state-machine driver for an IPMI SMIC driver * * It started as a copy of Corey Minyard's driver for the KSC interface * and the kernel patch "mmcdev-patch-245" by HP * * modified by: Hannes Schulz <schulz@schwaar.com> * ipmi@schwaar.com * * * Corey Minyard's driver for the KSC interface has the following * copyright notice: * Copyright 2002 MontaVista Software Inc. * * the kernel patch "mmcdev-patch-245" by HP has the following * copyright notice: * (c) Copyright 2001 Grant Grundler (c) Copyright * 2001 Hewlett-Packard Company * * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/kernel.h> /* For printk. */#include <linux/string.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/ipmi_msgdefs.h> /* for completion codes */#include "ipmi_si_sm.h"/* smic_debug is a bit-field * SMIC_DEBUG_ENABLE - turned on for now * SMIC_DEBUG_MSG - commands and their responses * SMIC_DEBUG_STATES - state machine*/#define SMIC_DEBUG_STATES 4#define SMIC_DEBUG_MSG 2#define SMIC_DEBUG_ENABLE 1static int smic_debug = 1;module_param(smic_debug, int, 0644);MODULE_PARM_DESC(smic_debug, "debug bitmask, 1=enable, 2=messages, 4=states");enum smic_states { SMIC_IDLE, SMIC_START_OP, SMIC_OP_OK, SMIC_WRITE_START, SMIC_WRITE_NEXT, SMIC_WRITE_END, SMIC_WRITE2READ, SMIC_READ_START, SMIC_READ_NEXT, SMIC_READ_END, SMIC_HOSED};#define MAX_SMIC_READ_SIZE 80#define MAX_SMIC_WRITE_SIZE 80#define SMIC_MAX_ERROR_RETRIES 3/* Timeouts in microseconds. */#define SMIC_RETRY_TIMEOUT 2000000/* SMIC Flags Register Bits */#define SMIC_RX_DATA_READY 0x80#define SMIC_TX_DATA_READY 0x40/* * SMIC_SMI and SMIC_EVM_DATA_AVAIL are only used by * a few systems, and then only by Systems Management * Interrupts, not by the OS. Always ignore these bits. * */#define SMIC_SMI 0x10#define SMIC_EVM_DATA_AVAIL 0x08#define SMIC_SMS_DATA_AVAIL 0x04#define SMIC_FLAG_BSY 0x01/* SMIC Error Codes */#define EC_NO_ERROR 0x00#define EC_ABORTED 0x01#define EC_ILLEGAL_CONTROL 0x02#define EC_NO_RESPONSE 0x03#define EC_ILLEGAL_COMMAND 0x04#define EC_BUFFER_FULL 0x05struct si_sm_data{ enum smic_states state; struct si_sm_io *io; unsigned char write_data[MAX_SMIC_WRITE_SIZE]; int write_pos; int write_count; int orig_write_count; unsigned char read_data[MAX_SMIC_READ_SIZE]; int read_pos; int truncated; unsigned int error_retries; long smic_timeout;};static unsigned int init_smic_data (struct si_sm_data *smic, struct si_sm_io *io){ smic->state = SMIC_IDLE; smic->io = io; smic->write_pos = 0; smic->write_count = 0; smic->orig_write_count = 0; smic->read_pos = 0; smic->error_retries = 0; smic->truncated = 0; smic->smic_timeout = SMIC_RETRY_TIMEOUT; /* We use 3 bytes of I/O. */ return 3;}static int start_smic_transaction(struct si_sm_data *smic, unsigned char *data, unsigned int size){ unsigned int i; if ((size < 2) || (size > MAX_SMIC_WRITE_SIZE)) { return -1; } if ((smic->state != SMIC_IDLE) && (smic->state != SMIC_HOSED)) { return -2; } if (smic_debug & SMIC_DEBUG_MSG) { printk(KERN_INFO "start_smic_transaction -"); for (i = 0; i < size; i ++) { printk (" %02x", (unsigned char) (data [i])); } printk ("\n"); } smic->error_retries = 0; memcpy(smic->write_data, data, size); smic->write_count = size; smic->orig_write_count = size; smic->write_pos = 0; smic->read_pos = 0; smic->state = SMIC_START_OP; smic->smic_timeout = SMIC_RETRY_TIMEOUT; return 0;}static int smic_get_result(struct si_sm_data *smic, unsigned char *data, unsigned int length){ int i; if (smic_debug & SMIC_DEBUG_MSG) { printk (KERN_INFO "smic_get result -"); for (i = 0; i < smic->read_pos; i ++) { printk (" %02x", (smic->read_data [i])); } printk ("\n"); } if (length < smic->read_pos) { smic->read_pos = length; smic->truncated = 1; } memcpy(data, smic->read_data, smic->read_pos); if ((length >= 3) && (smic->read_pos < 3)) { data[2] = IPMI_ERR_UNSPECIFIED; smic->read_pos = 3; } if (smic->truncated) { data[2] = IPMI_ERR_MSG_TRUNCATED; smic->truncated = 0; } return smic->read_pos;}static inline unsigned char read_smic_flags(struct si_sm_data *smic){ return smic->io->inputb(smic->io, 2);}static inline unsigned char read_smic_status(struct si_sm_data *smic){ return smic->io->inputb(smic->io, 1);}static inline unsigned char read_smic_data(struct si_sm_data *smic){ return smic->io->inputb(smic->io, 0);}static inline void write_smic_flags(struct si_sm_data *smic, unsigned char flags){ smic->io->outputb(smic->io, 2, flags);}static inline void write_smic_control(struct si_sm_data *smic, unsigned char control){ smic->io->outputb(smic->io, 1, control);}static inline void write_si_sm_data (struct si_sm_data *smic, unsigned char data){ smic->io->outputb(smic->io, 0, data);}static inline void start_error_recovery(struct si_sm_data *smic, char *reason){ (smic->error_retries)++; if (smic->error_retries > SMIC_MAX_ERROR_RETRIES) { if (smic_debug & SMIC_DEBUG_ENABLE) { printk(KERN_WARNING "ipmi_smic_drv: smic hosed: %s\n", reason); } smic->state = SMIC_HOSED; } else { smic->write_count = smic->orig_write_count; smic->write_pos = 0; smic->read_pos = 0; smic->state = SMIC_START_OP; smic->smic_timeout = SMIC_RETRY_TIMEOUT; }}static inline void write_next_byte(struct si_sm_data *smic){ write_si_sm_data(smic, smic->write_data[smic->write_pos]); (smic->write_pos)++; (smic->write_count)--;}static inline void read_next_byte (struct si_sm_data *smic){ if (smic->read_pos >= MAX_SMIC_READ_SIZE) { read_smic_data (smic); smic->truncated = 1; } else { smic->read_data[smic->read_pos] = read_smic_data(smic); (smic->read_pos)++; }}/* SMIC Control/Status Code Components */#define SMIC_GET_STATUS 0x00 /* Control form's name */#define SMIC_READY 0x00 /* Status form's name */#define SMIC_WR_START 0x01 /* Unified Control/Status names... */#define SMIC_WR_NEXT 0x02#define SMIC_WR_END 0x03#define SMIC_RD_START 0x04#define SMIC_RD_NEXT 0x05#define SMIC_RD_END 0x06#define SMIC_CODE_MASK 0x0f#define SMIC_CONTROL 0x00#define SMIC_STATUS 0x80#define SMIC_CS_MASK 0x80#define SMIC_SMS 0x40#define SMIC_SMM 0x60#define SMIC_STREAM_MASK 0x60/* SMIC Control Codes */#define SMIC_CC_SMS_GET_STATUS (SMIC_CONTROL|SMIC_SMS|SMIC_GET_STATUS)#define SMIC_CC_SMS_WR_START (SMIC_CONTROL|SMIC_SMS|SMIC_WR_START)#define SMIC_CC_SMS_WR_NEXT (SMIC_CONTROL|SMIC_SMS|SMIC_WR_NEXT)#define SMIC_CC_SMS_WR_END (SMIC_CONTROL|SMIC_SMS|SMIC_WR_END)#define SMIC_CC_SMS_RD_START (SMIC_CONTROL|SMIC_SMS|SMIC_RD_START)#define SMIC_CC_SMS_RD_NEXT (SMIC_CONTROL|SMIC_SMS|SMIC_RD_NEXT)#define SMIC_CC_SMS_RD_END (SMIC_CONTROL|SMIC_SMS|SMIC_RD_END)#define SMIC_CC_SMM_GET_STATUS (SMIC_CONTROL|SMIC_SMM|SMIC_GET_STATUS)#define SMIC_CC_SMM_WR_START (SMIC_CONTROL|SMIC_SMM|SMIC_WR_START)#define SMIC_CC_SMM_WR_NEXT (SMIC_CONTROL|SMIC_SMM|SMIC_WR_NEXT)#define SMIC_CC_SMM_WR_END (SMIC_CONTROL|SMIC_SMM|SMIC_WR_END)#define SMIC_CC_SMM_RD_START (SMIC_CONTROL|SMIC_SMM|SMIC_RD_START)#define SMIC_CC_SMM_RD_NEXT (SMIC_CONTROL|SMIC_SMM|SMIC_RD_NEXT)#define SMIC_CC_SMM_RD_END (SMIC_CONTROL|SMIC_SMM|SMIC_RD_END)/* SMIC Status Codes */#define SMIC_SC_SMS_READY (SMIC_STATUS|SMIC_SMS|SMIC_READY)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -