11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ipmi_smic_sm.c
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The state-machine driver for an IPMI SMIC driver
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * It started as a copy of Corey Minyard's driver for the KSC interface
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and the kernel patch "mmcdev-patch-245" by HP
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modified by:	Hannes Schulz <schulz@schwaar.com>
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		ipmi@schwaar.com
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Corey Minyard's driver for the KSC interface has the following
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * copyright notice:
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Copyright 2002 MontaVista Software Inc.
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the kernel patch "mmcdev-patch-245" by HP has the following
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * copyright notice:
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (c) Copyright 2001 Grant Grundler (c) Copyright
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001 Hewlett-Packard Company
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  This program is free software; you can redistribute it and/or modify it
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  under the terms of the GNU General Public License as published by the
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Free Software Foundation; either version 2 of the License, or (at your
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  option) any later version.
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  You should have received a copy of the GNU General Public License along
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  with this program; if not, write to the Free Software Foundation, Inc.,
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  675 Mass Ave, Cambridge, MA 02139, USA.  */
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> /* For printk. */
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
46c4edff1c19ef23e15aae64ca03f32c6719822d54Corey Minyard#include <linux/module.h>
47c4edff1c19ef23e15aae64ca03f32c6719822d54Corey Minyard#include <linux/moduleparam.h>
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ipmi_msgdefs.h>		/* for completion codes */
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "ipmi_si_sm.h"
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* smic_debug is a bit-field
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	SMIC_DEBUG_ENABLE -	turned on for now
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	SMIC_DEBUG_MSG -	commands and their responses
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	SMIC_DEBUG_STATES -	state machine
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMIC_DEBUG_STATES	4
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMIC_DEBUG_MSG		2
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_DEBUG_ENABLE	1
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smic_debug = 1;
61c4edff1c19ef23e15aae64ca03f32c6719822d54Corey Minyardmodule_param(smic_debug, int, 0644);
62c4edff1c19ef23e15aae64ca03f32c6719822d54Corey MinyardMODULE_PARM_DESC(smic_debug, "debug bitmask, 1=enable, 2=messages, 4=states");
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum smic_states {
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_IDLE,
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_START_OP,
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_OP_OK,
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_WRITE_START,
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_WRITE_NEXT,
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_WRITE_END,
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_WRITE2READ,
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_READ_START,
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_READ_NEXT,
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_READ_END,
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_HOSED
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_SMIC_READ_SIZE 80
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_SMIC_WRITE_SIZE 80
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMIC_MAX_ERROR_RETRIES 3
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Timeouts in microseconds. */
83ccb3368cb4b97e2d8a763b894303e6a127f87bc8Xie XiuQi#define SMIC_RETRY_TIMEOUT (2*USEC_PER_SEC)
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* SMIC Flags Register Bits */
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMIC_RX_DATA_READY	0x80
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMIC_TX_DATA_READY	0x40
88c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard
89d5a2b89a4943b423b5b0a07783fee4e08424b0b2Corey Minyard/*
90d5a2b89a4943b423b5b0a07783fee4e08424b0b2Corey Minyard * SMIC_SMI and SMIC_EVM_DATA_AVAIL are only used by
91d5a2b89a4943b423b5b0a07783fee4e08424b0b2Corey Minyard * a few systems, and then only by Systems Management
92d5a2b89a4943b423b5b0a07783fee4e08424b0b2Corey Minyard * Interrupts, not by the OS.  Always ignore these bits.
93d5a2b89a4943b423b5b0a07783fee4e08424b0b2Corey Minyard *
94d5a2b89a4943b423b5b0a07783fee4e08424b0b2Corey Minyard */
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMIC_SMI		0x10
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMIC_EVM_DATA_AVAIL	0x08
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMIC_SMS_DATA_AVAIL	0x04
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMIC_FLAG_BSY		0x01
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* SMIC Error Codes */
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	EC_NO_ERROR		0x00
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	EC_ABORTED		0x01
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	EC_ILLEGAL_CONTROL	0x02
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	EC_NO_RESPONSE		0x03
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	EC_ILLEGAL_COMMAND	0x04
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	EC_BUFFER_FULL		0x05
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
108c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyardstruct si_sm_data {
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	enum smic_states state;
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct si_sm_io *io;
111c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard	unsigned char	 write_data[MAX_SMIC_WRITE_SIZE];
112c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard	int		 write_pos;
113c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard	int		 write_count;
114c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard	int		 orig_write_count;
115c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard	unsigned char	 read_data[MAX_SMIC_READ_SIZE];
116c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard	int		 read_pos;
117c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard	int		 truncated;
118c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard	unsigned int	 error_retries;
119c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard	long		 smic_timeout;
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
122c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyardstatic unsigned int init_smic_data(struct si_sm_data *smic,
123c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard				   struct si_sm_io *io)
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->state = SMIC_IDLE;
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->io = io;
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->write_pos = 0;
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->write_count = 0;
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->orig_write_count = 0;
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->read_pos = 0;
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->error_retries = 0;
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->truncated = 0;
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->smic_timeout = SMIC_RETRY_TIMEOUT;
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We use 3 bytes of I/O. */
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 3;
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int start_smic_transaction(struct si_sm_data *smic,
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  unsigned char *data, unsigned int size)
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int i;
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1444d7cbac7c870ca66d8fb27d68188efbb5de2dffaCorey Minyard	if (size < 2)
1454d7cbac7c870ca66d8fb27d68188efbb5de2dffaCorey Minyard		return IPMI_REQ_LEN_INVALID_ERR;
1464d7cbac7c870ca66d8fb27d68188efbb5de2dffaCorey Minyard	if (size > MAX_SMIC_WRITE_SIZE)
1474d7cbac7c870ca66d8fb27d68188efbb5de2dffaCorey Minyard		return IPMI_REQ_LEN_EXCEEDED_ERR;
1484d7cbac7c870ca66d8fb27d68188efbb5de2dffaCorey Minyard
1494d7cbac7c870ca66d8fb27d68188efbb5de2dffaCorey Minyard	if ((smic->state != SMIC_IDLE) && (smic->state != SMIC_HOSED))
1504d7cbac7c870ca66d8fb27d68188efbb5de2dffaCorey Minyard		return IPMI_NOT_IN_MY_STATE_ERR;
1514d7cbac7c870ca66d8fb27d68188efbb5de2dffaCorey Minyard
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (smic_debug & SMIC_DEBUG_MSG) {
153c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		printk(KERN_DEBUG "start_smic_transaction -");
154c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		for (i = 0; i < size; i++)
155c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard			printk(" %02x", (unsigned char) data[i]);
156c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		printk("\n");
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->error_retries = 0;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(smic->write_data, data, size);
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->write_count = size;
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->orig_write_count = size;
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->write_pos = 0;
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->read_pos = 0;
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->state = SMIC_START_OP;
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->smic_timeout = SMIC_RETRY_TIMEOUT;
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smic_get_result(struct si_sm_data *smic,
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   unsigned char *data, unsigned int length)
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (smic_debug & SMIC_DEBUG_MSG) {
175c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		printk(KERN_DEBUG "smic_get result -");
176c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		for (i = 0; i < smic->read_pos; i++)
177c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard			printk(" %02x", smic->read_data[i]);
178c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		printk("\n");
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (length < smic->read_pos) {
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smic->read_pos = length;
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smic->truncated = 1;
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(data, smic->read_data, smic->read_pos);
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((length >= 3) && (smic->read_pos < 3)) {
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data[2] = IPMI_ERR_UNSPECIFIED;
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smic->read_pos = 3;
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (smic->truncated) {
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data[2] = IPMI_ERR_MSG_TRUNCATED;
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smic->truncated = 0;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return smic->read_pos;
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline unsigned char read_smic_flags(struct si_sm_data *smic)
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return smic->io->inputb(smic->io, 2);
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline unsigned char read_smic_status(struct si_sm_data *smic)
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return smic->io->inputb(smic->io, 1);
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline unsigned char read_smic_data(struct si_sm_data *smic)
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return smic->io->inputb(smic->io, 0);
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void write_smic_flags(struct si_sm_data *smic,
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    unsigned char   flags)
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->io->outputb(smic->io, 2, flags);
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void write_smic_control(struct si_sm_data *smic,
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      unsigned char   control)
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->io->outputb(smic->io, 1, control);
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
224c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyardstatic inline void write_si_sm_data(struct si_sm_data *smic,
225c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard				    unsigned char   data)
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->io->outputb(smic->io, 0, data);
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void start_error_recovery(struct si_sm_data *smic, char *reason)
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(smic->error_retries)++;
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (smic->error_retries > SMIC_MAX_ERROR_RETRIES) {
234c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		if (smic_debug & SMIC_DEBUG_ENABLE)
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_WARNING
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       "ipmi_smic_drv: smic hosed: %s\n", reason);
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smic->state = SMIC_HOSED;
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smic->write_count = smic->orig_write_count;
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smic->write_pos = 0;
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smic->read_pos = 0;
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smic->state = SMIC_START_OP;
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smic->smic_timeout = SMIC_RETRY_TIMEOUT;
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void write_next_byte(struct si_sm_data *smic)
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	write_si_sm_data(smic, smic->write_data[smic->write_pos]);
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(smic->write_pos)++;
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(smic->write_count)--;
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
254c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyardstatic inline void read_next_byte(struct si_sm_data *smic)
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (smic->read_pos >= MAX_SMIC_READ_SIZE) {
257c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		read_smic_data(smic);
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smic->truncated = 1;
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smic->read_data[smic->read_pos] = read_smic_data(smic);
261c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		smic->read_pos++;
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*  SMIC Control/Status Code Components */
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_GET_STATUS		0x00	/* Control form's name */
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_READY		0x00	/* Status  form's name */
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_WR_START		0x01	/* Unified Control/Status names... */
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_WR_NEXT		0x02
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_WR_END		0x03
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_RD_START		0x04
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_RD_NEXT		0x05
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_RD_END		0x06
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_CODE_MASK		0x0f
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_CONTROL		0x00
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_STATUS		0x80
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_CS_MASK		0x80
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_SMS		0x40
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_SMM		0x60
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_STREAM_MASK	0x60
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*  SMIC Control Codes */
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_CC_SMS_GET_STATUS	(SMIC_CONTROL|SMIC_SMS|SMIC_GET_STATUS)
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_CC_SMS_WR_START	(SMIC_CONTROL|SMIC_SMS|SMIC_WR_START)
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_CC_SMS_WR_NEXT	(SMIC_CONTROL|SMIC_SMS|SMIC_WR_NEXT)
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_CC_SMS_WR_END	(SMIC_CONTROL|SMIC_SMS|SMIC_WR_END)
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_CC_SMS_RD_START	(SMIC_CONTROL|SMIC_SMS|SMIC_RD_START)
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_CC_SMS_RD_NEXT	(SMIC_CONTROL|SMIC_SMS|SMIC_RD_NEXT)
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_CC_SMS_RD_END	(SMIC_CONTROL|SMIC_SMS|SMIC_RD_END)
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_CC_SMM_GET_STATUS	(SMIC_CONTROL|SMIC_SMM|SMIC_GET_STATUS)
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_CC_SMM_WR_START	(SMIC_CONTROL|SMIC_SMM|SMIC_WR_START)
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_CC_SMM_WR_NEXT	(SMIC_CONTROL|SMIC_SMM|SMIC_WR_NEXT)
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_CC_SMM_WR_END	(SMIC_CONTROL|SMIC_SMM|SMIC_WR_END)
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_CC_SMM_RD_START	(SMIC_CONTROL|SMIC_SMM|SMIC_RD_START)
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_CC_SMM_RD_NEXT	(SMIC_CONTROL|SMIC_SMM|SMIC_RD_NEXT)
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_CC_SMM_RD_END	(SMIC_CONTROL|SMIC_SMM|SMIC_RD_END)
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*  SMIC Status Codes */
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_SC_SMS_READY	(SMIC_STATUS|SMIC_SMS|SMIC_READY)
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_SC_SMS_WR_START	(SMIC_STATUS|SMIC_SMS|SMIC_WR_START)
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_SC_SMS_WR_NEXT	(SMIC_STATUS|SMIC_SMS|SMIC_WR_NEXT)
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_SC_SMS_WR_END	(SMIC_STATUS|SMIC_SMS|SMIC_WR_END)
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_SC_SMS_RD_START	(SMIC_STATUS|SMIC_SMS|SMIC_RD_START)
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_SC_SMS_RD_NEXT	(SMIC_STATUS|SMIC_SMS|SMIC_RD_NEXT)
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_SC_SMS_RD_END	(SMIC_STATUS|SMIC_SMS|SMIC_RD_END)
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_SC_SMM_READY	(SMIC_STATUS|SMIC_SMM|SMIC_READY)
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_SC_SMM_WR_START	(SMIC_STATUS|SMIC_SMM|SMIC_WR_START)
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_SC_SMM_WR_NEXT	(SMIC_STATUS|SMIC_SMM|SMIC_WR_NEXT)
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_SC_SMM_WR_END	(SMIC_STATUS|SMIC_SMM|SMIC_WR_END)
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_SC_SMM_RD_START	(SMIC_STATUS|SMIC_SMM|SMIC_RD_START)
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_SC_SMM_RD_NEXT	(SMIC_STATUS|SMIC_SMM|SMIC_RD_NEXT)
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SMIC_SC_SMM_RD_END	(SMIC_STATUS|SMIC_SMM|SMIC_RD_END)
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* these are the control/status codes we actually use
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_CC_SMS_GET_STATUS	0x40
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_CC_SMS_WR_START	0x41
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_CC_SMS_WR_NEXT	0x42
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_CC_SMS_WR_END	0x43
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_CC_SMS_RD_START	0x44
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_CC_SMS_RD_NEXT	0x45
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_CC_SMS_RD_END	0x46
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_SC_SMS_READY	0xC0
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_SC_SMS_WR_START	0xC1
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_SC_SMS_WR_NEXT	0xC2
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_SC_SMS_WR_END	0xC3
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_SC_SMS_RD_START	0xC4
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_SC_SMS_RD_NEXT	0xC5
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SMIC_SC_SMS_RD_END	0xC6
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
336c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyardstatic enum si_sm_result smic_event(struct si_sm_data *smic, long time)
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char status;
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char flags;
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char data;
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (smic->state == SMIC_HOSED) {
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		init_smic_data(smic, smic->io);
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return SI_SM_HOSED;
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (smic->state != SMIC_IDLE) {
347c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		if (smic_debug & SMIC_DEBUG_STATES)
348c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard			printk(KERN_DEBUG
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       "smic_event - smic->smic_timeout = %ld,"
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       " time = %ld\n",
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       smic->smic_timeout, time);
352c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		/*
353c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		 * FIXME: smic_event is sometimes called with time >
354c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		 * SMIC_RETRY_TIMEOUT
355c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		 */
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (time < SMIC_RETRY_TIMEOUT) {
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			smic->smic_timeout -= time;
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (smic->smic_timeout < 0) {
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				start_error_recovery(smic, "smic timed out.");
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return SI_SM_CALL_WITH_DELAY;
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flags = read_smic_flags(smic);
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (flags & SMIC_FLAG_BSY)
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return SI_SM_CALL_WITH_DELAY;
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
368c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard	status = read_smic_status(smic);
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (smic_debug & SMIC_DEBUG_STATES)
370c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		printk(KERN_DEBUG
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       "smic_event - state = %d, flags = 0x%02x,"
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       " status = 0x%02x\n",
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       smic->state, flags, status);
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (smic->state) {
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SMIC_IDLE:
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* in IDLE we check for available messages */
378d5a2b89a4943b423b5b0a07783fee4e08424b0b2Corey Minyard		if (flags & SMIC_SMS_DATA_AVAIL)
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SI_SM_ATTN;
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return SI_SM_IDLE;
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SMIC_START_OP:
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* sanity check whether smic is really idle */
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		write_smic_control(smic, SMIC_CC_SMS_GET_STATUS);
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		write_smic_flags(smic, flags | SMIC_FLAG_BSY);
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smic->state = SMIC_OP_OK;
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SMIC_OP_OK:
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status != SMIC_SC_SMS_READY) {
391c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard			/* this should not happen */
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start_error_recovery(smic,
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     "state = SMIC_OP_OK,"
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     " status != SMIC_SC_SMS_READY");
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SI_SM_CALL_WITH_DELAY;
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* OK so far; smic is idle let us start ... */
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		write_smic_control(smic, SMIC_CC_SMS_WR_START);
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		write_next_byte(smic);
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		write_smic_flags(smic, flags | SMIC_FLAG_BSY);
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smic->state = SMIC_WRITE_START;
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SMIC_WRITE_START:
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status != SMIC_SC_SMS_WR_START) {
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start_error_recovery(smic,
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     "state = SMIC_WRITE_START, "
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     "status != SMIC_SC_SMS_WR_START");
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SI_SM_CALL_WITH_DELAY;
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
411c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		/*
412c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		 * we must not issue WR_(NEXT|END) unless
413c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		 * TX_DATA_READY is set
414c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		 * */
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (flags & SMIC_TX_DATA_READY) {
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (smic->write_count == 1) {
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* last byte */
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				write_smic_control(smic, SMIC_CC_SMS_WR_END);
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				smic->state = SMIC_WRITE_END;
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				write_smic_control(smic, SMIC_CC_SMS_WR_NEXT);
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				smic->state = SMIC_WRITE_NEXT;
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			write_next_byte(smic);
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			write_smic_flags(smic, flags | SMIC_FLAG_BSY);
426c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		} else
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SI_SM_CALL_WITH_DELAY;
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SMIC_WRITE_NEXT:
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status != SMIC_SC_SMS_WR_NEXT) {
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start_error_recovery(smic,
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     "state = SMIC_WRITE_NEXT, "
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     "status != SMIC_SC_SMS_WR_NEXT");
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SI_SM_CALL_WITH_DELAY;
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* this is the same code as in SMIC_WRITE_START */
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (flags & SMIC_TX_DATA_READY) {
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (smic->write_count == 1) {
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				write_smic_control(smic, SMIC_CC_SMS_WR_END);
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				smic->state = SMIC_WRITE_END;
442c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard			} else {
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				write_smic_control(smic, SMIC_CC_SMS_WR_NEXT);
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				smic->state = SMIC_WRITE_NEXT;
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			write_next_byte(smic);
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			write_smic_flags(smic, flags | SMIC_FLAG_BSY);
448c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		} else
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SI_SM_CALL_WITH_DELAY;
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SMIC_WRITE_END:
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status != SMIC_SC_SMS_WR_END) {
454c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard			start_error_recovery(smic,
455c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard					     "state = SMIC_WRITE_END, "
456c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard					     "status != SMIC_SC_SMS_WR_END");
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SI_SM_CALL_WITH_DELAY;
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* data register holds an error code */
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data = read_smic_data(smic);
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (data != 0) {
462c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard			if (smic_debug & SMIC_DEBUG_ENABLE)
463c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard				printk(KERN_DEBUG
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       "SMIC_WRITE_END: data = %02x\n", data);
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start_error_recovery(smic,
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     "state = SMIC_WRITE_END, "
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     "data != SUCCESS");
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SI_SM_CALL_WITH_DELAY;
469c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		} else
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			smic->state = SMIC_WRITE2READ;
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SMIC_WRITE2READ:
474c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		/*
475c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		 * we must wait for RX_DATA_READY to be set before we
476c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		 * can continue
477c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		 */
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (flags & SMIC_RX_DATA_READY) {
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			write_smic_control(smic, SMIC_CC_SMS_RD_START);
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			write_smic_flags(smic, flags | SMIC_FLAG_BSY);
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			smic->state = SMIC_READ_START;
482c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		} else
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SI_SM_CALL_WITH_DELAY;
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SMIC_READ_START:
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status != SMIC_SC_SMS_RD_START) {
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start_error_recovery(smic,
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     "state = SMIC_READ_START, "
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     "status != SMIC_SC_SMS_RD_START");
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SI_SM_CALL_WITH_DELAY;
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (flags & SMIC_RX_DATA_READY) {
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			read_next_byte(smic);
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			write_smic_control(smic, SMIC_CC_SMS_RD_NEXT);
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			write_smic_flags(smic, flags | SMIC_FLAG_BSY);
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			smic->state = SMIC_READ_NEXT;
498c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		} else
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SI_SM_CALL_WITH_DELAY;
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SMIC_READ_NEXT:
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (status) {
504c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		/*
505c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		 * smic tells us that this is the last byte to be read
506c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		 * --> clean up
507c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard		 */
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case SMIC_SC_SMS_RD_END:
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			read_next_byte(smic);
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			write_smic_control(smic, SMIC_CC_SMS_RD_END);
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			write_smic_flags(smic, flags | SMIC_FLAG_BSY);
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			smic->state = SMIC_READ_END;
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case SMIC_SC_SMS_RD_NEXT:
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (flags & SMIC_RX_DATA_READY) {
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				read_next_byte(smic);
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				write_smic_control(smic, SMIC_CC_SMS_RD_NEXT);
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				write_smic_flags(smic, flags | SMIC_FLAG_BSY);
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				smic->state = SMIC_READ_NEXT;
520c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard			} else
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return SI_SM_CALL_WITH_DELAY;
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start_error_recovery(
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				smic,
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"state = SMIC_READ_NEXT, "
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"status != SMIC_SC_SMS_RD_(NEXT|END)");
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SI_SM_CALL_WITH_DELAY;
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SMIC_READ_END:
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status != SMIC_SC_SMS_READY) {
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start_error_recovery(smic,
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     "state = SMIC_READ_END, "
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     "status != SMIC_SC_SMS_READY");
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SI_SM_CALL_WITH_DELAY;
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data = read_smic_data(smic);
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* data register holds an error code */
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (data != 0) {
542c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard			if (smic_debug & SMIC_DEBUG_ENABLE)
543c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard				printk(KERN_DEBUG
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       "SMIC_READ_END: data = %02x\n", data);
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start_error_recovery(smic,
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     "state = SMIC_READ_END, "
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     "data != SUCCESS");
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SI_SM_CALL_WITH_DELAY;
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			smic->state = SMIC_IDLE;
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SI_SM_TRANSACTION_COMPLETE;
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SMIC_HOSED:
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		init_smic_data(smic, smic->io);
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return SI_SM_HOSED;
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (smic_debug & SMIC_DEBUG_ENABLE) {
560c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard			printk(KERN_DEBUG "smic->state = %d\n", smic->state);
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start_error_recovery(smic, "state = UNKNOWN");
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SI_SM_CALL_WITH_DELAY;
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smic->smic_timeout = SMIC_RETRY_TIMEOUT;
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return SI_SM_CALL_WITHOUT_DELAY;
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smic_detect(struct si_sm_data *smic)
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
571c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard	/*
572c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard	 * It's impossible for the SMIC fnags register to be all 1's,
573c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard	 * (assuming a properly functioning, self-initialized BMC)
574c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard	 * but that's what you get from reading a bogus address, so we
575c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard	 * test that first.
576c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyard	 */
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (read_smic_flags(smic) == 0xff)
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void smic_cleanup(struct si_sm_data *kcs)
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smic_size(void)
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sizeof(struct si_sm_data);
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
592c305e3d38e5f54a48a4618496cdc1ada970ebf68Corey Minyardstruct si_sm_handlers smic_smi_handlers = {
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.init_data         = init_smic_data,
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.start_transaction = start_smic_transaction,
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.get_result        = smic_get_result,
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.event             = smic_event,
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.detect            = smic_detect,
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.cleanup           = smic_cleanup,
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.size              = smic_size,
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
601