]> git.pld-linux.org Git - packages/kernel.git/blob - linux-2.4.23-ipmi-v28.patch
- fix unresolved symbols in ipv6 netfilter
[packages/kernel.git] / linux-2.4.23-ipmi-v28.patch
1 diff -urN linux-2.4.23.org/Documentation/Configure.help linux-2.4.23/Documentation/Configure.help
2 --- linux-2.4.23.org/Documentation/Configure.help       2004-01-02 23:33:09.001923647 +0100
3 +++ linux-2.4.23/Documentation/Configure.help   2004-01-02 23:33:47.987823068 +0100
4 @@ -4185,6 +4185,13 @@
5  
6    If unsure, say N.
7  
8 +IPMI sockets
9 +CONFIG_IPMI_SOCKET
10 +  If you say Y here, you will include support for IPMI sockets;
11 +  This is the better way for establishing and accessing IPMI devices.
12 +  
13 +  If unsure, say N.
14 +
15  # Choice: alphatype
16  Alpha system type
17  CONFIG_ALPHA_GENERIC
18 @@ -29534,14 +29541,41 @@
19    generate an IPMI event describing the panic to each interface
20    registered with the message handler.
21  
22 +Generate OEM events containing the panic string
23 +CONFIG_IPMI_PANIC_STRING
24 +  When a panic occurs, this will cause the IPMI message handler to
25 +  generate IPMI OEM type f0 events holding the IPMB address of the
26 +  panic generator (byte 4 of the event), a sequence number for the
27 +  string (byte 5 of the event) and part of the string (the rest of the
28 +  event).  Bytes 1, 2, and 3 are the normal usage for an OEM event.
29 +  You can fetch these events and use the sequence numbers to piece the
30 +  string together.
31 +
32  Device interface for IPMI
33  CONFIG_IPMI_DEVICE_INTERFACE
34    This provides an IOCTL interface to the IPMI message handler so
35    userland processes may use IPMI.  It supports poll() and select().
36  
37 +IPMI SI handler
38 +CONFIG_IPMI_SI
39 +  Provides a driver for System Interfaces (KCS, SMIC, BT).
40 +  Currently, only KCS and SMIC are supported.  If
41 +  you are using IPMI, you should probably say "y" here.
42 +
43  IPMI KCS handler
44  CONFIG_IPMI_KCS
45 -  Provides a driver for a KCS-style interface to a BMC.
46 +  Provides a driver for a KCS-style interface to a BMC.  This
47 +  is deprecated, please use the IPMI System Interface handler
48 +  instead.
49 +
50 +IPMI SMBus handler
51 +CONFIG_IPMI_SMB
52 +  Provides a driver for a SMBus interface to a BMC, meaning that you
53 +  have a driver that must be accessed over an I2C bus instead of a
54 +  standard interface.  This module requires I2C support.  Note that
55 +  you might need some I2C changes if CONFIG_IPMI_PANIC_EVENT is
56 +  enabled along with this, so the I2C driver knows to run to
57 +  completion during sending a panic event.
58  
59  IPMI Watchdog Timer
60  CONFIG_IPMI_WATCHDOG
61 diff -urN linux-2.4.23.org/Documentation/IPMI.txt linux-2.4.23/Documentation/IPMI.txt
62 --- linux-2.4.23.org/Documentation/IPMI.txt     2004-01-02 23:33:01.180548761 +0100
63 +++ linux-2.4.23/Documentation/IPMI.txt 2004-01-02 23:33:47.993821821 +0100
64 @@ -41,18 +41,33 @@
65  driver, each open file for this device ties in to the message handler
66  as an IPMI user.
67  
68 -ipmi_kcs_drv - A driver for the KCS SMI.  Most system have a KCS
69 -interface for IPMI.
70 +ipmi_si_drv - A driver for various system interfaces.  This supports
71 +KCS, SMIC, and may support BT in the future.  Unless you have your own
72 +custom interface, you probably need to use this.
73 +
74 +ipmi_kcs_drv - A driver for the KCS SI.  Most systems have a KCS
75 +interface for IPMI.  This is deprecated, ipmi_si_drv supports KCS and
76 +SMIC interfaces.
77 +
78 +ipmi_smb_intf - A driver for accessing BMCs on the SMBus. It uses the
79 +I2C kernel driver's SMBus interfaces to send and receive IPMI messages
80 +over the SMBus.
81 +
82 +af_ipmi - A network socket interface to IPMI.  This doesn't take up
83 +a character device in your system.
84  
85  
86  Much documentation for the interface is in the include files.  The
87  IPMI include files are:
88  
89 -ipmi.h - Contains the user interface and IOCTL interface for IPMI.
90 +net/af_ipmi.h - Contains the socket interface.
91 +
92 +linux/ipmi.h - Contains the user interface and IOCTL interface for IPMI.
93  
94 -ipmi_smi.h - Contains the interface for SMI drivers to use.
95 +linux/ipmi_smi.h - Contains the interface for system management interfaces
96 +(things that interface to IPMI controllers) to use.
97  
98 -ipmi_msgdefs.h - General definitions for base IPMI messaging.
99 +linux/ipmi_msgdefs.h - General definitions for base IPMI messaging.
100  
101  
102  Addressing
103 @@ -260,8 +275,66 @@
104  in the order they register, although if an SMI unregisters and then
105  another one registers, all bets are off.
106  
107 -The ipmi_smi.h defines the interface for SMIs, see that for more
108 -details.
109 +The ipmi_smi.h defines the interface for management interfaces, see
110 +that for more details.
111 +
112 +
113 +The SI Driver
114 +-------------
115 +
116 +The SI driver allows up to 4 KCS or SMIC interfaces to be configured
117 +in the system.  By default, scan the ACPI tables for interfaces, and
118 +if it doesn't find any the driver will attempt to register one KCS
119 +interface at the spec-specified I/O port 0xca2 without interrupts.
120 +You can change this at module load time (for a module) with:
121 +
122 +  insmod ipmi_si_drv.o si_type=<type1>,<type2>....
123 +       si_ports=<port1>,<port2>... si_addrs=<addr1>,<addr2>
124 +       si_irqs=<irq1>,<irq2>... si_trydefaults=[0|1]
125 +
126 +Each of these except si_trydefaults is a list, the first item for the
127 +first interface, second item for the second interface, etc.
128 +
129 +The si_type may be either "kcs", "smic", or "bt".  If you leave it blank, it
130 +defaults to "kcs".
131 +
132 +If you specify si_addrs as non-zero for an interface, the driver will
133 +use the memory address given as the address of the device.  This
134 +overrides si_ports.
135 +
136 +If you specify si_ports as non-zero for an interface, the driver will
137 +use the I/O port given as the device address.
138 +
139 +If you specify si_irqs as non-zero for an interface, the driver will
140 +attempt to use the given interrupt for the device.
141 +
142 +si_trydefaults sets whether the standard IPMI interface at 0xca2 and
143 +any interfaces specified by ACPE are tried.  By default, the driver
144 +tries it, set this value to zero to turn this off.
145 +
146 +When compiled into the kernel, the addresses can be specified on the
147 +kernel command line as:
148 +
149 +  ipmi_si=[<type>,]<bmc1>:<irq1>,[<type>,]<bmc2>:<irq2>....,[nodefault]
150 +
151 +The type is optional and may be either "kcs" for KCS, "smic" for
152 +SMIC, or "bt" for BT.  If not specified, it defaults to KCS.
153 +The <bmcx> values is either "p<port>" or "m<addr>" for port or memory
154 +addresses.  So for instance, a KCS interface at port 0xca2 using
155 +interrupt 9 and a SMIC memory interface at address 0xf9827341 with no
156 +interrupt would be specified "ipmi_si=k,p0xca2:9,s,m0xf9827341".  If you
157 +specify zero for in irq or don't specify it, the driver will run polled
158 +unless the software can detect the interrupt to use in the ACPI tables.
159 +
160 +By default, the driver will attempt to detect a KCS device at the
161 +spec-specified 0xca2 address and any address specified by ACPI.  If
162 +you want to turn this off, use the "nodefault" option.
163 +
164 +If you have high-res timers compiled into the kernel, the driver will
165 +use them to provide much better performance.  Note that if you do not
166 +have high-res timers enabled in the kernel and you don't have
167 +interrupts enabled, the driver will run VERY slowly.  Don't blame me,
168 +these interfaces suck.
169  
170  
171  The KCS Driver
172 @@ -309,6 +382,59 @@
173  the KCS interface sucks.
174  
175  
176 +The SMBus Driver
177 +----------------
178 +
179 +The SMBus driver allows up to 4 SMBus devices to be configured in the
180 +system.  By default, the driver will register any SMBus interfaces it finds
181 +in the I2C address range of 0x20 to 0x4f on any adapter.  You can change this
182 +at module load time (for a module) with:
183 +
184 +  insmod ipmi_smb_intf.o
185 +       smb_addr=<adapter1>,<i2caddr1>[,<adapter2>,<i2caddr2>[,...]]
186 +       smb_dbg=<flags1>,<flags2>...
187 +       [smb_defaultprobe=0] [smb_dbg_probe=1]
188 +
189 +The addresses are specified in pairs, the first is the adapter ID and the
190 +second is the I2C address on that adapter.
191 +
192 +The debug flags are bit flags for each BMC found, they are:
193 +IPMI messages: 1, driver state: 2, timing: 4, I2C probe: 8
194 +
195 +Setting smb_defaultprobe to zero disabled the default probing of SMBus
196 +interfaces at address range 0x20 to 0x4f.  This means that only the
197 +BMCs specified on the smb_addr line will be detected.
198 +
199 +Setting smb_dbg_probe to 1 will enable debugging of the probing and
200 +detection process for BMCs on the SMBusses.
201 +
202 +Discovering the IPMI compilant BMC on the SMBus can cause devices
203 +on the I2C bus to fail. The SMBus driver writes a "Get Device ID" IPMI
204 +message as a block write to the I2C bus and waits for a response.
205 +This action can be detrimental to some I2C devices. It is highly recommended
206 +that the known I2c address be given to the SMBus driver in the smb_addr
207 +parameter. The default adrress range will not be used when a smb_addr
208 +parameter is provided.
209 +
210 +When compiled into the kernel, the addresses can be specified on the
211 +kernel command line as:
212 +
213 +  ipmi_smb=[<adapter1>.]<addr1>[:<debug1>],[<adapter2>.<addr2>[:<debug1>]....
214 +
215 +The [<adapterx>.]<addrx>[:<debugx>] I2C address-debug flag are value
216 +set for each BMC.  If the adapter is not given, then it defaults to
217 +zero.  The debug flag is the same as the smb_dbg flag given above.
218 +
219 +You may also specify "nodefaults" and "debug_probe", separated by
220 +commas, on the ipmi_smb line.  These will disable the default SMB
221 +probe and enable debugging of the BMC probing and detection process,
222 +respectively.
223 +
224 +Note that you might need some I2C changes if CONFIG_IPMI_PANIC_EVENT
225 +is enabled along with this, so the I2C driver knows to run to
226 +completion during sending a panic event.
227 +
228 +
229  Other Pieces
230  ------------
231  
232 @@ -323,7 +449,10 @@
233  
234  The timeout is the number of seconds to the action, and the pretimeout
235  is the amount of seconds before the reset that the pre-timeout panic will
236 -occur (if pretimeout is zero, then pretimeout will not be enabled).
237 +occur (if pretimeout is zero, then pretimeout will not be enabled).  Note
238 +that the pretimeout is the time before the final timeout.  So if the
239 +timeout is 50 seconds and the pretimeout is 10 seconds, then the pretimeout
240 +will occur in 40 second (10 seconds before the timeout).
241  
242  The action may be "reset", "power_cycle", or "power_off", and
243  specifies what to do when the timer times out, and defaults to
244 diff -urN linux-2.4.23.org/drivers/char/Config.in linux-2.4.23/drivers/char/Config.in
245 --- linux-2.4.23.org/drivers/char/Config.in     2004-01-02 23:31:35.216409593 +0100
246 +++ linux-2.4.23/drivers/char/Config.in 2004-01-02 23:33:48.006819121 +0100
247 @@ -214,8 +214,11 @@
248  
249  tristate 'IPMI top-level message handler' CONFIG_IPMI_HANDLER
250  dep_mbool '  Generate a panic event to all BMCs on a panic' CONFIG_IPMI_PANIC_EVENT $CONFIG_IPMI_HANDLER
251 +dep_mbool '  Generate a OEM events holding the panic string' CONFIG_IPMI_PANIC_STRING $CONFIG_IPMI_PANIC_EVENT
252  dep_tristate '  Device interface for IPMI' CONFIG_IPMI_DEVICE_INTERFACE $CONFIG_IPMI_HANDLER
253 +dep_tristate '  IPMI SI handler' CONFIG_IPMI_SI $CONFIG_IPMI_HANDLER
254  dep_tristate '  IPMI KCS handler' CONFIG_IPMI_KCS $CONFIG_IPMI_HANDLER
255 +dep_tristate '  IPMI SMBus handler' CONFIG_IPMI_SMB $CONFIG_IPMI_HANDLER $CONFIG_I2C
256  dep_tristate '  IPMI Watchdog Timer' CONFIG_IPMI_WATCHDOG $CONFIG_IPMI_HANDLER
257  
258  mainmenu_option next_comment
259 diff -urN linux-2.4.23.org/drivers/char/ipmi/ipmi_bt_sm.c linux-2.4.23/drivers/char/ipmi/ipmi_bt_sm.c
260 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_bt_sm.c     1970-01-01 01:00:00.000000000 +0100
261 +++ linux-2.4.23/drivers/char/ipmi/ipmi_bt_sm.c 2004-01-02 23:33:48.010818290 +0100
262 @@ -0,0 +1,441 @@
263 +/*
264 + * ipmi_bt_sm.c
265 + *
266 + * The state-machine driver for an IPMI Block Transfer driver
267 + *
268 + * It started as a copy of Corey Minyard's driver for the KSC interface
269 + * and the kernel patch "mmcdev-patch-245" by HP
270 + *
271 + * modified by:        Jordan Hargrave <jordan_hargrave@dell.com>
272 + *
273 + * Corey Minyard's driver for the KSC interface has the following
274 + * copyright notice:
275 + *   Copyright 2002 MontaVista Software Inc.
276 + *
277 + * the kernel patch "mmcdev-patch-245" by HP has the following
278 + * copyright notice:
279 + * (c) Copyright 2001 Grant Grundler (c) Copyright
280 + * 2001 Hewlett-Packard Company
281 + * 
282 + *
283 + *  This program is free software; you can redistribute it and/or modify it
284 + *  under the terms of the GNU General Public License as published by the
285 + *  Free Software Foundation; either version 2 of the License, or (at your
286 + *  option) any later version.
287 + *
288 + *
289 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
290 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
291 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
292 + *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
293 + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
294 + *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
295 + *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
296 + *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
297 + *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
298 + *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
299 + *
300 + *  You should have received a copy of the GNU General Public License along
301 + *  with this program; if not, write to the Free Software Foundation, Inc.,
302 + *  675 Mass Ave, Cambridge, MA 02139, USA.
303 + */
304 +
305 +/* #define BT_DEBUG */
306 +
307 +#include <linux/kernel.h>
308 +#include <asm/string.h>
309 +#include "ipmi_si_sm.h"
310 +
311 +#define IPMI_BT_VERSION "v28"
312 +
313 +#ifdef BT_DEBUG
314 +static void dump(const void *b, int len)
315 +{
316 +       const uint8_t *buf = (const uint8_t *)b;
317 +       int i, j, c;
318 +
319 +       for(i=0; i<len; i+=16) {
320 +               for(j=0; j<16; j++) {
321 +                       if (i+j >= len) printk("XX "); 
322 +                       else printk("%.02x ", buf[i+j]);
323 +               }
324 +               printk("  ");
325 +               for(j=0; j<16; j++) {
326 +                       c = (i+j < len ? buf[i+j] : '.');
327 +                       printk("%c", (c >= ' ' && c <= 'z') ? c : '.');
328 +               }
329 +               printk("\n");
330 +       }
331 +}
332 +#define bt_printk printk
333 +#else
334 +#define bt_printk(x...) do { } while(0)
335 +#endif
336 +
337 +/*===========================================================================
338 + *
339 + *                       IPMI Block Transfer interface method
340 + *
341 + *===========================================================================*/
342 +#ifndef BIT
343 +#define BIT(n) (1L << (n))
344 +#endif
345 +
346 +#define BT_CTRL_REG      0
347 +# define BT_CLR_WR_PTR   BIT(0)
348 +# define BT_CLR_RD_PTR   BIT(1)
349 +# define BT_HOST2BMC_ATN BIT(2)
350 +# define BT_BMC2HOST_ATN BIT(3)
351 +# define BT_EVT_ATN      BIT(4)
352 +# define BT_HOST_BUSY    BIT(6)
353 +# define BT_BMC_BUSY     BIT(7)
354 +
355 +# define BT_RX_READY     (BT_BMC2HOST_ATN)
356 +# define BT_TX_READY     (BT_BMC_BUSY|BT_HOST2BMC_ATN)
357 +
358 +#define BT_BUFFER_REG         1
359 +
360 +#define BT_INTMASK_REG        2
361 +# define BT_BMC2HOST_IRQ_EN   BIT(0)
362 +# define BT_BMC2HOST_IRQ      BIT(1)
363 +# define BT_HOST2BMC_RESET    BIT(7)
364 +
365 +#define BT_SEQMASK     0x3F
366 +#define BT_MAXREQSZ    128
367 +#define BT_MINRESPSZ   4      /* len+nfln+seq+ccode */
368 +#define BT_MINPKTSZ    3      /* nfln+ccode+status */
369 +
370 +#define BT_IDLE        0
371 +#define BT_WRITE_START 1
372 +#define BT_WRITE       2
373 +#define BT_WRITE_END   3
374 +
375 +#define BT_READ_START  4
376 +#define BT_READ        5
377 +#define BT_READ_END    6
378 +
379 +#define BT_HOSED       7
380 +#define BT_ERROR       8
381 +
382 +#define bt(a,b) ((a)&(b) ? 1 : 0)
383 +#define port_outb(bt,port,val) bt->io->outputb(bt->io, port, val)
384 +#define port_inb(bt,port)      bt->io->inputb(bt->io, port)
385 +
386 +/* --== Block Transfer XMIT/RECV structure ==-- */
387 +struct bt_xmit
388 +{
389 +       int      seq;     // sequence number
390 +       int      len;     // length of data packet
391 +       int      pos;     // current write pos
392 +       uint8_t *ptr;     // current write ptr
393 +       uint8_t  data[BT_MAXREQSZ];
394 +};
395 +
396 +struct si_sm_data
397 +{
398 +       int      state;
399 +       int      status;
400 +       int      btSeq;
401 +       int      error_retries;
402 +       int      truncated;
403 +
404 +       /* --== read/write state ==-- */
405 +       struct bt_xmit wr;
406 +       struct bt_xmit rd;
407 +
408 +       /* --== I/O handler */
409 +       struct si_sm_io *io;
410 +};
411 +
412 +static void bt_print_status(int v, char *pfx)
413 +{
414 +       if (v == 0) return;
415 +
416 +#ifdef BT_DEBUG
417 +       printk("%16s bt_ctrl ="
418 +              " %.02x w:%d r:%d h2b:%d b2h:%d evt:%d hb:%d bb:%d\n",
419 +              pfx, v,
420 +              bt(v,BT_CLR_WR_PTR),
421 +              bt(v,BT_CLR_RD_PTR),
422 +              bt(v,BT_HOST2BMC_ATN),
423 +              bt(v,BT_BMC2HOST_ATN),
424 +              bt(v,BT_EVT_ATN),
425 +              bt(v,BT_HOST_BUSY),
426 +              bt(v,BT_BMC_BUSY));
427 +#endif
428 +}
429 +
430 +/*=================================================================
431 + * Read/Write BT registers
432 + *=================================================================*/
433 +#define bt_read_ctrl(bt)         port_inb((bt), BT_CTRL_REG)
434 +#define bt_write_ctrl(bt,val)    port_outb((bt), BT_CTRL_REG, (val))
435 +#define bt_read_buffer(bt)       port_inb((bt), BT_BUFFER_REG)
436 +#define bt_write_buffer(bt,val)  port_outb((bt), BT_BUFFER_REG, (val))
437 +#define bt_read_intmask(bt)      port_inb((bt), BT_INTMASK_REG)
438 +#define bt_write_intmask(bt,val) port_outb((bt), BT_INTMASK_REG, (val))
439 +
440 +/*=================================================================
441 + * Test BT state
442 + *=================================================================*/
443 +#define bt_rx_ready(sts)         ((sts) & BT_RX_READY)
444 +#define bt_evt_ready(sts)        ((sts) & BT_EVT_ATN)
445 +#define bt_tx_ready(sts)         (~(sts) & BT_TX_READY)
446 +
447 +/*=================================================================
448 + * Reset BT controller to known state
449 + *=================================================================*/
450 +static inline void bt_reset(struct si_sm_data *bt)
451 +{
452 +       unsigned char v;
453 +
454 +       v = bt_read_ctrl(bt) & BT_HOST_BUSY;
455 +       bt_write_ctrl(bt,
456 +                     v | (BT_CLR_WR_PTR | BT_CLR_RD_PTR | BT_BMC2HOST_ATN | 
457 +                          BT_EVT_ATN));
458 +}
459 +
460 +/*===================================================
461 + * bt_init_data - initialize si_sm_data structure
462 + *===================================================*/
463 +static unsigned int bt_init_data(struct si_sm_data *bt,
464 +                                struct si_sm_io *io)
465 +{
466 +       bt->state  = BT_IDLE;
467 +       bt->io     = io;
468 +       bt->wr.pos = 0;
469 +       bt->wr.len = 0;
470 +       bt->wr.ptr = bt->wr.data;
471 +       bt->rd.pos = 0;
472 +       bt->rd.len = 0;
473 +       bt->rd.ptr = bt->rd.data;
474 +       bt->error_retries = 0;
475 +       bt->truncated     = 0;
476 +
477 +       /* reserve 3 i/o bytes */
478 +       return 3;
479 +}
480 +
481 +/*===================================================
482 + * bt_start_transaction - issue IPMI command
483 + *===================================================*/
484 +static int bt_start_transaction(struct si_sm_data *bt,
485 +                               unsigned char *data, 
486 +                               unsigned int size)
487 +{
488 +       bt_printk("bt_start: %d bytes\n", size);
489 +
490 +       /* --== Validate size and state ==-- */
491 +       if (size < 2 || size > BT_MAXREQSZ) {
492 +               return -1;
493 +       }
494 +       if (bt->state != BT_IDLE && bt->state != BT_HOSED) {
495 +               return -2;
496 +       }
497 +
498 +       /* --== assert: data = netfn|cmd|data... ==-- */
499 +       bt->error_retries = 0;
500 +       bt->state         = BT_WRITE_START;
501 +       bt->wr.pos        = 0;
502 +       bt->wr.len        = size+1;
503 +       bt->wr.ptr        = bt->wr.data;
504 +       bt->wr.seq        = ++bt->btSeq & BT_SEQMASK;
505 +       memcpy(bt->wr.data, data, size);
506 +
507 +#ifdef BT_DEBUG
508 +       bt_printk("------ request ------\n");
509 +       dump(data, size);
510 +#endif
511 +
512 +       return 0;
513 +}
514 +
515 +
516 +/*=======================================================
517 + * bt_get_result - get event or result of IPMI command
518 + *=======================================================*/
519 +static int bt_get_result(struct si_sm_data *bt, 
520 +                        unsigned char *data, 
521 +                        unsigned int length)
522 +{
523 +       int rdlen = bt->rd.len-1;  /* skip sequence byte */
524 +
525 +       if (length < rdlen) {
526 +               rdlen = length;
527 +               bt->truncated = 1;
528 +       }
529 +       memcpy(data, bt->rd.data, rdlen);
530 +
531 +#ifdef BT_DEBUG
532 +       bt_printk("------ result ------ : %d %d\n", length, rdlen);
533 +       dump(data, rdlen);
534 +#endif
535 +
536 +       /* --== Minimum length is 3 bytes: nfLn, cCode, status, data[] ==-- */
537 +       if ((length >= BT_MINPKTSZ) &&  (rdlen < BT_MINPKTSZ)) {
538 +               data[2] = 0xFF;
539 +               rdlen   = 3;
540 +       }
541 +       if (bt->truncated) {
542 +               data[2] = 0xFE;
543 +               bt->truncated = 0;
544 +       }
545 +       return rdlen;
546 +}
547 +
548 +/*=======================================================
549 + * bt_event - state machine to retreive/send events
550 + *=======================================================*/
551 +static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
552 +{
553 +       /* --== Read current status ==-- */
554 +       bt->status = bt_read_ctrl(bt);
555 +
556 +       switch(bt->state) {
557 +       case BT_IDLE:
558 +               bt_print_status(bt->status, "idle");
559 +               if (bt_evt_ready(bt->status)) {
560 +                       bt_printk("*** EVENT READY\n");
561 +                       bt_write_ctrl(bt, BT_EVT_ATN);
562 +               }
563 +               if (bt_rx_ready(bt->status)) {
564 +                       bt_printk("*** READ READY\n");
565 +                       bt->state = BT_READ_START;
566 +                       return SI_SM_ATTN;
567 +               }
568 +               if (bt->status & BT_HOST_BUSY) {
569 +      bt_write_ctrl(bt, BT_HOST_BUSY);
570 +               }
571 +               return SI_SM_IDLE;
572 +
573 +       case BT_WRITE_START:
574 +               bt_print_status(bt->status,"write_start");
575 +               if (bt_tx_ready(bt->status)) {
576 +                       bt_write_ctrl(bt, BT_CLR_WR_PTR);   /* signal write */
577 +                       bt->state = BT_WRITE;
578 +               }
579 +               break;
580 +
581 +       case BT_WRITE:
582 +               bt_print_status(bt->status,"write");
583 +               if (bt->wr.pos == 0) {
584 +                       /* Write length of data */
585 +                       bt_write_buffer(bt, bt->wr.len);
586 +               }
587 +               else if (bt->wr.pos == 2) {
588 +                       /* Write sequence number */
589 +                       bt_write_buffer(bt, bt->wr.seq);
590 +               }
591 +               else {
592 +                       /* Write normal data */
593 +                       bt_write_buffer(bt, *(bt->wr.ptr++));
594 +               }
595 +               if (bt->wr.pos++ == bt->wr.len) {
596 +                       bt->state = BT_WRITE_END;
597 +               }
598 +               return SI_SM_CALL_WITH_DELAY;
599 +
600 +       case BT_WRITE_END:
601 +               bt_print_status(bt->status,"write_end");
602 +               bt_write_ctrl(bt, BT_HOST2BMC_ATN);
603 +               bt->state = BT_READ_START;
604 +               break;
605 +
606 +  case BT_READ_START:
607 +         bt_print_status(bt->status, "read_start");
608 +         if (bt_rx_ready(bt->status)) {
609 +                 bt_write_ctrl(bt, BT_HOST_BUSY);    /* mark host busy */
610 +                 bt_write_ctrl(bt, BT_BMC2HOST_ATN); /* clear bmc2host attn */
611 +                 bt_write_ctrl(bt, BT_CLR_RD_PTR);   /* signal read */
612 +      
613 +                 bt->rd.pos = 0;
614 +                 bt->rd.ptr = bt->rd.data;
615 +                 bt->state  = BT_READ;
616 +         }
617 +         return SI_SM_CALL_WITH_DELAY;
618 +
619 +       case BT_READ:
620 +               bt_print_status(bt->status, "read");
621 +               if (bt->rd.pos == 0) {
622 +                       /* Read total buffer length - check here */
623 +                       bt->rd.len = bt_read_buffer(bt);
624 +                       bt_printk("read length: %x\n", bt->rd.len);
625 +                       if (bt->rd.len < BT_MINRESPSZ) {
626 +                               bt->state = BT_READ_END;
627 +                       }
628 +               }
629 +               else if (bt->rd.pos == 2) {
630 +                       /* Read sequence */
631 +                       bt->rd.seq = bt_read_buffer(bt);
632 +                       if (bt->rd.seq != bt->wr.seq) {
633 +                               printk("Out of order sequence!\n");
634 +                       }
635 +               }
636 +               else {
637 +                       *(bt->rd.ptr++) = bt_read_buffer(bt);
638 +               }
639 +               if (bt->rd.pos++ == bt->rd.len) {
640 +                       bt->state = BT_READ_END;
641 +               }
642 +               return SI_SM_CALL_WITH_DELAY;
643 +
644 +       case BT_READ_END:
645 +               bt_print_status(bt->status, "read_end");
646 +               bt_write_ctrl(bt, BT_HOST_BUSY);    /* clear host busy */
647 +               bt->state = BT_IDLE;
648 +               return SI_SM_TRANSACTION_COMPLETE;
649 +       }
650 +
651 +       return SI_SM_CALL_WITHOUT_DELAY;
652 +}
653 +
654 +/*=======================================================
655 + * bt_detect - Detect if BT interface is supported
656 + *=======================================================*/
657 +static int bt_detect(struct si_sm_data *bt)
658 +{
659 +       int v;
660 +
661 +       bt->btSeq = 0x0;
662 +       bt->state = BT_IDLE;
663 +
664 +       /* Check intmask and control register - neither should be 0xFF */
665 +       v = bt_read_intmask(bt);
666 +       if (v == 0xFF) {
667 +               return 1;
668 +       }
669 +       v = bt_read_ctrl(bt);
670 +       if (v != 0xFF) {
671 +               bt_reset(bt);
672 +       }
673 +       bt_print_status(v, "detect");
674 +       return (v == 0xFF);
675 +}
676 +
677 +/*=======================================================
678 + * bt_cleanup - Cleanup register state
679 + *=======================================================*/
680 +static void bt_cleanup(struct si_sm_data *bt)
681 +{
682 +       bt_printk("bt_cleanup\n");
683 +}
684 +
685 +/*=======================================================
686 + * bt_size - Returns size of device extension
687 + *=======================================================*/
688 +static int bt_size(void)
689 +{
690 +       return sizeof(struct si_sm_data);
691 +}
692 +
693 +struct si_sm_handlers bt_smi_handlers = 
694 +{
695 +       .version           = IPMI_BT_VERSION,
696 +       .init_data         = bt_init_data,
697 +       .start_transaction = bt_start_transaction,
698 +       .get_result        = bt_get_result,
699 +       .event             = bt_event,
700 +       .detect            = bt_detect,
701 +       .cleanup           = bt_cleanup,
702 +       .size              = bt_size,
703 +};
704 diff -urN linux-2.4.23.org/drivers/char/ipmi/ipmi_devintf.c linux-2.4.23/drivers/char/ipmi/ipmi_devintf.c
705 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_devintf.c   2004-01-02 23:31:35.452360571 +0100
706 +++ linux-2.4.23/drivers/char/ipmi/ipmi_devintf.c       2004-01-02 23:33:48.026814966 +0100
707 @@ -44,6 +44,8 @@
708  #include <asm/semaphore.h>
709  #include <linux/init.h>
710  
711 +#define IPMI_DEVINTF_VERSION "v28"
712 +
713  struct ipmi_file_private
714  {
715         ipmi_user_t          user;
716 @@ -53,6 +55,8 @@
717         struct fasync_struct *fasync_queue;
718         wait_queue_head_t    wait;
719         struct semaphore     recv_sem;
720 +       int                  default_retries;
721 +       unsigned int         default_retry_time_ms;
722  };
723  
724  static void file_receive_handler(struct ipmi_recv_msg *msg,
725 @@ -105,7 +109,7 @@
726  
727  static struct ipmi_user_hndl ipmi_hndlrs =
728  {
729 -       ipmi_recv_hndl : file_receive_handler
730 +       .ipmi_recv_hndl = file_receive_handler,
731  };
732  
733  static int ipmi_open(struct inode *inode, struct file *file)
734 @@ -138,6 +142,10 @@
735         priv->fasync_queue = NULL;
736         sema_init(&(priv->recv_sem), 1);
737  
738 +       /* Use the low-level defaults. */
739 +       priv->default_retries = -1;
740 +       priv->default_retry_time_ms = 0;
741 +
742         return 0;
743  }
744  
745 @@ -158,6 +166,47 @@
746         return 0;
747  }
748  
749 +static int handle_send_req(ipmi_user_t     user,
750 +                          struct ipmi_req *req,
751 +                          int             retries,
752 +                          unsigned int    retry_time_ms)
753 +{
754 +       int              rv;
755 +       struct ipmi_addr addr;
756 +       unsigned char    msgdata[IPMI_MAX_MSG_LENGTH];
757 +
758 +       if (req->addr_len > sizeof(struct ipmi_addr))
759 +               return -EINVAL;
760 +
761 +       if (copy_from_user(&addr, req->addr, req->addr_len))
762 +               return -EFAULT;
763 +
764 +       rv = ipmi_validate_addr(&addr, req->addr_len);
765 +       if (rv)
766 +               return rv;
767 +
768 +       if (req->msg.data != NULL) {
769 +               if (req->msg.data_len > IPMI_MAX_MSG_LENGTH)
770 +                       return -EMSGSIZE;
771 +
772 +               if (copy_from_user(&msgdata,
773 +                                  req->msg.data,
774 +                                  req->msg.data_len))
775 +                       return -EFAULT;
776 +       } else {
777 +               req->msg.data_len = 0;
778 +       }
779 +       req->msg.data = msgdata;
780 +
781 +       return ipmi_request_settime(user,
782 +                                   &addr,
783 +                                   req->msgid,
784 +                                   &(req->msg),
785 +                                   0,
786 +                                   retries,
787 +                                   retry_time_ms);
788 +}
789 +
790  static int ipmi_ioctl(struct inode  *inode,
791                       struct file   *file,
792                       unsigned int  cmd,
793 @@ -170,54 +219,33 @@
794         {
795         case IPMICTL_SEND_COMMAND:
796         {
797 -               struct ipmi_req    req;
798 -               struct ipmi_addr   addr;
799 -               unsigned char msgdata[IPMI_MAX_MSG_LENGTH];
800 +               struct ipmi_req req;
801  
802                 if (copy_from_user(&req, (void *) data, sizeof(req))) {
803                         rv = -EFAULT;
804                         break;
805                 }
806  
807 -               if (req.addr_len > sizeof(struct ipmi_addr))
808 -               {
809 -                       rv = -EINVAL;
810 -                       break;
811 -               }
812 +               rv = handle_send_req(priv->user,
813 +                                    &req,
814 +                                    priv->default_retries,
815 +                                    priv->default_retry_time_ms);
816 +               break;
817 +       }
818  
819 -               if (copy_from_user(&addr, req.addr, req.addr_len)) {
820 +       case IPMICTL_SEND_COMMAND_SETTIME:
821 +       {
822 +               struct ipmi_req_settime req;
823 +
824 +               if (copy_from_user(&req, (void *) data, sizeof(req))) {
825                         rv = -EFAULT;
826                         break;
827                 }
828  
829 -               rv = ipmi_validate_addr(&addr, req.addr_len);
830 -               if (rv)
831 -                       break;
832 -
833 -               if (req.msg.data != NULL) {
834 -                       if (req.msg.data_len > IPMI_MAX_MSG_LENGTH) {
835 -                               rv = -EMSGSIZE;
836 -                               break;
837 -                       }
838 -
839 -                       if (copy_from_user(&msgdata,
840 -                                          req.msg.data,
841 -                                          req.msg.data_len))
842 -                       {
843 -                               rv = -EFAULT;
844 -                               break;
845 -                       }
846 -               } else {
847 -                       req.msg.data_len = 0;
848 -               }
849 -
850 -               req.msg.data = msgdata;
851 -
852 -               rv = ipmi_request(priv->user,
853 -                                 &addr,
854 -                                 req.msgid,
855 -                                 &(req.msg),
856 -                                 0);
857 +               rv = handle_send_req(priv->user,
858 +                                    &req.req,
859 +                                    req.retries,
860 +                                    req.retry_time_ms);
861                 break;
862         }
863  
864 @@ -416,7 +444,36 @@
865                 rv = 0;
866                 break;
867         }
868 +       case IPMICTL_SET_TIMING_PARMS_CMD:
869 +       {
870 +               struct ipmi_timing_parms parms;
871 +
872 +               if (copy_from_user(&parms, (void *) data, sizeof(parms))) {
873 +                       rv = -EFAULT;
874 +                       break;
875 +               }
876 +
877 +               priv->default_retries = parms.retries;
878 +               priv->default_retry_time_ms = parms.retry_time_ms;
879 +               rv = 0;
880 +               break;
881 +       }
882 +
883 +       case IPMICTL_GET_TIMING_PARMS_CMD:
884 +       {
885 +               struct ipmi_timing_parms parms;
886 +
887 +               parms.retries = priv->default_retries;
888 +               parms.retry_time_ms = priv->default_retry_time_ms;
889  
890 +               if (copy_to_user((void *) data, &parms, sizeof(parms))) {
891 +                       rv = -EFAULT;
892 +                       break;
893 +               }
894 +
895 +               rv = 0;
896 +               break;
897 +       }
898         }
899    
900         return rv;
901 @@ -424,12 +481,12 @@
902  
903  
904  static struct file_operations ipmi_fops = {
905 -       owner:   THIS_MODULE,
906 -       ioctl:   ipmi_ioctl,
907 -       open:    ipmi_open,
908 -       release: ipmi_release,
909 -       fasync:  ipmi_fasync,
910 -       poll:    ipmi_poll
911 +       .owner          = THIS_MODULE,
912 +       .ioctl          = ipmi_ioctl,
913 +       .open           = ipmi_open,
914 +       .release        = ipmi_release,
915 +       .fasync         = ipmi_fasync,
916 +       .poll           = ipmi_poll,
917  };
918  
919  #define DEVICE_NAME     "ipmidev"
920 @@ -468,8 +525,9 @@
921  
922  static struct ipmi_smi_watcher smi_watcher =
923  {
924 -       new_smi  : ipmi_new_smi,
925 -       smi_gone : ipmi_smi_gone
926 +       .owner    = THIS_MODULE,
927 +       .new_smi  = ipmi_new_smi,
928 +       .smi_gone = ipmi_smi_gone,
929  };
930  
931  static __init int init_ipmi_devintf(void)
932 @@ -479,6 +537,9 @@
933         if (ipmi_major < 0)
934                 return -EINVAL;
935  
936 +       printk(KERN_INFO "ipmi device interface version "
937 +              IPMI_DEVINTF_VERSION "\n");
938 +
939         rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
940         if (rv < 0) {
941                 printk(KERN_ERR "ipmi: can't get major %d\n", ipmi_major);
942 @@ -498,9 +559,6 @@
943                 return rv;
944         }
945  
946 -       printk(KERN_INFO "ipmi: device interface at char major %d\n",
947 -              ipmi_major);
948 -
949         return 0;
950  }
951  module_init(init_ipmi_devintf);
952 diff -urN linux-2.4.23.org/drivers/char/ipmi/ipmi_kcs_intf.c linux-2.4.23/drivers/char/ipmi/ipmi_kcs_intf.c
953 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_kcs_intf.c  2004-01-02 23:31:35.446361818 +0100
954 +++ linux-2.4.23/drivers/char/ipmi/ipmi_kcs_intf.c      2004-01-02 23:33:48.034813304 +0100
955 @@ -54,7 +54,7 @@
956  #include <linux/interrupt.h>
957  #include <linux/ipmi_smi.h>
958  #include <asm/io.h>
959 -#include "ipmi_kcs_sm.h"
960 +#include "ipmi_si_sm.h"
961  #include <linux/init.h>
962  
963  /* Measure times between events in the driver. */
964 @@ -72,6 +72,8 @@
965  /* This forces a dependency to the config file for this option. */
966  #endif
967  
968 +extern struct si_sm_handlers kcs_smi_handlers;
969 +
970  enum kcs_intf_state {
971         KCS_NORMAL,
972         KCS_GETTING_FLAGS,
973 @@ -87,7 +89,7 @@
974  struct kcs_info
975  {
976         ipmi_smi_t          intf;
977 -       struct kcs_data     *kcs_sm;
978 +       struct si_sm_data   *kcs_sm;
979         spinlock_t          kcs_lock;
980         spinlock_t          msg_lock;
981         struct list_head    xmit_msgs;
982 @@ -112,8 +114,10 @@
983            out. */
984         int                 run_to_completion;
985  
986 +       struct si_sm_io     io;
987 +
988         /* The I/O port of a KCS interface. */
989 -       int                 port;
990 +       unsigned int        port;
991  
992         /* zero if no irq; */
993         int                 irq;
994 @@ -164,7 +168,7 @@
995         deliver_recv_msg(kcs_info, msg);
996  }
997  
998 -static enum kcs_result start_next_msg(struct kcs_info *kcs_info)
999 +static enum si_sm_result start_next_msg(struct kcs_info *kcs_info)
1000  {
1001         int              rv;
1002         struct list_head *entry = NULL;
1003 @@ -185,7 +189,7 @@
1004  
1005         if (!entry) {
1006                 kcs_info->curr_msg = NULL;
1007 -               rv = KCS_SM_IDLE;
1008 +               rv = SI_SM_IDLE;
1009         } else {
1010                 int err;
1011  
1012 @@ -197,14 +201,15 @@
1013                 do_gettimeofday(&t);
1014                 printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec);
1015  #endif
1016 -               err = start_kcs_transaction(kcs_info->kcs_sm,
1017 -                                          kcs_info->curr_msg->data,
1018 -                                          kcs_info->curr_msg->data_size);
1019 +               err = kcs_smi_handlers.start_transaction(
1020 +                   kcs_info->kcs_sm,
1021 +                   kcs_info->curr_msg->data,
1022 +                   kcs_info->curr_msg->data_size);
1023                 if (err) {
1024                         return_hosed_msg(kcs_info);
1025                 }
1026  
1027 -               rv = KCS_CALL_WITHOUT_DELAY;
1028 +               rv = SI_SM_CALL_WITHOUT_DELAY;
1029         }
1030         spin_unlock(&(kcs_info->msg_lock));
1031  
1032 @@ -220,7 +225,7 @@
1033         msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
1034         msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
1035  
1036 -       start_kcs_transaction(kcs_info->kcs_sm, msg, 2);
1037 +       kcs_smi_handlers.start_transaction(kcs_info->kcs_sm, msg, 2);
1038         kcs_info->kcs_state = KCS_ENABLE_INTERRUPTS1;
1039  }
1040  
1041 @@ -233,7 +238,7 @@
1042         msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD;
1043         msg[2] = WDT_PRE_TIMEOUT_INT;
1044  
1045 -       start_kcs_transaction(kcs_info->kcs_sm, msg, 3);
1046 +       kcs_smi_handlers.start_transaction(kcs_info->kcs_sm, msg, 3);
1047         kcs_info->kcs_state = KCS_CLEARING_FLAGS;
1048  }
1049  
1050 @@ -280,9 +285,10 @@
1051                 kcs_info->curr_msg->data[1] = IPMI_GET_MSG_CMD;
1052                 kcs_info->curr_msg->data_size = 2;
1053  
1054 -               start_kcs_transaction(kcs_info->kcs_sm,
1055 -                                     kcs_info->curr_msg->data,
1056 -                                     kcs_info->curr_msg->data_size);
1057 +               kcs_smi_handlers.start_transaction(
1058 +                   kcs_info->kcs_sm,
1059 +                   kcs_info->curr_msg->data,
1060 +                   kcs_info->curr_msg->data_size);
1061                 kcs_info->kcs_state = KCS_GETTING_MESSAGES;
1062         } else if (kcs_info->msg_flags & EVENT_MSG_BUFFER_FULL) {
1063                 /* Events available. */
1064 @@ -298,9 +304,10 @@
1065                 kcs_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD;
1066                 kcs_info->curr_msg->data_size = 2;
1067  
1068 -               start_kcs_transaction(kcs_info->kcs_sm,
1069 -                                     kcs_info->curr_msg->data,
1070 -                                     kcs_info->curr_msg->data_size);
1071 +               kcs_smi_handlers.start_transaction(
1072 +                   kcs_info->kcs_sm,
1073 +                   kcs_info->curr_msg->data,
1074 +                   kcs_info->curr_msg->data_size);
1075                 kcs_info->kcs_state = KCS_GETTING_EVENTS;
1076         } else {
1077                 kcs_info->kcs_state = KCS_NORMAL;
1078 @@ -322,9 +329,10 @@
1079                         break;
1080                         
1081                 kcs_info->curr_msg->rsp_size
1082 -                       = kcs_get_result(kcs_info->kcs_sm,
1083 -                                        kcs_info->curr_msg->rsp,
1084 -                                        IPMI_MAX_MSG_LENGTH);
1085 +                       = kcs_smi_handlers.get_result(
1086 +                           kcs_info->kcs_sm,
1087 +                           kcs_info->curr_msg->rsp,
1088 +                           IPMI_MAX_MSG_LENGTH);
1089                 
1090                 /* Do this here becase deliver_recv_msg() releases the
1091                    lock, and a new message can be put in during the
1092 @@ -340,7 +348,7 @@
1093                 unsigned int  len;
1094  
1095                 /* We got the flags from the KCS, now handle them. */
1096 -               len = kcs_get_result(kcs_info->kcs_sm, msg, 4);
1097 +               len = kcs_smi_handlers.get_result(kcs_info->kcs_sm, msg, 4);
1098                 if (msg[2] != 0) {
1099                         /* Error fetching flags, just give up for
1100                            now. */
1101 @@ -362,7 +370,7 @@
1102                 unsigned char msg[3];
1103  
1104                 /* We cleared the flags. */
1105 -               kcs_get_result(kcs_info->kcs_sm, msg, 3);
1106 +               kcs_smi_handlers.get_result(kcs_info->kcs_sm, msg, 3);
1107                 if (msg[2] != 0) {
1108                         /* Error clearing flags */
1109                         printk(KERN_WARNING
1110 @@ -379,9 +387,9 @@
1111         case KCS_GETTING_EVENTS:
1112         {
1113                 kcs_info->curr_msg->rsp_size
1114 -                       = kcs_get_result(kcs_info->kcs_sm,
1115 -                                        kcs_info->curr_msg->rsp,
1116 -                                        IPMI_MAX_MSG_LENGTH);
1117 +                       = kcs_smi_handlers.get_result(kcs_info->kcs_sm,
1118 +                                                     kcs_info->curr_msg->rsp,
1119 +                                                     IPMI_MAX_MSG_LENGTH);
1120  
1121                 /* Do this here becase deliver_recv_msg() releases the
1122                    lock, and a new message can be put in during the
1123 @@ -404,9 +412,9 @@
1124         case KCS_GETTING_MESSAGES:
1125         {
1126                 kcs_info->curr_msg->rsp_size
1127 -                       = kcs_get_result(kcs_info->kcs_sm,
1128 -                                        kcs_info->curr_msg->rsp,
1129 -                                        IPMI_MAX_MSG_LENGTH);
1130 +                       = kcs_smi_handlers.get_result(kcs_info->kcs_sm,
1131 +                                                     kcs_info->curr_msg->rsp,
1132 +                                                     IPMI_MAX_MSG_LENGTH);
1133  
1134                 /* Do this here becase deliver_recv_msg() releases the
1135                    lock, and a new message can be put in during the
1136 @@ -431,7 +439,7 @@
1137                 unsigned char msg[4];
1138  
1139                 /* We got the flags from the KCS, now handle them. */
1140 -               kcs_get_result(kcs_info->kcs_sm, msg, 4);
1141 +               kcs_smi_handlers.get_result(kcs_info->kcs_sm, msg, 4);
1142                 if (msg[2] != 0) {
1143                         printk(KERN_WARNING
1144                                "ipmi_kcs: Could not enable interrupts"
1145 @@ -441,7 +449,8 @@
1146                         msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
1147                         msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
1148                         msg[2] = msg[3] | 1; /* enable msg queue int */
1149 -                       start_kcs_transaction(kcs_info->kcs_sm, msg,3);
1150 +                       kcs_smi_handlers.start_transaction(
1151 +                           kcs_info->kcs_sm, msg,3);
1152                         kcs_info->kcs_state = KCS_ENABLE_INTERRUPTS2;
1153                 }
1154                 break;
1155 @@ -452,7 +461,7 @@
1156                 unsigned char msg[4];
1157  
1158                 /* We got the flags from the KCS, now handle them. */
1159 -               kcs_get_result(kcs_info->kcs_sm, msg, 4);
1160 +               kcs_smi_handlers.get_result(kcs_info->kcs_sm, msg, 4);
1161                 if (msg[2] != 0) {
1162                         printk(KERN_WARNING
1163                                "ipmi_kcs: Could not enable interrupts"
1164 @@ -466,9 +475,10 @@
1165  
1166  /* Called on timeouts and events.  Timeouts should pass the elapsed
1167     time, interrupts should pass in zero. */
1168 -static enum kcs_result kcs_event_handler(struct kcs_info *kcs_info, int time)
1169 +static enum si_sm_result kcs_event_handler(struct kcs_info *kcs_info,
1170 +                                          int time)
1171  {
1172 -       enum kcs_result kcs_result;
1173 +       enum si_sm_result kcs_result;
1174  
1175   restart:
1176         /* There used to be a loop here that waited a little while
1177 @@ -477,19 +487,19 @@
1178            range, which is far too long to wait in an interrupt.  So
1179            we just run until the state machine tells us something
1180            happened or it needs a delay. */
1181 -       kcs_result = kcs_event(kcs_info->kcs_sm, time);
1182 +       kcs_result = kcs_smi_handlers.event(kcs_info->kcs_sm, time);
1183         time = 0;
1184 -       while (kcs_result == KCS_CALL_WITHOUT_DELAY)
1185 +       while (kcs_result == SI_SM_CALL_WITHOUT_DELAY)
1186         {
1187 -               kcs_result = kcs_event(kcs_info->kcs_sm, 0);
1188 +               kcs_result = kcs_smi_handlers.event(kcs_info->kcs_sm, 0);
1189         }
1190  
1191 -       if (kcs_result == KCS_TRANSACTION_COMPLETE)
1192 +       if (kcs_result == SI_SM_TRANSACTION_COMPLETE)
1193         {
1194                 handle_transaction_done(kcs_info);
1195 -               kcs_result = kcs_event(kcs_info->kcs_sm, 0);
1196 +               kcs_result = kcs_smi_handlers.event(kcs_info->kcs_sm, 0);
1197         }
1198 -       else if (kcs_result == KCS_SM_HOSED)
1199 +       else if (kcs_result == SI_SM_HOSED)
1200         {
1201                 if (kcs_info->curr_msg != NULL) {
1202                         /* If we were handling a user message, format
1203 @@ -497,12 +507,12 @@
1204                             tell it about the error. */
1205                         return_hosed_msg(kcs_info);
1206                 }
1207 -               kcs_result = kcs_event(kcs_info->kcs_sm, 0);
1208 +               kcs_result = kcs_smi_handlers.event(kcs_info->kcs_sm, 0);
1209                 kcs_info->kcs_state = KCS_NORMAL;
1210         }
1211  
1212         /* We prefer handling attn over new messages. */
1213 -       if (kcs_result == KCS_ATTN)
1214 +       if (kcs_result == SI_SM_ATTN)
1215         {
1216                 unsigned char msg[2];
1217  
1218 @@ -514,19 +524,19 @@
1219                 msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
1220                 msg[1] = IPMI_GET_MSG_FLAGS_CMD;
1221  
1222 -               start_kcs_transaction(kcs_info->kcs_sm, msg, 2);
1223 +               kcs_smi_handlers.start_transaction(kcs_info->kcs_sm, msg, 2);
1224                 kcs_info->kcs_state = KCS_GETTING_FLAGS;
1225                 goto restart;
1226         }
1227  
1228         /* If we are currently idle, try to start the next message. */
1229 -       if (kcs_result == KCS_SM_IDLE) {
1230 +       if (kcs_result == SI_SM_IDLE) {
1231                 kcs_result = start_next_msg(kcs_info);
1232 -               if (kcs_result != KCS_SM_IDLE)
1233 +               if (kcs_result != SI_SM_IDLE)
1234                         goto restart;
1235          }
1236  
1237 -       if ((kcs_result == KCS_SM_IDLE)
1238 +       if ((kcs_result == SI_SM_IDLE)
1239             && (atomic_read(&kcs_info->req_events)))
1240         {
1241                 /* We are idle and the upper layer requested that I fetch
1242 @@ -537,7 +547,7 @@
1243                 msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
1244                 msg[1] = IPMI_GET_MSG_FLAGS_CMD;
1245  
1246 -               start_kcs_transaction(kcs_info->kcs_sm, msg, 2);
1247 +               kcs_smi_handlers.start_transaction(kcs_info->kcs_sm, msg, 2);
1248                 kcs_info->kcs_state = KCS_GETTING_FLAGS;
1249                 goto restart;
1250         }
1251 @@ -549,11 +559,11 @@
1252                    struct ipmi_smi_msg *msg,
1253                    int                 priority)
1254  {
1255 -       struct kcs_info *kcs_info = (struct kcs_info *) send_info;
1256 -       enum kcs_result result;
1257 -       unsigned long   flags;
1258 +       struct kcs_info    *kcs_info = (struct kcs_info *) send_info;
1259 +       enum si_sm_result  result;
1260 +       unsigned long      flags;
1261  #ifdef DEBUG_TIMING
1262 -       struct timeval t;
1263 +       struct timeval     t;
1264  #endif
1265  
1266         spin_lock_irqsave(&(kcs_info->msg_lock), flags);
1267 @@ -574,7 +584,7 @@
1268  
1269                 spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
1270                 result = kcs_event_handler(kcs_info, 0);
1271 -               while (result != KCS_SM_IDLE) {
1272 +               while (result != SI_SM_IDLE) {
1273                         udelay(KCS_SHORT_TIMEOUT_USEC);
1274                         result = kcs_event_handler(kcs_info,
1275                                                    KCS_SHORT_TIMEOUT_USEC);
1276 @@ -602,16 +612,16 @@
1277  
1278  static void set_run_to_completion(void *send_info, int i_run_to_completion)
1279  {
1280 -       struct kcs_info *kcs_info = (struct kcs_info *) send_info;
1281 -       enum kcs_result result;
1282 -       unsigned long   flags;
1283 +       struct kcs_info    *kcs_info = (struct kcs_info *) send_info;
1284 +       enum si_sm_result  result;
1285 +       unsigned long      flags;
1286  
1287         spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
1288  
1289         kcs_info->run_to_completion = i_run_to_completion;
1290         if (i_run_to_completion) {
1291                 result = kcs_event_handler(kcs_info, 0);
1292 -               while (result != KCS_SM_IDLE) {
1293 +               while (result != SI_SM_IDLE) {
1294                         udelay(KCS_SHORT_TIMEOUT_USEC);
1295                         result = kcs_event_handler(kcs_info,
1296                                                    KCS_SHORT_TIMEOUT_USEC);
1297 @@ -676,13 +686,13 @@
1298  
1299  static void kcs_timeout(unsigned long data)
1300  {
1301 -       struct kcs_info *kcs_info = (struct kcs_info *) data;
1302 -       enum kcs_result kcs_result;
1303 -       unsigned long   flags;
1304 -       unsigned long   jiffies_now;
1305 -       unsigned long   time_diff;
1306 +       struct kcs_info    *kcs_info = (struct kcs_info *) data;
1307 +       enum si_sm_result  kcs_result;
1308 +       unsigned long      flags;
1309 +       unsigned long      jiffies_now;
1310 +       unsigned long      time_diff;
1311  #ifdef DEBUG_TIMING
1312 -       struct timeval t;
1313 +       struct timeval     t;
1314  #endif
1315  
1316         if (kcs_info->stop_operation) {
1317 @@ -712,7 +722,7 @@
1318         /* If the state machine asks for a short delay, then shorten
1319             the timer timeout. */
1320  #ifdef CONFIG_HIGH_RES_TIMERS
1321 -       if (kcs_result == KCS_CALL_WITH_DELAY) {
1322 +       if (kcs_result == SI_SM_CALL_WITH_DELAY) {
1323                 kcs_info->kcs_timer.sub_expires
1324                         += usec_to_arch_cycles(KCS_SHORT_TIMEOUT_USEC);
1325                 while (kcs_info->kcs_timer.sub_expires >= cycles_per_jiffies) {
1326 @@ -725,7 +735,7 @@
1327         }
1328  #else
1329         /* If requested, take the shortest delay possible */
1330 -       if (kcs_result == KCS_CALL_WITH_DELAY) {
1331 +       if (kcs_result == SI_SM_CALL_WITH_DELAY) {
1332                 kcs_info->kcs_timer.expires = jiffies + 1;
1333         } else {
1334                 kcs_info->kcs_timer.expires = jiffies + KCS_TIMEOUT_JIFFIES;
1335 @@ -776,12 +786,12 @@
1336  extern int kcs_dbg;
1337  static int ipmi_kcs_detect_hardware(unsigned int port,
1338                                     unsigned char *addr,
1339 -                                   struct kcs_data *data)
1340 +                                   struct si_sm_data *data)
1341  {
1342 -       unsigned char   msg[2];
1343 -       unsigned char   resp[IPMI_MAX_MSG_LENGTH];
1344 -       unsigned long   resp_len;
1345 -       enum kcs_result kcs_result;
1346 +       unsigned char      msg[2];
1347 +       unsigned char      resp[IPMI_MAX_MSG_LENGTH];
1348 +       unsigned long      resp_len;
1349 +       enum si_sm_result  kcs_result;
1350  
1351         /* It's impossible for the KCS status register to be all 1's,
1352            (assuming a properly functioning, self-initialized BMC)
1353 @@ -798,29 +808,31 @@
1354            useful info. */
1355         msg[0] = IPMI_NETFN_APP_REQUEST << 2;
1356         msg[1] = IPMI_GET_DEVICE_ID_CMD;
1357 -       start_kcs_transaction(data, msg, 2);
1358 +       kcs_smi_handlers.start_transaction(data, msg, 2);
1359         
1360 -       kcs_result = kcs_event(data, 0);
1361 +       kcs_result = kcs_smi_handlers.event(data, 0);
1362         for (;;)
1363         {
1364 -               if (kcs_result == KCS_CALL_WITH_DELAY) {
1365 -                       udelay(100);
1366 -                       kcs_result = kcs_event(data, 100);
1367 +               if (kcs_result == SI_SM_CALL_WITH_DELAY) {
1368 +                       set_current_state(TASK_UNINTERRUPTIBLE);
1369 +                       schedule_timeout(1);
1370 +                       kcs_result = kcs_smi_handlers.event(data, 100);
1371                 }
1372 -               else if (kcs_result == KCS_CALL_WITHOUT_DELAY)
1373 +               else if (kcs_result == SI_SM_CALL_WITHOUT_DELAY)
1374                 {
1375 -                       kcs_result = kcs_event(data, 0);
1376 +                       kcs_result = kcs_smi_handlers.event(data, 0);
1377                 }
1378                 else
1379                         break;
1380         }
1381 -       if (kcs_result == KCS_SM_HOSED) {
1382 +       if (kcs_result == SI_SM_HOSED) {
1383                 /* We couldn't get the state machine to run, so whatever's at
1384                    the port is probably not an IPMI KCS interface. */
1385                 return -ENODEV;
1386         }
1387         /* Otherwise, we got some data. */
1388 -       resp_len = kcs_get_result(data, resp, IPMI_MAX_MSG_LENGTH);
1389 +       resp_len = kcs_smi_handlers.get_result(data, resp,
1390 +                                              IPMI_MAX_MSG_LENGTH);
1391         if (resp_len < 6)
1392                 /* That's odd, it should be longer. */
1393                 return -EINVAL;
1394 @@ -860,6 +872,36 @@
1395  MODULE_PARM(kcs_irqs, "1-4i");
1396  MODULE_PARM(kcs_ports, "1-4i");
1397  
1398 +static unsigned char port_inb(struct si_sm_io *io, unsigned int offset)
1399 +{
1400 +       struct kcs_info *info = io->info;
1401 +
1402 +       return inb(info->port+offset);
1403 +}
1404 +
1405 +static void port_outb(struct si_sm_io *io, unsigned int offset,
1406 +                     unsigned char b)
1407 +{
1408 +       struct kcs_info *info = io->info;
1409 +
1410 +       outb(b, info->port+offset);
1411 +}
1412 +
1413 +static unsigned char mem_inb(struct si_sm_io *io, unsigned int offset)
1414 +{
1415 +       struct kcs_info *info = io->info;
1416 +
1417 +       return readb(info->addr+offset);
1418 +}
1419 +
1420 +static void mem_outb(struct si_sm_io *io, unsigned int offset,
1421 +                    unsigned char b)
1422 +{
1423 +       struct kcs_info *info = io->info;
1424 +
1425 +       writeb(b, info->addr+offset);
1426 +}
1427 +
1428  /* Returns 0 if initialized, or negative on an error. */
1429  static int init_one_kcs(int kcs_port, 
1430                         int irq, 
1431 @@ -902,6 +944,9 @@
1432                                kcs_port);
1433                         return -EIO;
1434                 }
1435 +               new_kcs->io.outputb = port_outb;
1436 +               new_kcs->io.inputb = port_inb;
1437 +               new_kcs->io.info = new_kcs;
1438         } else {
1439                 if (request_mem_region(kcs_physaddr, 2, DEVICE_NAME) == NULL) {
1440                         kfree(new_kcs);
1441 @@ -917,15 +962,18 @@
1442                                kcs_physaddr);
1443                         return -EIO;
1444                 }
1445 +               new_kcs->io.outputb = mem_outb;
1446 +               new_kcs->io.inputb = mem_inb;
1447 +               new_kcs->io.info = new_kcs;
1448         }
1449  
1450 -       new_kcs->kcs_sm = kmalloc(kcs_size(), GFP_KERNEL);
1451 +       new_kcs->kcs_sm = kmalloc(kcs_smi_handlers.size(), GFP_KERNEL);
1452         if (!new_kcs->kcs_sm) {
1453                 printk(KERN_ERR "ipmi_kcs: out of memory\n");
1454                 rv = -ENOMEM;
1455                 goto out_err;
1456         }
1457 -       init_kcs_data(new_kcs->kcs_sm, kcs_port, new_kcs->addr);
1458 +       kcs_smi_handlers.init_data(new_kcs->kcs_sm, &(new_kcs->io));
1459         spin_lock_init(&(new_kcs->kcs_lock));
1460         spin_lock_init(&(new_kcs->msg_lock));
1461  
1462 @@ -1027,11 +1075,7 @@
1463  
1464  #ifdef CONFIG_ACPI_INTERPRETER
1465  
1466 -/* Retrieve the base physical address from ACPI tables.  Originally
1467 -   from Hewlett-Packard simple bmc.c, a GPL KCS driver. */
1468 -
1469  #include <linux/acpi.h>
1470 -/* A real hack, but everything's not there yet in 2.4. */
1471  #include <acpi/acpi.h>
1472  #include <acpi/actypes.h>
1473  #include <acpi/actbl.h>
1474 @@ -1046,37 +1090,69 @@
1475         s8      OEMRevision[4];
1476         s8      CreatorID[4];
1477         s8      CreatorRevision[4];
1478 -       s16     InterfaceType;
1479 +       u8      InterfaceType[2];
1480         s16     SpecificationRevision;
1481 +
1482 +       /*
1483 +        * Bit 0 - SCI interrupt supported
1484 +        * Bit 1 - I/O APIC/SAPIC
1485 +        */
1486         u8      InterruptType;
1487 +
1488 +       /* If bit 0 of InterruptType is set, then this is the SCI
1489 +           interrupt in the GPEx_STS register. */
1490         u8      GPE;
1491 +
1492         s16     Reserved;
1493 -       u64     GlobalSystemInterrupt;
1494 -       u8      BaseAddress[12];
1495 +
1496 +       /* If bit 1 of InterruptType is set, then this is the I/O
1497 +           APIC/SAPIC interrupt. */
1498 +       u32     GlobalSystemInterrupt;
1499 +
1500 +       /* The actual register address. */
1501 +       struct acpi_generic_address addr;
1502 +
1503         u8      UID[4];
1504 -} __attribute__ ((packed));
1505  
1506 -static unsigned long acpi_find_bmc(void)
1507 +       s8      spmi_id[1]; /* A '\0' terminated array starts here. */
1508 +};
1509 +
1510 +static int acpi_find_bmc(unsigned long *physaddr, int *port)
1511  {
1512         acpi_status       status;
1513 -       struct acpi_table_header *spmi;
1514 -       static unsigned long io_base = 0;
1515 -
1516 -       if (io_base != 0)
1517 -               return io_base;
1518 +       struct SPMITable  *spmi;
1519  
1520         status = acpi_get_firmware_table("SPMI", 1,
1521 -                       ACPI_LOGICAL_ADDRESSING, &spmi);
1522 +                                        ACPI_LOGICAL_ADDRESSING,
1523 +                                        (struct acpi_table_header **) &spmi);
1524 +       if (status != AE_OK)
1525 +               goto not_found;
1526 +
1527 +       if (spmi->InterfaceType[0] != 1)
1528 +               /* Not IPMI. */
1529 +               goto not_found;
1530 +
1531 +       if (spmi->InterfaceType[1] != 1)
1532 +               /* Not KCS. */
1533 +               goto not_found;
1534 +
1535 +       if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
1536 +               *physaddr = spmi->addr.address;
1537 +               printk("ipmi_kcs_intf: Found ACPI-specified state machine"
1538 +                      " at memory address 0x%lx\n",
1539 +                      (unsigned long) spmi->addr.address);
1540 +       } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
1541 +               *port = spmi->addr.address;
1542 +               printk("ipmi_kcs_intf: Found ACPI-specified state machine"
1543 +                      " at I/O address 0x%x\n",
1544 +                      (int) spmi->addr.address);
1545 +       } else
1546 +               goto not_found; /* Not an address type we recognise. */
1547  
1548 -       if (status != AE_OK) {
1549 -               printk(KERN_ERR "ipmi_kcs: SPMI table not found.\n");
1550 -               return 0;
1551 -       }
1552 +       return 0;
1553  
1554 -       memcpy(&io_base, ((struct SPMITable *)spmi)->BaseAddress,
1555 -                       sizeof(io_base));
1556 -       
1557 -       return io_base;
1558 + not_found:
1559 +       return -ENODEV;
1560  }
1561  #endif
1562  
1563 @@ -1087,6 +1163,7 @@
1564         int             i = 0;
1565  #ifdef CONFIG_ACPI_INTERPRETER
1566         unsigned long   physaddr = 0;
1567 +       int             port = 0;
1568  #endif
1569  
1570         if (initialized)
1571 @@ -1114,26 +1191,25 @@
1572         /* Only try the defaults if enabled and resources are available
1573            (because they weren't already specified above). */
1574  
1575 -       if (kcs_trydefaults) {
1576 +       if (kcs_trydefaults && (pos == 0)) {
1577 +               rv = -EINVAL;
1578  #ifdef CONFIG_ACPI_INTERPRETER
1579 -               if ((physaddr = acpi_find_bmc())) {
1580 -                       if (!check_mem_region(physaddr, 2)) {
1581 -                               rv = init_one_kcs(0, 
1582 -                                                 0, 
1583 -                                                 physaddr, 
1584 -                                                 &(kcs_infos[pos]));
1585 -                               if (rv == 0)
1586 -                                       pos++;
1587 -                       }
1588 +               if (rv && (acpi_find_bmc(&physaddr, &port) == 0)) {
1589 +                       rv = init_one_kcs(port, 
1590 +                                         0, 
1591 +                                         physaddr, 
1592 +                                         &(kcs_infos[pos]));
1593 +                       if (rv == 0)
1594 +                               pos++;
1595                 }
1596  #endif
1597 -               if (!check_region(DEFAULT_IO_PORT, 2)) {
1598 +               if (rv) {
1599                         rv = init_one_kcs(DEFAULT_IO_PORT, 
1600                                           0, 
1601                                           0, 
1602                                           &(kcs_infos[pos]));
1603                         if (rv == 0)
1604 -                               pos++;
1605 +                           pos++;
1606                 }
1607         }
1608  
1609 @@ -1185,8 +1261,10 @@
1610            conditions removing the timer here.  Hopefully this will be
1611            long enough to avoid problems with interrupts still
1612            running. */
1613 +       set_current_state(TASK_UNINTERRUPTIBLE);
1614         schedule_timeout(2);
1615         while (!to_clean->timer_stopped) {
1616 +               set_current_state(TASK_UNINTERRUPTIBLE);
1617                 schedule_timeout(1);
1618         }
1619  
1620 diff -urN linux-2.4.23.org/drivers/char/ipmi/ipmi_kcs_sm.c linux-2.4.23/drivers/char/ipmi/ipmi_kcs_sm.c
1621 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_kcs_sm.c    2004-01-02 23:31:35.451360779 +0100
1622 +++ linux-2.4.23/drivers/char/ipmi/ipmi_kcs_sm.c        2004-01-02 23:33:48.038812473 +0100
1623 @@ -37,10 +37,11 @@
1624   * that document.
1625   */
1626  
1627 -#include <asm/io.h>
1628 -#include <asm/string.h>                /* Gets rid of memcpy warning */
1629 +#include <linux/kernel.h> /* For printk. */
1630 +#include <linux/string.h>
1631 +#include "ipmi_si_sm.h"
1632  
1633 -#include "ipmi_kcs_sm.h"
1634 +#define IPMI_KCS_VERSION "v28"
1635  
1636  /* Set this if you want a printout of why the state machine was hosed
1637     when it gets hosed. */
1638 @@ -95,29 +96,28 @@
1639  #define IPMI_ERR_MSG_TRUNCATED 0xc6
1640  #define IPMI_ERR_UNSPECIFIED   0xff
1641  
1642 -struct kcs_data
1643 +struct si_sm_data
1644  {
1645 -       enum kcs_states state;
1646 -       unsigned int    port;
1647 -       unsigned char   *addr;
1648 -       unsigned char   write_data[MAX_KCS_WRITE_SIZE];
1649 -       int             write_pos;
1650 -       int             write_count;
1651 -       int             orig_write_count;
1652 -       unsigned char   read_data[MAX_KCS_READ_SIZE];
1653 -       int             read_pos;
1654 -       int             truncated;
1655 +       enum kcs_states  state;
1656 +       struct si_sm_io *io;
1657 +       unsigned char    write_data[MAX_KCS_WRITE_SIZE];
1658 +       int              write_pos;
1659 +       int              write_count;
1660 +       int              orig_write_count;
1661 +       unsigned char    read_data[MAX_KCS_READ_SIZE];
1662 +       int              read_pos;
1663 +       int              truncated;
1664  
1665         unsigned int  error_retries;
1666         long          ibf_timeout;
1667         long          obf_timeout;
1668  };
1669  
1670 -void init_kcs_data(struct kcs_data *kcs, unsigned int port, unsigned char *addr)
1671 +static unsigned int init_kcs_data(struct si_sm_data *kcs,
1672 +                                 struct si_sm_io *io)
1673  {
1674         kcs->state = KCS_IDLE;
1675 -       kcs->port = port;
1676 -       kcs->addr = addr;
1677 +       kcs->io = io;
1678         kcs->write_pos = 0;
1679         kcs->write_count = 0;
1680         kcs->orig_write_count = 0;
1681 @@ -126,40 +126,29 @@
1682         kcs->truncated = 0;
1683         kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
1684         kcs->obf_timeout = OBF_RETRY_TIMEOUT;
1685 -}
1686  
1687 -/* Remember, init_one_kcs() insured port and addr can't both be set */
1688 +       /* Reserve 2 I/O bytes. */
1689 +       return 2;
1690 +}
1691  
1692 -static inline unsigned char read_status(struct kcs_data *kcs)
1693 +static inline unsigned char read_status(struct si_sm_data *kcs)
1694  {
1695 -        if (kcs->port)
1696 -               return inb(kcs->port + 1);
1697 -        else
1698 -               return readb(kcs->addr + 1);
1699 +       return kcs->io->inputb(kcs->io, 1);
1700  }
1701  
1702 -static inline unsigned char read_data(struct kcs_data *kcs)
1703 +static inline unsigned char read_data(struct si_sm_data *kcs)
1704  {
1705 -        if (kcs->port)
1706 -               return inb(kcs->port + 0);
1707 -        else
1708 -               return readb(kcs->addr + 0);
1709 +       return kcs->io->inputb(kcs->io, 0);
1710  }
1711  
1712 -static inline void write_cmd(struct kcs_data *kcs, unsigned char data)
1713 +static inline void write_cmd(struct si_sm_data *kcs, unsigned char data)
1714  {
1715 -        if (kcs->port)
1716 -               outb(data, kcs->port + 1);
1717 -        else
1718 -               writeb(data, kcs->addr + 1);
1719 +       kcs->io->outputb(kcs->io, 1, data);
1720  }
1721  
1722 -static inline void write_data(struct kcs_data *kcs, unsigned char data)
1723 +static inline void write_data(struct si_sm_data *kcs, unsigned char data)
1724  {
1725 -        if (kcs->port)
1726 -               outb(data, kcs->port + 0);
1727 -        else
1728 -               writeb(data, kcs->addr + 0);
1729 +       kcs->io->outputb(kcs->io, 0, data);
1730  }
1731  
1732  /* Control codes. */
1733 @@ -179,14 +168,14 @@
1734  #define GET_STATUS_OBF(status) ((status) & 0x01)
1735  
1736  
1737 -static inline void write_next_byte(struct kcs_data *kcs)
1738 +static inline void write_next_byte(struct si_sm_data *kcs)
1739  {
1740         write_data(kcs, kcs->write_data[kcs->write_pos]);
1741         (kcs->write_pos)++;
1742         (kcs->write_count)--;
1743  }
1744  
1745 -static inline void start_error_recovery(struct kcs_data *kcs, char *reason)
1746 +static inline void start_error_recovery(struct si_sm_data *kcs, char *reason)
1747  {
1748         (kcs->error_retries)++;
1749         if (kcs->error_retries > MAX_ERROR_RETRIES) {
1750 @@ -199,7 +188,7 @@
1751         }
1752  }
1753  
1754 -static inline void read_next_byte(struct kcs_data *kcs)
1755 +static inline void read_next_byte(struct si_sm_data *kcs)
1756  {
1757         if (kcs->read_pos >= MAX_KCS_READ_SIZE) {
1758                 /* Throw the data away and mark it truncated. */
1759 @@ -212,9 +201,8 @@
1760         write_data(kcs, KCS_READ_BYTE);
1761  }
1762  
1763 -static inline int check_ibf(struct kcs_data *kcs,
1764 -                           unsigned char   status,
1765 -                           long            time)
1766 +static inline int check_ibf(struct si_sm_data *kcs, unsigned char status,
1767 +                           long time)
1768  {
1769         if (GET_STATUS_IBF(status)) {
1770                 kcs->ibf_timeout -= time;
1771 @@ -229,9 +217,8 @@
1772         return 1;
1773  }
1774  
1775 -static inline int check_obf(struct kcs_data *kcs,
1776 -                           unsigned char   status,
1777 -                           long            time)
1778 +static inline int check_obf(struct si_sm_data *kcs, unsigned char status,
1779 +                           long time)
1780  {
1781         if (! GET_STATUS_OBF(status)) {
1782                 kcs->obf_timeout -= time;
1783 @@ -245,13 +232,13 @@
1784         return 1;
1785  }
1786  
1787 -static void clear_obf(struct kcs_data *kcs, unsigned char status)
1788 +static void clear_obf(struct si_sm_data *kcs, unsigned char status)
1789  {
1790         if (GET_STATUS_OBF(status))
1791                 read_data(kcs);
1792  }
1793  
1794 -static void restart_kcs_transaction(struct kcs_data *kcs)
1795 +static void restart_kcs_transaction(struct si_sm_data *kcs)
1796  {
1797         kcs->write_count = kcs->orig_write_count;
1798         kcs->write_pos = 0;
1799 @@ -262,7 +249,8 @@
1800         write_cmd(kcs, KCS_WRITE_START);
1801  }
1802  
1803 -int start_kcs_transaction(struct kcs_data *kcs, char *data, unsigned int size)
1804 +static int start_kcs_transaction(struct si_sm_data *kcs, unsigned char *data,
1805 +                                unsigned int size)
1806  {
1807         if ((size < 2) || (size > MAX_KCS_WRITE_SIZE)) {
1808                 return -1;
1809 @@ -284,7 +272,8 @@
1810         return 0;
1811  }
1812  
1813 -int kcs_get_result(struct kcs_data *kcs, unsigned char *data, int length)
1814 +static int get_kcs_result(struct si_sm_data *kcs, unsigned char *data,
1815 +                         unsigned int length)
1816  {
1817         if (length < kcs->read_pos) {
1818                 kcs->read_pos = length;
1819 @@ -313,7 +302,7 @@
1820  /* This implements the state machine defined in the IPMI manual, see
1821     that for details on how this works.  Divide that flowchart into
1822     sections delimited by "Wait for IBF" and this will become clear. */
1823 -enum kcs_result kcs_event(struct kcs_data *kcs, long time)
1824 +static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
1825  {
1826         unsigned char status;
1827         unsigned char state;
1828 @@ -325,7 +314,7 @@
1829  #endif
1830         /* All states wait for ibf, so just do it here. */
1831         if (!check_ibf(kcs, status, time))
1832 -               return KCS_CALL_WITH_DELAY;
1833 +               return SI_SM_CALL_WITH_DELAY;
1834  
1835         /* Just about everything looks at the KCS state, so grab that, too. */
1836         state = GET_STATUS_STATE(status);
1837 @@ -336,9 +325,9 @@
1838                 clear_obf(kcs, status);
1839  
1840                 if (GET_STATUS_ATN(status))
1841 -                       return KCS_ATTN;
1842 +                       return SI_SM_ATTN;
1843                 else
1844 -                       return KCS_SM_IDLE;
1845 +                       return SI_SM_IDLE;
1846  
1847         case KCS_START_OP:
1848                 if (state != KCS_IDLE) {
1849 @@ -405,7 +394,7 @@
1850  
1851                 if (state == KCS_READ_STATE) {
1852                         if (! check_obf(kcs, status, time))
1853 -                               return KCS_CALL_WITH_DELAY;
1854 +                               return SI_SM_CALL_WITH_DELAY;
1855                         read_next_byte(kcs);
1856                 } else {
1857                         /* We don't implement this exactly like the state
1858 @@ -418,7 +407,7 @@
1859                         clear_obf(kcs, status);
1860                         kcs->orig_write_count = 0;
1861                         kcs->state = KCS_IDLE;
1862 -                       return KCS_TRANSACTION_COMPLETE;
1863 +                       return SI_SM_TRANSACTION_COMPLETE;
1864                 }
1865                 break;
1866  
1867 @@ -441,7 +430,7 @@
1868                         break;
1869                 }
1870                 if (! check_obf(kcs, status, time))
1871 -                       return KCS_CALL_WITH_DELAY;
1872 +                       return SI_SM_CALL_WITH_DELAY;
1873  
1874                 clear_obf(kcs, status);
1875                 write_data(kcs, KCS_READ_BYTE);
1876 @@ -456,14 +445,14 @@
1877                 }
1878  
1879                 if (! check_obf(kcs, status, time))
1880 -                       return KCS_CALL_WITH_DELAY;
1881 +                       return SI_SM_CALL_WITH_DELAY;
1882  
1883                 clear_obf(kcs, status);
1884                 if (kcs->orig_write_count) {
1885                         restart_kcs_transaction(kcs);
1886                 } else {
1887                         kcs->state = KCS_IDLE;
1888 -                       return KCS_TRANSACTION_COMPLETE;
1889 +                       return SI_SM_TRANSACTION_COMPLETE;
1890                 }
1891                 break;
1892                         
1893 @@ -472,14 +461,42 @@
1894         }
1895  
1896         if (kcs->state == KCS_HOSED) {
1897 -               init_kcs_data(kcs, kcs->port, kcs->addr);
1898 -               return KCS_SM_HOSED;
1899 +               init_kcs_data(kcs, kcs->io);
1900 +               return SI_SM_HOSED;
1901         }
1902  
1903 -       return KCS_CALL_WITHOUT_DELAY;
1904 +       return SI_SM_CALL_WITHOUT_DELAY;
1905  }
1906  
1907 -int kcs_size(void)
1908 +static int kcs_size(void)
1909  {
1910 -       return sizeof(struct kcs_data);
1911 +       return sizeof(struct si_sm_data);
1912 +}
1913 +
1914 +static int kcs_detect(struct si_sm_data *kcs)
1915 +{
1916 +       /* It's impossible for the KCS status register to be all 1's,
1917 +          (assuming a properly functioning, self-initialized BMC)
1918 +          but that's what you get from reading a bogus address, so we
1919 +          test that first. */
1920 +       if (read_status(kcs) == 0xff)
1921 +               return 1; 
1922 +
1923 +       return 0;
1924  }
1925 +
1926 +static void kcs_cleanup(struct si_sm_data *kcs)
1927 +{
1928 +}
1929 +
1930 +struct si_sm_handlers kcs_smi_handlers =
1931 +{
1932 +       .version           = IPMI_KCS_VERSION,
1933 +       .init_data         = init_kcs_data,
1934 +       .start_transaction = start_kcs_transaction,
1935 +       .get_result        = get_kcs_result,
1936 +       .event             = kcs_event,
1937 +       .detect            = kcs_detect,
1938 +       .cleanup           = kcs_cleanup,
1939 +       .size              = kcs_size,
1940 +};
1941 diff -urN linux-2.4.23.org/drivers/char/ipmi/ipmi_msghandler.c linux-2.4.23/drivers/char/ipmi/ipmi_msghandler.c
1942 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_msghandler.c        2004-01-02 23:31:35.450360987 +0100
1943 +++ linux-2.4.23/drivers/char/ipmi/ipmi_msghandler.c    2004-01-02 23:33:48.046810811 +0100
1944 @@ -44,16 +44,21 @@
1945  #include <linux/ipmi_smi.h>
1946  #include <linux/notifier.h>
1947  #include <linux/init.h>
1948 +#include <linux/proc_fs.h>
1949 +
1950 +#define IPMI_MSGHANDLER_VERSION "v28"
1951  
1952  struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
1953  static int ipmi_init_msghandler(void);
1954  
1955  static int initialized = 0;
1956  
1957 +static struct proc_dir_entry *proc_ipmi_root = NULL;
1958 +
1959  #define MAX_EVENTS_IN_QUEUE    25
1960  
1961  /* Don't let a message sit in a queue forever, always time it with at lest
1962 -   the max message timer. */
1963 +   the max message timer.  This is in milliseconds. */
1964  #define MAX_MSG_TIMEOUT                60000
1965  
1966  struct ipmi_user
1967 @@ -82,7 +87,8 @@
1968  
1969  struct seq_table
1970  {
1971 -       int                  inuse : 1;
1972 +       unsigned int         inuse : 1;
1973 +       unsigned int         broadcast : 1;
1974  
1975         unsigned long        timeout;
1976         unsigned long        orig_timeout;
1977 @@ -169,6 +175,72 @@
1978         /* My LUN.  This should generally stay the SMS LUN, but just in
1979            case... */
1980         unsigned char my_lun;
1981 +
1982 +       /* The event receiver for my BMC, only really used at panic
1983 +          shutdown as a place to store this. */
1984 +       unsigned char event_receiver;
1985 +       unsigned char event_receiver_lun;
1986 +       unsigned char local_sel_device;
1987 +       unsigned char local_event_generator;
1988 +
1989 +       /* A cheap hack, if this is non-null and a message to an
1990 +          interface comes in with a NULL user, call this routine with
1991 +          it.  Note that the message will still be freed by the
1992 +          caller.  This only works on the system interface. */
1993 +       void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_smi_msg *msg);
1994 +
1995 +       /* Proc FS stuff. */
1996 +       struct proc_dir_entry *proc_dir;
1997 +       char                  proc_dir_name[10];
1998 +
1999 +       spinlock_t   counter_lock; /* For making counters atomic. */
2000 +
2001 +       /* Commands we got that were invalid. */
2002 +       unsigned int sent_invalid_commands;
2003 +
2004 +       /* Commands we sent to the MC. */
2005 +       unsigned int sent_local_commands;
2006 +       /* Responses from the MC that were delivered to a user. */
2007 +       unsigned int handled_local_responses;
2008 +       /* Responses from the MC that were not delivered to a user. */
2009 +       unsigned int unhandled_local_responses;
2010 +
2011 +       /* Commands we sent out to the IPMB bus. */
2012 +       unsigned int sent_ipmb_commands;
2013 +       /* Commands sent on the IPMB that had errors on the SEND CMD */
2014 +       unsigned int sent_ipmb_command_errs;
2015 +       /* Each retransmit increments this count. */
2016 +       unsigned int retransmitted_ipmb_commands;
2017 +       /* When a message times out (runs out of retransmits) this is
2018 +           incremented. */
2019 +       unsigned int timed_out_ipmb_commands;
2020 +
2021 +       /* This is like above, but for broadcasts.  Broadcasts are
2022 +           *not* included in the above count (they are expected to
2023 +           time out). */
2024 +       unsigned int timed_out_ipmb_broadcasts;
2025 +
2026 +       /* Responses I have sent to the IPMB bus. */
2027 +       unsigned int sent_ipmb_responses;
2028 +
2029 +       /* The response was delivered to the user. */
2030 +       unsigned int handled_ipmb_responses;
2031 +       /* The response had invalid data in it. */
2032 +       unsigned int invalid_ipmb_responses;
2033 +       /* The response didn't have anyone waiting for it. */
2034 +       unsigned int unhandled_ipmb_responses;
2035 +
2036 +       /* The command was delivered to the user. */
2037 +       unsigned int handled_commands;
2038 +       /* The command had invalid data in it. */
2039 +       unsigned int invalid_commands;
2040 +       /* The command didn't have anyone waiting for it. */
2041 +       unsigned int unhandled_commands;
2042 +
2043 +       /* Invalid data in an event. */
2044 +       unsigned int invalid_events;
2045 +       /* Events that were received with the proper format. */
2046 +       unsigned int events;
2047  };
2048  
2049  int
2050 @@ -328,7 +400,7 @@
2051  
2052  static void deliver_response(struct ipmi_recv_msg *msg)
2053  {
2054 -    msg->user->handler->ipmi_recv_hndl(msg, msg->user->handler_data);
2055 +       msg->user->handler->ipmi_recv_hndl(msg, msg->user->handler_data);
2056  }
2057  
2058  /* Find the next sequence number not being used and add the given
2059 @@ -338,6 +410,7 @@
2060                          struct ipmi_recv_msg *recv_msg,
2061                          unsigned long        timeout,
2062                          int                  retries,
2063 +                        int                  broadcast,
2064                          unsigned char        *seq,
2065                          long                 *seqid)
2066  {
2067 @@ -360,6 +433,7 @@
2068                 intf->seq_table[i].timeout = MAX_MSG_TIMEOUT;
2069                 intf->seq_table[i].orig_timeout = timeout;
2070                 intf->seq_table[i].retries_left = retries;
2071 +               intf->seq_table[i].broadcast = broadcast;
2072                 intf->seq_table[i].inuse = 1;
2073                 intf->seq_table[i].seqid = NEXT_SEQID(intf->seq_table[i].seqid);
2074                 *seq = i;
2075 @@ -412,8 +486,8 @@
2076  
2077  
2078  /* Start the timer for a specific sequence table entry. */
2079 -static int intf_start_seq_timer(ipmi_smi_t           intf,
2080 -                               long                 msgid)
2081 +static int intf_start_seq_timer(ipmi_smi_t intf,
2082 +                               long       msgid)
2083  {
2084         int           rv = -ENODEV;
2085         unsigned long flags;
2086 @@ -431,9 +505,50 @@
2087         {
2088                 struct seq_table *ent = &(intf->seq_table[seq]);
2089                 ent->timeout = ent->orig_timeout;
2090 +               rv = 0;
2091 +       }
2092 +       spin_unlock_irqrestore(&(intf->seq_lock), flags);
2093 +
2094 +       return rv;
2095 +}
2096 +
2097 +/* Got an error for the send message for a specific sequence number. */
2098 +static int intf_err_seq(ipmi_smi_t   intf,
2099 +                       long         msgid,
2100 +                       unsigned int err)
2101 +{
2102 +       int                  rv = -ENODEV;
2103 +       unsigned long        flags;
2104 +       unsigned char        seq;
2105 +       unsigned long        seqid;
2106 +       struct ipmi_recv_msg *msg = NULL;
2107 +
2108 +
2109 +       GET_SEQ_FROM_MSGID(msgid, seq, seqid);
2110 +
2111 +       spin_lock_irqsave(&(intf->seq_lock), flags);
2112 +       /* We do this verification because the user can be deleted
2113 +           while a message is outstanding. */
2114 +       if ((intf->seq_table[seq].inuse)
2115 +           && (intf->seq_table[seq].seqid == seqid))
2116 +       {
2117 +               struct seq_table *ent = &(intf->seq_table[seq]);
2118 +
2119 +               ent->inuse = 0;
2120 +               msg = ent->recv_msg;
2121 +               rv = 0;
2122         }
2123         spin_unlock_irqrestore(&(intf->seq_lock), flags);
2124  
2125 +       if (msg) {
2126 +               msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
2127 +               msg->msg_data[0] = err;
2128 +               msg->msg.netfn |= 1; /* Convert to a response. */
2129 +               msg->msg.data_len = 1;
2130 +               msg->msg.data = msg->msg_data;
2131 +               deliver_response(msg);
2132 +       }
2133 +
2134         return rv;
2135  }
2136  
2137 @@ -769,7 +884,9 @@
2138                                  struct ipmi_recv_msg *supplied_recv,
2139                                  int                  priority,
2140                                  unsigned char        source_address,
2141 -                                unsigned char        source_lun)
2142 +                                unsigned char        source_lun,
2143 +                                int                  retries,
2144 +                                unsigned int         retry_time_ms)
2145  {
2146         int                  rv = 0;
2147         struct ipmi_smi_msg  *smi_msg;
2148 @@ -797,8 +914,11 @@
2149         }
2150  
2151         if (addr->channel > IPMI_NUM_CHANNELS) {
2152 -           rv = -EINVAL;
2153 -           goto out_err;
2154 +               spin_lock_irqsave(&intf->counter_lock, flags);
2155 +               intf->sent_invalid_commands++;
2156 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2157 +               rv = -EINVAL;
2158 +               goto out_err;
2159         }
2160  
2161         recv_msg->user = user;
2162 @@ -812,8 +932,12 @@
2163  
2164  
2165                 smi_addr = (struct ipmi_system_interface_addr *) addr;
2166 -               if (smi_addr->lun > 3)
2167 +               if (smi_addr->lun > 3) {
2168 +                       spin_lock_irqsave(&intf->counter_lock, flags);
2169 +                       intf->sent_invalid_commands++;
2170 +                       spin_unlock_irqrestore(&intf->counter_lock, flags);
2171                         return -EINVAL;
2172 +               }
2173  
2174                 memcpy(&recv_msg->addr, smi_addr, sizeof(*smi_addr));
2175  
2176 @@ -824,11 +948,17 @@
2177                 {
2178                         /* We don't let the user do these, since we manage
2179                            the sequence numbers. */
2180 +                       spin_lock_irqsave(&intf->counter_lock, flags);
2181 +                       intf->sent_invalid_commands++;
2182 +                       spin_unlock_irqrestore(&intf->counter_lock, flags);
2183                         rv = -EINVAL;
2184                         goto out_err;
2185                 }
2186  
2187                 if ((msg->data_len + 2) > IPMI_MAX_MSG_LENGTH) {
2188 +                       spin_lock_irqsave(&intf->counter_lock, flags);
2189 +                       intf->sent_invalid_commands++;
2190 +                       spin_unlock_irqrestore(&intf->counter_lock, flags);
2191                         rv = -EMSGSIZE;
2192                         goto out_err;
2193                 }
2194 @@ -840,41 +970,59 @@
2195                 if (msg->data_len > 0)
2196                         memcpy(&(smi_msg->data[2]), msg->data, msg->data_len);
2197                 smi_msg->data_size = msg->data_len + 2;
2198 +               spin_lock_irqsave(&intf->counter_lock, flags);
2199 +               intf->sent_local_commands++;
2200 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2201         } else if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE)
2202                    || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
2203         {
2204                 struct ipmi_ipmb_addr *ipmb_addr;
2205                 unsigned char         ipmb_seq;
2206                 long                  seqid;
2207 -               int                   broadcast;
2208 -               int                   retries;
2209 +               int                   broadcast = 0;
2210  
2211                 if (addr == NULL) {
2212 +                       spin_lock_irqsave(&intf->counter_lock, flags);
2213 +                       intf->sent_invalid_commands++;
2214 +                       spin_unlock_irqrestore(&intf->counter_lock, flags);
2215                         rv = -EINVAL;
2216                         goto out_err;
2217                 }
2218  
2219 +               if (retries < 0) {
2220 +                   if (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)
2221 +                       retries = 0; /* Don't retry broadcasts. */
2222 +                   else
2223 +                       retries = 4;
2224 +               }
2225                 if (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE) {
2226                     /* Broadcasts add a zero at the beginning of the
2227                        message, but otherwise is the same as an IPMB
2228                        address. */
2229                     addr->addr_type = IPMI_IPMB_ADDR_TYPE;
2230                     broadcast = 1;
2231 -                   retries = 0; /* Don't retry broadcasts. */
2232 -               } else {
2233 -                   broadcast = 0;
2234 -                   retries = 4;
2235                 }
2236  
2237 +
2238 +               /* Default to 1 second retries. */
2239 +               if (retry_time_ms == 0)
2240 +                   retry_time_ms = 1000;
2241 +
2242                 /* 9 for the header and 1 for the checksum, plus
2243                     possibly one for the broadcast. */
2244                 if ((msg->data_len + 10 + broadcast) > IPMI_MAX_MSG_LENGTH) {
2245 +                       spin_lock_irqsave(&intf->counter_lock, flags);
2246 +                       intf->sent_invalid_commands++;
2247 +                       spin_unlock_irqrestore(&intf->counter_lock, flags);
2248                         rv = -EMSGSIZE;
2249                         goto out_err;
2250                 }
2251  
2252                 ipmb_addr = (struct ipmi_ipmb_addr *) addr;
2253                 if (ipmb_addr->lun > 3) {
2254 +                       spin_lock_irqsave(&intf->counter_lock, flags);
2255 +                       intf->sent_invalid_commands++;
2256 +                       spin_unlock_irqrestore(&intf->counter_lock, flags);
2257                         rv = -EINVAL;
2258                         goto out_err;
2259                 }
2260 @@ -884,6 +1032,9 @@
2261                 if (recv_msg->msg.netfn & 0x1) {
2262                         /* It's a response, so use the user's sequence
2263                             from msgid. */
2264 +                       spin_lock_irqsave(&intf->counter_lock, flags);
2265 +                       intf->sent_ipmb_responses++;
2266 +                       spin_unlock_irqrestore(&intf->counter_lock, flags);
2267                         format_ipmb_msg(smi_msg, msg, ipmb_addr, msgid,
2268                                         msgid, broadcast,
2269                                         source_address, source_lun);
2270 @@ -892,13 +1043,17 @@
2271  
2272                         spin_lock_irqsave(&(intf->seq_lock), flags);
2273  
2274 +                       spin_lock(&intf->counter_lock);
2275 +                       intf->sent_ipmb_commands++;
2276 +                       spin_unlock(&intf->counter_lock);
2277 +
2278                         /* Create a sequence number with a 1 second
2279                             timeout and 4 retries. */
2280 -                       /* FIXME - magic number for the timeout. */
2281                         rv = intf_next_seq(intf,
2282                                            recv_msg,
2283 -                                          1000,
2284 +                                          retry_time_ms,
2285                                            retries,
2286 +                                          broadcast,
2287                                            &ipmb_seq,
2288                                            &seqid);
2289                         if (rv) {
2290 @@ -934,16 +1089,19 @@
2291                 }
2292         } else {
2293             /* Unknown address type. */
2294 -           rv = -EINVAL;
2295 -           goto out_err;
2296 +               spin_lock_irqsave(&intf->counter_lock, flags);
2297 +               intf->sent_invalid_commands++;
2298 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2299 +               rv = -EINVAL;
2300 +               goto out_err;
2301         }
2302  
2303  #if DEBUG_MSGING
2304         {
2305 -           int m;
2306 -           for (m=0; m<smi_msg->data_size; m++)
2307 -               printk(" %2.2x", smi_msg->data[m]);
2308 -           printk("\n");
2309 +               int m;
2310 +               for (m=0; m<smi_msg->data_size; m++)
2311 +                       printk(" %2.2x", smi_msg->data[m]);
2312 +               printk("\n");
2313         }
2314  #endif
2315         intf->handlers->sender(intf->send_info, smi_msg, priority);
2316 @@ -970,7 +1128,29 @@
2317                               NULL, NULL,
2318                               priority,
2319                               user->intf->my_address,
2320 -                             user->intf->my_lun);
2321 +                             user->intf->my_lun,
2322 +                             -1, 0);
2323 +}
2324 +
2325 +int ipmi_request_settime(ipmi_user_t      user,
2326 +                        struct ipmi_addr *addr,
2327 +                        long             msgid,
2328 +                        struct ipmi_msg  *msg,
2329 +                        int              priority,
2330 +                        int              retries,
2331 +                        unsigned int     retry_time_ms)
2332 +{
2333 +       return i_ipmi_request(user,
2334 +                             user->intf,
2335 +                             addr,
2336 +                             msgid,
2337 +                             msg,
2338 +                             NULL, NULL,
2339 +                             priority,
2340 +                             user->intf->my_address,
2341 +                             user->intf->my_lun,
2342 +                             retries,
2343 +                             retry_time_ms);
2344  }
2345  
2346  int ipmi_request_supply_msgs(ipmi_user_t          user,
2347 @@ -990,7 +1170,8 @@
2348                               supplied_recv,
2349                               priority,
2350                               user->intf->my_address,
2351 -                             user->intf->my_lun);
2352 +                             user->intf->my_lun,
2353 +                             -1, 0);
2354  }
2355  
2356  int ipmi_request_with_source(ipmi_user_t      user,
2357 @@ -1009,7 +1190,124 @@
2358                               NULL, NULL,
2359                               priority,
2360                               source_address,
2361 -                             source_lun);
2362 +                             source_lun,
2363 +                             -1, 0);
2364 +}
2365 +
2366 +static int ipmb_file_read_proc(char *page, char **start, off_t off,
2367 +                              int count, int *eof, void *data)
2368 +{
2369 +       char       *out = (char *) page;
2370 +       ipmi_smi_t intf = data;
2371 +
2372 +       return sprintf(out, "%x\n", intf->my_address);
2373 +}
2374 +
2375 +static int version_file_read_proc(char *page, char **start, off_t off,
2376 +                                 int count, int *eof, void *data)
2377 +{
2378 +       char       *out = (char *) page;
2379 +       ipmi_smi_t intf = data;
2380 +
2381 +       return sprintf(out, "%d.%d\n",
2382 +                      intf->version_major, intf->version_minor);
2383 +}
2384 +
2385 +static int stat_file_read_proc(char *page, char **start, off_t off,
2386 +                              int count, int *eof, void *data)
2387 +{
2388 +       char       *out = (char *) page;
2389 +       ipmi_smi_t intf = data;
2390 +
2391 +       out += sprintf(out, "sent_invalid_commands:       %d\n",
2392 +                      intf->sent_invalid_commands);
2393 +       out += sprintf(out, "sent_local_commands:         %d\n",
2394 +                      intf->sent_local_commands);
2395 +       out += sprintf(out, "handled_local_responses:     %d\n",
2396 +                      intf->handled_local_responses);
2397 +       out += sprintf(out, "unhandled_local_responses:   %d\n",
2398 +                      intf->unhandled_local_responses);
2399 +       out += sprintf(out, "sent_ipmb_commands:          %d\n",
2400 +                      intf->sent_ipmb_commands);
2401 +       out += sprintf(out, "sent_ipmb_command_errs:      %d\n",
2402 +                      intf->sent_ipmb_command_errs);
2403 +       out += sprintf(out, "retransmitted_ipmb_commands: %d\n",
2404 +                      intf->retransmitted_ipmb_commands);
2405 +       out += sprintf(out, "timed_out_ipmb_commands:     %d\n",
2406 +                      intf->timed_out_ipmb_commands);
2407 +       out += sprintf(out, "timed_out_ipmb_broadcasts:   %d\n",
2408 +                      intf->timed_out_ipmb_broadcasts);
2409 +       out += sprintf(out, "sent_ipmb_responses:         %d\n",
2410 +                      intf->sent_ipmb_responses);
2411 +       out += sprintf(out, "handled_ipmb_responses:      %d\n",
2412 +                      intf->handled_ipmb_responses);
2413 +       out += sprintf(out, "invalid_ipmb_responses:      %d\n",
2414 +                      intf->invalid_ipmb_responses);
2415 +       out += sprintf(out, "unhandled_ipmb_responses:    %d\n",
2416 +                      intf->unhandled_ipmb_responses);
2417 +       out += sprintf(out, "handled_commands:            %d\n",
2418 +                      intf->handled_commands);
2419 +       out += sprintf(out, "invalid_commands:            %d\n",
2420 +                      intf->invalid_commands);
2421 +       out += sprintf(out, "unhandled_commands:          %d\n",
2422 +                      intf->unhandled_commands);
2423 +       out += sprintf(out, "invalid_events:              %d\n",
2424 +                      intf->invalid_events);
2425 +       out += sprintf(out, "events:                      %d\n",
2426 +                      intf->events);
2427 +
2428 +       return (out - ((char *) page));
2429 +}
2430 +
2431 +int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
2432 +                           read_proc_t *read_proc, write_proc_t *write_proc,
2433 +                           void *data, struct module *owner)
2434 +{
2435 +       struct proc_dir_entry *file;
2436 +       int                   rv = 0;
2437 +
2438 +       file = create_proc_entry(name, 0, smi->proc_dir);
2439 +       if (!file)
2440 +               rv = -ENOMEM;
2441 +       else {
2442 +               file->nlink = 1;
2443 +               file->data = data;
2444 +               file->read_proc = read_proc;
2445 +               file->write_proc = write_proc;
2446 +               file->owner = owner;
2447 +       }
2448 +
2449 +       return rv;
2450 +}
2451 +
2452 +static int add_proc_entries(ipmi_smi_t smi, int num)
2453 +{
2454 +       int rv = 0;
2455 +
2456 +       sprintf(smi->proc_dir_name, "%d", num);
2457 +       smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root);
2458 +       if (!smi->proc_dir)
2459 +               rv = -ENOMEM;
2460 +       else {
2461 +               smi->proc_dir->owner = THIS_MODULE;
2462 +       }
2463 +
2464 +       if (rv == 0)
2465 +               rv = ipmi_smi_add_proc_entry(smi, "stats",
2466 +                                            stat_file_read_proc, NULL,
2467 +                                            smi, THIS_MODULE);
2468 +
2469 +       if (rv == 0)
2470 +               rv = ipmi_smi_add_proc_entry(smi, "ipmb",
2471 +                                            ipmb_file_read_proc, NULL,
2472 +                                            smi, THIS_MODULE);
2473 +
2474 +       if (rv == 0)
2475 +               rv = ipmi_smi_add_proc_entry(smi, "version",
2476 +                                            version_file_read_proc, NULL,
2477 +                                            smi, THIS_MODULE);
2478 +
2479 +       return rv;
2480  }
2481  
2482  int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
2483 @@ -1040,6 +1338,9 @@
2484         new_intf = kmalloc(sizeof(*new_intf), GFP_KERNEL);
2485         if (!new_intf)
2486                 return -ENOMEM;
2487 +       memset(new_intf, 0, sizeof(*new_intf));
2488 +
2489 +       new_intf->proc_dir = NULL;
2490  
2491         rv = -ENOMEM;
2492  
2493 @@ -1069,6 +1370,8 @@
2494                         INIT_LIST_HEAD(&(new_intf->cmd_rcvrs));
2495                         new_intf->all_cmd_rcvr = NULL;
2496  
2497 +                       spin_lock_init(&(new_intf->counter_lock));
2498 +
2499                         spin_lock_irqsave(&interfaces_lock, flags);
2500                         ipmi_interfaces[i] = new_intf;
2501                         spin_unlock_irqrestore(&interfaces_lock, flags);
2502 @@ -1089,6 +1392,9 @@
2503                 /* Well, it went away.  Just return. */
2504                 goto out;
2505  
2506 +       if (rv == 0)
2507 +               rv = add_proc_entries(*intf, i);
2508 +
2509         if (rv == 0) {
2510                 /* Call all the watcher interfaces to tell them that a
2511                    new interface is available. */
2512 @@ -1096,7 +1402,11 @@
2513                 list_for_each(entry, &smi_watchers) {
2514                         struct ipmi_smi_watcher *w;
2515                         w = list_entry(entry, struct ipmi_smi_watcher, link);
2516 -                       w->new_smi(i);
2517 +                       if (try_inc_mod_count(w->owner)) {
2518 +                               w->new_smi(i);
2519 +                               if (w->owner)
2520 +                                       __MOD_DEC_USE_COUNT(w->owner);
2521 +                       }
2522                 }
2523                 up_read(&smi_watchers_sem);
2524         }
2525 @@ -1104,8 +1414,12 @@
2526   out:
2527         up_read(&interfaces_sem);
2528  
2529 -       if (rv)
2530 +       if (rv) {
2531 +               if (new_intf->proc_dir)
2532 +                       remove_proc_entry(new_intf->proc_dir_name,
2533 +                                         proc_ipmi_root);
2534                 kfree(new_intf);
2535 +       }
2536  
2537         return rv;
2538  }
2539 @@ -1163,6 +1477,8 @@
2540         {
2541                 for (i=0; i<MAX_IPMI_INTERFACES; i++) {
2542                         if (ipmi_interfaces[i] == intf) {
2543 +                               remove_proc_entry(intf->proc_dir_name,
2544 +                                                 proc_ipmi_root);
2545                                 spin_lock_irqsave(&interfaces_lock, flags);
2546                                 ipmi_interfaces[i] = NULL;
2547                                 clean_up_interface_data(intf);
2548 @@ -1204,15 +1520,21 @@
2549  {
2550         struct ipmi_ipmb_addr ipmb_addr;
2551         struct ipmi_recv_msg  *recv_msg;
2552 +       unsigned long         flags;
2553  
2554         
2555 -       if (msg->rsp_size < 11)
2556 +       if (msg->rsp_size < 11) {
2557                 /* Message not big enough, just ignore it. */
2558 +               spin_lock_irqsave(&intf->counter_lock, flags);
2559 +               intf->invalid_ipmb_responses++;
2560 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2561                 return 0;
2562 +       }
2563  
2564 -       if (msg->rsp[2] != 0)
2565 +       if (msg->rsp[2] != 0) {
2566                 /* An error getting the response, just ignore it. */
2567                 return 0;
2568 +       }
2569  
2570         ipmb_addr.addr_type = IPMI_IPMB_ADDR_TYPE;
2571         ipmb_addr.slave_addr = msg->rsp[6];
2572 @@ -1231,6 +1553,9 @@
2573         {
2574                 /* We were unable to find the sequence number,
2575                    so just nuke the message. */
2576 +               spin_lock_irqsave(&intf->counter_lock, flags);
2577 +               intf->unhandled_ipmb_responses++;
2578 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2579                 return 0;
2580         }
2581  
2582 @@ -1244,6 +1569,9 @@
2583         recv_msg->msg.data = recv_msg->msg_data;
2584         recv_msg->msg.data_len = msg->rsp_size - 10;
2585         recv_msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
2586 +       spin_lock_irqsave(&intf->counter_lock, flags);
2587 +       intf->handled_ipmb_responses++;
2588 +       spin_unlock_irqrestore(&intf->counter_lock, flags);
2589         deliver_response(recv_msg);
2590  
2591         return 0;
2592 @@ -1252,18 +1580,23 @@
2593  static int handle_get_msg_cmd(ipmi_smi_t          intf,
2594                               struct ipmi_smi_msg *msg)
2595  {
2596 -       struct list_head *entry;
2597 +       struct list_head      *entry;
2598         struct cmd_rcvr       *rcvr;
2599 -       int              rv = 0;
2600 -       unsigned char    netfn;
2601 -       unsigned char    cmd;
2602 -       ipmi_user_t      user = NULL;
2603 +       int                   rv = 0;
2604 +       unsigned char         netfn;
2605 +       unsigned char         cmd;
2606 +       ipmi_user_t           user = NULL;
2607         struct ipmi_ipmb_addr *ipmb_addr;
2608         struct ipmi_recv_msg  *recv_msg;
2609 +       unsigned long         flags;
2610  
2611 -       if (msg->rsp_size < 10)
2612 +       if (msg->rsp_size < 10) {
2613                 /* Message not big enough, just ignore it. */
2614 +               spin_lock_irqsave(&intf->counter_lock, flags);
2615 +               intf->invalid_commands++;
2616 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2617                 return 0;
2618 +       }
2619  
2620         if (msg->rsp[2] != 0) {
2621                 /* An error getting the response, just ignore it. */
2622 @@ -1291,6 +1624,10 @@
2623  
2624         if (user == NULL) {
2625                 /* We didn't find a user, deliver an error response. */
2626 +               spin_lock_irqsave(&intf->counter_lock, flags);
2627 +               intf->unhandled_commands++;
2628 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2629 +
2630                 msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
2631                 msg->data[1] = IPMI_SEND_MSG_CMD;
2632                 msg->data[2] = msg->rsp[3];
2633 @@ -1311,6 +1648,10 @@
2634                             causes it to not be freed or queued. */
2635         } else {
2636                 /* Deliver the message to the user. */
2637 +               spin_lock_irqsave(&intf->counter_lock, flags);
2638 +               intf->handled_commands++;
2639 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2640 +
2641                 recv_msg = ipmi_alloc_recv_msg();
2642                 if (! recv_msg) {
2643                         /* We couldn't allocate memory for the
2644 @@ -1374,6 +1715,9 @@
2645  
2646         if (msg->rsp_size < 19) {
2647                 /* Message is too small to be an IPMB event. */
2648 +               spin_lock_irqsave(&intf->counter_lock, flags);
2649 +               intf->invalid_events++;
2650 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2651                 return 0;
2652         }
2653  
2654 @@ -1386,6 +1730,10 @@
2655  
2656         spin_lock_irqsave(&(intf->events_lock), flags);
2657  
2658 +       spin_lock(&intf->counter_lock);
2659 +       intf->events++;
2660 +       spin_unlock(&intf->counter_lock);
2661 +
2662         /* Allocate and fill in one message for every user that is getting
2663            events. */
2664         list_for_each(entry, &(intf->users)) {
2665 @@ -1459,6 +1807,7 @@
2666         struct ipmi_recv_msg *recv_msg;
2667         int                  found = 0;
2668         struct list_head     *entry;
2669 +       unsigned long        flags;
2670  
2671         recv_msg = (struct ipmi_recv_msg *) msg->user_data;
2672  
2673 @@ -1474,11 +1823,20 @@
2674         }
2675  
2676         if (!found) {
2677 +               /* Special handling for NULL users. */
2678 +               if (!recv_msg->user && intf->null_user_handler)
2679 +                       intf->null_user_handler(intf, msg);
2680                 /* The user for the message went away, so give up. */
2681 +               spin_lock_irqsave(&intf->counter_lock, flags);
2682 +               intf->unhandled_local_responses++;
2683 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2684                 ipmi_free_recv_msg(recv_msg);
2685         } else {
2686                 struct ipmi_system_interface_addr *smi_addr;
2687  
2688 +               spin_lock_irqsave(&intf->counter_lock, flags);
2689 +               intf->handled_local_responses++;
2690 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2691                 recv_msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
2692                 recv_msg->msgid = msg->msgid;
2693                 smi_addr = ((struct ipmi_system_interface_addr *)
2694 @@ -1505,7 +1863,7 @@
2695  static int handle_new_recv_msg(ipmi_smi_t          intf,
2696                                struct ipmi_smi_msg *msg)
2697  {
2698 -       int requeue;
2699 +       int           requeue;
2700  
2701         if (msg->rsp_size < 2) {
2702                 /* Message is too small to be correct. */
2703 @@ -1551,10 +1909,30 @@
2704            working on it. */
2705         read_lock(&(intf->users_lock));
2706  
2707 -       if ((msg->data_size >= 2) && (msg->data[1] == IPMI_SEND_MSG_CMD)) {
2708 +       if ((msg->data_size >= 2)
2709 +           && (msg->data[0] == (IPMI_NETFN_APP_REQUEST << 2))
2710 +           && (msg->data[1] == IPMI_SEND_MSG_CMD)) {
2711                 /* This is the local response to a send, start the
2712                     timer for these. */
2713 -               intf_start_seq_timer(intf, msg->msgid);
2714 +
2715 +               /* Check for errors, if we get certain errors (ones
2716 +                   that mean basically we can try again later), we
2717 +                   ignore them and start the timer.  Otherwise we
2718 +                   report the error immediately. */
2719 +               if ((msg->rsp_size >= 3) && (msg->rsp[2] != 0)
2720 +                   && (msg->rsp[2] != IPMI_NODE_BUSY_ERR)
2721 +                   && (msg->rsp[2] != IPMI_LOST_ARBITRATION_ERR))
2722 +               {
2723 +                       /* Got an error sending the message, handle it. */
2724 +                       spin_lock_irqsave(&intf->counter_lock, flags);
2725 +                       intf->sent_ipmb_command_errs++;
2726 +                       spin_unlock_irqrestore(&intf->counter_lock, flags);
2727 +                       intf_err_seq(intf, msg->msgid, msg->rsp[2]);
2728 +               } else {
2729 +                       /* The message was sent, start the timer. */
2730 +                       intf_start_seq_timer(intf, msg->msgid);
2731 +               }
2732 +
2733                 ipmi_free_smi_msg(msg);
2734                 goto out_unlock;
2735         }
2736 @@ -1699,6 +2077,12 @@
2737                                 ent->inuse = 0;
2738                                 msg = ent->recv_msg;
2739                                 list_add_tail(&(msg->link), &timeouts);
2740 +                               spin_lock(&intf->counter_lock);
2741 +                               if (ent->broadcast)
2742 +                                       intf->timed_out_ipmb_broadcasts++;
2743 +                               else
2744 +                                       intf->timed_out_ipmb_commands++;
2745 +                               spin_unlock(&intf->counter_lock);
2746                         } else {
2747                                 /* More retries, send again. */
2748  
2749 @@ -1708,6 +2092,9 @@
2750                                 ent->retries_left--;
2751                                 send_from_recv_msg(intf, ent->recv_msg, NULL,
2752                                                    j, ent->seqid);
2753 +                               spin_lock(&intf->counter_lock);
2754 +                               intf->retransmitted_ipmb_commands++;
2755 +                               spin_unlock(&intf->counter_lock);
2756                         }
2757                 }
2758                 spin_unlock_irqrestore(&(intf->seq_lock), flags);
2759 @@ -1740,13 +2127,16 @@
2760  
2761  static struct timer_list ipmi_timer;
2762  
2763 -/* Call every 100 ms. */
2764 +/* Call every ~100 ms. */
2765  #define IPMI_TIMEOUT_TIME      100
2766 -#define IPMI_TIMEOUT_JIFFIES   (IPMI_TIMEOUT_TIME/(1000/HZ))
2767  
2768 -/* Request events from the queue every second.  Hopefully, in the
2769 -   future, IPMI will add a way to know immediately if an event is
2770 -   in the queue. */
2771 +/* How many jiffies does it take to get to the timeout time. */
2772 +#define IPMI_TIMEOUT_JIFFIES   ((IPMI_TIMEOUT_TIME * HZ) / 1000)
2773 +
2774 +/* Request events from the queue every second (this is the number of
2775 +   IPMI_TIMEOUT_TIMES between event requests).  Hopefully, in the
2776 +   future, IPMI will add a way to know immediately if an event is in
2777 +   the queue and this silliness can go away. */
2778  #define IPMI_REQUEST_EV_TIME   (1000 / (IPMI_TIMEOUT_TIME))
2779  
2780  static volatile int stop_operation = 0;
2781 @@ -1822,18 +2212,48 @@
2782  {
2783  }
2784  
2785 -static void send_panic_events(void)
2786 +#ifdef CONFIG_IPMI_PANIC_STRING
2787 +static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
2788 +{
2789 +       if ((msg->rsp[0] == (IPMI_NETFN_SENSOR_EVENT_RESPONSE << 2))
2790 +           && (msg->rsp[1] == IPMI_GET_EVENT_RECEIVER_CMD)
2791 +           && (msg->rsp[2] == IPMI_CC_NO_ERROR))
2792 +       {
2793 +               /* A get event receiver command, save it. */
2794 +               intf->event_receiver = msg->rsp[3];
2795 +               intf->event_receiver_lun = msg->rsp[4] & 0x3;
2796 +       }
2797 +}
2798 +
2799 +static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
2800 +{
2801 +       if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2))
2802 +           && (msg->rsp[1] == IPMI_GET_DEVICE_ID_CMD)
2803 +           && (msg->rsp[2] == IPMI_CC_NO_ERROR))
2804 +       {
2805 +               /* A get device id command, save if we are an event
2806 +                  receiver or generator. */
2807 +               intf->local_sel_device = (msg->rsp[8] >> 2) & 1;
2808 +               intf->local_event_generator = (msg->rsp[8] >> 5) & 1;
2809 +       }
2810 +}
2811 +#endif
2812 +
2813 +static void send_panic_events(char *str)
2814  {
2815         struct ipmi_msg                   msg;
2816         ipmi_smi_t                        intf;
2817 -       unsigned char                     data[8];
2818 +       unsigned char                     data[16];
2819         int                               i;
2820 -       struct ipmi_system_interface_addr addr;
2821 +       struct ipmi_system_interface_addr *si;
2822 +       struct ipmi_addr                  addr;
2823         struct ipmi_smi_msg               smi_msg;
2824         struct ipmi_recv_msg              recv_msg;
2825  
2826 -       addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
2827 -       addr.channel = IPMI_BMC_CHANNEL;
2828 +       si = (struct ipmi_system_interface_addr *) &addr;
2829 +       si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
2830 +       si->channel = IPMI_BMC_CHANNEL;
2831 +       si->lun = 0;
2832  
2833         /* Fill in an event telling that we have failed. */
2834         msg.netfn = 0x04; /* Sensor or Event. */
2835 @@ -1846,12 +2266,13 @@
2836         data[4] = 0x6f; /* Sensor specific, IPMI table 36-1 */
2837         data[5] = 0xa1; /* Runtime stop OEM bytes 2 & 3. */
2838  
2839 -       /* These used to have the first three bytes of the panic string,
2840 -          but not only is that not terribly useful, it's not available
2841 -          any more. */
2842 -       data[3] = 0;
2843 -       data[6] = 0;
2844 -       data[7] = 0;
2845 +       /* Put a few breadcrums in.  Hopefully later we can add more things
2846 +          to make the panic events more useful. */
2847 +       if (str) {
2848 +               data[3] = str[0];
2849 +               data[6] = str[1];
2850 +               data[7] = str[2];
2851 +       }
2852  
2853         smi_msg.done = dummy_smi_done_handler;
2854         recv_msg.done = dummy_recv_done_handler;
2855 @@ -1862,18 +2283,147 @@
2856                 if (intf == NULL)
2857                         continue;
2858  
2859 +               /* Send the event announcing the panic. */
2860                 intf->handlers->set_run_to_completion(intf->send_info, 1);
2861                 i_ipmi_request(NULL,
2862                                intf,
2863 -                              (struct ipmi_addr *) &addr,
2864 +                              &addr,
2865                                0,
2866                                &msg,
2867                                &smi_msg,
2868                                &recv_msg,
2869                                0,
2870                                intf->my_address,
2871 -                              intf->my_lun);
2872 +                              intf->my_lun,
2873 +                              0, 1); /* Don't retry, and don't wait. */
2874         }
2875 +
2876 +#ifdef CONFIG_IPMI_PANIC_STRING
2877 +       /* On every interface, dump a bunch of OEM event holding the
2878 +          string. */
2879 +       if (!str) 
2880 +               return;
2881 +
2882 +       for (i=0; i<MAX_IPMI_INTERFACES; i++) {
2883 +               char                  *p = str;
2884 +               struct ipmi_ipmb_addr *ipmb;
2885 +               int                   j;
2886 +
2887 +               intf = ipmi_interfaces[i];
2888 +               if (intf == NULL)
2889 +                       continue;
2890 +
2891 +               /* First job here is to figure out where to send the
2892 +                  OEM events.  There's no way in IPMI to send OEM
2893 +                  events using an event send command, so we have to
2894 +                  find the SEL to put them in and stick them in
2895 +                  there. */
2896 +
2897 +               /* Get capabilities from the get device id. */
2898 +               intf->local_sel_device = 0;
2899 +               intf->local_event_generator = 0;
2900 +               intf->event_receiver = 0;
2901 +
2902 +               /* Request the device info from the local MC. */
2903 +               msg.netfn = IPMI_NETFN_APP_REQUEST;
2904 +               msg.cmd = IPMI_GET_DEVICE_ID_CMD;
2905 +               msg.data = NULL;
2906 +               msg.data_len = 0;
2907 +               intf->null_user_handler = device_id_fetcher;
2908 +               i_ipmi_request(NULL,
2909 +                              intf,
2910 +                              &addr,
2911 +                              0,
2912 +                              &msg,
2913 +                              &smi_msg,
2914 +                              &recv_msg,
2915 +                              0,
2916 +                              intf->my_address,
2917 +                              intf->my_lun,
2918 +                              0, 1); /* Don't retry, and don't wait. */
2919 +
2920 +               if (intf->local_event_generator) {
2921 +                       /* Request the event receiver from the local MC. */
2922 +                       msg.netfn = IPMI_NETFN_SENSOR_EVENT_REQUEST;
2923 +                       msg.cmd = IPMI_GET_EVENT_RECEIVER_CMD;
2924 +                       msg.data = NULL;
2925 +                       msg.data_len = 0;
2926 +                       intf->null_user_handler = event_receiver_fetcher;
2927 +                       i_ipmi_request(NULL,
2928 +                                      intf,
2929 +                                      &addr,
2930 +                                      0,
2931 +                                      &msg,
2932 +                                      &smi_msg,
2933 +                                      &recv_msg,
2934 +                                      0,
2935 +                                      intf->my_address,
2936 +                                      intf->my_lun,
2937 +                                      0, 1); /* no retry, and no wait. */
2938 +               }
2939 +               intf->null_user_handler = NULL;
2940 +
2941 +               /* Validate the event receiver.  The low bit must not
2942 +                  be 1 (it must be a valid IPMB address), it cannot
2943 +                  be zero, and it must not be my address. */
2944 +                if (((intf->event_receiver & 1) == 0)
2945 +                   && (intf->event_receiver != 0)
2946 +                   && (intf->event_receiver != intf->my_address))
2947 +               {
2948 +                       /* The event receiver is valid, send an IPMB
2949 +                          message. */
2950 +                       ipmb = (struct ipmi_ipmb_addr *) &addr;
2951 +                       ipmb->addr_type = IPMI_IPMB_ADDR_TYPE;
2952 +                       ipmb->channel = 0; /* FIXME - is this right? */
2953 +                       ipmb->lun = intf->event_receiver_lun;
2954 +                       ipmb->slave_addr = intf->event_receiver;
2955 +               } else if (intf->local_sel_device) {
2956 +                       /* The event receiver was not valid (or was
2957 +                          me), but I am an SEL device, just dump it
2958 +                          in my SEL. */
2959 +                       si = (struct ipmi_system_interface_addr *) &addr;
2960 +                       si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
2961 +                       si->channel = IPMI_BMC_CHANNEL;
2962 +                       si->lun = 0;
2963 +               } else
2964 +                       continue; /* No where to send the event. */
2965 +
2966 +               
2967 +               msg.netfn = IPMI_NETFN_STORAGE_REQUEST; /* Storage. */
2968 +               msg.cmd = IPMI_ADD_SEL_ENTRY_CMD;
2969 +               msg.data = data;
2970 +               msg.data_len = 16;
2971 +
2972 +               j = 0;
2973 +               while (*p) {
2974 +                       int size = strlen(p);
2975 +
2976 +                       if (size > 11)
2977 +                               size = 11;
2978 +                       data[0] = 0;
2979 +                       data[1] = 0;
2980 +                       data[2] = 0xf0; /* OEM event without timestamp. */
2981 +                       data[3] = intf->my_address;
2982 +                       data[4] = j++; /* sequence # */
2983 +                       /* Always give 11 bytes, so strncpy will fill
2984 +                          it with zeroes for me. */
2985 +                       strncpy(data+5, p, 11);
2986 +                       p += size;
2987 +
2988 +                       i_ipmi_request(NULL,
2989 +                                      intf,
2990 +                                      &addr,
2991 +                                      0,
2992 +                                      &msg,
2993 +                                      &smi_msg,
2994 +                                      &recv_msg,
2995 +                                      0,
2996 +                                      intf->my_address,
2997 +                                      intf->my_lun,
2998 +                                      0, 1); /* no retry, and no wait. */
2999 +               }
3000 +       }       
3001 +#endif /* CONFIG_IPMI_PANIC_STRING */
3002  }
3003  #endif /* CONFIG_IPMI_PANIC_EVENT */
3004  
3005 @@ -1900,7 +2450,7 @@
3006         }
3007  
3008  #ifdef CONFIG_IPMI_PANIC_EVENT
3009 -       send_panic_events();
3010 +       send_panic_events(ptr);
3011  #endif
3012  
3013         return NOTIFY_DONE;
3014 @@ -1912,7 +2462,6 @@
3015         200   /* priority: INT_MAX >= x >= 0 */
3016  };
3017  
3018 -
3019  static __init int ipmi_init_msghandler(void)
3020  {
3021         int i;
3022 @@ -1920,10 +2469,21 @@
3023         if (initialized)
3024                 return 0;
3025  
3026 +       printk(KERN_INFO "ipmi message handler version "
3027 +              IPMI_MSGHANDLER_VERSION "\n");
3028 +
3029         for (i=0; i<MAX_IPMI_INTERFACES; i++) {
3030                 ipmi_interfaces[i] = NULL;
3031         }
3032  
3033 +       proc_ipmi_root = proc_mkdir("ipmi", 0);
3034 +       if (!proc_ipmi_root) {
3035 +           printk("Unable to create IPMI proc dir\n");
3036 +           return -ENOMEM;
3037 +       }
3038 +
3039 +       proc_ipmi_root->owner = THIS_MODULE;
3040 +
3041         init_timer(&ipmi_timer);
3042         ipmi_timer.data = 0;
3043         ipmi_timer.function = ipmi_timeout;
3044 @@ -1934,8 +2494,6 @@
3045  
3046         initialized = 1;
3047  
3048 -       printk(KERN_INFO "ipmi: message handler initialized\n");
3049 -
3050         return 0;
3051  }
3052  
3053 @@ -1955,6 +2513,7 @@
3054            problems with race conditions removing the timer here. */
3055         stop_operation = 1;
3056         while (!timer_stopped) {
3057 +               set_current_state(TASK_UNINTERRUPTIBLE);
3058                 schedule_timeout(1);
3059         }
3060  
3061 @@ -1980,6 +2539,7 @@
3062  EXPORT_SYMBOL(ipmi_destroy_user);
3063  EXPORT_SYMBOL(ipmi_get_version);
3064  EXPORT_SYMBOL(ipmi_request);
3065 +EXPORT_SYMBOL(ipmi_request_settime);
3066  EXPORT_SYMBOL(ipmi_request_supply_msgs);
3067  EXPORT_SYMBOL(ipmi_request_with_source);
3068  EXPORT_SYMBOL(ipmi_register_smi);
3069 @@ -2001,3 +2561,4 @@
3070  EXPORT_SYMBOL(ipmi_get_my_address);
3071  EXPORT_SYMBOL(ipmi_set_my_LUN);
3072  EXPORT_SYMBOL(ipmi_get_my_LUN);
3073 +EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
3074 diff -urN linux-2.4.23.org/drivers/char/ipmi/ipmi_si.c linux-2.4.23/drivers/char/ipmi/ipmi_si.c
3075 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_si.c        1970-01-01 01:00:00.000000000 +0100
3076 +++ linux-2.4.23/drivers/char/ipmi/ipmi_si.c    2004-01-02 23:33:48.054809149 +0100
3077 @@ -0,0 +1,2083 @@
3078 +/*
3079 + * ipmi_si.c
3080 + *
3081 + * The interface to the IPMI driver for the system interfaces (KCS, SMIC,
3082 + * BT in the future).
3083 + *
3084 + * Author: MontaVista Software, Inc.
3085 + *         Corey Minyard <minyard@mvista.com>
3086 + *         source@mvista.com
3087 + *
3088 + * Copyright 2002 MontaVista Software Inc.
3089 + *
3090 + *  This program is free software; you can redistribute it and/or modify it
3091 + *  under the terms of the GNU General Public License as published by the
3092 + *  Free Software Foundation; either version 2 of the License, or (at your
3093 + *  option) any later version.
3094 + *
3095 + *
3096 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
3097 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
3098 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
3099 + *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3100 + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
3101 + *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
3102 + *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
3103 + *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
3104 + *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
3105 + *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3106 + *
3107 + *  You should have received a copy of the GNU General Public License along
3108 + *  with this program; if not, write to the Free Software Foundation, Inc.,
3109 + *  675 Mass Ave, Cambridge, MA 02139, USA.
3110 + */
3111 +
3112 +/*
3113 + * This file holds the "policy" for the interface to the SMI state
3114 + * machine.  It does the configuration, handles timers and interrupts,
3115 + * and drives the real SMI state machine.
3116 + */
3117 +
3118 +#include <linux/config.h>
3119 +#include <linux/module.h>
3120 +#include <asm/system.h>
3121 +#include <linux/sched.h>
3122 +#include <linux/timer.h>
3123 +#include <linux/errno.h>
3124 +#include <linux/spinlock.h>
3125 +#include <linux/slab.h>
3126 +#include <linux/delay.h>
3127 +#include <linux/list.h>
3128 +#include <linux/pci.h>
3129 +#include <linux/ioport.h>
3130 +#ifdef CONFIG_HIGH_RES_TIMERS
3131 +#include <linux/hrtime.h>
3132 +# if defined(schedule_next_int)
3133 +/* Old high-res timer code, do translations. */
3134 +#  define get_arch_cycles(a) quick_update_jiffies_sub(a) 
3135 +#  define arch_cycles_per_jiffy cycles_per_jiffies
3136 +# endif
3137 +static inline void add_usec_to_timer(struct timer_list *t, long v)
3138 +{
3139 +       t->sub_expires += nsec_to_arch_cycle(v * 1000);
3140 +       while (t->sub_expires >= arch_cycles_per_jiffy)
3141 +       {
3142 +               t->expires++;
3143 +               t->sub_expires -= arch_cycles_per_jiffy;
3144 +       }
3145 +}
3146 +#endif
3147 +#include <linux/interrupt.h>
3148 +#include <linux/ipmi_smi.h>
3149 +#include <asm/io.h>
3150 +#include "ipmi_si_sm.h"
3151 +#include <linux/init.h>
3152 +
3153 +#define IPMI_SI_VERSION "v28"
3154 +
3155 +/* Measure times between events in the driver. */
3156 +#undef DEBUG_TIMING
3157 +
3158 +/* Call every 10 ms when nothing is going on. */
3159 +#define SI_TIMEOUT_TIME_USEC   10000
3160 +#define SI_USEC_PER_JIFFY      (1000000/HZ)
3161 +#define SI_TIMEOUT_JIFFIES     (SI_TIMEOUT_TIME_USEC/SI_USEC_PER_JIFFY)
3162 +#define SI_SHORT_TIMEOUT_USEC  250 /* .25ms when the SM request a
3163 +                                       short timeout */
3164 +
3165 +enum si_intf_state {
3166 +       SI_NORMAL,
3167 +       SI_GETTING_FLAGS,
3168 +       SI_GETTING_EVENTS,
3169 +       SI_CLEARING_FLAGS,
3170 +       SI_CLEARING_FLAGS_THEN_SET_IRQ,
3171 +       SI_GETTING_MESSAGES,
3172 +       SI_ENABLE_INTERRUPTS1,
3173 +       SI_ENABLE_INTERRUPTS2
3174 +       /* FIXME - add watchdog stuff. */
3175 +};
3176 +
3177 +enum si_type {
3178 +       SI_KCS, SI_SMIC, SI_BT
3179 +};
3180 +
3181 +struct smi_info
3182 +{
3183 +       ipmi_smi_t             intf;
3184 +       struct si_sm_data      *si_sm;
3185 +       struct si_sm_handlers  *handlers;
3186 +       enum si_type           si_type;
3187 +       spinlock_t             si_lock;
3188 +       spinlock_t             msg_lock;
3189 +       struct list_head       xmit_msgs;
3190 +       struct list_head       hp_xmit_msgs;
3191 +       struct ipmi_smi_msg    *curr_msg;
3192 +       enum si_intf_state     si_state;
3193 +
3194 +       /* Used to handle the various types of I/O that can occur with
3195 +           IPMI */
3196 +       struct si_sm_io io;
3197 +       int (*io_setup)(struct smi_info *info);
3198 +       void (*io_cleanup)(struct smi_info *info);
3199 +       int (*irq_setup)(struct smi_info *info);
3200 +       void (*irq_cleanup)(struct smi_info *info);
3201 +       unsigned int io_size;
3202 +
3203 +       /* Flags from the last GET_MSG_FLAGS command, used when an ATTN
3204 +          is set to hold the flags until we are done handling everything
3205 +          from the flags. */
3206 +#define RECEIVE_MSG_AVAIL      0x01
3207 +#define EVENT_MSG_BUFFER_FULL  0x02
3208 +#define WDT_PRE_TIMEOUT_INT    0x08
3209 +       unsigned char       msg_flags;
3210 +
3211 +       /* If set to true, this will request events the next time the
3212 +          state machine is idle. */
3213 +       atomic_t            req_events;
3214 +
3215 +       /* If true, run the state machine to completion on every send
3216 +          call.  Generally used after a panic to make sure stuff goes
3217 +          out. */
3218 +       int                 run_to_completion;
3219 +
3220 +       /* The I/O port of an SI interface. */
3221 +       int                 port;
3222 +
3223 +       /* zero if no irq; */
3224 +       int                 irq;
3225 +
3226 +       /* The timer for this si. */
3227 +       struct timer_list   si_timer;
3228 +
3229 +       /* The time (in jiffies) the last timeout occurred at. */
3230 +       unsigned long       last_timeout_jiffies;
3231 +
3232 +       /* Used to gracefully stop the timer without race conditions. */
3233 +       volatile int        stop_operation;
3234 +       volatile int        timer_stopped;
3235 +
3236 +       /* The driver will disable interrupts when it gets into a
3237 +          situation where it cannot handle messages due to lack of
3238 +          memory.  Once that situation clears up, it will re-enable
3239 +          interrupts. */
3240 +       int interrupt_disabled;
3241 +
3242 +       unsigned char ipmi_si_dev_rev;
3243 +       unsigned char ipmi_si_fw_rev_major;
3244 +       unsigned char ipmi_si_fw_rev_minor;
3245 +       unsigned char ipmi_version_major;
3246 +       unsigned char ipmi_version_minor;
3247 +
3248 +       /* Counters and things for the proc filesystem. */
3249 +       spinlock_t count_lock;
3250 +       unsigned long short_timeouts;
3251 +       unsigned long long_timeouts;
3252 +       unsigned long timeout_restarts;
3253 +       unsigned long idles;
3254 +       unsigned long interrupts;
3255 +       unsigned long attentions;
3256 +       unsigned long flag_fetches;
3257 +       unsigned long hosed_count;
3258 +       unsigned long complete_transactions;
3259 +       unsigned long events;
3260 +       unsigned long watchdog_pretimeouts;
3261 +       unsigned long incoming_messages;
3262 +};
3263 +
3264 +static void si_restart_short_timer(struct smi_info *smi_info);
3265 +
3266 +static void deliver_recv_msg(struct smi_info *smi_info,
3267 +                            struct ipmi_smi_msg *msg)
3268 +{
3269 +       /* Deliver the message to the upper layer with the lock
3270 +           released. */
3271 +       spin_unlock(&(smi_info->si_lock));
3272 +       ipmi_smi_msg_received(smi_info->intf, msg);
3273 +       spin_lock(&(smi_info->si_lock));
3274 +}
3275 +
3276 +static void return_hosed_msg(struct smi_info *smi_info)
3277 +{
3278 +       struct ipmi_smi_msg *msg = smi_info->curr_msg;
3279 +
3280 +       /* Make it a reponse */
3281 +       msg->rsp[0] = msg->data[0] | 4;
3282 +       msg->rsp[1] = msg->data[1];
3283 +       msg->rsp[2] = 0xFF; /* Unknown error. */
3284 +       msg->rsp_size = 3;
3285 +                       
3286 +       smi_info->curr_msg = NULL;
3287 +       deliver_recv_msg(smi_info, msg);
3288 +}
3289 +
3290 +static enum si_sm_result start_next_msg(struct smi_info *smi_info)
3291 +{
3292 +       int              rv;
3293 +       struct list_head *entry = NULL;
3294 +#ifdef DEBUG_TIMING
3295 +       struct timeval t;
3296 +#endif
3297 +
3298 +       /* No need to save flags, we aleady have interrupts off and we
3299 +          already hold the SMI lock. */
3300 +       spin_lock(&(smi_info->msg_lock));
3301 +       
3302 +       /* Pick the high priority queue first. */
3303 +       if (! list_empty(&(smi_info->hp_xmit_msgs))) {
3304 +               entry = smi_info->hp_xmit_msgs.next;
3305 +       } else if (! list_empty(&(smi_info->xmit_msgs))) {
3306 +               entry = smi_info->xmit_msgs.next;
3307 +       }
3308 +
3309 +       if (!entry) {
3310 +               smi_info->curr_msg = NULL;
3311 +               rv = SI_SM_IDLE;
3312 +       } else {
3313 +               int err;
3314 +
3315 +               list_del(entry);
3316 +               smi_info->curr_msg = list_entry(entry,
3317 +                                               struct ipmi_smi_msg,
3318 +                                               link);
3319 +#ifdef DEBUG_TIMING
3320 +               do_gettimeofday(&t);
3321 +               printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec);
3322 +#endif
3323 +               err = smi_info->handlers->start_transaction(
3324 +                       smi_info->si_sm,
3325 +                       smi_info->curr_msg->data,
3326 +                       smi_info->curr_msg->data_size);
3327 +               if (err) {
3328 +                       return_hosed_msg(smi_info);
3329 +               }
3330 +
3331 +               rv = SI_SM_CALL_WITHOUT_DELAY;
3332 +       }
3333 +       spin_unlock(&(smi_info->msg_lock));
3334 +
3335 +       return rv;
3336 +}
3337 +
3338 +static void start_enable_irq(struct smi_info *smi_info)
3339 +{
3340 +       unsigned char msg[2];
3341 +
3342 +       /* If we are enabling interrupts, we have to tell the
3343 +          BMC to use them. */
3344 +       msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
3345 +       msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
3346 +
3347 +       smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
3348 +       smi_info->si_state = SI_ENABLE_INTERRUPTS1;
3349 +}
3350 +
3351 +static void start_clear_flags(struct smi_info *smi_info)
3352 +{
3353 +       unsigned char msg[3];
3354 +
3355 +       /* Make sure the watchdog pre-timeout flag is not set at startup. */
3356 +       msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
3357 +       msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD;
3358 +       msg[2] = WDT_PRE_TIMEOUT_INT;
3359 +
3360 +       smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3);
3361 +       smi_info->si_state = SI_CLEARING_FLAGS;
3362 +}
3363 +
3364 +/* When we have a situtaion where we run out of memory and cannot
3365 +   allocate messages, we just leave them in the BMC and run the system
3366 +   polled until we can allocate some memory.  Once we have some
3367 +   memory, we will re-enable the interrupt. */
3368 +static inline void disable_si_irq(struct smi_info *smi_info)
3369 +{
3370 +       if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
3371 +               disable_irq_nosync(smi_info->irq);
3372 +               smi_info->interrupt_disabled = 1;
3373 +       }
3374 +}
3375 +
3376 +static inline void enable_si_irq(struct smi_info *smi_info)
3377 +{
3378 +       if ((smi_info->irq) && (smi_info->interrupt_disabled)) {
3379 +               enable_irq(smi_info->irq);
3380 +               smi_info->interrupt_disabled = 0;
3381 +       }
3382 +}
3383 +
3384 +static void handle_flags(struct smi_info *smi_info)
3385 +{
3386 +       if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) {
3387 +               /* Watchdog pre-timeout */
3388 +               spin_lock(&smi_info->count_lock);
3389 +               smi_info->watchdog_pretimeouts++;
3390 +               spin_unlock(&smi_info->count_lock);
3391 +
3392 +               start_clear_flags(smi_info);
3393 +               smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT;
3394 +               spin_unlock(&(smi_info->si_lock));
3395 +               ipmi_smi_watchdog_pretimeout(smi_info->intf);
3396 +               spin_lock(&(smi_info->si_lock));
3397 +       } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) {
3398 +               /* Messages available. */
3399 +               smi_info->curr_msg = ipmi_alloc_smi_msg();
3400 +               if (!smi_info->curr_msg) {
3401 +                       disable_si_irq(smi_info);
3402 +                       smi_info->si_state = SI_NORMAL;
3403 +                       return;
3404 +               }
3405 +               enable_si_irq(smi_info);
3406 +
3407 +               smi_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
3408 +               smi_info->curr_msg->data[1] = IPMI_GET_MSG_CMD;
3409 +               smi_info->curr_msg->data_size = 2;
3410 +
3411 +               smi_info->handlers->start_transaction(
3412 +                       smi_info->si_sm,
3413 +                       smi_info->curr_msg->data,
3414 +                       smi_info->curr_msg->data_size);
3415 +               smi_info->si_state = SI_GETTING_MESSAGES;
3416 +       } else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) {
3417 +               /* Events available. */
3418 +               smi_info->curr_msg = ipmi_alloc_smi_msg();
3419 +               if (!smi_info->curr_msg) {
3420 +                       disable_si_irq(smi_info);
3421 +                       smi_info->si_state = SI_NORMAL;
3422 +                       return;
3423 +               }
3424 +               enable_si_irq(smi_info);
3425 +
3426 +               smi_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
3427 +               smi_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD;
3428 +               smi_info->curr_msg->data_size = 2;
3429 +
3430 +               smi_info->handlers->start_transaction(
3431 +                       smi_info->si_sm,
3432 +                       smi_info->curr_msg->data,
3433 +                       smi_info->curr_msg->data_size);
3434 +               smi_info->si_state = SI_GETTING_EVENTS;
3435 +       } else {
3436 +               smi_info->si_state = SI_NORMAL;
3437 +       }
3438 +}
3439 +
3440 +static void handle_transaction_done(struct smi_info *smi_info)
3441 +{
3442 +       struct ipmi_smi_msg *msg;
3443 +#ifdef DEBUG_TIMING
3444 +       struct timeval t;
3445 +
3446 +       do_gettimeofday(&t);
3447 +       printk("**Done: %d.%9.9d\n", t.tv_sec, t.tv_usec);
3448 +#endif
3449 +       switch (smi_info->si_state) {
3450 +       case SI_NORMAL:
3451 +               if (!smi_info->curr_msg)
3452 +                       break;
3453 +                       
3454 +               smi_info->curr_msg->rsp_size
3455 +                       = smi_info->handlers->get_result(
3456 +                               smi_info->si_sm,
3457 +                               smi_info->curr_msg->rsp,
3458 +                               IPMI_MAX_MSG_LENGTH);
3459 +               
3460 +               /* Do this here becase deliver_recv_msg() releases the
3461 +                  lock, and a new message can be put in during the
3462 +                  time the lock is released. */
3463 +               msg = smi_info->curr_msg;
3464 +               smi_info->curr_msg = NULL;
3465 +               deliver_recv_msg(smi_info, msg);
3466 +               break;
3467 +               
3468 +       case SI_GETTING_FLAGS:
3469 +       {
3470 +               unsigned char msg[4];
3471 +               unsigned int  len;
3472 +
3473 +               /* We got the flags from the SMI, now handle them. */
3474 +               len = smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
3475 +               if (msg[2] != 0) {
3476 +                       /* Error fetching flags, just give up for
3477 +                          now. */
3478 +                       smi_info->si_state = SI_NORMAL;
3479 +               } else if (len < 3) {
3480 +                       /* Hmm, no flags.  That's technically illegal, but
3481 +                          don't use uninitialized data. */
3482 +                       smi_info->si_state = SI_NORMAL;
3483 +               } else {
3484 +                       smi_info->msg_flags = msg[3];
3485 +                       handle_flags(smi_info);
3486 +               }
3487 +               break;
3488 +       }
3489 +
3490 +       case SI_CLEARING_FLAGS:
3491 +       case SI_CLEARING_FLAGS_THEN_SET_IRQ:
3492 +       {
3493 +               unsigned char msg[3];
3494 +
3495 +               /* We cleared the flags. */
3496 +               smi_info->handlers->get_result(smi_info->si_sm, msg, 3);
3497 +               if (msg[2] != 0) {
3498 +                       /* Error clearing flags */
3499 +                       printk(KERN_WARNING
3500 +                              "ipmi_smi: Error clearing flags: %2.2x\n",
3501 +                              msg[2]);
3502 +               }
3503 +               if (smi_info->si_state == SI_CLEARING_FLAGS_THEN_SET_IRQ)
3504 +                       start_enable_irq(smi_info);
3505 +               else
3506 +                       smi_info->si_state = SI_NORMAL;
3507 +               break;
3508 +       }
3509 +
3510 +       case SI_GETTING_EVENTS:
3511 +       {
3512 +               smi_info->curr_msg->rsp_size
3513 +                       = smi_info->handlers->get_result(
3514 +                               smi_info->si_sm,
3515 +                               smi_info->curr_msg->rsp,
3516 +                               IPMI_MAX_MSG_LENGTH);
3517 +
3518 +               /* Do this here becase deliver_recv_msg() releases the
3519 +                  lock, and a new message can be put in during the
3520 +                  time the lock is released. */
3521 +               msg = smi_info->curr_msg;
3522 +               smi_info->curr_msg = NULL;
3523 +               if (msg->rsp[2] != 0) {
3524 +                       /* Error getting event, probably done. */
3525 +                       msg->done(msg);
3526 +
3527 +                       /* Take off the event flag. */
3528 +                       smi_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
3529 +               } else {
3530 +                       spin_lock(&smi_info->count_lock);
3531 +                       smi_info->events++;
3532 +                       spin_unlock(&smi_info->count_lock);
3533 +
3534 +                       deliver_recv_msg(smi_info, msg);
3535 +               }
3536 +               handle_flags(smi_info);
3537 +               break;
3538 +       }
3539 +
3540 +       case SI_GETTING_MESSAGES:
3541 +       {
3542 +               smi_info->curr_msg->rsp_size
3543 +                       = smi_info->handlers->get_result(
3544 +                               smi_info->si_sm,
3545 +                               smi_info->curr_msg->rsp,
3546 +                               IPMI_MAX_MSG_LENGTH);
3547 +
3548 +               /* Do this here becase deliver_recv_msg() releases the
3549 +                  lock, and a new message can be put in during the
3550 +                  time the lock is released. */
3551 +               msg = smi_info->curr_msg;
3552 +               smi_info->curr_msg = NULL;
3553 +               if (msg->rsp[2] != 0) {
3554 +                       /* Error getting event, probably done. */
3555 +                       msg->done(msg);
3556 +
3557 +                       /* Take off the msg flag. */
3558 +                       smi_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
3559 +               } else {
3560 +                       spin_lock(&smi_info->count_lock);
3561 +                       smi_info->incoming_messages++;
3562 +                       spin_unlock(&smi_info->count_lock);
3563 +
3564 +                       deliver_recv_msg(smi_info, msg);
3565 +               }
3566 +               handle_flags(smi_info);
3567 +               break;
3568 +       }
3569 +
3570 +       case SI_ENABLE_INTERRUPTS1:
3571 +       {
3572 +               unsigned char msg[4];
3573 +
3574 +               /* We got the flags from the SMI, now handle them. */
3575 +               smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
3576 +               if (msg[2] != 0) {
3577 +                       printk(KERN_WARNING
3578 +                              "ipmi_smi: Could not enable interrupts"
3579 +                              ", failed get, using polled mode.\n");
3580 +                       smi_info->si_state = SI_NORMAL;
3581 +               } else {
3582 +                       msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
3583 +                       msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
3584 +                       msg[2] = msg[3] | 1; /* enable msg queue int */
3585 +                       smi_info->handlers->start_transaction(
3586 +                               smi_info->si_sm, msg, 3);
3587 +                       smi_info->si_state = SI_ENABLE_INTERRUPTS2;
3588 +               }
3589 +               break;
3590 +       }
3591 +
3592 +       case SI_ENABLE_INTERRUPTS2:
3593 +       {
3594 +               unsigned char msg[4];
3595 +
3596 +               /* We got the flags from the SMI, now handle them. */
3597 +               smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
3598 +               if (msg[2] != 0) {
3599 +                       printk(KERN_WARNING
3600 +                              "ipmi_smi: Could not enable interrupts"
3601 +                              ", failed set, using polled mode.\n");
3602 +               }
3603 +               smi_info->si_state = SI_NORMAL;
3604 +               break;
3605 +       }
3606 +       }
3607 +}
3608 +
3609 +/* Called on timeouts and events.  Timeouts should pass the elapsed
3610 +   time, interrupts should pass in zero. */
3611 +static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
3612 +                                          int time)
3613 +{
3614 +       enum si_sm_result si_sm_result;
3615 +
3616 + restart:
3617 +       /* There used to be a loop here that waited a little while
3618 +          (around 25us) before giving up.  That turned out to be
3619 +          pointless, the minimum delays I was seeing were in the 300us
3620 +          range, which is far too long to wait in an interrupt.  So
3621 +          we just run until the state machine tells us something
3622 +          happened or it needs a delay. */
3623 +       si_sm_result = smi_info->handlers->event(smi_info->si_sm, time);
3624 +       time = 0;
3625 +       while (si_sm_result == SI_SM_CALL_WITHOUT_DELAY)
3626 +       {
3627 +               si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
3628 +       }
3629 +
3630 +       if (si_sm_result == SI_SM_TRANSACTION_COMPLETE)
3631 +       {
3632 +               spin_lock(&smi_info->count_lock);
3633 +               smi_info->complete_transactions++;
3634 +               spin_unlock(&smi_info->count_lock);
3635 +
3636 +               handle_transaction_done(smi_info);
3637 +               si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
3638 +       }
3639 +       else if (si_sm_result == SI_SM_HOSED)
3640 +       {
3641 +               spin_lock(&smi_info->count_lock);
3642 +               smi_info->hosed_count++;
3643 +               spin_unlock(&smi_info->count_lock);
3644 +
3645 +               if (smi_info->curr_msg != NULL) {
3646 +                       /* If we were handling a user message, format
3647 +                           a response to send to the upper layer to
3648 +                           tell it about the error. */
3649 +                       return_hosed_msg(smi_info);
3650 +               }
3651 +               si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
3652 +               smi_info->si_state = SI_NORMAL;
3653 +       }
3654 +
3655 +       /* We prefer handling attn over new messages. */
3656 +       if (si_sm_result == SI_SM_ATTN)
3657 +       {
3658 +               unsigned char msg[2];
3659 +
3660 +               spin_lock(&smi_info->count_lock);
3661 +               smi_info->attentions++;
3662 +               spin_unlock(&smi_info->count_lock);
3663 +
3664 +               /* Got a attn, send down a get message flags to see
3665 +                   what's causing it.  It would be better to handle
3666 +                   this in the upper layer, but due to the way
3667 +                   interrupts work with the SMI, that's not really
3668 +                   possible. */
3669 +               msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
3670 +               msg[1] = IPMI_GET_MSG_FLAGS_CMD;
3671 +
3672 +               smi_info->handlers->start_transaction(
3673 +                       smi_info->si_sm, msg, 2);
3674 +               smi_info->si_state = SI_GETTING_FLAGS;
3675 +               goto restart;
3676 +       }
3677 +
3678 +       /* If we are currently idle, try to start the next message. */
3679 +       if (si_sm_result == SI_SM_IDLE) {
3680 +               spin_lock(&smi_info->count_lock);
3681 +               smi_info->idles++;
3682 +               spin_unlock(&smi_info->count_lock);
3683 +
3684 +               si_sm_result = start_next_msg(smi_info);
3685 +               if (si_sm_result != SI_SM_IDLE)
3686 +                       goto restart;
3687 +        }
3688 +
3689 +       if ((si_sm_result == SI_SM_IDLE)
3690 +           && (atomic_read(&smi_info->req_events)))
3691 +       {
3692 +               /* We are idle and the upper layer requested that I fetch
3693 +                  events, so do so. */
3694 +               unsigned char msg[2];
3695 +
3696 +               spin_lock(&smi_info->count_lock);
3697 +               smi_info->flag_fetches++;
3698 +               spin_unlock(&smi_info->count_lock);
3699 +
3700 +               atomic_set(&smi_info->req_events, 0);
3701 +               msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
3702 +               msg[1] = IPMI_GET_MSG_FLAGS_CMD;
3703 +
3704 +               smi_info->handlers->start_transaction(
3705 +                       smi_info->si_sm, msg, 2);
3706 +               smi_info->si_state = SI_GETTING_FLAGS;
3707 +               goto restart;
3708 +       }
3709 +
3710 +       return si_sm_result;
3711 +}
3712 +
3713 +static void sender(void                *send_info,
3714 +                  struct ipmi_smi_msg *msg,
3715 +                  int                 priority)
3716 +{
3717 +       struct smi_info   *smi_info = (struct smi_info *) send_info;
3718 +       enum si_sm_result result;
3719 +       unsigned long     flags;
3720 +#ifdef DEBUG_TIMING
3721 +       struct timeval    t;
3722 +#endif
3723 +
3724 +       spin_lock_irqsave(&(smi_info->msg_lock), flags);
3725 +#ifdef DEBUG_TIMING
3726 +       do_gettimeofday(&t);
3727 +       printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec);
3728 +#endif
3729 +
3730 +       if (smi_info->run_to_completion) {
3731 +               /* If we are running to completion, then throw it in
3732 +                  the list and run transactions until everything is
3733 +                  clear.  Priority doesn't matter here. */
3734 +               list_add_tail(&(msg->link), &(smi_info->xmit_msgs));
3735 +
3736 +               /* We have to release the msg lock and claim the smi
3737 +                  lock in this case, because of race conditions. */
3738 +               spin_unlock_irqrestore(&(smi_info->msg_lock), flags);
3739 +
3740 +               spin_lock_irqsave(&(smi_info->si_lock), flags);
3741 +               result = smi_event_handler(smi_info, 0);
3742 +               while (result != SI_SM_IDLE) {
3743 +                       udelay(SI_SHORT_TIMEOUT_USEC);
3744 +                       result = smi_event_handler(smi_info,
3745 +                                                  SI_SHORT_TIMEOUT_USEC);
3746 +               }
3747 +               spin_unlock_irqrestore(&(smi_info->si_lock), flags);
3748 +               return;
3749 +       } else {
3750 +               if (priority > 0) {
3751 +                       list_add_tail(&(msg->link), &(smi_info->hp_xmit_msgs));
3752 +               } else {
3753 +                       list_add_tail(&(msg->link), &(smi_info->xmit_msgs));
3754 +               }
3755 +       }
3756 +       spin_unlock_irqrestore(&(smi_info->msg_lock), flags);
3757 +
3758 +       spin_lock_irqsave(&(smi_info->si_lock), flags);
3759 +       if ((smi_info->si_state == SI_NORMAL)
3760 +           && (smi_info->curr_msg == NULL))
3761 +       {
3762 +               start_next_msg(smi_info);
3763 +               si_restart_short_timer(smi_info);
3764 +       }
3765 +       spin_unlock_irqrestore(&(smi_info->si_lock), flags);
3766 +}
3767 +
3768 +static void set_run_to_completion(void *send_info, int i_run_to_completion)
3769 +{
3770 +       struct smi_info   *smi_info = (struct smi_info *) send_info;
3771 +       enum si_sm_result result;
3772 +       unsigned long     flags;
3773 +
3774 +       spin_lock_irqsave(&(smi_info->si_lock), flags);
3775 +
3776 +       smi_info->run_to_completion = i_run_to_completion;
3777 +       if (i_run_to_completion) {
3778 +               result = smi_event_handler(smi_info, 0);
3779 +               while (result != SI_SM_IDLE) {
3780 +                       udelay(SI_SHORT_TIMEOUT_USEC);
3781 +                       result = smi_event_handler(smi_info,
3782 +                                                  SI_SHORT_TIMEOUT_USEC);
3783 +               }
3784 +       }
3785 +
3786 +       spin_unlock_irqrestore(&(smi_info->si_lock), flags);
3787 +}
3788 +
3789 +static void request_events(void *send_info)
3790 +{
3791 +       struct smi_info *smi_info = (struct smi_info *) send_info;
3792 +
3793 +       atomic_set(&smi_info->req_events, 1);
3794 +}
3795 +
3796 +static int new_user(void *send_info)
3797 +{
3798 +       if (!try_inc_mod_count(THIS_MODULE))
3799 +               return -EBUSY;
3800 +       return 0;
3801 +}
3802 +
3803 +static void user_left(void *send_info)
3804 +{
3805 +       MOD_DEC_USE_COUNT;
3806 +}
3807 +
3808 +static int initialized = 0;
3809 +
3810 +/* Must be called with interrupts off and with the si_lock held. */
3811 +static void si_restart_short_timer(struct smi_info *smi_info)
3812 +{
3813 +#if defined(CONFIG_HIGH_RES_TIMERS)
3814 +       unsigned long flags;
3815 +       unsigned long jiffies_now;
3816 +
3817 +       if (del_timer(&(smi_info->si_timer))) {
3818 +               /* If we don't delete the timer, then it will go off
3819 +                  immediately, anyway.  So we only process if we
3820 +                  actually delete the timer. */
3821 +
3822 +               /* We already have irqsave on, so no need for it
3823 +                   here. */
3824 +               read_lock(&xtime_lock);
3825 +               jiffies_now = jiffies;
3826 +               smi_info->si_timer.expires = jiffies_now;
3827 +               smi_info->si_timer.sub_expires = get_arch_cycles(jiffies_now);
3828 +               read_unlock(&xtime_lock);
3829 +
3830 +               add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC);
3831 +
3832 +               add_timer(&(smi_info->si_timer));
3833 +               spin_lock_irqsave(&smi_info->count_lock, flags);
3834 +               smi_info->timeout_restarts++;
3835 +               spin_unlock_irqrestore(&smi_info->count_lock, flags);
3836 +       }
3837 +#endif
3838 +}
3839 +
3840 +static void smi_timeout(unsigned long data)
3841 +{
3842 +       struct smi_info   *smi_info = (struct smi_info *) data;
3843 +       enum si_sm_result smi_result;
3844 +       unsigned long     flags;
3845 +       unsigned long     jiffies_now;
3846 +       unsigned long     time_diff;
3847 +#ifdef DEBUG_TIMING
3848 +       struct timeval    t;
3849 +#endif
3850 +
3851 +       if (smi_info->stop_operation) {
3852 +               smi_info->timer_stopped = 1;
3853 +               return;
3854 +       }
3855 +
3856 +       spin_lock_irqsave(&(smi_info->si_lock), flags);
3857 +#ifdef DEBUG_TIMING
3858 +       do_gettimeofday(&t);
3859 +       printk("**Timer: %d.%9.9d\n", t.tv_sec, t.tv_usec);
3860 +#endif
3861 +       jiffies_now = jiffies;
3862 +       time_diff = ((jiffies_now - smi_info->last_timeout_jiffies)
3863 +                    * SI_USEC_PER_JIFFY);
3864 +       smi_result = smi_event_handler(smi_info, time_diff);
3865 +
3866 +       spin_unlock_irqrestore(&(smi_info->si_lock), flags);
3867 +
3868 +       smi_info->last_timeout_jiffies = jiffies_now;
3869 +
3870 +       if ((smi_info->irq) && (! smi_info->interrupt_disabled)) {
3871 +               /* Running with interrupts, only do long timeouts. */
3872 +               smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
3873 +               spin_lock_irqsave(&smi_info->count_lock, flags);
3874 +               smi_info->long_timeouts++;
3875 +               spin_unlock_irqrestore(&smi_info->count_lock, flags);
3876 +               goto do_add_timer;
3877 +       }
3878 +
3879 +       /* If the state machine asks for a short delay, then shorten
3880 +           the timer timeout. */
3881 +       if (smi_result == SI_SM_CALL_WITH_DELAY) {
3882 +               spin_lock_irqsave(&smi_info->count_lock, flags);
3883 +               smi_info->short_timeouts++;
3884 +               spin_unlock_irqrestore(&smi_info->count_lock, flags);
3885 +#if defined(CONFIG_HIGH_RES_TIMERS)
3886 +               read_lock(&xtime_lock);
3887 +                smi_info->si_timer.expires = jiffies;
3888 +                smi_info->si_timer.sub_expires
3889 +                        = get_arch_cycles(smi_info->si_timer.expires);
3890 +                read_unlock(&xtime_lock);
3891 +               add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC);
3892 +#else
3893 +               smi_info->si_timer.expires = jiffies + 1;
3894 +#endif
3895 +       } else {
3896 +               spin_lock_irqsave(&smi_info->count_lock, flags);
3897 +               smi_info->long_timeouts++;
3898 +               spin_unlock_irqrestore(&smi_info->count_lock, flags);
3899 +               smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
3900 +#if defined(CONFIG_HIGH_RES_TIMERS)
3901 +               smi_info->si_timer.sub_expires = 0;
3902 +#endif
3903 +       }
3904 +
3905 + do_add_timer:
3906 +       add_timer(&(smi_info->si_timer));
3907 +}
3908 +
3909 +static void si_irq_handler(int irq, void *data, struct pt_regs *regs)
3910 +{
3911 +       struct smi_info *smi_info = (struct smi_info *) data;
3912 +       unsigned long   flags;
3913 +#ifdef DEBUG_TIMING
3914 +       struct timeval  t;
3915 +#endif
3916 +
3917 +       spin_lock_irqsave(&(smi_info->si_lock), flags);
3918 +
3919 +       spin_lock(&smi_info->count_lock);
3920 +       smi_info->interrupts++;
3921 +       spin_unlock(&smi_info->count_lock);
3922 +
3923 +       if (smi_info->stop_operation)
3924 +               goto out;
3925 +
3926 +#ifdef DEBUG_TIMING
3927 +       do_gettimeofday(&t);
3928 +       printk("**Interrupt: %d.%9.9d\n", t.tv_sec, t.tv_usec);
3929 +#endif
3930 +       smi_event_handler(smi_info, 0);
3931 + out:
3932 +       spin_unlock_irqrestore(&(smi_info->si_lock), flags);
3933 +}
3934 +
3935 +static struct ipmi_smi_handlers handlers =
3936 +{
3937 +       sender:                sender,
3938 +       request_events:        request_events,
3939 +       new_user:              new_user,
3940 +       user_left:             user_left,
3941 +       set_run_to_completion: set_run_to_completion
3942 +};
3943 +
3944 +/* There can be 4 IO ports passed in (with or without IRQs), 4 addresses,
3945 +   a default IO port, and 1 ACPI/SPMI address.  That sets SI_MAX_DRIVERS */
3946 +
3947 +#define SI_MAX_PARMS 4
3948 +#define SI_MAX_DRIVERS ((SI_MAX_PARMS * 2) + 2)
3949 +static struct smi_info *smi_infos[SI_MAX_DRIVERS] =
3950 +{ NULL, NULL, NULL, NULL };
3951 +
3952 +#define DEVICE_NAME "ipmi_si"
3953 +
3954 +#define DEFAULT_KCS_IO_PORT 0xca2
3955 +#define DEFAULT_SMIC_IO_PORT 0xca9
3956 +#define DEFAULT_BT_IO_PORT   0xe4
3957 +
3958 +static int           si_trydefaults = 1;
3959 +static char          *si_type[SI_MAX_PARMS] = { NULL, NULL, NULL, NULL };
3960 +static unsigned long si_addrs[SI_MAX_PARMS] = { 0, 0, 0, 0 };
3961 +static unsigned int  si_ports[SI_MAX_PARMS] = { 0, 0, 0, 0 };
3962 +static int           si_irqs[SI_MAX_PARMS] = { 0, 0, 0, 0 };
3963 +
3964 +
3965 +MODULE_PARM(si_trydefaults, "i");
3966 +MODULE_PARM(si_type, "1-4s");
3967 +MODULE_PARM(si_addrs, "1-4l");
3968 +MODULE_PARM(si_irqs, "1-4i");
3969 +MODULE_PARM(si_ports, "1-4i");
3970 +
3971 +
3972 +#if defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_X86) || defined(CONFIG_PCI)
3973 +#define IPMI_MEM_ADDR_SPACE 1
3974 +#define IPMI_IO_ADDR_SPACE  2
3975 +static int is_new_interface(int intf, u8 addr_space, unsigned long base_addr)
3976 +{
3977 +       int i;
3978 +
3979 +       for (i = 0; i < SI_MAX_PARMS; ++i) {
3980 +               /* Don't check our address. */
3981 +               if (i == intf)
3982 +                       continue;
3983 +               if (si_type[i] != NULL) {
3984 +                       if ((addr_space == IPMI_MEM_ADDR_SPACE && 
3985 +                            base_addr == si_addrs[i]) ||
3986 +                           (addr_space == IPMI_IO_ADDR_SPACE &&
3987 +                            base_addr == si_ports[i]))
3988 +                               return 0;
3989 +               }
3990 +               else
3991 +                       break;
3992 +       }
3993 +       
3994 +       return 1;
3995 +}
3996 +#endif
3997
3998 +static int std_irq_setup(struct smi_info *info)
3999 +{
4000 +       int rv;
4001 +
4002 +       if (!info->irq)
4003 +               return 0;
4004 +
4005 +       rv = request_irq(info->irq,
4006 +                        si_irq_handler,
4007 +                        SA_INTERRUPT,
4008 +                        DEVICE_NAME,
4009 +                        info);
4010 +       if (rv) {
4011 +               printk(KERN_WARNING
4012 +                      "ipmi_smi: %s unable to claim interrupt %d,"
4013 +                      " running polled\n",
4014 +                      DEVICE_NAME, info->irq);
4015 +               info->irq = 0;
4016 +       } else {
4017 +               printk("  Using irq %d\n", info->irq);
4018 +       }
4019 +
4020 +       return rv;
4021 +}
4022 +
4023 +static void std_irq_cleanup(struct smi_info *info)
4024 +{
4025 +       if (!info->irq)
4026 +               return;
4027 +
4028 +       free_irq(info->irq, info);
4029 +}
4030 +
4031 +static unsigned char port_inb(struct si_sm_io *io, unsigned int offset)
4032 +{
4033 +       unsigned int *addr = io->info;
4034 +
4035 +       return inb((*addr)+offset);
4036 +}
4037 +
4038 +static void port_outb(struct si_sm_io *io, unsigned int offset,
4039 +                     unsigned char b)
4040 +{
4041 +       unsigned int *addr = io->info;
4042 +
4043 +       outb(b, (*addr)+offset);
4044 +}
4045 +
4046 +static int port_setup(struct smi_info *info)
4047 +{
4048 +       unsigned int *addr = info->io.info;
4049 +
4050 +       if (!addr || (!*addr))
4051 +               return -ENODEV;
4052 +
4053 +       if (request_region(*addr, info->io_size, DEVICE_NAME) == NULL)
4054 +               return -EIO;
4055 +       return 0;
4056 +}
4057 +
4058 +static void port_cleanup(struct smi_info *info)
4059 +{
4060 +       unsigned int *addr = info->io.info;
4061 +
4062 +       if (addr && (*addr)) 
4063 +               release_region (*addr, info->io_size);
4064 +       kfree(info);
4065 +}
4066 +
4067 +static int try_init_port(int intf_num, struct smi_info **new_info)
4068 +{
4069 +       struct smi_info *info;
4070 +
4071 +       if (!si_ports[intf_num])
4072 +               return -ENODEV;
4073 +
4074 +       if (!is_new_interface(intf_num, IPMI_IO_ADDR_SPACE,
4075 +                             si_ports[intf_num]))
4076 +               return -ENODEV;
4077 +
4078 +       info = kmalloc(sizeof(*info), GFP_KERNEL);
4079 +       if (!info) {
4080 +               printk("ipmi_smi: Could not allocate SMI data\n");
4081 +               return -ENOMEM;
4082 +       }
4083 +       memset(info, 0, sizeof(*info));
4084 +
4085 +       info->io_setup = port_setup;
4086 +       info->io_cleanup = port_cleanup;
4087 +       info->io.inputb = port_inb;
4088 +       info->io.outputb = port_outb;
4089 +       info->io.info = &(si_ports[intf_num]);
4090 +       info->irq = 0;
4091 +       info->irq_setup = NULL;
4092 +       *new_info = info;
4093 +
4094 +       printk("ipmi_smi: Trying state machine at I/O address 0x%x\n",
4095 +              si_ports[intf_num]);
4096 +       return 0;
4097 +}
4098 +
4099 +static unsigned char mem_inb(struct si_sm_io *io, unsigned int offset)
4100 +{
4101 +       return readb((io->addr)+offset);
4102 +}
4103 +
4104 +static void mem_outb(struct si_sm_io *io, unsigned int offset,
4105 +                    unsigned char b)
4106 +{
4107 +       writeb(b, (io->addr)+offset);
4108 +}
4109 +
4110 +static int mem_setup(struct smi_info *info)
4111 +{
4112 +       unsigned long addr = (unsigned long) info->io.info;
4113 +
4114 +       if (!addr)
4115 +               return -ENODEV;
4116 +
4117 +       if (request_mem_region(addr, info->io_size, DEVICE_NAME) == NULL)
4118 +               return -EIO;
4119 +       info->io.addr = ioremap(addr, info->io_size);
4120 +       if (info->io.addr == NULL) {
4121 +               release_mem_region(addr, info->io_size);
4122 +               return -EIO;
4123 +       }
4124 +       return 0;
4125 +}
4126 +
4127 +static void mem_cleanup(struct smi_info *info)
4128 +{
4129 +       unsigned long addr = (unsigned long) info->io.info;
4130 +
4131 +       if (info->io.addr) {
4132 +               iounmap(info->io.addr);
4133 +               release_mem_region(addr, info->io_size);
4134 +       }
4135 +       kfree(info);
4136 +}
4137 +
4138 +static int try_init_mem(int intf_num, struct smi_info **new_info)
4139 +{
4140 +       struct smi_info *info;
4141 +
4142 +       if (!si_addrs[intf_num])
4143 +               return -ENODEV;
4144 +
4145 +       if (!is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE,
4146 +                             si_addrs[intf_num]))
4147 +               return -ENODEV;
4148 +
4149 +       info = kmalloc(sizeof(*info), GFP_KERNEL);
4150 +       if (!info) {
4151 +               printk("ipmi_smi: Could not allocate SMI data\n");
4152 +               return -ENOMEM;
4153 +       }
4154 +       memset(info, 0, sizeof(*info));
4155 +
4156 +       info->io_setup = mem_setup;
4157 +       info->io_cleanup = mem_cleanup;
4158 +       info->io.inputb = mem_inb;
4159 +       info->io.outputb = mem_outb;
4160 +       info->io.info = (void *) si_addrs[intf_num];
4161 +       info->irq = 0;
4162 +       info->irq_setup = NULL;
4163 +       *new_info = info;
4164 +
4165 +       printk("ipmi_smi: Trying state machine at memory address 0x%lx\n",
4166 +              si_addrs[intf_num]);
4167 +       return 0;
4168 +}
4169 +
4170 +#ifdef CONFIG_ACPI_INTERPRETER
4171 +
4172 +#include <linux/acpi.h>
4173 +#include <acpi/acpi.h>
4174 +#include <acpi/actypes.h>
4175 +#include <acpi/actbl.h>
4176 +
4177 +/* Once we get an ACPI failure, we don't try any more, because we go
4178 +   through the tables sequentially.  Once we don't find a table, there
4179 +   are no more. */
4180 +static int acpi_failure = 0;
4181 +
4182 +/* For GPE-type interrupts. */
4183 +void ipmi_acpi_gpe(void *context)
4184 +{
4185 +       struct smi_info *smi_info = context;
4186 +       unsigned long   flags;
4187 +#ifdef DEBUG_TIMING
4188 +       struct timeval t;
4189 +#endif
4190 +
4191 +       spin_lock_irqsave(&(smi_info->si_lock), flags);
4192 +
4193 +       spin_lock(&smi_info->count_lock);
4194 +       smi_info->interrupts++;
4195 +       spin_unlock(&smi_info->count_lock);
4196 +
4197 +       if (smi_info->stop_operation)
4198 +               goto out;
4199 +
4200 +#ifdef DEBUG_TIMING
4201 +       do_gettimeofday(&t);
4202 +       printk("**ACPI_GPE: %d.%9.9d\n", t.tv_sec, t.tv_usec);
4203 +#endif
4204 +       smi_event_handler(smi_info, 0);
4205 + out:
4206 +       spin_unlock_irqrestore(&(smi_info->si_lock), flags);
4207 +}
4208 +
4209 +static int acpi_gpe_irq_setup(struct smi_info *info)
4210 +{
4211 +       acpi_status status;
4212 +
4213 +       if (!info->irq)
4214 +               return 0;
4215 +
4216 +       /* FIXME - is level triggered right? */
4217 +       status = acpi_install_gpe_handler(NULL,
4218 +                                         info->irq,
4219 +                                         ACPI_GPE_LEVEL_TRIGGERED,
4220 +                                         ipmi_acpi_gpe,
4221 +                                         info);
4222 +       if (status != AE_OK) {
4223 +               printk(KERN_WARNING
4224 +                      "ipmi_smi: %s unable to claim ACPI GPE %d,"
4225 +                      " running polled\n",
4226 +                      DEVICE_NAME, info->irq);
4227 +               info->irq = 0;
4228 +               return -EINVAL;
4229 +       } else {
4230 +               printk("  Using ACPI GPE %d\n", info->irq);
4231 +               return 0;
4232 +       }
4233 +
4234 +}
4235 +
4236 +static void acpi_gpe_irq_cleanup(struct smi_info *info)
4237 +{
4238 +       if (!info->irq)
4239 +               return;
4240 +
4241 +       acpi_remove_gpe_handler(NULL, info->irq, ipmi_acpi_gpe);
4242 +}
4243 +
4244 +/*
4245 + * Defined at
4246 + * http://h21007.www2.hp.com/dspp/files/unprotected/devresource/Docs/TechPapers/IA64/hpspmi.pdf
4247 + */
4248 +struct SPMITable {
4249 +       s8      Signature[4];
4250 +       u32     Length;
4251 +       u8      Revision;
4252 +       u8      Checksum;
4253 +       s8      OEMID[6];
4254 +       s8      OEMTableID[8];
4255 +       s8      OEMRevision[4];
4256 +       s8      CreatorID[4];
4257 +       s8      CreatorRevision[4];
4258 +       u8      InterfaceType[2];
4259 +       s16     SpecificationRevision;
4260 +
4261 +       /*
4262 +        * Bit 0 - SCI interrupt supported
4263 +        * Bit 1 - I/O APIC/SAPIC
4264 +        */
4265 +       u8      InterruptType;
4266 +
4267 +       /* If bit 0 of InterruptType is set, then this is the SCI
4268 +           interrupt in the GPEx_STS register. */
4269 +       u8      GPE;
4270 +
4271 +       s16     Reserved;
4272 +
4273 +       /* If bit 1 of InterruptType is set, then this is the I/O
4274 +           APIC/SAPIC interrupt. */
4275 +       u32     GlobalSystemInterrupt;
4276 +
4277 +       /* The actual register address. */
4278 +       struct acpi_generic_address addr;
4279 +
4280 +       u8      UID[4];
4281 +
4282 +       s8      spmi_id[1]; /* A '\0' terminated array starts here. */
4283 +};
4284 +
4285 +static int try_init_acpi(int intf_num, struct smi_info **new_info)
4286 +{
4287 +       struct smi_info  *info;
4288 +       acpi_status      status;
4289 +       struct SPMITable *spmi;
4290 +       char             *io_type;
4291 +       u8               addr_space;
4292 +
4293 +       if (acpi_failure)
4294 +               return -ENODEV;
4295 +
4296 +       status = acpi_get_firmware_table("SPMI", intf_num+1,
4297 +                                        ACPI_LOGICAL_ADDRESSING,
4298 +                                        (struct acpi_table_header **) &spmi);
4299 +       if (status != AE_OK) {
4300 +               acpi_failure = 1;
4301 +               return -ENODEV;
4302 +       }
4303 +
4304 +       if (spmi->InterfaceType[0] != 1)
4305 +           return -ENODEV;
4306 +
4307 +       if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
4308 +               addr_space = IPMI_MEM_ADDR_SPACE;
4309 +       else
4310 +               addr_space = IPMI_IO_ADDR_SPACE;
4311 +       if (!is_new_interface(-1, addr_space, spmi->addr.address))
4312 +               return -ENODEV;
4313 +
4314 +       /* Figure out the interface type. */
4315 +       switch (spmi->InterfaceType[1])
4316 +       {
4317 +       case 1: /* KCS */
4318 +               si_type[intf_num] = "kcs";
4319 +               break;
4320 +
4321 +       case 2: /* SMIC */
4322 +               si_type[intf_num] = "smic";
4323 +               break;
4324 +
4325 +       case 3: /* BT */
4326 +               si_type[intf_num] = "bt";
4327 +               break;
4328 +
4329 +       default:
4330 +               printk("ipmi_smi: Unknown ACPI SMI type.\n");
4331 +               return -EIO;
4332 +       } 
4333 +
4334 +       info = kmalloc(sizeof(*info), GFP_KERNEL);
4335 +       if (!info) {
4336 +               printk("ipmi_smi: Could not allocate SMI data\n");
4337 +               return -ENOMEM;
4338 +       }
4339 +       memset(info, 0, sizeof(*info));
4340 +
4341 +       if (spmi->InterruptType & 1) {
4342 +               /* We've got a GPE interrupt. */
4343 +               info->irq = spmi->GPE;
4344 +               info->irq_setup = acpi_gpe_irq_setup;
4345 +               info->irq_cleanup = acpi_gpe_irq_cleanup;
4346 +       } else if (spmi->InterruptType & 2) {
4347 +               /* We've got an APIC/SAPIC interrupt. */
4348 +               info->irq = spmi->GlobalSystemInterrupt;
4349 +               info->irq_setup = std_irq_setup;
4350 +               info->irq_cleanup = std_irq_cleanup;
4351 +       } else {
4352 +               /* Use the default interrupt setting. */
4353 +               info->irq = 0;
4354 +               info->irq_setup = NULL;
4355 +       }
4356 +
4357 +       if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
4358 +               io_type = "memory";
4359 +               info->io_setup = mem_setup;
4360 +               info->io_cleanup = mem_cleanup;
4361 +               si_addrs[intf_num] = spmi->addr.address;
4362 +               info->io.inputb = mem_inb;
4363 +               info->io.outputb = mem_outb;
4364 +               info->io.info = &(si_addrs[intf_num]);
4365 +       } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
4366 +               io_type = "I/O";
4367 +               info->io_setup = port_setup;
4368 +               info->io_cleanup = port_cleanup;
4369 +               si_ports[intf_num] = spmi->addr.address;
4370 +               info->io.inputb = port_inb;
4371 +               info->io.outputb = port_outb;
4372 +               info->io.info = &(si_ports[intf_num]);
4373 +       } else {
4374 +               kfree(info);
4375 +               printk("ipmi_smi: Unknown ACPI I/O Address type.\n");
4376 +               return -EIO;
4377 +       }
4378 +
4379 +       *new_info = info;
4380 +
4381 +       printk("ipmi_smi: Found ACPI-specified state machine at %s"
4382 +              " address 0x%lx\n",
4383 +              io_type, (unsigned long) spmi->addr.address);
4384 +       return 0;
4385 +}
4386 +#endif
4387 +
4388 +#ifdef CONFIG_X86
4389 +
4390 +typedef struct dmi_ipmi_data
4391 +{
4392 +       u8              type;
4393 +       u8              addr_space;
4394 +       unsigned long   base_addr;
4395 +       u8              irq;
4396 +}dmi_ipmi_data_t;
4397 +
4398 +typedef struct dmi_header
4399 +{
4400 +       u8      type;
4401 +       u8      length;
4402 +       u16     handle;
4403 +}dmi_header_t;
4404 +
4405 +static int decode_dmi(dmi_header_t *dm, dmi_ipmi_data_t *ipmi_data)
4406 +{
4407 +       u8              *data = (u8 *)dm;
4408 +       unsigned long   base_addr;
4409 +       
4410 +       ipmi_data->type = data[0x04];
4411 +       
4412 +       memcpy(&base_addr,&data[0x08],sizeof(unsigned long));
4413 +       if (base_addr & 1) {
4414 +               /* I/O */
4415 +               base_addr &= 0xFFFE;
4416 +               ipmi_data->addr_space = IPMI_IO_ADDR_SPACE;
4417 +       }
4418 +       else {
4419 +               /* Memory */
4420 +               ipmi_data->addr_space = IPMI_MEM_ADDR_SPACE;
4421 +       }
4422 +               
4423 +       ipmi_data->base_addr = base_addr;
4424 +       ipmi_data->irq = data[0x11];
4425 +       
4426 +       if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr))
4427 +           return 0;
4428 +           
4429 +       memset(ipmi_data,0,sizeof(dmi_ipmi_data_t));
4430 +           
4431 +       return -1;
4432 +}
4433 +
4434 +static int dmi_table(u32 base, int len, int num, 
4435 +       dmi_ipmi_data_t *ipmi_data)
4436 +{
4437 +       u8                *buf;
4438 +       struct dmi_header *dm;
4439 +       u8                *data;
4440 +       int               i=1;
4441 +       int               status=-1;
4442 +
4443 +       buf = ioremap(base, len);
4444 +       if(buf==NULL)
4445 +               return -1;
4446 +
4447 +       data = buf;
4448 +
4449 +       while(i<num && (data - buf) < len)
4450 +       {        
4451 +               dm=(dmi_header_t *)data;
4452 +
4453 +               if((data-buf+dm->length) >= len)
4454 +                       break;
4455 +       
4456 +               if (dm->type == 38) {
4457 +                       if (decode_dmi(dm, ipmi_data) == 0) {
4458 +                               status = 0;
4459 +                               break;
4460 +                       }
4461 +               }
4462 +       
4463 +               data+=dm->length;
4464 +               while((data-buf) < len && (*data || data[1]))
4465 +                       data++;
4466 +               data+=2;
4467 +               i++;
4468 +       }
4469 +       iounmap(buf);
4470 +       
4471 +       return status;
4472 +}
4473 +
4474 +inline static int dmi_checksum(u8 *buf)
4475 +{
4476 +       u8   sum=0;
4477 +       int  a;
4478 +       
4479 +       for(a=0; a<15; a++)
4480 +               sum+=buf[a];
4481 +       return (sum==0);
4482 +}
4483 +
4484 +static int dmi_iterator(dmi_ipmi_data_t *ipmi_data)
4485 +{
4486 +       u8   buf[15];
4487 +       u32  fp=0xF0000;
4488 +
4489 +#ifdef CONFIG_SIMNOW
4490 +       return -1;
4491 +#endif
4492 +       
4493 +       while(fp < 0xFFFFF)
4494 +       {
4495 +               isa_memcpy_fromio(buf, fp, 15);
4496 +               if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
4497 +               {
4498 +                       u16 num=buf[13]<<8|buf[12];
4499 +                       u16 len=buf[7]<<8|buf[6];
4500 +                       u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
4501 +
4502 +                       if(dmi_table(base, len, num, ipmi_data) == 0)
4503 +                               return 0;
4504 +               }
4505 +               fp+=16;
4506 +       }
4507 +       
4508 +       return -1;
4509 +}
4510 +
4511 +static int try_init_smbios(int intf_num, struct smi_info **new_info)
4512 +{
4513 +       struct smi_info   *info;
4514 +       dmi_ipmi_data_t   ipmi_data;
4515 +       char              *io_type;
4516 +       int               status;
4517 +
4518 +       status = dmi_iterator(&ipmi_data);
4519 +
4520 +       if (status < 0)
4521 +               return -ENODEV;
4522 +       
4523 +       switch(ipmi_data.type) {
4524 +               case 0x01: /* KCS */
4525 +                       si_type[intf_num] = "kcs";
4526 +                       break;
4527 +               case 0x02: /* SMIC */
4528 +                       si_type[intf_num] = "smic";
4529 +                       break;
4530 +               case 0x03: /* BT */
4531 +                       si_type[intf_num] = "bt";
4532 +                       break;
4533 +               default:
4534 +                       printk("ipmi_smi: Unknown SMBIOS SMI type.\n");
4535 +                       return -EIO;
4536 +       }
4537 +       
4538 +       info = kmalloc(sizeof(*info), GFP_KERNEL);
4539 +       if (!info) {
4540 +               printk("ipmi_smi: Could not allocate SMI data\n");
4541 +               return -ENOMEM;
4542 +       }
4543 +       memset(info, 0, sizeof(*info));
4544 +
4545 +       if (ipmi_data.addr_space == 1) {
4546 +               io_type = "memory";
4547 +               info->io_setup = mem_setup;
4548 +               info->io_cleanup = mem_cleanup;
4549 +               si_addrs[intf_num] = ipmi_data.base_addr;
4550 +               info->io.inputb = mem_inb;
4551 +               info->io.outputb = mem_outb;
4552 +               info->io.info = &(si_addrs[intf_num]);
4553 +       } else if (ipmi_data.addr_space == 2) {
4554 +               io_type = "I/O";
4555 +               info->io_setup = port_setup;
4556 +               info->io_cleanup = port_cleanup;
4557 +               si_ports[intf_num] = ipmi_data.base_addr;
4558 +               info->io.inputb = port_inb;
4559 +               info->io.outputb = port_outb;
4560 +               info->io.info = &(si_ports[intf_num]);
4561 +       } else {
4562 +               kfree(info);
4563 +               printk("ipmi_smi: Unknown SMBIOS I/O Address type.\n");
4564 +               return -EIO;
4565 +       }
4566 +
4567 +       si_irqs[intf_num] = ipmi_data.irq;
4568 +
4569 +       *new_info = info;
4570 +
4571 +       printk("ipmi_smi: Found SMBIOS-specified state machine at %s"
4572 +              " address 0x%lx\n",
4573 +              io_type, (unsigned long)ipmi_data.base_addr);
4574 +       return 0;
4575 +}
4576 +#endif /* CONFIG_X86 */
4577 +
4578 +#ifdef CONFIG_PCI
4579 +
4580 +#define PCI_ERMC_CLASSCODE  0x0C0700
4581 +#define PCI_HP_VENDOR_ID    0x103C
4582 +#define PCI_MMC_DEVICE_ID   0x121A
4583 +#define PCI_MMC_ADDR_CW     0x10
4584 +
4585 +/* Avoid more than one attempt to probe pci smic. */
4586 +static int pci_smic_checked = 0;
4587 +
4588 +static int find_pci_smic(int intf_num, struct smi_info **new_info)
4589 +{
4590 +       struct smi_info  *info;
4591 +       int              error;
4592 +       struct pci_dev   *pci_dev = NULL;
4593 +       u16              base_addr;
4594 +       int              fe_rmc = 0;
4595 +       
4596 +       if (!pci_present() || pci_smic_checked)
4597 +               return -ENODEV;
4598 +
4599 +       pci_smic_checked = 1;
4600 +       
4601 +       if ((pci_dev = pci_find_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID,
4602 +                                      NULL)))
4603 +               ;
4604 +       else if ((pci_dev = pci_find_class(PCI_ERMC_CLASSCODE, NULL)) &&
4605 +                pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID)
4606 +               fe_rmc = 1;
4607 +       else
4608 +               return -ENODEV;
4609 +       
4610 +       error = pci_read_config_word(pci_dev, PCI_MMC_ADDR_CW, &base_addr);
4611 +       if (error)
4612 +       {
4613 +               printk(KERN_ERR
4614 +                      "ipmi_smi: pci_read_config_word() failed (%d).\n",
4615 +                      error);
4616 +               return -ENODEV;
4617 +       }
4618 +       
4619 +       /* Bit 0: 1 specifies programmed I/O, 0 specifies memory mapped I/O */
4620 +       if (!(base_addr & 0x0001))
4621 +       {
4622 +               printk(KERN_ERR
4623 +                      "ipmi_smi: memory mapped I/O not supported for PCI"
4624 +                      " smic.\n");
4625 +               return -ENODEV;
4626 +       }
4627 +       
4628 +       base_addr &= 0xFFFE;
4629 +       if (!fe_rmc)
4630 +               /* Data register starts at base address + 1 in eRMC */
4631 +               ++base_addr;
4632 +       
4633 +       if (!is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr))
4634 +           return -ENODEV;
4635 +       
4636 +       info = kmalloc(sizeof(*info), GFP_KERNEL);
4637 +       if (!info) {
4638 +               printk("ipmi_smi: Could not allocate SMI data\n");
4639 +               return -ENOMEM;
4640 +       }
4641 +       memset(info, 0, sizeof(*info));
4642 +       
4643 +       info->io_setup = port_setup;
4644 +       info->io_cleanup = port_cleanup;
4645 +       si_ports[intf_num] = base_addr;
4646 +       info->io.inputb = port_inb;
4647 +       info->io.outputb = port_outb;
4648 +       info->io.info = &(si_ports[intf_num]);
4649 +
4650 +       *new_info = info;
4651 +       
4652 +       si_irqs[intf_num] = pci_dev->irq;
4653 +       si_type[intf_num] = "smic";
4654 +
4655 +       printk("ipmi_smi: Found PCI SMIC at I/O address 0x%lx\n",
4656 +               (long unsigned int) base_addr);
4657 +       
4658 +       return 0;
4659 +}
4660 +#endif /* CONFIG_PCI */
4661 +
4662 +static int try_init_plug_and_play(int intf_num, struct smi_info **new_info)
4663 +{
4664 +#ifdef CONFIG_PCI
4665 +       if (find_pci_smic(intf_num, new_info)==0)
4666 +               return 0;
4667 +#endif
4668 +       /* Include other methods here. */
4669 +    
4670 +       return -ENODEV;
4671 +}
4672 +
4673 +
4674 +static int try_get_dev_id(struct smi_info *smi_info)
4675 +{
4676 +       unsigned char      msg[2];
4677 +       unsigned char      resp[IPMI_MAX_MSG_LENGTH];
4678 +       unsigned long      resp_len;
4679 +       enum si_sm_result smi_result;
4680 +
4681 +       /* Do a Get Device ID command, since it comes back with some
4682 +          useful info. */
4683 +       msg[0] = IPMI_NETFN_APP_REQUEST << 2;
4684 +       msg[1] = IPMI_GET_DEVICE_ID_CMD;
4685 +       smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
4686 +       
4687 +       smi_result = smi_info->handlers->event(smi_info->si_sm, 0);
4688 +       for (;;)
4689 +       {
4690 +               if (smi_result == SI_SM_CALL_WITH_DELAY) {
4691 +                       set_current_state(TASK_UNINTERRUPTIBLE);
4692 +                       schedule_timeout(1);
4693 +                       smi_result = smi_info->handlers->event(
4694 +                               smi_info->si_sm, 100);
4695 +               }
4696 +               else if (smi_result == SI_SM_CALL_WITHOUT_DELAY)
4697 +               {
4698 +                       smi_result = smi_info->handlers->event(
4699 +                               smi_info->si_sm, 0);
4700 +               }
4701 +               else
4702 +                       break;
4703 +       }
4704 +       if (smi_result == SI_SM_HOSED)
4705 +               /* We couldn't get the state machine to run, so whatever's at
4706 +                  the port is probably not an IPMI SMI interface. */
4707 +               return -ENODEV;
4708 +
4709 +       /* Otherwise, we got some data. */
4710 +       resp_len = smi_info->handlers->get_result(smi_info->si_sm,
4711 +                                                 resp, IPMI_MAX_MSG_LENGTH);
4712 +       if (resp_len < 6)
4713 +               /* That's odd, it should be longer. */
4714 +               return -EINVAL;
4715 +       
4716 +       if ((resp[1] != IPMI_GET_DEVICE_ID_CMD) || (resp[2] != 0))
4717 +               /* That's odd, it shouldn't be able to fail. */
4718 +               return -EINVAL;
4719 +
4720 +       /* Record info from the get device id, in case we need it. */
4721 +       smi_info->ipmi_si_dev_rev = resp[4] & 0xf;
4722 +       smi_info->ipmi_si_fw_rev_major = resp[5] & 0x7f;
4723 +       smi_info->ipmi_si_fw_rev_minor = resp[6];
4724 +       smi_info->ipmi_version_major = resp[7] & 0xf;
4725 +       smi_info->ipmi_version_minor = resp[7] >> 4;
4726 +
4727 +       return 0;
4728 +}
4729 +
4730 +extern struct si_sm_handlers kcs_smi_handlers;
4731 +extern struct si_sm_handlers smic_smi_handlers;
4732 +extern struct si_sm_handlers bt_smi_handlers;
4733 +
4734 +static int type_file_read_proc(char *page, char **start, off_t off,
4735 +                              int count, int *eof, void *data)
4736 +{
4737 +       char            *out = (char *) page;
4738 +       struct smi_info *smi = data;
4739 +
4740 +       switch (smi->si_type) {
4741 +           case SI_KCS:
4742 +               return sprintf(out, "kcs\n");
4743 +           case SI_SMIC:
4744 +               return sprintf(out, "smic\n");
4745 +           case SI_BT:
4746 +               return sprintf(out, "bt\n");
4747 +           default:
4748 +               return 0;
4749 +       }
4750 +}
4751 +
4752 +static int stat_file_read_proc(char *page, char **start, off_t off,
4753 +                              int count, int *eof, void *data)
4754 +{
4755 +       char            *out = (char *) page;
4756 +       struct smi_info *smi = data;
4757 +
4758 +       out += sprintf(out, "interrupts_enabled:    %d\n",
4759 +                      smi->irq && !smi->interrupt_disabled);
4760 +       out += sprintf(out, "short_timeouts:        %ld\n",
4761 +                      smi->short_timeouts);
4762 +       out += sprintf(out, "long_timeouts:         %ld\n",
4763 +                      smi->long_timeouts);
4764 +       out += sprintf(out, "timeout_restarts:      %ld\n",
4765 +                      smi->timeout_restarts);
4766 +       out += sprintf(out, "idles:                 %ld\n",
4767 +                      smi->idles);
4768 +       out += sprintf(out, "interrupts:            %ld\n",
4769 +                      smi->interrupts);
4770 +       out += sprintf(out, "attentions:            %ld\n",
4771 +                      smi->attentions);
4772 +       out += sprintf(out, "flag_fetches:          %ld\n",
4773 +                      smi->flag_fetches);
4774 +       out += sprintf(out, "hosed_count:           %ld\n",
4775 +                      smi->hosed_count);
4776 +       out += sprintf(out, "complete_transactions: %ld\n",
4777 +                      smi->complete_transactions);
4778 +       out += sprintf(out, "events:                %ld\n",
4779 +                      smi->events);
4780 +       out += sprintf(out, "watchdog_pretimeouts:  %ld\n",
4781 +                      smi->watchdog_pretimeouts);
4782 +       out += sprintf(out, "incoming_messages:     %ld\n",
4783 +                      smi->incoming_messages);
4784 +
4785 +       return (out - ((char *) page));
4786 +}
4787 +
4788 +/* Returns 0 if initialized, or negative on an error. */
4789 +static int init_one_smi(int intf_num, struct smi_info **smi)
4790 +{
4791 +       int             rv;
4792 +       struct smi_info *new_smi;
4793 +
4794 +
4795 +       rv = try_init_mem(intf_num, &new_smi);
4796 +       if (rv)
4797 +               rv = try_init_port(intf_num, &new_smi);
4798 +#ifdef CONFIG_ACPI_INTERPRETER
4799 +       if ((rv) && (si_trydefaults)) {
4800 +               rv = try_init_acpi(intf_num, &new_smi);
4801 +       }
4802 +#endif
4803 +#ifdef CONFIG_X86
4804 +       if ((rv) && (si_trydefaults)) {
4805 +               rv = try_init_smbios(intf_num, &new_smi);
4806 +        }
4807 +#endif
4808 +       if ((rv) && (si_trydefaults)) {
4809 +               rv = try_init_plug_and_play(intf_num, &new_smi);
4810 +       }
4811 +
4812 +
4813 +       if (rv)
4814 +               return rv;
4815 +
4816 +       /* So we know not to free it unless we have allocated one. */
4817 +       new_smi->intf = NULL;
4818 +       new_smi->si_sm = NULL;
4819 +       new_smi->handlers = 0;
4820 +
4821 +       if (!new_smi->irq_setup) {
4822 +               new_smi->irq = si_irqs[intf_num];
4823 +               new_smi->irq_setup = std_irq_setup;
4824 +               new_smi->irq_cleanup = std_irq_cleanup;
4825 +       }
4826 +
4827 +       /* Default to KCS if no type is specified. */
4828 +       if (si_type[intf_num] == NULL) {
4829 +               if (si_trydefaults)
4830 +                       si_type[intf_num] = "kcs";
4831 +               else {
4832 +                       rv = -EINVAL;
4833 +                       goto out_err;
4834 +               }
4835 +       }
4836 +
4837 +       /* Set up the state machine to use. */
4838 +       if (strcmp(si_type[intf_num], "kcs") == 0) {
4839 +               new_smi->handlers = &kcs_smi_handlers;
4840 +               new_smi->si_type = SI_KCS;
4841 +       } else if (strcmp(si_type[intf_num], "smic") == 0) {
4842 +               new_smi->handlers = &smic_smi_handlers;
4843 +               new_smi->si_type = SI_SMIC;
4844 +       } else if (strcmp(si_type[intf_num], "bt") == 0) {
4845 +               new_smi->handlers = &bt_smi_handlers;
4846 +               new_smi->si_type = SI_BT;
4847 +       } else {
4848 +               /* No support for anything else yet. */
4849 +               rv = -EIO;
4850 +               goto out_err;
4851 +       }
4852 +
4853 +       /* Allocate the state machine's data and initialize it. */
4854 +       new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL);
4855 +       if (!new_smi->si_sm) {
4856 +               printk(" Could not allocate state machine memory\n");
4857 +               rv = -ENOMEM;
4858 +               goto out_err;
4859 +       }
4860 +       new_smi->io_size = new_smi->handlers->init_data(new_smi->si_sm,
4861 +                                                       &new_smi->io);
4862 +
4863 +       /* Now that we know the I/O size, we can set up the I/O. */
4864 +       rv = new_smi->io_setup(new_smi);
4865 +       if (rv) {
4866 +               printk(" Could not set up I/O space\n");
4867 +               goto out_err;
4868 +       }
4869 +       
4870 +       spin_lock_init(&(new_smi->si_lock));
4871 +       spin_lock_init(&(new_smi->msg_lock));
4872 +       spin_lock_init(&(new_smi->count_lock));
4873 +
4874 +       /* Do low-level detection first. */
4875 +       if (new_smi->handlers->detect(new_smi->si_sm)) {
4876 +               rv = -ENODEV;
4877 +               goto out_err;
4878 +       }
4879 +
4880 +       /* Attempt a get device id command.  If it fails, we probably
4881 +           don't have a SMI here. */
4882 +       rv = try_get_dev_id(new_smi);
4883 +       if (rv)
4884 +               goto out_err;
4885 +
4886 +       /* Try to claim any interrupts. */
4887 +       new_smi->irq_setup(new_smi);
4888 +
4889 +       INIT_LIST_HEAD(&(new_smi->xmit_msgs));
4890 +       INIT_LIST_HEAD(&(new_smi->hp_xmit_msgs));
4891 +       new_smi->curr_msg = NULL;
4892 +       atomic_set(&new_smi->req_events, 0);
4893 +       new_smi->run_to_completion = 0;
4894 +
4895 +       rv = ipmi_register_smi(&handlers,
4896 +                              new_smi,
4897 +                              new_smi->ipmi_version_major,
4898 +                              new_smi->ipmi_version_minor,
4899 +                              &(new_smi->intf));
4900 +       if (rv) {
4901 +               printk(KERN_ERR 
4902 +                      "ipmi_smi: Unable to register device: error %d\n",
4903 +                      rv);
4904 +               goto out_err;
4905 +       }
4906 +
4907 +       rv = ipmi_smi_add_proc_entry(new_smi->intf, "type",
4908 +                                    type_file_read_proc, NULL,
4909 +                                    new_smi, THIS_MODULE);
4910 +       if (rv) {
4911 +               printk(KERN_ERR 
4912 +                      "ipmi_smi: Unable to create proc entry: %d\n",
4913 +                      rv);
4914 +               goto out_err;
4915 +       }
4916 +
4917 +       rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats",
4918 +                                    stat_file_read_proc, NULL,
4919 +                                    new_smi, THIS_MODULE);
4920 +       if (rv) {
4921 +               printk(KERN_ERR 
4922 +                      "ipmi_smi: Unable to create proc entry: %d\n",
4923 +                      rv);
4924 +               goto out_err;
4925 +       }
4926 +
4927 +       start_clear_flags(new_smi);
4928 +
4929 +       /* IRQ is defined to be set when non-zero. */
4930 +       if (new_smi->irq)
4931 +               new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ;
4932 +
4933 +       new_smi->interrupt_disabled = 0;
4934 +       new_smi->timer_stopped = 0;
4935 +       new_smi->stop_operation = 0;
4936 +
4937 +       init_timer(&(new_smi->si_timer));
4938 +       new_smi->si_timer.data = (long) new_smi;
4939 +       new_smi->si_timer.function = smi_timeout;
4940 +       new_smi->last_timeout_jiffies = jiffies;
4941 +       new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
4942 +       add_timer(&(new_smi->si_timer));
4943 +
4944 +       *smi = new_smi;
4945 +
4946 +       printk(" IPMI %s interface initialized\n", si_type[intf_num]);
4947 +
4948 +       return 0;
4949 +
4950 + out_err:
4951 +       if (new_smi->intf)
4952 +               ipmi_unregister_smi(new_smi->intf);
4953 +
4954 +       new_smi->irq_cleanup(new_smi);
4955 +       if (new_smi->si_sm) {
4956 +               if (new_smi->handlers)
4957 +                       new_smi->handlers->cleanup(new_smi->si_sm);
4958 +               kfree(new_smi->si_sm);
4959 +       }
4960 +       new_smi->io_cleanup(new_smi);
4961 +       return rv;
4962 +}
4963 +
4964 +static __init int init_ipmi_si(void)
4965 +{
4966 +       int             rv = 0;
4967 +       int             pos = 0;
4968 +       int             i = 0;
4969 +
4970 +       if (initialized)
4971 +               return 0;
4972 +       initialized = 1;
4973 +
4974 +       printk(KERN_INFO "IPMI System Interface driver version "
4975 +              IPMI_SI_VERSION);
4976 +       if (kcs_smi_handlers.version)
4977 +               printk(", KCS version %s", kcs_smi_handlers.version);
4978 +       if (smic_smi_handlers.version)
4979 +               printk(", SMIC version %s", smic_smi_handlers.version);
4980 +       if (bt_smi_handlers.version)
4981 +               printk(", BT version %s", bt_smi_handlers.version);
4982 +       printk("\n");
4983 +
4984 +       rv = init_one_smi(0, &(smi_infos[pos]));
4985 +       if (rv && !si_ports[0] && si_trydefaults) {
4986 +               /* If we are trying defaults and the initial port is
4987 +                   not set, then set it. */
4988 +               si_type[0] = "kcs";
4989 +               si_ports[0] = DEFAULT_KCS_IO_PORT;
4990 +               rv = init_one_smi(0, &(smi_infos[pos]));
4991 +               if (rv) {
4992 +                       /* No KCS - try SMIC */
4993 +                       si_type[0] = "smic";
4994 +                       si_ports[0] = DEFAULT_SMIC_IO_PORT;
4995 +                       rv = init_one_smi(0, &(smi_infos[pos]));
4996 +               }
4997 +               if (rv) {
4998 +                       /* No SMIC - try BT */
4999 +                       si_type[0] = "bt";
5000 +                       si_ports[0] = DEFAULT_BT_IO_PORT;
5001 +                       rv = init_one_smi(0, &(smi_infos[pos]));
5002 +               }
5003 +       }
5004 +       if (rv == 0)
5005 +               pos++;
5006 +
5007 +       for (i=1; i < SI_MAX_PARMS; i++) {
5008 +               rv = init_one_smi(i, &(smi_infos[pos]));
5009 +               if (rv == 0)
5010 +                       pos++;
5011 +       }
5012 +
5013 +       if (smi_infos[0] == NULL) {
5014 +               printk("ipmi_smi: Unable to find any SMI interfaces\n");
5015 +               return -ENODEV;
5016 +       } 
5017 +
5018 +       return 0;
5019 +}
5020 +module_init(init_ipmi_si);
5021 +
5022 +#ifdef MODULE
5023 +void __exit cleanup_one_si(struct smi_info *to_clean)
5024 +{
5025 +       int           rv;
5026 +       unsigned long flags;
5027 +
5028 +       if (! to_clean)
5029 +               return;
5030 +
5031 +       /* Tell the timer and interrupt handlers that we are shutting
5032 +          down. */
5033 +       spin_lock_irqsave(&(to_clean->si_lock), flags);
5034 +       spin_lock(&(to_clean->msg_lock));
5035 +
5036 +       to_clean->stop_operation = 1;
5037 +
5038 +       to_clean->irq_cleanup(to_clean);
5039 +
5040 +       spin_unlock(&(to_clean->msg_lock));
5041 +       spin_unlock_irqrestore(&(to_clean->si_lock), flags);
5042 +
5043 +       /* Wait for the timer to stop.  This avoids problems with race
5044 +          conditions removing the timer here.  Hopefully this will be
5045 +          long enough to avoid problems with interrupts still
5046 +          running. */
5047 +       set_current_state(TASK_UNINTERRUPTIBLE);
5048 +       schedule_timeout(2);
5049 +       while (!to_clean->timer_stopped) {
5050 +               set_current_state(TASK_UNINTERRUPTIBLE);
5051 +               schedule_timeout(1);
5052 +       }
5053 +
5054 +       rv = ipmi_unregister_smi(to_clean->intf);
5055 +       if (rv) {
5056 +               printk(KERN_ERR 
5057 +                      "ipmi_smi: Unable to unregister device: errno=%d\n",
5058 +                      rv);
5059 +       }
5060 +
5061 +       to_clean->handlers->cleanup(to_clean->si_sm);
5062 +
5063 +       kfree(to_clean->si_sm);
5064 +
5065 +       to_clean->io_cleanup(to_clean);
5066 +}
5067 +
5068 +static __exit void cleanup_ipmi_si(void)
5069 +{
5070 +       int i;
5071 +
5072 +       if (!initialized)
5073 +               return;
5074 +
5075 +       for (i=0; i<SI_MAX_DRIVERS; i++) {
5076 +               cleanup_one_si(smi_infos[i]);
5077 +       }
5078 +}
5079 +module_exit(cleanup_ipmi_si);
5080 +#else
5081 +
5082 +/* Unfortunately, cmdline::get_options() only returns integers, not
5083 +   longs.  Since we need ulongs (64-bit physical addresses) parse the 
5084 +   comma-separated list manually.  Arguments can be one of these forms:
5085 +   m0xaabbccddeeff     A physical memory address without an IRQ
5086 +   m0xaabbccddeeff:cc  A physical memory address with an IRQ
5087 +   p0xaabb             An IO port without an IRQ
5088 +   p0xaabb:cc          An IO port with an IRQ
5089 +   nodefaults          Suppress trying the default IO port or ACPI address 
5090 +
5091 +   For example, to pass one IO port with an IRQ, one address, and 
5092 +   suppress the use of the default IO port and ACPI address,
5093 +   use this option string: ipmi_smi=p0xCA2:5,m0xFF5B0022,nodefaults
5094 +
5095 +   Remember, ipmi_si_setup() is passed the string after the equal sign. */
5096 +
5097 +static int __init ipmi_si_setup(char *str)
5098 +{
5099 +       unsigned long val;
5100 +       char *cur, *colon;
5101 +       int pos;
5102 +
5103 +       pos = 0;
5104 +       
5105 +       cur = strsep(&str, ",");
5106 +       while ((cur) && (*cur) && (pos < SI_MAX_PARMS)) {
5107 +               switch (*cur) {
5108 +               case 'n':
5109 +                       if (strcmp(cur, "nodefaults") == 0)
5110 +                               si_trydefaults = 0;
5111 +                       else
5112 +                               printk(KERN_INFO 
5113 +                                      "ipmi_si: bad parameter value %s\n",
5114 +                                      cur);
5115 +                       break;
5116 +
5117 +               case 'k': /* KCS */
5118 +                       si_type[pos] = "kcs";
5119 +                       break;
5120 +               
5121 +               case 's': /* SMIC */
5122 +                       si_type[pos] = "smic";
5123 +                       break;
5124 +               
5125 +               case 'b': /* BT */
5126 +                       si_type[pos] = "bt";
5127 +                       break;
5128 +               
5129 +               case 'm':
5130 +               case 'p':
5131 +                       val = simple_strtoul(cur + 1,
5132 +                                            &colon,
5133 +                                            0);
5134 +                       if (*cur == 'p')
5135 +                               si_ports[pos] = val;
5136 +                       else
5137 +                               si_addrs[pos] = val;
5138 +                       if (*colon == ':') {
5139 +                               val = simple_strtoul(colon + 1,
5140 +                                                    &colon,
5141 +                                                    0);
5142 +                               si_irqs[pos] = val;
5143 +                       }
5144 +                       pos++;
5145 +                       break;
5146 +
5147 +               default:
5148 +                       printk(KERN_INFO 
5149 +                              "ipmi_si: bad parameter value %s\n",
5150 +                              cur);
5151 +               }
5152 +               cur = strsep(&str, ",");
5153 +       }
5154 +
5155 +       return 1;
5156 +}
5157 +__setup("ipmi_si=", ipmi_si_setup);
5158 +#endif
5159 +
5160 +MODULE_LICENSE("GPL");
5161 diff -urN linux-2.4.23.org/drivers/char/ipmi/ipmi_si_sm.h linux-2.4.23/drivers/char/ipmi/ipmi_si_sm.h
5162 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_si_sm.h     1970-01-01 01:00:00.000000000 +0100
5163 +++ linux-2.4.23/drivers/char/ipmi/ipmi_si_sm.h 2004-01-02 23:33:48.056808733 +0100
5164 @@ -0,0 +1,112 @@
5165 +/*
5166 + * ipmi_si_sm.h
5167 + *
5168 + * State machine interface for low-level IPMI system management
5169 + * interface state machines.  This code is the interface between
5170 + * the ipmi_smi code (that handles the policy of a KCS, SMIC, or
5171 + * BT interface) and the actual low-level state machine.
5172 + *
5173 + * Author: MontaVista Software, Inc.
5174 + *         Corey Minyard <minyard@mvista.com>
5175 + *         source@mvista.com
5176 + *
5177 + * Copyright 2002 MontaVista Software Inc.
5178 + *
5179 + *  This program is free software; you can redistribute it and/or modify it
5180 + *  under the terms of the GNU General Public License as published by the
5181 + *  Free Software Foundation; either version 2 of the License, or (at your
5182 + *  option) any later version.
5183 + *
5184 + *
5185 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
5186 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
5187 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5188 + *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
5189 + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
5190 + *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
5191 + *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
5192 + *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
5193 + *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
5194 + *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5195 + *
5196 + *  You should have received a copy of the GNU General Public License along
5197 + *  with this program; if not, write to the Free Software Foundation, Inc.,
5198 + *  675 Mass Ave, Cambridge, MA 02139, USA.
5199 + */
5200 +
5201 +/* This is defined by the state machines themselves, it is an opaque
5202 +   data type for them to use. */
5203 +struct si_sm_data;
5204 +
5205 +/* The structure for doing I/O in the state machine.  The state
5206 +   machine doesn't have the actual I/O routines, they are done through
5207 +   this interface. */
5208 +struct si_sm_io
5209 +{
5210 +       unsigned char (*inputb)(struct si_sm_io *io, unsigned int offset);
5211 +       void (*outputb)(struct si_sm_io *io,
5212 +                       unsigned int  offset,
5213 +                       unsigned char b);
5214 +
5215 +       /* Generic info used by the actual handling routines, the
5216 +           state machine shouldn't touch these. */
5217 +       void *info;
5218 +       void *addr;
5219 +};
5220 +
5221 +/* Results of SMI events. */
5222 +enum si_sm_result
5223 +{
5224 +       SI_SM_CALL_WITHOUT_DELAY, /* Call the driver again immediately */
5225 +       SI_SM_CALL_WITH_DELAY,  /* Delay some before calling again. */
5226 +       SI_SM_TRANSACTION_COMPLETE, /* A transaction is finished. */
5227 +       SI_SM_IDLE,             /* The SM is in idle state. */
5228 +       SI_SM_HOSED,            /* The hardware violated the state machine. */
5229 +       SI_SM_ATTN              /* The hardware is asserting attn and the
5230 +                                  state machine is idle. */
5231 +};
5232 +
5233 +/* Handlers for the SMI state machine. */
5234 +struct si_sm_handlers
5235 +{
5236 +       /* Put the version number of the state machine here so the
5237 +           upper layer can print it. */
5238 +       char *version;
5239 +
5240 +       /* Initialize the data and return the amount of I/O space to
5241 +           reserve for the space. */
5242 +       unsigned int (*init_data)(struct si_sm_data *smi,
5243 +                                 struct si_sm_io   *io);
5244 +
5245 +       /* Start a new transaction in the state machine.  This will
5246 +          return -2 if the state machine is not idle, -1 if the size
5247 +          is invalid (to large or too small), or 0 if the transaction
5248 +          is successfully completed. */
5249 +       int (*start_transaction)(struct si_sm_data *smi,
5250 +                                unsigned char *data, unsigned int size);
5251 +
5252 +       /* Return the results after the transaction.  This will return
5253 +          -1 if the buffer is too small, zero if no transaction is
5254 +          present, or the actual length of the result data. */
5255 +       int (*get_result)(struct si_sm_data *smi,
5256 +                         unsigned char *data, unsigned int length);
5257 +
5258 +       /* Call this periodically (for a polled interface) or upon
5259 +          receiving an interrupt (for a interrupt-driven interface).
5260 +          If interrupt driven, you should probably poll this
5261 +          periodically when not in idle state.  This should be called
5262 +          with the time that passed since the last call, if it is
5263 +          significant.  Time is in microseconds. */
5264 +       enum si_sm_result (*event)(struct si_sm_data *smi, long time);
5265 +
5266 +       /* Attempt to detect an SMI.  Returns 0 on success or nonzero
5267 +           on failure. */
5268 +       int (*detect)(struct si_sm_data *smi);
5269 +
5270 +       /* The interface is shutting down, so clean it up. */
5271 +       void (*cleanup)(struct si_sm_data *smi);
5272 +
5273 +       /* Return the size of the SMI structure in bytes. */
5274 +       int (*size)(void);
5275 +};
5276 +
5277 diff -urN linux-2.4.23.org/drivers/char/ipmi/ipmi_smb_intf.c linux-2.4.23/drivers/char/ipmi/ipmi_smb_intf.c
5278 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_smb_intf.c  1970-01-01 01:00:00.000000000 +0100
5279 +++ linux-2.4.23/drivers/char/ipmi/ipmi_smb_intf.c      2004-01-02 23:33:48.062807487 +0100
5280 @@ -0,0 +1,1308 @@
5281 +/*
5282 + * ipmi_smb_intf.c
5283 + *
5284 + * The interface to the IPMI driver for SMBus access to a SMBus compliant device.
5285 + *
5286 + * Author: Intel Corporation
5287 + *         Todd Davis <todd.c.davis@intel.com>
5288 +  *
5289 + * Copyright 2003 Intel Corporation
5290 + *
5291 + *  This program is free software; you can redistribute it and/or modify it
5292 + *  under the terms of the GNU General Public License as published by the
5293 + *  Free Software Foundation; either version 2 of the License, or (at your
5294 + *  option) any later version.
5295 + *
5296 + *
5297 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
5298 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
5299 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5300 + *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
5301 + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
5302 + *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
5303 + *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
5304 + *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
5305 + *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
5306 + *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5307 + *
5308 + *  You should have received a copy of the GNU General Public License along
5309 + *  with this program; if not, write to the Free Software Foundation, Inc.,
5310 + *  675 Mass Ave, Cambridge, MA 02139, USA.
5311 + */
5312 +
5313 +/*
5314 + * This file holds the "policy" for the interface to the SMB state
5315 + * machine.  It does the configuration, handles timers and interrupts,
5316 + * and drives the real SMB state machine.
5317 + */
5318 +
5319 +#include <linux/config.h>
5320 +#include <linux/version.h>
5321 +#if defined(MODVERSIONS)
5322 +#include <linux/modversions.h>
5323 +#endif
5324 +
5325 +#include <linux/module.h>
5326 +#include <asm/system.h>
5327 +#include <linux/sched.h>
5328 +#include <linux/timer.h>
5329 +#include <linux/errno.h>
5330 +#include <linux/spinlock.h>
5331 +#include <linux/slab.h>
5332 +#include <linux/delay.h>
5333 +#include <linux/list.h>
5334 +#include <linux/i2c.h>
5335 +#include <linux/ipmi_smi.h>
5336 +#include <linux/init.h>
5337 +
5338 +
5339 +#define IPMI_SMB_VERSION "v28"
5340 +
5341 +/* module feature switches */
5342 +#define        REGISTER_SMI    1
5343 +#define        SMB_KTHREAD     1
5344 +
5345 +#ifdef SMB_KTHREAD
5346 +#include <linux/kernel.h>
5347 +#include <linux/smp_lock.h>
5348 +
5349 +/* a structure to store all information we need
5350 +   for our thread */
5351 +typedef struct kthread_struct
5352 +{
5353 +        /* Linux task structure of thread */
5354 +        struct task_struct *thread;
5355 +        /* Task queue need to launch thread */
5356 +        struct tq_struct tq;
5357 +       /* semaphore needed on start and creation of thread. */
5358 +        struct semaphore startstop_sem;
5359 +
5360 +        /* queue thread is waiting on. Gets initialized by
5361 +           init_kthread, can be used by thread itself.
5362 +        */
5363 +        wait_queue_head_t queue;
5364 +        /* flag to tell thread whether to die or not.
5365 +           When the thread receives a signal, it must check
5366 +           the value of terminate and call exit_kthread and terminate
5367 +           if set.
5368 +        */
5369 +       int terminate;
5370 +} kthread_t;   /* the variable that contains the thread data */
5371 +#endif
5372 +
5373 +#define        SMB_IPMI_REQUEST        2
5374 +#define        SMB_IPMI_RESPONSE       3
5375 +
5376 +/* smb_debug is a bit-field 
5377 + *     SMB_DEBUG_MSG - commands and their responses
5378 + *     SMB_DEBUG_STATES -      message states
5379 + *     SMB_DEBUG_TIMING -       Measure times between events in the driver
5380 + */
5381 +#define SMB_DEBUG_TIMING       4
5382 +#define SMB_DEBUG_STATE                2
5383 +#define SMB_DEBUG_MSG          1
5384 +#define SMB_NODEBUG            0
5385 +#define SMB_DEFAULT_DEBUG      (SMB_NODEBUG)
5386 +
5387 +#ifdef CONFIG_IPMI_SMB
5388 +/* This forces a dependency to the config file for this option. */
5389 +#endif
5390 +
5391 +enum smb_intf_state {
5392 +       SMB_NORMAL,
5393 +       SMB_GETTING_FLAGS,
5394 +       SMB_GETTING_EVENTS,
5395 +       SMB_CLEARING_FLAGS,
5396 +       SMB_CLEARING_FLAGS_THEN_SET_IRQ,
5397 +       SMB_GETTING_MESSAGES,
5398 +       SMB_ENABLE_INTERRUPTS1,
5399 +       SMB_ENABLE_INTERRUPTS2
5400 +       /* FIXME - add watchdog stuff. */
5401 +};
5402 +
5403 +#define SMB_IDLE(smb)   ((smb)->smb_state == SMB_NORMAL \
5404 +                         && (smb)->curr_msg == NULL \
5405 +                         && ! atomic_read(&(smb)->req_events))
5406 +                                           
5407 +#define        SMB_MSG_RETRIES 10
5408 +
5409 +struct smb_info
5410 +{
5411 +       int                 pos;
5412 +       ipmi_smi_t          intf;
5413 +       spinlock_t          msg_lock;
5414 +       struct list_head    xmit_msgs;
5415 +       struct list_head    hp_xmit_msgs;
5416 +       struct ipmi_smi_msg *curr_msg;
5417 +       enum smb_intf_state smb_state;
5418 +       unsigned long       smb_debug;
5419 +
5420 +       /* Flags from the last GET_MSG_FLAGS command, used when an ATTN
5421 +          is set to hold the flags until we are done handling everything
5422 +          from the flags. */
5423 +#define RECEIVE_MSG_AVAIL      0x01
5424 +#define EVENT_MSG_BUFFER_FULL  0x02
5425 +#define WDT_PRE_TIMEOUT_INT    0x08
5426 +       unsigned char       msg_flags;
5427 +
5428 +       /* If set to true, this will request events the next time the
5429 +          state machine is idle. */
5430 +       atomic_t            req_events;
5431 +
5432 +       /* If true, run the state machine to completion on every send
5433 +          call.  Generally used after a panic to make sure stuff goes
5434 +          out. */
5435 +       int                 run_to_completion;
5436 +
5437 +#ifdef SMB_KTHREAD
5438 +       kthread_t smb_thread;
5439 +#endif 
5440 +       struct i2c_client client;
5441 +       unsigned char ipmi_smb_dev_rev;
5442 +       unsigned char ipmi_smb_fw_rev_major;
5443 +       unsigned char ipmi_smb_fw_rev_minor;
5444 +       unsigned char ipmi_version_major;
5445 +       unsigned char ipmi_version_minor;
5446 +};
5447 +
5448 +static int initialized = 0;
5449 +static void return_hosed_msg(struct smb_info *smb_info);
5450 +
5451 +static void deliver_recv_msg(struct smb_info *smb_info,
5452 +                            struct ipmi_smi_msg *msg)
5453 +{
5454 +       if (msg->rsp_size < 0) {
5455 +               if (smb_info->curr_msg == NULL) {
5456 +                       smb_info->curr_msg = msg;
5457 +                       return_hosed_msg(smb_info);
5458 +               } else {
5459 +                       printk(KERN_ERR
5460 +                              "malformed message in deliver_recv_msg:"
5461 +                              " rsp_size = %d\n", msg->rsp_size);
5462 +                       ipmi_free_smi_msg(msg);
5463 +               }
5464 +       } else {
5465 +               ipmi_smi_msg_received(smb_info->intf, msg);
5466 +       }
5467 +}
5468 +
5469 +static void return_hosed_msg(struct smb_info *smb_info)
5470 +{
5471 +       struct ipmi_smi_msg *msg = smb_info->curr_msg;
5472 +
5473 +       /* Make it a reponse */
5474 +       msg->rsp[0] = msg->data[0] | 4;
5475 +       msg->rsp[1] = msg->data[1];
5476 +       msg->rsp[2] = 0xFF; /* Unknown error. */
5477 +       msg->rsp_size = 3;
5478 +
5479 +       smb_info->curr_msg = NULL;
5480 +       deliver_recv_msg(smb_info, msg);
5481 +}
5482 +
5483 +static s32 smbus_client_read_block_data(struct i2c_client *client, int debug,
5484 +                                       u8 *values)
5485 +{
5486 +       s32 resp_len;
5487 +       int retries = 0;
5488 +
5489 +       /* FIXME - is there a way to limit the read size?  This culd
5490 +        * be an overrun situation otherwise. */
5491 +       while ((resp_len = i2c_smbus_read_block_data (client,
5492 +                                                     SMB_IPMI_RESPONSE,
5493 +                                                     values)) < 0)
5494 +       {
5495 +               if ((retries += 1) >= SMB_MSG_RETRIES) {
5496 +                       printk(KERN_ERR
5497 +                              "smb_smbus_read_block_data failed: %d\n",
5498 +                              resp_len);
5499 +                       break;
5500 +               } else if (debug & (SMB_DEBUG_MSG|SMB_DEBUG_TIMING)) {
5501 +                       printk(KERN_WARNING
5502 +                              "smb_smbus_read_block_data: retry %d\n",
5503 +                              retries);
5504 +               }
5505 +       }
5506 +
5507 +       if (debug & SMB_DEBUG_TIMING) {
5508 +               struct timeval t;
5509 +               do_gettimeofday(&t);
5510 +               printk(KERN_INFO "**Response %02x %02x %02x: %ld.%9.9ld\n",
5511 +                      values[0], values[1], values[2], t.tv_sec, t.tv_usec);
5512 +       }
5513 +
5514 +       if (debug & SMB_DEBUG_MSG) {
5515 +               int i;
5516 +               printk(KERN_INFO "ipmi response:");
5517 +               for (i = 0; i < resp_len; i ++) {
5518 +                       printk (" %02x", (unsigned char) (values[i]));
5519 +               }
5520 +               printk ("\n");
5521 +       }
5522 +
5523 +       return resp_len;
5524 +}
5525 +
5526 +static s32 smb_smbus_read_block_data(struct smb_info *smb_info, u8 *values)
5527 +{
5528 +       return smbus_client_read_block_data(&smb_info->client,
5529 +                                           smb_info->smb_debug, values);
5530 +}
5531 +
5532 +static s32 smbus_client_write_block_data(struct i2c_client *client, int debug,
5533 +                                        u8 length, u8 *values)
5534 +{
5535 +       s32 ret;
5536 +       int retries = 0;
5537 +
5538 +       if (debug & SMB_DEBUG_MSG) {
5539 +               int i ;
5540 +
5541 +               printk(KERN_INFO "ipmi request:");
5542 +               for (i = 0; i < length; i ++) {
5543 +                       printk (" %02x", (unsigned char) (values [i]));
5544 +               }
5545 +               printk ("\n");
5546 +       }
5547 +
5548 +       if (debug & SMB_DEBUG_TIMING) {
5549 +               struct timeval t;
5550 +               do_gettimeofday(&t);
5551 +               printk(KERN_INFO "**Request %02x %02x: %ld.%9.9ld\n",
5552 +                      values [0],values [1], t.tv_sec, t.tv_usec);
5553 +       }
5554 +
5555 +       while ((ret = i2c_smbus_write_block_data (client,
5556 +                                                 SMB_IPMI_REQUEST,
5557 +                                                 length, values)) < 0)
5558 +       {
5559 +               if ((retries += 1) >= SMB_MSG_RETRIES) {
5560 +                       printk(KERN_ERR
5561 +                              "smb_smbus_write_block_data failed: %d\n", ret);
5562 +                       break;
5563 +               } else if (debug & (SMB_DEBUG_MSG|SMB_DEBUG_TIMING)) {
5564 +                       printk(KERN_WARNING
5565 +                              "smb_smbus_write_block_data: retry %d\n",
5566 +                              retries);
5567 +               }
5568 +       }
5569 +       return ret;
5570 +}
5571 +
5572 +static s32 smb_smbus_write_block_data(struct smb_info *smb_info,
5573 +                                      u8 length,  u8 *values)
5574 +{
5575 +       return smbus_client_write_block_data(&smb_info->client,
5576 +                                            smb_info->smb_debug,
5577 +                                            length,
5578 +                                            values);
5579 +}
5580 +
5581 +static void send_next_msg(struct smb_info *smb_info)
5582 +{
5583 +       s32              rv;
5584 +       struct list_head *entry = NULL;
5585 +
5586 +       spin_lock(&(smb_info->msg_lock));
5587 +       
5588 +       /* Pick the high priority queue first. */
5589 +       if (! list_empty(&(smb_info->hp_xmit_msgs))) {
5590 +               entry = smb_info->hp_xmit_msgs.next;
5591 +       } else if (! list_empty(&(smb_info->xmit_msgs))) {
5592 +               entry = smb_info->xmit_msgs.next;
5593 +       }
5594 +
5595 +       if (!entry) {
5596 +               spin_unlock(&(smb_info->msg_lock));
5597 +               smb_info->curr_msg = NULL;
5598 +               return;
5599 +       } 
5600 +       list_del(entry);
5601 +       smb_info->curr_msg = list_entry(entry,
5602 +                                       struct ipmi_smi_msg,
5603 +                                       link);
5604 +       spin_unlock(&(smb_info->msg_lock));
5605 +       rv = smb_smbus_write_block_data(
5606 +           smb_info,
5607 +           smb_info->curr_msg->data_size,
5608 +           smb_info->curr_msg->data);
5609 +       if (rv) {
5610 +               return_hosed_msg(smb_info);
5611 +       }
5612 +}
5613 +
5614 +static void start_enable_irq(struct smb_info *smb_info)
5615 +{
5616 +       unsigned char msg[2];
5617 +
5618 +       /* If we are enabling interrupts, we have to tell the
5619 +          IPMI device to use them. */
5620 +       msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
5621 +       msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
5622 +
5623 +       if (smb_smbus_write_block_data(smb_info, 2, msg) == 0) {
5624 +               smb_info->smb_state = SMB_ENABLE_INTERRUPTS1;
5625 +       } else {
5626 +               smb_info->smb_state = SMB_NORMAL;
5627 +       }
5628 +}
5629 +
5630 +static void start_clear_flags(struct smb_info *smb_info)
5631 +{
5632 +       unsigned char msg[3];
5633 +
5634 +       /* Make sure the watchdog pre-timeout flag is not set at startup. */
5635 +       msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
5636 +       msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD;
5637 +       msg[2] = WDT_PRE_TIMEOUT_INT;
5638 +
5639 +       if (smb_smbus_write_block_data(smb_info, 3, msg) == 0) {
5640 +               smb_info->smb_state = SMB_CLEARING_FLAGS;
5641 +       } else {
5642 +               smb_info->smb_state = SMB_NORMAL;
5643 +       }
5644 +}
5645 +
5646 +static void handle_flags(struct smb_info *smb_info)
5647 +{
5648 +       if (smb_info->msg_flags & WDT_PRE_TIMEOUT_INT) {
5649 +               /* Watchdog pre-timeout */
5650 +               start_clear_flags(smb_info);
5651 +               smb_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT;
5652 +               ipmi_smi_watchdog_pretimeout(smb_info->intf);
5653 +       } else if (smb_info->msg_flags & RECEIVE_MSG_AVAIL) {
5654 +               /* Messages available. */
5655 +               smb_info->curr_msg = ipmi_alloc_smi_msg();
5656 +               if (!smb_info->curr_msg) {
5657 +                       smb_info->smb_state = SMB_NORMAL;
5658 +                       return;
5659 +               }
5660 +
5661 +               smb_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
5662 +               smb_info->curr_msg->data[1] = IPMI_GET_MSG_CMD;
5663 +               smb_info->curr_msg->data_size = 2;
5664 +
5665 +               if (smb_smbus_write_block_data(
5666 +                   smb_info,
5667 +                   smb_info->curr_msg->data_size,
5668 +                   smb_info->curr_msg->data) == 0) {
5669 +                       smb_info->smb_state = SMB_GETTING_MESSAGES;
5670 +               } else {
5671 +                       ipmi_free_smi_msg(smb_info->curr_msg);
5672 +                       smb_info->curr_msg = NULL;
5673 +                       smb_info->smb_state = SMB_NORMAL;
5674 +                       return;
5675 +               }
5676 +       } else if (smb_info->msg_flags & EVENT_MSG_BUFFER_FULL) {
5677 +               /* Events available. */
5678 +               smb_info->curr_msg = ipmi_alloc_smi_msg();
5679 +               if (!smb_info->curr_msg) {
5680 +                       smb_info->smb_state = SMB_NORMAL;
5681 +                       return;
5682 +               }
5683 +
5684 +               smb_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
5685 +               smb_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD;
5686 +               smb_info->curr_msg->data_size = 2;
5687 +
5688 +               if (smb_smbus_write_block_data(
5689 +                   smb_info,
5690 +                   smb_info->curr_msg->data_size,
5691 +                   smb_info->curr_msg->data) == 0) {
5692 +                       smb_info->smb_state = SMB_GETTING_EVENTS;
5693 +               } else {
5694 +                       ipmi_free_smi_msg(smb_info->curr_msg);
5695 +                       smb_info->curr_msg = NULL;
5696 +                       smb_info->smb_state = SMB_NORMAL;
5697 +                       return;
5698 +               }
5699 +       } else {
5700 +               smb_info->smb_state = SMB_NORMAL;
5701 +       }
5702 +}
5703 +
5704 +static void handle_transaction_done(struct smb_info *smb_info)
5705 +{
5706 +       struct ipmi_smi_msg *msg;
5707 +       unsigned int  len;
5708 +
5709 +       if (smb_info->smb_debug & SMB_DEBUG_STATE) {
5710 +               printk(KERN_INFO "DONE 1: state = %d.\n", smb_info->smb_state);
5711 +       }
5712 +       switch (smb_info->smb_state) {
5713 +       case SMB_NORMAL:
5714 +               if (!smb_info->curr_msg)
5715 +                       break;
5716 +
5717 +               smb_info->curr_msg->rsp_size
5718 +                       = smb_smbus_read_block_data(
5719 +                           smb_info,
5720 +                           smb_info->curr_msg->rsp);
5721 +
5722 +               msg = smb_info->curr_msg;
5723 +               smb_info->curr_msg = NULL;
5724 +               deliver_recv_msg(smb_info, msg);
5725 +               break;
5726 +
5727 +       case SMB_GETTING_FLAGS:
5728 +       {
5729 +               unsigned char msg[4];
5730 +
5731 +               /* We got the flags from the SMB, now handle them. */
5732 +               len = smb_smbus_read_block_data(smb_info, msg);
5733 +               if (len < 0) {
5734 +                       /* Error fetching flags, just give up for  now. */
5735 +                       smb_info->smb_state = SMB_NORMAL;
5736 +               } else if (msg[2] != 0) {
5737 +                       /* Error fetching flags, just give up for  now. */
5738 +                       smb_info->smb_state = SMB_NORMAL;
5739 +               } else if (len < 3) {
5740 +                       /* Hmm, no flags.  That's technically illegal, but
5741 +                          don't use uninitialized data. */
5742 +                       smb_info->smb_state = SMB_NORMAL;
5743 +               } else {
5744 +                       smb_info->msg_flags = msg[3];
5745 +                       handle_flags(smb_info);
5746 +               }
5747 +               break;
5748 +       }
5749 +
5750 +       case SMB_CLEARING_FLAGS:
5751 +       case SMB_CLEARING_FLAGS_THEN_SET_IRQ:
5752 +       {
5753 +               unsigned char msg[3];
5754 +
5755 +               /* We cleared the flags. */
5756 +               len = smb_smbus_read_block_data(smb_info, msg);
5757 +               if (len < 0 || msg[2] != 0) {
5758 +                       /* Error clearing flags */
5759 +                       printk(KERN_WARNING
5760 +                              "ipmi_smb: Error clearing flags: %2.2x\n",
5761 +                              msg[2]);
5762 +               }
5763 +               if (smb_info->smb_state == SMB_CLEARING_FLAGS_THEN_SET_IRQ)
5764 +                       start_enable_irq(smb_info);
5765 +               else
5766 +                       smb_info->smb_state = SMB_NORMAL;
5767 +               break;
5768 +       }
5769 +
5770 +       case SMB_GETTING_EVENTS:
5771 +       {
5772 +               smb_info->curr_msg->rsp_size
5773 +                       = smb_smbus_read_block_data(smb_info,
5774 +                                                   smb_info->curr_msg->rsp);
5775 +
5776 +               msg = smb_info->curr_msg;
5777 +               smb_info->curr_msg = NULL;
5778 +               if (msg->rsp_size < 0 || msg->rsp[2] != 0) {
5779 +                       /* Error getting event, probably done. */
5780 +                       msg->done(msg);
5781 +
5782 +                       /* Take off the event flag. */
5783 +                       smb_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
5784 +               } else {
5785 +                       deliver_recv_msg(smb_info, msg);
5786 +               }
5787 +               handle_flags(smb_info);
5788 +               break;
5789 +       }
5790 +
5791 +       case SMB_GETTING_MESSAGES:
5792 +       {
5793 +               smb_info->curr_msg->rsp_size
5794 +                       = smb_smbus_read_block_data(smb_info,
5795 +                                                     smb_info->curr_msg->rsp);
5796 +
5797 +               msg = smb_info->curr_msg;
5798 +               smb_info->curr_msg = NULL;
5799 +               if (msg->rsp_size < 0 || msg->rsp[2] != 0) {
5800 +                       /* Error getting event, probably done. */
5801 +                       msg->done(msg);
5802 +
5803 +                       /* Take off the msg flag. */
5804 +                       smb_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
5805 +               } else {
5806 +                       deliver_recv_msg(smb_info, msg);
5807 +               }
5808 +               handle_flags(smb_info);
5809 +               break;
5810 +       }
5811 +
5812 +       case SMB_ENABLE_INTERRUPTS1:
5813 +       {
5814 +               unsigned char msg[4];
5815 +
5816 +               /* We got the flags from the SMB, now handle them. */
5817 +               len = smb_smbus_read_block_data(smb_info, msg);
5818 +               if (len < 0 || msg[2] != 0) {
5819 +                       printk(KERN_WARNING
5820 +                              "ipmi_smb: Could not enable interrupts"
5821 +                              ", failed get, using polled mode.\n");
5822 +                       smb_info->smb_state = SMB_NORMAL;
5823 +               } else {
5824 +                       msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
5825 +                       msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
5826 +                       msg[2] = msg[3] | 1; /* enable msg queue int */
5827 +                       if (smb_smbus_write_block_data(
5828 +                           smb_info,3, msg) == 0) {
5829 +                               smb_info->smb_state = SMB_ENABLE_INTERRUPTS2;
5830 +                       } else
5831 +                               smb_info->smb_state = SMB_NORMAL;
5832 +               }
5833 +               break;
5834 +       }
5835 +
5836 +       case SMB_ENABLE_INTERRUPTS2:
5837 +       {
5838 +               unsigned char msg[4];
5839 +
5840 +               /* We got the flags from the SMB, now handle them. */
5841 +               len = smb_smbus_read_block_data(smb_info, msg);
5842 +               if (len < 0 || msg[2] != 0) {
5843 +                       printk(KERN_WARNING
5844 +                              "ipmi_smb: Could not enable interrupts"
5845 +                              ", failed set, using polled mode.\n");
5846 +               }
5847 +               smb_info->smb_state = SMB_NORMAL;
5848 +               break;
5849 +       }
5850 +       }
5851 +       if (smb_info->smb_debug & SMB_DEBUG_STATE) {
5852 +               printk(KERN_INFO "DONE 2: state = %d.\n", smb_info->smb_state);
5853 +       }
5854 +}
5855 +
5856 +/*
5857 + * smb_event_handler must have a user context for calls to lm_sensors'
5858 + * SMBus interface
5859 + */
5860 +static void smb_event_handler(struct smb_info *smb_info)
5861 +{
5862 +       s32 rv;
5863 +       if (smb_info->smb_debug & SMB_DEBUG_STATE) {
5864 +               printk(KERN_INFO "smb_event_handler: state = %d.\n",
5865 +                      smb_info->smb_state);
5866 +       }
5867 +       if (smb_info->smb_state == SMB_NORMAL) {
5868 +               if (smb_info->curr_msg != NULL)
5869 +               {
5870 +                       handle_transaction_done(smb_info);
5871 +               } else {
5872 +                       /* If we are currently idle, try to start the
5873 +                        * next message. */
5874 +                       send_next_msg(smb_info);
5875 +               }
5876 +       } else {
5877 +               handle_transaction_done(smb_info);
5878 +       }
5879 +
5880 +       if (smb_info->smb_state == SMB_NORMAL &&
5881 +           smb_info->curr_msg == NULL &&
5882 +            atomic_read(&smb_info->req_events))
5883 +       {
5884 +               /* We are idle and the upper layer requested that I fetch
5885 +                  events, so do so. */
5886 +               unsigned char msg[2];
5887 +
5888 +               atomic_set(&smb_info->req_events, 0);
5889 +               msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
5890 +               msg[1] = IPMI_GET_MSG_FLAGS_CMD;
5891 +
5892 +               rv = smb_smbus_write_block_data(smb_info, 2, msg);
5893 +               if(rv == 0) {
5894 +                       smb_info->smb_state = SMB_GETTING_FLAGS;
5895 +               }
5896 +       }
5897 +}
5898 +
5899 +#ifdef REGISTER_SMI
5900 +static void sender(void                *send_info,
5901 +                  struct ipmi_smi_msg *msg,
5902 +                  int                 priority)
5903 +{
5904 +       struct smb_info *smb_info = (struct smb_info *) send_info;
5905 +
5906 +#ifdef CONFIG_IPMI_PANIC_EVENT
5907 +       if (smb_info->run_to_completion) {
5908 +               /* If we are running to completion, then throw it in
5909 +                  the list and run transactions until everything is
5910 +                  clear.  Priority doesn't matter here. */
5911 +               list_add_tail(&(msg->link), &(smb_info->xmit_msgs));
5912 +
5913 +               smb_event_handler(smb_info);
5914 +               while  (! SMB_IDLE(smb_info)) {
5915 +                       smb_event_handler(smb_info);
5916 +               }
5917 +               return;
5918 +       }
5919 +#endif
5920 +       if (smb_info->smb_debug & SMB_DEBUG_TIMING) {
5921 +               struct timeval     t;
5922 +               do_gettimeofday(&t);
5923 +               printk(KERN_INFO
5924 +                      "**Enqueue %02x %02x: %ld.%9.9ld\n",
5925 +                      msg->data[0], msg->data[1], t.tv_sec, t.tv_usec);
5926 +       }
5927 +
5928 +       spin_lock(&(smb_info->msg_lock));
5929 +       if (priority > 0) {
5930 +               list_add_tail(&(msg->link), &(smb_info->hp_xmit_msgs));
5931 +       } else {
5932 +               list_add_tail(&(msg->link), &(smb_info->xmit_msgs));
5933 +       }
5934 +       spin_unlock(&(smb_info->msg_lock));
5935 +
5936 +#ifdef SMB_KTHREAD
5937 +       wake_up_interruptible(&smb_info->smb_thread.queue);
5938 +#endif
5939 +}
5940 +
5941 +static void request_events(void *send_info)
5942 +{
5943 +       struct smb_info *smb_info = (struct smb_info *) send_info;
5944 +
5945 +       atomic_set(&smb_info->req_events, 1);
5946 +#ifdef SMB_KTHREAD
5947 +       wake_up_interruptible(&smb_info->smb_thread.queue);
5948 +#endif
5949 +}
5950 +
5951 +static int new_user(void *send_info)
5952 +{
5953 +       if (!try_inc_mod_count(THIS_MODULE))
5954 +               return -EBUSY;
5955 +       return 0;
5956 +}
5957 +
5958 +static void user_left(void *send_info)
5959 +{
5960 +       MOD_DEC_USE_COUNT;
5961 +}
5962 +
5963 +static void set_run_to_completion(void *send_info, int i_run_to_completion)
5964 +{
5965 +       struct smb_info *smb_info = (struct smb_info *) send_info;
5966 +
5967 +       smb_info->run_to_completion = i_run_to_completion;
5968 +#ifdef CONFIG_IPMI_PANIC_EVENT
5969 +       /* Note that if this does not compile, there are some I2C
5970 +          changes that you need to handle this properly. */
5971 +       i2c_set_panic_thread(i_run_to_completion);
5972 +       if (i_run_to_completion) {
5973 +               smb_event_handler(smb_info);
5974 +               while  (! SMB_IDLE(smb_info)) {
5975 +                       smb_event_handler(smb_info);
5976 +               }
5977 +       }
5978 +#endif
5979 +}
5980 +
5981 +static struct ipmi_smi_handlers handlers =
5982 +{
5983 +       sender:                sender,
5984 +       request_events:        request_events,
5985 +       new_user:              new_user,
5986 +       user_left:             user_left,
5987 +       set_run_to_completion: set_run_to_completion
5988 +};
5989 +#endif /* REGISTER_SMI */
5990 +
5991 +#ifdef SMB_KTHREAD
5992 +/* initialize new created thread. Called by the new thread. */
5993 +static void init_kthread(kthread_t *kthread, char *name)
5994 +{
5995 +        /* lock the kernel. A new kernel thread starts without
5996 +           the big kernel lock, regardless of the lock state
5997 +           of the creator (the lock level is *not* inheritated)
5998 +        */
5999 +        lock_kernel();
6000 +
6001 +        /* fill in thread structure */
6002 +        kthread->thread = current;
6003 +
6004 +        /* set signal mask to what we want to respond */
6005 +        siginitsetinv(&current->blocked,
6006 +                     sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM));
6007 +
6008 +        /* initialise wait queue */
6009 +        init_waitqueue_head(&kthread->queue);
6010 +
6011 +        /* initialise termination flag */
6012 +        kthread->terminate = 0;
6013 +
6014 +        /* set name of this process (max 15 chars + 0 !) */
6015 +        sprintf(current->comm, name);
6016 +
6017 +        /* let others run */
6018 +        unlock_kernel();
6019 +
6020 +        /* tell the creator that we are ready and let him continue */
6021 +        up(&kthread->startstop_sem);
6022 +
6023 +}
6024 +
6025 +/* cleanup of thread. Called by the exiting thread. */
6026 +static void exit_kthread(kthread_t *kthread)
6027 +{
6028 +        /* we are terminating */
6029 +
6030 +       /* lock the kernel, the exit will unlock it */
6031 +        lock_kernel();
6032 +        kthread->thread = NULL;
6033 +        mb();
6034 +
6035 +        /* notify the stop_kthread() routine that we are terminating. */
6036 +       up(&kthread->startstop_sem);
6037 +       /* the kernel_thread that called clone() does a do_exit here. */
6038 +
6039 +       /* there is no race here between execution of the "killer" and
6040 +          real termination of the thread (race window between up and
6041 +          do_exit), since both the thread and the "killer" function
6042 +          are running with the kernel lock held.  The kernel lock
6043 +          will be freed after the thread exited, so the code is
6044 +          really not executed anymore as soon as the unload functions
6045 +          gets the kernel lock back.  The init process may not have
6046 +          made the cleanup of the process here, but the cleanup can
6047 +          be done safely with the module unloaded.
6048 +       */
6049 +
6050 +}
6051 +
6052 +/* this is the thread function for making SMBus function calls into
6053 + * the lm_sensors' i2c-core module */
6054 +static void smb_thread(struct smb_info *smb_info)
6055 +{
6056 +        kthread_t *kthread = &smb_info->smb_thread;
6057 +       /* setup the thread environment */
6058 +        init_kthread(kthread, "IPMI SMBus thread");
6059 +
6060 +        /* an endless loop in which we are doing our work */
6061 +        for(;;)
6062 +        {
6063 +               smb_event_handler(smb_info);
6064 +               while  (! SMB_IDLE(smb_info)) {
6065 +                       smb_event_handler(smb_info);
6066 +               }
6067 +
6068 +                interruptible_sleep_on(&kthread->queue);
6069 +
6070 +                /* We need to do a memory barrier here to be sure that
6071 +                   the flags are visible on all CPUs.
6072 +                */
6073 +                 mb();
6074 +
6075 +                /* here we are back from sleep, either due to the timeout
6076 +                   (one second), or because we caught a signal.
6077 +                */
6078 +                if (kthread->terminate)
6079 +                {
6080 +                        /* we received a request to terminate ourself */
6081 +                        break;
6082 +                }
6083 +         }
6084 +        /* cleanup the thread, leave */
6085 +        exit_kthread(kthread);
6086 +
6087 +       /* returning from the thread here calls the exit functions */
6088 +}
6089 +
6090 +static void kthread_launcher(void *data)
6091 +{
6092 +        kernel_thread((int (*)(void *))smb_thread, data, 0);
6093 +}
6094 +
6095 +/* create a new kernel thread. Called by the creator. */
6096 +static void start_kthread(struct smb_info *smb_info)
6097 +{
6098 +       kthread_t *kthread = &smb_info->smb_thread;
6099 +        /* initialize the semaphore:
6100 +           we start with the semaphore locked. The new kernel
6101 +           thread will setup its stuff and unlock it. This
6102 +           control flow (the one that creates the thread) blocks
6103 +           in the down operation below until the thread has reached
6104 +           the up() operation.
6105 +         */
6106 +        init_MUTEX_LOCKED(&kthread->startstop_sem);
6107 +
6108 +        /* create the new thread my running a task through keventd */
6109 +
6110 +        /* initialize the task queue structure */
6111 +        kthread->tq.sync = 0;
6112 +        INIT_LIST_HEAD(&kthread->tq.list);
6113 +        kthread->tq.routine =  kthread_launcher;
6114 +        kthread->tq.data = smb_info;
6115 +
6116 +        /* and schedule it for execution */
6117 +        schedule_task(&kthread->tq);
6118 +
6119 +        /* wait till it has reached the setup_thread routine */
6120 +        down(&kthread->startstop_sem);
6121 +               
6122 +}
6123 +
6124 +/* stop a kernel thread. Called by the removing instance */
6125 +static void stop_kthread(kthread_t *kthread)
6126 +{
6127 +        if (kthread->thread == NULL)
6128 +        {
6129 +                printk(KERN_WARNING
6130 +                      "stop_kthread: killing non existing thread!\n");
6131 +                return;
6132 +        }
6133 +
6134 +        /* this function needs to be protected with the big
6135 +          kernel lock (lock_kernel()). The lock must be
6136 +           grabbed before changing the terminate
6137 +          flag and released after the down() call. */
6138 +        lock_kernel();
6139 +        
6140 +        /* initialize the semaphore. We lock it here, the
6141 +           leave_thread call of the thread to be terminated
6142 +           will unlock it. As soon as we see the semaphore
6143 +           unlocked, we know that the thread has exited.
6144 +       */
6145 +        init_MUTEX_LOCKED(&kthread->startstop_sem);
6146 +
6147 +        /* We need to do a memory barrier here to be sure that
6148 +           the flags are visible on all CPUs. 
6149 +        */
6150 +        mb();
6151 +
6152 +        /* set flag to request thread termination */
6153 +        kthread->terminate = 1;
6154 +       wake_up_interruptible(&kthread->queue);
6155 +
6156 +        /* We need to do a memory barrier here to be sure that
6157 +           the flags are visible on all CPUs. 
6158 +        */
6159 +        mb();
6160 +        kill_proc(kthread->thread->pid, SIGKILL, 1);
6161 +       
6162 +        /* block till thread terminated */
6163 +        down(&kthread->startstop_sem);
6164 +
6165 +        /* release the big kernel lock */
6166 +        unlock_kernel();
6167 +
6168 +        /* now we are sure the thread is in zombie state. We
6169 +           notify keventd to clean the process up.
6170 +        */
6171 +        kill_proc(2, SIGCHLD, 1);
6172 +
6173 +}
6174 +#endif
6175 +
6176 +static int ipmi_smb_detect_hardware(struct i2c_client *client, int debug,
6177 +                                   struct smb_info **smb_info)
6178 +{
6179 +       unsigned char   msg[2];
6180 +       unsigned char   resp[IPMI_MAX_MSG_LENGTH];
6181 +       unsigned long   resp_len;
6182 +       s32             ret;
6183 +       struct smb_info *info;
6184 +
6185 +       /* Do a Get Device ID command, since it comes back with some
6186 +          useful info. */
6187 +       msg[0] = IPMI_NETFN_APP_REQUEST << 2;
6188 +       msg[1] = IPMI_GET_DEVICE_ID_CMD;
6189 +       
6190 +       ret = smbus_client_write_block_data(client, debug, 2, msg);
6191 +       if (ret)
6192 +               return -ENODEV;
6193 +
6194 +       /* Otherwise, we got some data. */
6195 +       resp_len = smbus_client_read_block_data(client, debug, resp);
6196 +       if (resp_len < 6)
6197 +               /* That's odd, it should be longer. */
6198 +               return -EINVAL;
6199 +       
6200 +       if ((resp[1] != IPMI_GET_DEVICE_ID_CMD) || (resp[2] != 0))
6201 +               /* That's odd, it shouldn't be able to fail. */
6202 +               return -EINVAL;
6203 +
6204 +       info = kmalloc(sizeof(*info), GFP_KERNEL);
6205 +       if (!info)
6206 +               return -ENOMEM;
6207 +       memset(info, 0, sizeof(*info));
6208 +
6209 +       info->ipmi_smb_dev_rev = resp[4] & 0xf;
6210 +       info->ipmi_smb_fw_rev_major = resp[5] & 0x7f;
6211 +       info->ipmi_smb_fw_rev_minor = resp[6];
6212 +       info->ipmi_version_major = resp[7] & 0xf;
6213 +       info->ipmi_version_minor = resp[7] >> 4;
6214 +       info->client = *client;
6215 +       info->client.data = info;
6216 +
6217 +       *smb_info = info;
6218 +
6219 +       return 0;
6220 +}
6221 +
6222 +#define MAX_SMB_BMCS 4
6223 +
6224 +/* An array of SMB interfaces. */
6225 +static struct smb_info *smb_infos[MAX_SMB_BMCS];
6226 +
6227 +/*
6228 + * An array of pairs of numbers to specify where specific BMCs exist.
6229 + * Each pair specifies the adapter number and address on the adapter.
6230 + * A BMC will be forced at that position.
6231 + *
6232 + * Always provide the i2c address if it is known.
6233 + */
6234 +static unsigned short __initdata smb_addr[MAX_SMB_BMCS*2 + 2];
6235 +MODULE_PARM(smb_addr, "1-"__MODULE_STRING(MAX_SMB_BMCS*2)"h");
6236 +
6237 +/*
6238 + * If this is sent, don't probe for adapters anywhere but where the
6239 + * smb_addr array gives.
6240 + */
6241 +static int smb_defaultprobe = 1;
6242 +MODULE_PARM(smb_defaultprobe, "i");
6243 +
6244 +/*
6245 + * Turn debugging on for specific BMCs.  This array is indexed by
6246 + * BMC number.
6247 + *
6248 + * Debug bit flags: IPMI messages: 1, driver state: 2, timing: 4, I2C probe: 8
6249 + */
6250 +static int smb_dbg[MAX_SMB_BMCS];
6251 +MODULE_PARM(smb_dbg, "1-"__MODULE_STRING(MAX_SMB_BMCS)"i");
6252 +
6253 +/*
6254 + * Debug the probing of adapters.
6255 + */
6256 +static int smb_dbg_probe = 0;
6257 +MODULE_PARM(smb_dbg_probe, "i");
6258 +
6259 +#define SMB_I2C_START_ADDR     0x20
6260 +#define SMB_I2C_END_ADDR       0x4f
6261 +static unsigned short normal_i2c[] = { I2C_CLIENT_END, I2C_CLIENT_END };
6262 +static unsigned short normal_i2c_range[] = { SMB_I2C_START_ADDR, 
6263 +                                            SMB_I2C_END_ADDR,
6264 +                                            I2C_CLIENT_END };
6265 +/*
6266 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
6267 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
6268 +*/
6269 +static unsigned short reserved[] =
6270 +{
6271 +/* As defined by SMBus Spec. Appendix C */
6272 +       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x28,
6273 +       0x37,
6274 +/* As defined by SMBus Spec. Sect. 5.2 */
6275 +       0x01, 0x02, 0x03, 0x04, 0x05,
6276 +       0x06, 0x07, 0x78, 0x79, 0x7a, 0x7b,
6277 +       0x7c, 0x7d, 0x7e, 0x7f,
6278 +/* Common PC addresses (bad idea) */
6279 +       0x2d, 0x48, 0x49, /* sensors */
6280 +       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* eeproms */
6281 +       0x69, /* clock chips */
6282 +
6283 +       I2C_CLIENT_END
6284 +};
6285 +
6286 +static unsigned short smb_empty_list[] = { I2C_CLIENT_END, I2C_CLIENT_END };
6287 +
6288 +static struct i2c_client_address_data smb_address_data = {
6289 +       .normal_i2c             = normal_i2c,
6290 +       .normal_i2c_range       = normal_i2c_range,
6291 +       .probe                  = smb_empty_list,
6292 +       .probe_range            = smb_empty_list,
6293 +       .ignore                 = reserved,
6294 +       .ignore_range           = smb_empty_list,
6295 +       .force                  = smb_addr,
6296 +};
6297 +
6298 +static unsigned int pos_reserved_as(int pos)
6299 +{
6300 +       if (smb_addr[pos*2+1] != 0)
6301 +               return (smb_addr[pos*2] << 16) | smb_addr[pos*2+1];
6302 +
6303 +       return 0;
6304 +}
6305 +
6306 +static int smb_found_addr_proc(struct i2c_adapter *adapter, int addr,
6307 +                              unsigned short flags, int kind)
6308 +{
6309 +       int id = i2c_adapter_id(adapter);
6310 +       int debug = smb_dbg[id];
6311 +       int rv;
6312 +       int i;
6313 +       int next_pos;
6314 +       struct i2c_client client;
6315 +       struct smb_info *smb_info;
6316 +
6317 +       memset(&client, 0, sizeof(&client));
6318 +       strcpy(client.name, "IPMI");
6319 +       client.addr = addr;
6320 +       client.adapter = adapter;
6321 +       
6322 +       rv = ipmi_smb_detect_hardware(&client, debug, &smb_info);
6323 +       if (rv) {
6324 +               if (smb_dbg_probe) {
6325 +                       printk(KERN_INFO
6326 +                              "smb_found_addr_proc:No IPMI client 0x%x: %d\n",
6327 +                              addr, rv);
6328 +               }
6329 +               return 0;
6330 +       }
6331 +
6332 +       if (smb_dbg_probe) {
6333 +               printk(KERN_INFO
6334 +                      "smb_found_addr_proc: i2c_probe found device at"
6335 +                      " i2c address %x\n", addr);
6336 +       }
6337 +
6338 +       spin_lock_init(&(smb_info->msg_lock));
6339 +       INIT_LIST_HEAD(&(smb_info->xmit_msgs));
6340 +       INIT_LIST_HEAD(&(smb_info->hp_xmit_msgs));
6341 +       smb_info->curr_msg = NULL;
6342 +       atomic_set(&smb_info->req_events, 0);
6343 +       smb_info->run_to_completion = 0;
6344 +       smb_info->smb_state = SMB_NORMAL;
6345 +
6346 +       next_pos = -1;
6347 +       for (i=0; i < MAX_SMB_BMCS; i++) {
6348 +               unsigned int res = pos_reserved_as(i);
6349 +
6350 +               if (res == ((id << 16) | addr)) {
6351 +                       /* We have a reserved position, use it. */
6352 +                       next_pos = i;
6353 +                       break;
6354 +               }
6355 +
6356 +               /* Claim the first unused position */
6357 +               if (!res && (next_pos == -1) && (smb_infos[next_pos] == NULL))
6358 +                       next_pos = i;
6359 +       }
6360 +       if (next_pos == -1) {
6361 +               rv = -EBUSY;
6362 +               goto out_err;
6363 +       }
6364 +
6365 +#ifdef REGISTER_SMI
6366 +       rv = ipmi_register_smi(&handlers,
6367 +                              smb_info,
6368 +                              smb_info->ipmi_version_major,
6369 +                              smb_info->ipmi_version_minor,
6370 +                              &(smb_info->intf));
6371 +       if (rv) {
6372 +               printk(KERN_ERR
6373 +                      "ipmi_smb: Unable to register device: error %d\n",
6374 +                      rv);
6375 +               goto out_err;
6376 +       }
6377 +#endif
6378 +
6379 +       rv = i2c_attach_client(&smb_info->client);
6380 +       if (rv) {
6381 +               printk(KERN_ERR
6382 +                      "smb_found_one_addr_proc:"
6383 +                      " Unable to attach i2c client: error %d\n",
6384 +                      rv);
6385 +#ifdef REGISTER_SMI
6386 +               ipmi_unregister_smi(smb_info->intf);
6387 +#endif
6388 +               goto out_err;
6389 +       }
6390 +
6391 +       smb_info->pos = next_pos;
6392 +       smb_infos[next_pos] = smb_info;
6393 +
6394 +#ifdef SMB_KTHREAD
6395 +       start_kthread(smb_info);
6396 +#endif
6397 +
6398 +       start_clear_flags(smb_info);
6399 +       smb_event_handler(smb_info);
6400 +
6401 +       return addr;
6402 +
6403 + out_err:
6404 +       kfree(smb_info);
6405 +       return 0;
6406 +}
6407 +
6408 +static int attach_adapter(struct i2c_adapter *adapter)
6409 +{
6410 +       int id = i2c_adapter_id(adapter);
6411 +
6412 +       if (smb_dbg_probe) {
6413 +               printk(KERN_INFO "init_one_smb: Checking SMBus adapter %d:"
6414 +                      " %s\n", id, adapter->name);
6415 +       }
6416 +       if ((i2c_get_functionality(adapter) & (I2C_FUNC_SMBUS_BLOCK_DATA))
6417 +           == (I2C_FUNC_SMBUS_BLOCK_DATA))
6418 +       {
6419 +               if (smb_dbg_probe) {
6420 +                       printk(KERN_INFO "init_one_smb: found SMBus adapter:"
6421 +                              " %s\n", adapter->name);
6422 +               }
6423 +               i2c_probe(adapter, &smb_address_data, smb_found_addr_proc);
6424 +       }
6425 +
6426 +       return 0;
6427 +}
6428 +
6429 +void cleanup_one_smb(struct smb_info *to_clean)
6430 +{
6431 +       int rv;
6432 +
6433 +       if (! to_clean)
6434 +               return;
6435 +
6436 +#ifdef SMB_KTHREAD
6437 +       stop_kthread(&to_clean->smb_thread);
6438 +#endif
6439 +
6440 +#ifdef REGISTER_SMI
6441 +       rv = ipmi_unregister_smi(to_clean->intf);
6442 +       if (rv) {
6443 +               printk(KERN_ERR 
6444 +                      "ipmi_smb: Unable to unregister device: errno=%d\n",
6445 +                      rv);
6446 +       }
6447 +#endif
6448 +
6449 +       rv = i2c_detach_client(&to_clean->client);
6450 +       if (rv) {
6451 +               printk(KERN_ERR 
6452 +                      "ipmi_smb: Unable to detach SMBUS client: errno=%d\n",
6453 +                      rv);
6454 +       }
6455 +
6456 +       smb_infos[to_clean->pos] = NULL;
6457 +       kfree(to_clean);
6458 +}
6459 +
6460 +static int detach_client(struct i2c_client *client)
6461 +{
6462 +       struct smb_info *smb_info = client->data;
6463 +
6464 +       cleanup_one_smb(smb_info);
6465 +}
6466 +
6467 +static struct i2c_driver smb_i2c_driver =
6468 +{
6469 +       
6470 +       .name = "IPMI",
6471 +       .flags = I2C_DF_NOTIFY,
6472 +       .attach_adapter = attach_adapter,
6473 +       .detach_client = detach_client,
6474 +       .command = NULL,
6475 +
6476 +};
6477 +
6478 +static __init int init_ipmi_smb(void)
6479 +{
6480 +       int i;
6481 +       int rv;
6482 +
6483 +       if (initialized)
6484 +               return 0;
6485 +
6486 +       printk(KERN_INFO "IPMI SMB Interface driver version "
6487 +              IPMI_SMB_VERSION "\n");
6488 +
6489 +       /* Make sure the smb_addr array is terminated. */
6490 +       for (i=0; i<MAX_SMB_BMCS*2; i+=2) {
6491 +               if (smb_addr[i+1] == 0)
6492 +                       break;
6493 +       }
6494 +       smb_addr[i] = I2C_CLIENT_END;
6495 +       smb_addr[i+2] = I2C_CLIENT_END;
6496 +
6497 +       /* If the default probing is turned off, then disable the
6498 +        * range scanning. */
6499 +       if (!smb_defaultprobe)
6500 +               normal_i2c_range[0] = I2C_CLIENT_END;
6501 +
6502 +       rv = i2c_add_driver(&smb_i2c_driver);
6503 +       if (!rv)
6504 +               initialized = 1;
6505 +
6506 +       return rv;
6507 +}
6508 +module_init(init_ipmi_smb);
6509 +
6510 +#ifdef MODULE
6511 +static __exit void cleanup_ipmi_smb(void)
6512 +{
6513 +       int i;
6514 +
6515 +       if (!initialized)
6516 +               return;
6517 +
6518 +       for (i=0; i<MAX_SMB_BMCS; i++) {
6519 +               cleanup_one_smb(smb_infos[i]);
6520 +       }
6521 +
6522 +       initialized = 0;
6523 +}
6524 +module_exit(cleanup_ipmi_smb);
6525 +#else
6526 +
6527 +/* [<adapter>.]addr[:debug]  Force a BMC at the given address on the
6528 +                       given adapter (or adapter 0 if not given).  If
6529 +                       the debug portion is given, this this is the
6530 +                       debug bits as explained in the definition of
6531 +                       smb_dbg above.
6532 +   nodefaults          Suppress trying the default address range
6533 +   debug_probe         Debug probing of adapters
6534 +
6535 +   For example, to pass one IO port with an IRQ, one address, and
6536 +   suppress the use of the default IO port and ACPI address,
6537 +   use this option string: ipmi_kcs=p0xCA2:5,m0xFF5B0022,nodefaults
6538 +
6539 +   Remember, ipmi_smb_setup() is passed the string after the equal sign. */
6540 +
6541 +static int __init ipmi_smb_setup(char *str)
6542 +{
6543 +       unsigned long val;
6544 +       char *cur, *sep;
6545 +       int pos;
6546 +
6547 +       pos = 0;
6548 +
6549 +       cur = strsep(&str, ",");
6550 +       while ((cur) && (*cur) && (pos < MAX_SMB_BMCS)) {
6551 +               if (strcmp(cur, "nodefaults") == 0) {
6552 +                       smb_defaultprobe = 0;
6553 +                       continue;
6554 +               }
6555 +               if (strcmp(cur, "debug_probe") == 0) {
6556 +                       smb_dbg_probe = 1;
6557 +                       continue;
6558 +               }
6559 +               val = simple_strtoul(cur,
6560 +                                    &sep,
6561 +                                    0);
6562 +               if (*sep == '.') {
6563 +                       smb_addr[pos*2] = val;
6564 +                       val = simple_strtoul(sep + 1,
6565 +                                            &sep,
6566 +                                            0);
6567 +               } else
6568 +                       smb_addr[pos*2] = 0;
6569 +
6570 +               smb_addr[pos*2+1] = val;
6571 +
6572 +               if (*sep == ':') {
6573 +                       val = simple_strtoul(sep + 1,
6574 +                                            &sep,
6575 +                                            0);
6576 +                       smb_dbg[pos] = val;
6577 +               }
6578 +               pos++;
6579 +               cur = strsep(&str, ",");
6580 +       }
6581 +       return 1;
6582 +}
6583 +__setup("ipmi_smb=", ipmi_smb_setup);
6584 +#endif
6585 +
6586 +MODULE_AUTHOR("Todd C Davis <todd.c.davis@intel.com>");
6587 +MODULE_DESCRIPTION("IPMI system interface driver for management controllers on a SMBus");
6588 +MODULE_LICENSE("GPL");
6589 diff -urN linux-2.4.23.org/drivers/char/ipmi/ipmi_smic_sm.c linux-2.4.23/drivers/char/ipmi/ipmi_smic_sm.c
6590 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_smic_sm.c   1970-01-01 01:00:00.000000000 +0100
6591 +++ linux-2.4.23/drivers/char/ipmi/ipmi_smic_sm.c       2004-01-02 23:33:48.066806656 +0100
6592 @@ -0,0 +1,601 @@
6593 +/*
6594 + * ipmi_smic_sm.c
6595 + *
6596 + * The state-machine driver for an IPMI SMIC driver
6597 + *
6598 + * It started as a copy of Corey Minyard's driver for the KSC interface
6599 + * and the kernel patch "mmcdev-patch-245" by HP
6600 + *
6601 + * modified by:        Hannes Schulz <schulz@schwaar.com>
6602 + *             ipmi@schwaar.com
6603 + *
6604 + *
6605 + * Corey Minyard's driver for the KSC interface has the following
6606 + * copyright notice:
6607 + *   Copyright 2002 MontaVista Software Inc.
6608 + *
6609 + * the kernel patch "mmcdev-patch-245" by HP has the following
6610 + * copyright notice:
6611 + * (c) Copyright 2001 Grant Grundler (c) Copyright
6612 + * 2001 Hewlett-Packard Company
6613 + * 
6614 + *
6615 + *  This program is free software; you can redistribute it and/or modify it
6616 + *  under the terms of the GNU General Public License as published by the
6617 + *  Free Software Foundation; either version 2 of the License, or (at your
6618 + *  option) any later version.
6619 + *
6620 + *
6621 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
6622 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
6623 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
6624 + *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
6625 + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
6626 + *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
6627 + *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
6628 + *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
6629 + *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
6630 + *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6631 + *
6632 + *  You should have received a copy of the GNU General Public License along
6633 + *  with this program; if not, write to the Free Software Foundation, Inc.,
6634 + *  675 Mass Ave, Cambridge, MA 02139, USA.  */
6635 +
6636 +#include <linux/kernel.h> /* For printk. */
6637 +#include <linux/string.h>
6638 +#include "ipmi_si_sm.h"
6639 +
6640 +#define IPMI_SMIC_VERSION "v28"
6641 +
6642 +/* smic_debug is a bit-field 
6643 + *     SMIC_DEBUG_ENABLE -     turned on for now 
6644 + *     SMIC_DEBUG_MSG -        commands and their responses
6645 + *     SMIC_DEBUG_STATES -     state machine
6646 +*/
6647 +#define SMIC_DEBUG_STATES      4
6648 +#define SMIC_DEBUG_MSG         2
6649 +#define        SMIC_DEBUG_ENABLE       1
6650 +
6651 +static int smic_debug = 1;
6652 +
6653 +enum smic_states {
6654 +       SMIC_IDLE,
6655 +       SMIC_START_OP,
6656 +       SMIC_OP_OK,
6657 +       SMIC_WRITE_START,
6658 +       SMIC_WRITE_NEXT,
6659 +       SMIC_WRITE_END,
6660 +       SMIC_WRITE2READ,
6661 +       SMIC_READ_START,
6662 +       SMIC_READ_NEXT,
6663 +       SMIC_READ_END,
6664 +       SMIC_HOSED
6665 +};
6666 +
6667 +#define MAX_SMIC_READ_SIZE 80
6668 +#define MAX_SMIC_WRITE_SIZE 80
6669 +#define SMIC_MAX_ERROR_RETRIES 3
6670 +
6671 +/* Timeouts in microseconds. */
6672 +#define SMIC_RETRY_TIMEOUT 100000
6673 +#define IPMI_ERR_MSG_TRUNCATED 0xc6
6674 +#define IPMI_ERR_UNSPECIFIED   0xff
6675 +
6676 +
6677 +/* SMIC Flags Register Bits */
6678 +#define SMIC_RX_DATA_READY     0x80
6679 +#define SMIC_TX_DATA_READY     0x40
6680 +#define SMIC_SMI               0x10
6681 +#define SMIC_EVM_DATA_AVAIL    0x08
6682 +#define SMIC_SMS_DATA_AVAIL    0x04
6683 +#define SMIC_FLAG_BSY          0x01
6684 +
6685 +/* SMIC Error Codes */
6686 +#define        EC_NO_ERROR             0x00
6687 +#define        EC_ABORTED              0x01
6688 +#define        EC_ILLEGAL_CONTROL      0x02
6689 +#define        EC_NO_RESPONSE          0x03
6690 +#define        EC_ILLEGAL_COMMAND      0x04
6691 +#define        EC_BUFFER_FULL          0x05
6692 +
6693 +struct si_sm_data
6694 +{
6695 +       enum smic_states state;
6696 +       struct si_sm_io *io;
6697 +        unsigned char   write_data[MAX_SMIC_WRITE_SIZE];
6698 +        int             write_pos;
6699 +        int             write_count;
6700 +        int             orig_write_count;
6701 +        unsigned char   read_data[MAX_SMIC_READ_SIZE];
6702 +        int             read_pos;
6703 +        int             truncated;
6704 +        unsigned int    error_retries;
6705 +        long            smic_timeout;
6706 +};
6707 +
6708 +static unsigned int init_smic_data (struct si_sm_data *smic,
6709 +                                   struct si_sm_io *io)
6710 +{
6711 +       smic->state = SMIC_IDLE;
6712 +       smic->io = io;
6713 +       smic->write_pos = 0;
6714 +       smic->write_count = 0;
6715 +       smic->orig_write_count = 0;
6716 +       smic->read_pos = 0;
6717 +       smic->error_retries = 0;
6718 +       smic->truncated = 0;
6719 +       smic->smic_timeout = SMIC_RETRY_TIMEOUT;
6720 +
6721 +       /* We use 3 bytes of I/O. */
6722 +       return 3;
6723 +}
6724 +
6725 +static int start_smic_transaction(struct si_sm_data *smic,
6726 +                                 unsigned char *data, unsigned int size)
6727 +{
6728 +       unsigned int i;
6729 +
6730 +       if ((size < 2) || (size > MAX_SMIC_WRITE_SIZE)) {
6731 +               return -1;
6732 +       }
6733 +       if ((smic->state != SMIC_IDLE) && (smic->state != SMIC_HOSED)) {
6734 +               return -2;
6735 +       }
6736 +       if (smic_debug & SMIC_DEBUG_MSG) {
6737 +               printk(KERN_INFO "start_smic_transaction -");
6738 +               for (i = 0; i < size; i ++) {
6739 +                       printk (" %02x", (unsigned char) (data [i]));
6740 +               }
6741 +               printk ("\n");
6742 +       }
6743 +       smic->error_retries = 0;
6744 +       memcpy(smic->write_data, data, size);
6745 +       smic->write_count = size;
6746 +       smic->orig_write_count = size;
6747 +       smic->write_pos = 0;
6748 +       smic->read_pos = 0;
6749 +       smic->state = SMIC_START_OP;
6750 +       smic->smic_timeout = SMIC_RETRY_TIMEOUT;
6751 +       return 0;
6752 +}
6753 +
6754 +static int smic_get_result(struct si_sm_data *smic,
6755 +                          unsigned char *data, unsigned int length)
6756 +{
6757 +       int i;
6758 +
6759 +       if (smic_debug & SMIC_DEBUG_MSG) {
6760 +               printk (KERN_INFO "smic_get result -");
6761 +               for (i = 0; i < smic->read_pos; i ++) {
6762 +                       printk (" %02x", (smic->read_data [i]));
6763 +               }
6764 +               printk ("\n");
6765 +       }
6766 +       if (length < smic->read_pos) {
6767 +               smic->read_pos = length;
6768 +               smic->truncated = 1;
6769 +       }
6770 +       memcpy(data, smic->read_data, smic->read_pos);
6771 +
6772 +       if ((length >= 3) && (smic->read_pos < 3)) {
6773 +               data[2] = IPMI_ERR_UNSPECIFIED;
6774 +               smic->read_pos = 3;
6775 +       }
6776 +       if (smic->truncated) {
6777 +               data[2] = IPMI_ERR_MSG_TRUNCATED;
6778 +               smic->truncated = 0;
6779 +       }
6780 +       return smic->read_pos;
6781 +}
6782 +
6783 +static inline unsigned char read_smic_flags(struct si_sm_data *smic)
6784 +{
6785 +       return smic->io->inputb(smic->io, 2);
6786 +}
6787 +
6788 +static inline unsigned char read_smic_status(struct si_sm_data *smic)
6789 +{
6790 +       return smic->io->inputb(smic->io, 1);
6791 +}
6792 +
6793 +static inline unsigned char read_smic_data(struct si_sm_data *smic)
6794 +{
6795 +       return smic->io->inputb(smic->io, 0);
6796 +}
6797 +
6798 +static inline void write_smic_flags(struct si_sm_data *smic,
6799 +                                   unsigned char   flags)
6800 +{
6801 +       smic->io->outputb(smic->io, 2, flags);
6802 +}
6803 +
6804 +static inline void write_smic_control(struct si_sm_data *smic,
6805 +                                     unsigned char   control)
6806 +{
6807 +       smic->io->outputb(smic->io, 1, control);
6808 +}
6809 +
6810 +static inline void write_si_sm_data (struct si_sm_data *smic,
6811 +                                  unsigned char   data)
6812 +{
6813 +       smic->io->outputb(smic->io, 0, data);
6814 +}
6815 +
6816 +static inline void start_error_recovery(struct si_sm_data *smic, char *reason)
6817 +{
6818 +       (smic->error_retries)++;
6819 +       if (smic->error_retries > SMIC_MAX_ERROR_RETRIES) {
6820 +               if (smic_debug & SMIC_DEBUG_ENABLE) {
6821 +                       printk(KERN_WARNING
6822 +                              "ipmi_smic_drv: smic hosed: %s\n", reason);
6823 +               }       
6824 +               smic->state = SMIC_HOSED;
6825 +       } else {
6826 +               smic->write_count = smic->orig_write_count;
6827 +               smic->write_pos = 0;
6828 +               smic->read_pos = 0;
6829 +               smic->state = SMIC_START_OP;
6830 +               smic->smic_timeout = SMIC_RETRY_TIMEOUT;
6831 +       }
6832 +}
6833 +
6834 +static inline void write_next_byte(struct si_sm_data *smic)
6835 +{
6836 +       write_si_sm_data(smic, smic->write_data[smic->write_pos]);
6837 +       (smic->write_pos)++;
6838 +       (smic->write_count)--;
6839 +}
6840 +
6841 +static inline void read_next_byte (struct si_sm_data *smic)
6842 +{
6843 +       if (smic->read_pos >= MAX_SMIC_READ_SIZE) {
6844 +               read_smic_data (smic);
6845 +               smic->truncated = 1;
6846 +       } else {
6847 +               smic->read_data[smic->read_pos] = read_smic_data(smic); 
6848 +               (smic->read_pos)++;
6849 +       }
6850 +}
6851 +
6852 +/*  SMIC Control/Status Code Components */
6853 +#define        SMIC_GET_STATUS         0x00    /* Control form's name */
6854 +#define        SMIC_READY              0x00    /* Status  form's name */
6855 +#define        SMIC_WR_START           0x01    /* Unified Control/Status names... */
6856 +#define        SMIC_WR_NEXT            0x02
6857 +#define        SMIC_WR_END             0x03
6858 +#define        SMIC_RD_START           0x04
6859 +#define        SMIC_RD_NEXT            0x05
6860 +#define        SMIC_RD_END             0x06
6861 +#define        SMIC_CODE_MASK          0x0f
6862 +
6863 +#define        SMIC_CONTROL            0x00
6864 +#define        SMIC_STATUS             0x80
6865 +#define        SMIC_CS_MASK            0x80
6866 +
6867 +#define        SMIC_SMS                0x40
6868 +#define        SMIC_SMM                0x60
6869 +#define        SMIC_STREAM_MASK        0x60
6870 +
6871 +/*  SMIC Control Codes */
6872 +#define        SMIC_CC_SMS_GET_STATUS  (SMIC_CONTROL|SMIC_SMS|SMIC_GET_STATUS)
6873 +#define        SMIC_CC_SMS_WR_START    (SMIC_CONTROL|SMIC_SMS|SMIC_WR_START)
6874 +#define        SMIC_CC_SMS_WR_NEXT     (SMIC_CONTROL|SMIC_SMS|SMIC_WR_NEXT)
6875 +#define        SMIC_CC_SMS_WR_END      (SMIC_CONTROL|SMIC_SMS|SMIC_WR_END)
6876 +#define        SMIC_CC_SMS_RD_START    (SMIC_CONTROL|SMIC_SMS|SMIC_RD_START)
6877 +#define        SMIC_CC_SMS_RD_NEXT     (SMIC_CONTROL|SMIC_SMS|SMIC_RD_NEXT)
6878 +#define        SMIC_CC_SMS_RD_END      (SMIC_CONTROL|SMIC_SMS|SMIC_RD_END)
6879 +
6880 +#define        SMIC_CC_SMM_GET_STATUS  (SMIC_CONTROL|SMIC_SMM|SMIC_GET_STATUS)
6881 +#define        SMIC_CC_SMM_WR_START    (SMIC_CONTROL|SMIC_SMM|SMIC_WR_START)
6882 +#define        SMIC_CC_SMM_WR_NEXT     (SMIC_CONTROL|SMIC_SMM|SMIC_WR_NEXT)
6883 +#define        SMIC_CC_SMM_WR_END      (SMIC_CONTROL|SMIC_SMM|SMIC_WR_END)
6884 +#define        SMIC_CC_SMM_RD_START    (SMIC_CONTROL|SMIC_SMM|SMIC_RD_START)
6885 +#define        SMIC_CC_SMM_RD_NEXT     (SMIC_CONTROL|SMIC_SMM|SMIC_RD_NEXT)
6886 +#define        SMIC_CC_SMM_RD_END      (SMIC_CONTROL|SMIC_SMM|SMIC_RD_END)
6887 +
6888 +/*  SMIC Status Codes */
6889 +#define        SMIC_SC_SMS_READY       (SMIC_STATUS|SMIC_SMS|SMIC_READY)
6890 +#define        SMIC_SC_SMS_WR_START    (SMIC_STATUS|SMIC_SMS|SMIC_WR_START)
6891 +#define        SMIC_SC_SMS_WR_NEXT     (SMIC_STATUS|SMIC_SMS|SMIC_WR_NEXT)
6892 +#define        SMIC_SC_SMS_WR_END      (SMIC_STATUS|SMIC_SMS|SMIC_WR_END)
6893 +#define        SMIC_SC_SMS_RD_START    (SMIC_STATUS|SMIC_SMS|SMIC_RD_START)
6894 +#define        SMIC_SC_SMS_RD_NEXT     (SMIC_STATUS|SMIC_SMS|SMIC_RD_NEXT)
6895 +#define        SMIC_SC_SMS_RD_END      (SMIC_STATUS|SMIC_SMS|SMIC_RD_END)
6896 +
6897 +#define        SMIC_SC_SMM_READY       (SMIC_STATUS|SMIC_SMM|SMIC_READY)
6898 +#define        SMIC_SC_SMM_WR_START    (SMIC_STATUS|SMIC_SMM|SMIC_WR_START)
6899 +#define        SMIC_SC_SMM_WR_NEXT     (SMIC_STATUS|SMIC_SMM|SMIC_WR_NEXT)
6900 +#define        SMIC_SC_SMM_WR_END      (SMIC_STATUS|SMIC_SMM|SMIC_WR_END)
6901 +#define        SMIC_SC_SMM_RD_START    (SMIC_STATUS|SMIC_SMM|SMIC_RD_START)
6902 +#define        SMIC_SC_SMM_RD_NEXT     (SMIC_STATUS|SMIC_SMM|SMIC_RD_NEXT)
6903 +#define        SMIC_SC_SMM_RD_END      (SMIC_STATUS|SMIC_SMM|SMIC_RD_END)
6904 +
6905 +/* these are the control/status codes we actually use
6906 +       SMIC_CC_SMS_GET_STATUS  0x40
6907 +       SMIC_CC_SMS_WR_START    0x41
6908 +       SMIC_CC_SMS_WR_NEXT     0x42
6909 +       SMIC_CC_SMS_WR_END      0x43
6910 +       SMIC_CC_SMS_RD_START    0x44
6911 +       SMIC_CC_SMS_RD_NEXT     0x45
6912 +       SMIC_CC_SMS_RD_END      0x46
6913 +
6914 +       SMIC_SC_SMS_READY       0xC0
6915 +       SMIC_SC_SMS_WR_START    0xC1
6916 +       SMIC_SC_SMS_WR_NEXT     0xC2
6917 +       SMIC_SC_SMS_WR_END      0xC3
6918 +       SMIC_SC_SMS_RD_START    0xC4
6919 +       SMIC_SC_SMS_RD_NEXT     0xC5
6920 +       SMIC_SC_SMS_RD_END      0xC6
6921 +*/
6922 +
6923 +static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
6924 +{
6925 +       unsigned char status;
6926 +       unsigned char flags;
6927 +       unsigned char data;
6928 +
6929 +       if (smic->state == SMIC_HOSED) {
6930 +               init_smic_data(smic, smic->io);
6931 +               return SI_SM_HOSED;
6932 +       }
6933 +       if (smic->state != SMIC_IDLE) {
6934 +               if (smic_debug & SMIC_DEBUG_STATES) {
6935 +                       printk(KERN_INFO
6936 +                              "smic_event - smic->smic_timeout = %ld,"
6937 +                              " time = %ld\n",
6938 +                              smic->smic_timeout, time);
6939 +               }
6940 +/* FIXME: smic_event is sometimes called with time > SMIC_RETRY_TIMEOUT */
6941 +               if (time < SMIC_RETRY_TIMEOUT) {
6942 +                       smic->smic_timeout -= time;
6943 +                       if (smic->smic_timeout < 0) {
6944 +                               start_error_recovery(smic, "smic timed out.");
6945 +                               return SI_SM_CALL_WITH_DELAY;
6946 +                       }
6947 +               }
6948 +       }
6949 +       flags = read_smic_flags(smic);
6950 +       if (flags & SMIC_FLAG_BSY)
6951 +               return SI_SM_CALL_WITH_DELAY;
6952 +
6953 +       status = read_smic_status (smic);
6954 +       if (smic_debug & SMIC_DEBUG_STATES)
6955 +               printk(KERN_INFO
6956 +                      "smic_event - state = %d, flags = 0x%02x,"
6957 +                      " status = 0x%02x\n",
6958 +                      smic->state, flags, status);
6959 +
6960 +       switch (smic->state) {
6961 +       case SMIC_IDLE:
6962 +               /* in IDLE we check for available messages */
6963 +               if (flags & (SMIC_SMI |
6964 +                            SMIC_EVM_DATA_AVAIL | SMIC_SMS_DATA_AVAIL))
6965 +               {
6966 +                       return SI_SM_ATTN;
6967 +               }
6968 +               return SI_SM_IDLE;
6969 +
6970 +       case SMIC_START_OP:
6971 +               /* sanity check whether smic is really idle */
6972 +               write_smic_control(smic, SMIC_CC_SMS_GET_STATUS);
6973 +               write_smic_flags(smic, flags | SMIC_FLAG_BSY);
6974 +               smic->state = SMIC_OP_OK;
6975 +               break;
6976 +
6977 +       case SMIC_OP_OK:
6978 +               if (status != SMIC_SC_SMS_READY) {
6979 +                               /* this should not happen */
6980 +                       start_error_recovery(smic,
6981 +                                            "state = SMIC_OP_OK,"
6982 +                                            " status != SMIC_SC_SMS_READY");
6983 +                       return SI_SM_CALL_WITH_DELAY;
6984 +               }
6985 +               /* OK so far; smic is idle let us start ... */
6986 +               write_smic_control(smic, SMIC_CC_SMS_WR_START);
6987 +               write_next_byte(smic);
6988 +               write_smic_flags(smic, flags | SMIC_FLAG_BSY);
6989 +               smic->state = SMIC_WRITE_START;
6990 +               break;
6991 +
6992 +       case SMIC_WRITE_START:
6993 +               if (status != SMIC_SC_SMS_WR_START) {
6994 +                       start_error_recovery(smic,
6995 +                                            "state = SMIC_WRITE_START, "
6996 +                                            "status != SMIC_SC_SMS_WR_START");
6997 +                       return SI_SM_CALL_WITH_DELAY;
6998 +               }
6999 +               /* we must not issue WR_(NEXT|END) unless
7000 +                   TX_DATA_READY is set */
7001 +               if (flags & SMIC_TX_DATA_READY) {
7002 +                       if (smic->write_count == 1) {
7003 +                               /* last byte */
7004 +                               write_smic_control(smic, SMIC_CC_SMS_WR_END);
7005 +                               smic->state = SMIC_WRITE_END;
7006 +                       } else {
7007 +                               write_smic_control(smic, SMIC_CC_SMS_WR_NEXT);
7008 +                               smic->state = SMIC_WRITE_NEXT;
7009 +                       }
7010 +                       write_next_byte(smic);
7011 +                       write_smic_flags(smic, flags | SMIC_FLAG_BSY);
7012 +               }
7013 +               else {
7014 +                       return SI_SM_CALL_WITH_DELAY;
7015 +               }
7016 +               break;
7017 +
7018 +       case SMIC_WRITE_NEXT:
7019 +               if (status != SMIC_SC_SMS_WR_NEXT) {
7020 +                       start_error_recovery(smic,
7021 +                                            "state = SMIC_WRITE_NEXT, "
7022 +                                            "status != SMIC_SC_SMS_WR_NEXT");
7023 +                       return SI_SM_CALL_WITH_DELAY;
7024 +               }
7025 +               /* this is the same code as in SMIC_WRITE_START */
7026 +               if (flags & SMIC_TX_DATA_READY) {
7027 +                       if (smic->write_count == 1) {
7028 +                               write_smic_control(smic, SMIC_CC_SMS_WR_END);
7029 +                               smic->state = SMIC_WRITE_END;
7030 +                       }
7031 +                       else {
7032 +                               write_smic_control(smic, SMIC_CC_SMS_WR_NEXT);
7033 +                               smic->state = SMIC_WRITE_NEXT;
7034 +                       }
7035 +                       write_next_byte(smic);
7036 +                       write_smic_flags(smic, flags | SMIC_FLAG_BSY);
7037 +               }
7038 +               else {
7039 +                       return SI_SM_CALL_WITH_DELAY;
7040 +               }
7041 +               break;
7042 +
7043 +       case SMIC_WRITE_END:
7044 +               if (status != SMIC_SC_SMS_WR_END) {
7045 +                       start_error_recovery (smic,
7046 +                                             "state = SMIC_WRITE_END, "
7047 +                                             "status != SMIC_SC_SMS_WR_END");
7048 +                       return SI_SM_CALL_WITH_DELAY;
7049 +               }
7050 +               /* data register holds an error code */
7051 +               data = read_smic_data(smic);
7052 +               if (data != 0) {
7053 +                       if (smic_debug & SMIC_DEBUG_ENABLE) {
7054 +                               printk(KERN_INFO
7055 +                                      "SMIC_WRITE_END: data = %02x\n", data);
7056 +                       }
7057 +                       start_error_recovery(smic,
7058 +                                            "state = SMIC_WRITE_END, "
7059 +                                            "data != SUCCESS");
7060 +                       return SI_SM_CALL_WITH_DELAY;
7061 +               } else {
7062 +                       smic->state = SMIC_WRITE2READ;
7063 +               }
7064 +               break;
7065 +
7066 +       case SMIC_WRITE2READ:
7067 +               /* we must wait for RX_DATA_READY to be set before we
7068 +                   can continue */
7069 +               if (flags & SMIC_RX_DATA_READY) {
7070 +                       write_smic_control(smic, SMIC_CC_SMS_RD_START);
7071 +                       write_smic_flags(smic, flags | SMIC_FLAG_BSY);
7072 +                       smic->state = SMIC_READ_START;
7073 +               } else {
7074 +                       return SI_SM_CALL_WITH_DELAY;
7075 +               }
7076 +               break;
7077 +
7078 +       case SMIC_READ_START:
7079 +               if (status != SMIC_SC_SMS_RD_START) {
7080 +                       start_error_recovery(smic,
7081 +                                            "state = SMIC_READ_START, "
7082 +                                            "status != SMIC_SC_SMS_RD_START");
7083 +                       return SI_SM_CALL_WITH_DELAY;
7084 +               }
7085 +               if (flags & SMIC_RX_DATA_READY) {
7086 +                       read_next_byte(smic);
7087 +                       write_smic_control(smic, SMIC_CC_SMS_RD_NEXT);
7088 +                       write_smic_flags(smic, flags | SMIC_FLAG_BSY);
7089 +                       smic->state = SMIC_READ_NEXT;
7090 +               } else {
7091 +                       return SI_SM_CALL_WITH_DELAY;
7092 +               }
7093 +               break;
7094 +
7095 +       case SMIC_READ_NEXT:
7096 +               switch (status) {
7097 +               /* smic tells us that this is the last byte to be read
7098 +                   --> clean up */
7099 +               case SMIC_SC_SMS_RD_END:
7100 +                       read_next_byte(smic);
7101 +                       write_smic_control(smic, SMIC_CC_SMS_RD_END);
7102 +                       write_smic_flags(smic, flags | SMIC_FLAG_BSY);
7103 +                       smic->state = SMIC_READ_END;
7104 +                       break;
7105 +               case SMIC_SC_SMS_RD_NEXT:
7106 +                       if (flags & SMIC_RX_DATA_READY) {
7107 +                               read_next_byte(smic);
7108 +                               write_smic_control(smic, SMIC_CC_SMS_RD_NEXT);
7109 +                               write_smic_flags(smic, flags | SMIC_FLAG_BSY);
7110 +                               smic->state = SMIC_READ_NEXT;
7111 +                       } else {
7112 +                               return SI_SM_CALL_WITH_DELAY;
7113 +                       }
7114 +                       break;
7115 +               default:
7116 +                       start_error_recovery(
7117 +                               smic,
7118 +                               "state = SMIC_READ_NEXT, "
7119 +                               "status != SMIC_SC_SMS_RD_(NEXT|END)");
7120 +                       return SI_SM_CALL_WITH_DELAY;
7121 +               }
7122 +               break;
7123 +
7124 +       case SMIC_READ_END:
7125 +               if (status != SMIC_SC_SMS_READY) {
7126 +                       start_error_recovery(smic,
7127 +                                            "state = SMIC_READ_END, "
7128 +                                            "status != SMIC_SC_SMS_READY");
7129 +                       return SI_SM_CALL_WITH_DELAY;
7130 +               }
7131 +               data = read_smic_data(smic);
7132 +               /* data register holds an error code */
7133 +               if (data != 0) {
7134 +                       if (smic_debug & SMIC_DEBUG_ENABLE) {
7135 +                               printk(KERN_INFO
7136 +                                      "SMIC_READ_END: data = %02x\n", data);
7137 +                       }
7138 +                       start_error_recovery(smic,
7139 +                                            "state = SMIC_READ_END, "
7140 +                                            "data != SUCCESS");
7141 +                       return SI_SM_CALL_WITH_DELAY;
7142 +               } else {
7143 +                       smic->state = SMIC_IDLE;
7144 +                       return SI_SM_TRANSACTION_COMPLETE;
7145 +               }
7146 +
7147 +       case SMIC_HOSED:
7148 +               init_smic_data(smic, smic->io);
7149 +               return SI_SM_HOSED;
7150 +
7151 +       default:
7152 +               if (smic_debug & SMIC_DEBUG_ENABLE) {
7153 +                       printk(KERN_WARNING "smic->state = %d\n", smic->state);
7154 +                       start_error_recovery(smic, "state = UNKNOWN");
7155 +                       return SI_SM_CALL_WITH_DELAY;
7156 +               }
7157 +       }
7158 +       smic->smic_timeout = SMIC_RETRY_TIMEOUT;
7159 +       return SI_SM_CALL_WITHOUT_DELAY;
7160 +}
7161 +
7162 +static int smic_detect(struct si_sm_data *smic)
7163 +{
7164 +       /* It's impossible for the SMIC fnags register to be all 1's,
7165 +          (assuming a properly functioning, self-initialized BMC)
7166 +          but that's what you get from reading a bogus address, so we
7167 +          test that first. */
7168 +       if (read_smic_flags(smic) == 0xff)
7169 +               return 1; 
7170 +
7171 +       return 0;
7172 +}
7173 +
7174 +static void smic_cleanup(struct si_sm_data *kcs)
7175 +{
7176 +}
7177 +
7178 +static int smic_size(void)
7179 +{
7180 +       return sizeof(struct si_sm_data);
7181 +}
7182 +
7183 +struct si_sm_handlers smic_smi_handlers =
7184 +{
7185 +       .version           = IPMI_SMIC_VERSION,
7186 +       .init_data         = init_smic_data,
7187 +       .start_transaction = start_smic_transaction,
7188 +       .get_result        = smic_get_result,
7189 +       .event             = smic_event,
7190 +       .detect            = smic_detect,
7191 +       .cleanup           = smic_cleanup,
7192 +       .size              = smic_size,
7193 +};
7194 diff -urN linux-2.4.23.org/drivers/char/ipmi/ipmi_watchdog.c linux-2.4.23/drivers/char/ipmi/ipmi_watchdog.c
7195 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_watchdog.c  2004-01-02 23:31:35.448361402 +0100
7196 +++ linux-2.4.23/drivers/char/ipmi/ipmi_watchdog.c      2004-01-02 23:33:48.069806033 +0100
7197 @@ -50,6 +50,8 @@
7198  #include <asm/apic.h>
7199  #endif
7200  
7201 +#define IPMI_WATCHDOG_VERSION "v28"
7202 +
7203  /*
7204   * The IPMI command/response information for the watchdog timer.
7205   */
7206 @@ -153,10 +155,18 @@
7207  static char pretimeout_since_last_heartbeat = 0;
7208  
7209  MODULE_PARM(timeout, "i");
7210 +MODULE_PARM_DESC(timeout, "Timeout value in seconds.");
7211  MODULE_PARM(pretimeout, "i");
7212 +MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds.");
7213  MODULE_PARM(action, "s");
7214 +MODULE_PARM_DESC(action, "Timeout action. One of: "
7215 +                "reset, none, power_cycle, power_off.");
7216  MODULE_PARM(preaction, "s");
7217 +MODULE_PARM_DESC(preaction, "Pretimeout action.  One of: "
7218 +                "pre_none, pre_smi, pre_nmi, pre_int.");
7219  MODULE_PARM(preop, "s");
7220 +MODULE_PARM_DESC(preop, "Pretimeout driver operation.  One of: "
7221 +                "preop_none, preop_panic, preop_give_data.");
7222  
7223  /* Default state of the timer. */
7224  static unsigned char ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
7225 @@ -899,6 +909,7 @@
7226  
7227  static struct ipmi_smi_watcher smi_watcher =
7228  {
7229 +       .owner    = THIS_MODULE,
7230         .new_smi  = ipmi_new_smi,
7231         .smi_gone = ipmi_smi_gone
7232  };
7233 @@ -907,6 +918,9 @@
7234  {
7235         int rv;
7236  
7237 +       printk(KERN_INFO "IPMI watchdog driver version "
7238 +              IPMI_WATCHDOG_VERSION "\n");
7239 +
7240         if (strcmp(action, "reset") == 0) {
7241                 action_val = WDOG_TIMEOUT_RESET;
7242         } else if (strcmp(action, "none") == 0) {
7243 @@ -995,9 +1009,6 @@
7244         register_reboot_notifier(&wdog_reboot_notifier);
7245         notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier);
7246  
7247 -       printk(KERN_INFO "IPMI watchdog by "
7248 -              "Corey Minyard (minyard@mvista.com)\n");
7249 -
7250         return 0;
7251  }
7252  
7253 @@ -1030,6 +1041,7 @@
7254            pointers to our buffers, we want to make sure they are done before
7255            we release our memory. */
7256         while (atomic_read(&set_timeout_tofree)) {
7257 +               set_current_state(TASK_UNINTERRUPTIBLE);
7258                 schedule_timeout(1);
7259         }
7260  
7261 diff -urN linux-2.4.23.org/drivers/char/ipmi/Makefile linux-2.4.23/drivers/char/ipmi/Makefile
7262 --- linux-2.4.23.org/drivers/char/ipmi/Makefile 2004-01-02 23:31:35.453360363 +0100
7263 +++ linux-2.4.23/drivers/char/ipmi/Makefile     2004-01-02 23:33:48.071805617 +0100
7264 @@ -6,15 +6,21 @@
7265  
7266  export-objs    := ipmi_msghandler.o ipmi_watchdog.o
7267  
7268 -list-multi := ipmi_kcs_drv.o
7269 +list-multi := ipmi_kcs_drv.o ipmi_si_drv.o
7270  ipmi_kcs_drv-objs := ipmi_kcs_sm.o ipmi_kcs_intf.o
7271 +ipmi_si_drv-objs := ipmi_si.o ipmi_kcs_sm.o ipmi_smic_sm.o ipmi_bt_sm.o
7272  
7273  obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o
7274  obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o
7275 +obj-$(CONFIG_IPMI_SI) += ipmi_si_drv.o
7276  obj-$(CONFIG_IPMI_KCS) += ipmi_kcs_drv.o
7277 +obj-$(CONFIG_IPMI_SMB) += ipmi_smb_intf.o
7278  obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
7279  
7280  include $(TOPDIR)/Rules.make
7281  
7282  ipmi_kcs_drv.o:        $(ipmi_kcs_drv-objs)
7283         $(LD) -r -o $@ $(ipmi_kcs_drv-objs) 
7284 +
7285 +ipmi_si_drv.o: $(ipmi_si_drv-objs)
7286 +       $(LD) -r -o $@ $(ipmi_si_drv-objs) 
7287 diff -urN linux-2.4.23.org/include/linux/ipmi.h linux-2.4.23/include/linux/ipmi.h
7288 --- linux-2.4.23.org/include/linux/ipmi.h       2004-01-02 23:30:59.366857718 +0100
7289 +++ linux-2.4.23/include/linux/ipmi.h   2004-01-02 23:33:48.094800839 +0100
7290 @@ -160,6 +160,7 @@
7291   * The in-kernel interface.
7292   */
7293  #include <linux/list.h>
7294 +#include <linux/module.h>
7295  
7296  /* Opaque type for a IPMI message user.  One of these is needed to
7297     send and receive messages. */
7298 @@ -221,7 +222,12 @@
7299                      void                  *handler_data,
7300                      ipmi_user_t           *user);
7301  
7302 -/* Destroy the given user of the IPMI layer. */
7303 +/* Destroy the given user of the IPMI layer.  Note that after this
7304 +   function returns, the system is guaranteed to not call any
7305 +   callbacks for the user.  Thus as long as you destroy all the users
7306 +   before you unload a module, you will be safe.  And if you destroy
7307 +   the users before you destroy the callback structures, it should be
7308 +   safe, too. */
7309  int ipmi_destroy_user(ipmi_user_t user);
7310  
7311  /* Get the IPMI version of the BMC we are talking to. */
7312 @@ -261,6 +267,27 @@
7313                  int              priority);
7314  
7315  /*
7316 + * Like ipmi_request, but lets you specify the number of retries and
7317 + * the retry time.  The retries is the number of times the message
7318 + * will be resent if no reply is received.  If set to -1, the default
7319 + * value will be used.  The retry time is the time in milliseconds
7320 + * between retries.  If set to zero, the default value will be
7321 + * used.
7322 + *
7323 + * Don't use this unless you *really* have to.  It's primarily for the
7324 + * IPMI over LAN converter; since the LAN stuff does its own retries,
7325 + * it makes no sense to do it here.  However, this can be used if you
7326 + * have unusual requirements.
7327 + */
7328 +int ipmi_request_settime(ipmi_user_t      user,
7329 +                        struct ipmi_addr *addr,
7330 +                        long             msgid,
7331 +                        struct ipmi_msg  *msg,
7332 +                        int              priority,
7333 +                        int              max_retries,
7334 +                        unsigned int     retry_time_ms);
7335 +
7336 +/*
7337   * Like ipmi_request, but lets you specify the slave return address.
7338   */
7339  int ipmi_request_with_source(ipmi_user_t      user,
7340 @@ -331,6 +358,10 @@
7341  {
7342         struct list_head link;
7343  
7344 +       /* You must set the owner to the current module, if you are in
7345 +          a module (generally just set it to "THIS_MODULE"). */
7346 +       struct module *owner;
7347 +
7348         /* These two are called with read locks held for the interface
7349            the watcher list.  So you can add and remove users from the
7350            IPMI interface, send messages, etc., but you cannot add
7351 @@ -422,6 +453,29 @@
7352  #define IPMICTL_SEND_COMMAND           _IOR(IPMI_IOC_MAGIC, 13,        \
7353                                              struct ipmi_req)
7354  
7355 +/* Messages sent to the interface with timing parameters are this
7356 +   format. */
7357 +struct ipmi_req_settime
7358 +{
7359 +       struct ipmi_req req;
7360 +
7361 +       /* See ipmi_request_settime() above for details on these
7362 +           values. */
7363 +       int          retries;
7364 +       unsigned int retry_time_ms;
7365 +};
7366 +/*
7367 + * Send a message to the interfaces with timing parameters.  error values
7368 + * are:
7369 + *   - EFAULT - an address supplied was invalid.
7370 + *   - EINVAL - The address supplied was not valid, or the command
7371 + *              was not allowed.
7372 + *   - EMSGSIZE - The message to was too large.
7373 + *   - ENOMEM - Buffers could not be allocated for the command.
7374 + */
7375 +#define IPMICTL_SEND_COMMAND_SETTIME   _IOR(IPMI_IOC_MAGIC, 21,        \
7376 +                                            struct ipmi_req_settime)
7377 +
7378  /* Messages received from the interface are this format. */
7379  struct ipmi_recv
7380  {
7381 @@ -513,4 +567,18 @@
7382  #define IPMICTL_SET_MY_LUN_CMD         _IOR(IPMI_IOC_MAGIC, 19, unsigned int)
7383  #define IPMICTL_GET_MY_LUN_CMD         _IOR(IPMI_IOC_MAGIC, 20, unsigned int)
7384  
7385 +/*
7386 + * Get/set the default timing values for an interface.  You shouldn't
7387 + * generally mess with these.
7388 + */
7389 +struct ipmi_timing_parms
7390 +{
7391 +       int          retries;
7392 +       unsigned int retry_time_ms;
7393 +};
7394 +#define IPMICTL_SET_TIMING_PARMS_CMD   _IOR(IPMI_IOC_MAGIC, 22, \
7395 +                                            struct ipmi_timing_parms)
7396 +#define IPMICTL_GET_TIMING_PARMS_CMD   _IOR(IPMI_IOC_MAGIC, 23, \
7397 +                                            struct ipmi_timing_parms)
7398 +
7399  #endif /* __LINUX_IPMI_H */
7400 diff -urN linux-2.4.23.org/include/linux/ipmi_msgdefs.h linux-2.4.23/include/linux/ipmi_msgdefs.h
7401 --- linux-2.4.23.org/include/linux/ipmi_msgdefs.h       2004-01-02 23:30:59.337863741 +0100
7402 +++ linux-2.4.23/include/linux/ipmi_msgdefs.h   2004-01-02 23:33:48.096800424 +0100
7403 @@ -37,22 +37,34 @@
7404  /* Various definitions for IPMI messages used by almost everything in
7405     the IPMI stack. */
7406  
7407 -#define IPMI_NETFN_APP_REQUEST 0x06
7408 -#define IPMI_NETFN_APP_RESPONSE        0x07
7409 -
7410 -#define IPMI_BMC_SLAVE_ADDR    0x20
7411 +/* NetFNs and commands used inside the IPMI stack. */
7412
7413 +#define IPMI_NETFN_SENSOR_EVENT_REQUEST                0x04
7414 +#define IPMI_NETFN_SENSOR_EVENT_RESPONSE       0x05
7415 +#define IPMI_GET_EVENT_RECEIVER_CMD    0x01
7416  
7417 +#define IPMI_NETFN_APP_REQUEST                 0x06
7418 +#define IPMI_NETFN_APP_RESPONSE                        0x07
7419  #define IPMI_GET_DEVICE_ID_CMD         0x01
7420 -
7421  #define IPMI_CLEAR_MSG_FLAGS_CMD       0x30
7422  #define IPMI_GET_MSG_FLAGS_CMD         0x31
7423  #define IPMI_SEND_MSG_CMD              0x34
7424  #define IPMI_GET_MSG_CMD               0x33
7425 -
7426  #define IPMI_SET_BMC_GLOBAL_ENABLES_CMD        0x2e
7427  #define IPMI_GET_BMC_GLOBAL_ENABLES_CMD        0x2f
7428  #define IPMI_READ_EVENT_MSG_BUFFER_CMD 0x35
7429  
7430 +#define IPMI_NETFN_STORAGE_REQUEST             0x0a
7431 +#define IPMI_NETFN_STORAGE_RESPONSE            0x0b
7432 +#define IPMI_ADD_SEL_ENTRY_CMD         0x44
7433 +
7434 +/* The default slave address */
7435 +#define IPMI_BMC_SLAVE_ADDR    0x20
7436 +
7437  #define IPMI_MAX_MSG_LENGTH    80
7438  
7439 +#define IPMI_CC_NO_ERROR       0
7440 +#define IPMI_NODE_BUSY_ERR             0xc0
7441 +#define IPMI_LOST_ARBITRATION_ERR      0x81
7442 +
7443  #endif /* __LINUX_IPMI_MSGDEFS_H */
7444 diff -urN linux-2.4.23.org/include/linux/ipmi_smi.h linux-2.4.23/include/linux/ipmi_smi.h
7445 --- linux-2.4.23.org/include/linux/ipmi_smi.h   2004-01-02 23:30:59.336863949 +0100
7446 +++ linux-2.4.23/include/linux/ipmi_smi.h       2004-01-02 23:33:48.098800008 +0100
7447 @@ -35,6 +35,8 @@
7448  #define __LINUX_IPMI_SMI_H
7449  
7450  #include <linux/ipmi_msgdefs.h>
7451 +#include <linux/proc_fs.h>
7452 +#include <linux/module.h>
7453  
7454  /* This files describes the interface for IPMI system management interface
7455     drivers to bind into the IPMI message handler. */
7456 @@ -141,4 +143,11 @@
7457         msg->done(msg);
7458  }
7459  
7460 +/* Allow the lower layer to add things to the proc filesystem
7461 +   directory for this interface.  Note that the entry will
7462 +   automatically be dstroyed when the interface is destroyed. */
7463 +int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
7464 +                           read_proc_t *read_proc, write_proc_t *write_proc,
7465 +                           void *data, struct module *owner);
7466 +
7467  #endif /* __LINUX_IPMI_SMI_H */
7468 diff -urN linux-2.4.23.org/include/linux/net.h linux-2.4.23/include/linux/net.h
7469 --- linux-2.4.23.org/include/linux/net.h        2004-01-02 23:30:59.030927510 +0100
7470 +++ linux-2.4.23/include/linux/net.h    2004-01-02 23:33:48.123794815 +0100
7471 @@ -24,7 +24,7 @@
7472  
7473  struct poll_table_struct;
7474  
7475 -#define NPROTO         32              /* should be enough for now..   */
7476 +#define NPROTO         64              /* should be enough for now..   */
7477  
7478  
7479  #define SYS_SOCKET     1               /* sys_socket(2)                */
7480 diff -urN linux-2.4.23.org/include/linux/socket.h linux-2.4.23/include/linux/socket.h
7481 --- linux-2.4.23.org/include/linux/socket.h     2004-01-02 23:30:58.991935611 +0100
7482 +++ linux-2.4.23/include/linux/socket.h 2004-01-02 23:33:48.151788998 +0100
7483 @@ -175,7 +175,8 @@
7484  #define AF_WANPIPE     25      /* Wanpipe API Sockets */
7485  #define AF_LLC         26      /* Linux LLC                    */
7486  #define AF_BLUETOOTH   31      /* Bluetooth sockets            */
7487 -#define AF_MAX         32      /* For now.. */
7488 +#define AF_IPMI                32      /* IPMI sockers                 */
7489 +#define AF_MAX         33      /* For now.. */
7490  
7491  /* Protocol families, same as address families. */
7492  #define PF_UNSPEC      AF_UNSPEC
7493 @@ -207,6 +208,7 @@
7494  #define PF_WANPIPE     AF_WANPIPE
7495  #define PF_LLC         AF_LLC
7496  #define PF_BLUETOOTH   AF_BLUETOOTH
7497 +#define PF_IPMI                AF_IPMI
7498  #define PF_MAX         AF_MAX
7499  
7500  /* Maximum queue length specifiable by listen.  */
7501 diff -urN linux-2.4.23.org/include/net/af_ipmi.h linux-2.4.23/include/net/af_ipmi.h
7502 --- linux-2.4.23.org/include/net/af_ipmi.h      1970-01-01 01:00:00.000000000 +0100
7503 +++ linux-2.4.23/include/net/af_ipmi.h  2004-01-02 23:33:48.155788167 +0100
7504 @@ -0,0 +1,66 @@
7505 +#ifndef _NET_IPMI_H
7506 +#define _NET_IPMI_H
7507 +
7508 +#include <linux/ipmi.h>
7509 +
7510 +/*
7511 + * This is ipmi address for socket
7512 + */
7513 +struct sockaddr_ipmi {
7514 +       sa_family_t      sipmi_family; /* AF_IPMI */
7515 +       int              if_num; /* IPMI interface number */
7516 +       struct ipmi_addr ipmi_addr;
7517 +};
7518 +#define SOCKADDR_IPMI_OVERHEAD (sizeof(struct sockaddr_ipmi) \
7519 +                               - sizeof(struct ipmi_addr))
7520 +
7521 +/* A msg_control item, this takes a 'struct ipmi_timing_parms' */
7522 +#define IPMI_CMSG_TIMING_PARMS 0x01
7523 +
7524 +/* 
7525 + * This is ipmi message for socket
7526 + */
7527 +struct ipmi_sock_msg {
7528 +       int                   recv_type;
7529 +       long                  msgid;
7530 +
7531 +       unsigned char         netfn;
7532 +       unsigned char         cmd;
7533 +       int                   data_len;
7534 +       unsigned char         data[0];
7535 +};
7536 +
7537 +#define IPMI_MAX_SOCK_MSG_LENGTH (sizeof(struct ipmi_sock_msg)+IPMI_MAX_MSG_LENGTH)
7538 +
7539 +/* Register/unregister to receive specific commands.  Uses struct
7540 +   ipmi_cmdspec from linux/ipmi.h */
7541 +#define SIOCIPMIREGCMD         (SIOCPROTOPRIVATE + 0)
7542 +#define SIOCIPMIUNREGCMD       (SIOCPROTOPRIVATE + 1)
7543 +
7544 +/* Register to receive events.  Takes an integer */
7545 +#define SIOCIPMIGETEVENT       (SIOCPROTOPRIVATE + 2)
7546 +
7547 +/* Set the default timing parameters for the socket.  Takes a struct
7548 +   ipmi_timing_parms from linux/ipmi.h */
7549 +#define SIOCIPMISETTIMING      (SIOCPROTOPRIVATE + 3)
7550 +#define SIOCIPMIGETTIMING      (SIOCPROTOPRIVATE + 4)
7551 +
7552 +/* Set/Get the IPMB address of the MC we are connected to, takes an
7553 +   unsigned int. */
7554 +#define SIOCIPMISETADDR                (SIOCPROTOPRIVATE + 5)
7555 +#define SIOCIPMIGETADDR                (SIOCPROTOPRIVATE + 6)
7556 +
7557 +/* Socket information for IPMI for protinfo. */
7558 +struct ipmi_sock {
7559 +       ipmi_user_t user;
7560 +       struct sockaddr_ipmi addr;
7561 +       struct list_head msg_list;
7562 +       
7563 +       wait_queue_head_t wait; 
7564 +       spinlock_t lock;
7565 +
7566 +       int          default_retries;
7567 +       unsigned int default_retry_time_ms;
7568 +};
7569 +
7570 +#endif/*_NET_IPMI_H*/
7571 diff -urN linux-2.4.23.org/include/net/sock.h linux-2.4.23/include/net/sock.h
7572 --- linux-2.4.23.org/include/net/sock.h 2004-01-02 23:31:07.058259765 +0100
7573 +++ linux-2.4.23/include/net/sock.h     2004-01-02 23:33:48.166785882 +0100
7574 @@ -98,6 +98,10 @@
7575  #include <net/irda/irda.h>
7576  #endif
7577  
7578 +#if defined(CONFIG_IPMI_SOCKET) || defined(CONFIG_IPMI_SOCKET_MODULE)
7579 +#include <net/af_ipmi.h>
7580 +#endif
7581 +
7582  #if defined(CONFIG_ATM) || defined(CONFIG_ATM_MODULE)
7583  struct atm_vcc;
7584  #endif
7585 @@ -673,6 +677,9 @@
7586  #if defined(CONFIG_WAN_ROUTER) || defined(CONFIG_WAN_ROUTER_MODULE)
7587                 struct wanpipe_opt      *af_wanpipe;
7588  #endif
7589 +#if defined(CONFIG_IPMI_SOCKET) || defined(CONFIG_IPMI_SOCKET_MODULE)
7590 +              struct ipmi_sock        af_ipmi;
7591 +#endif
7592         } protinfo;             
7593  
7594  
7595 diff -urN linux-2.4.23.org/net/Config.in linux-2.4.23/net/Config.in
7596 --- linux-2.4.23.org/net/Config.in      2004-01-02 23:31:20.022566302 +0100
7597 +++ linux-2.4.23/net/Config.in  2004-01-02 23:33:48.180782973 +0100
7598 @@ -16,6 +16,7 @@
7599  fi
7600  bool 'Socket Filtering'  CONFIG_FILTER
7601  tristate 'Unix domain sockets' CONFIG_UNIX
7602 +tristate 'IPMI sockets' CONFIG_IPMI_SOCKET
7603  bool 'TCP/IP networking' CONFIG_INET
7604  if [ "$CONFIG_INET" = "y" ]; then
7605     source net/ipv4/Config.in
7606 diff -urN linux-2.4.23.org/net/ipmi/af_ipmi.c linux-2.4.23/net/ipmi/af_ipmi.c
7607 --- linux-2.4.23.org/net/ipmi/af_ipmi.c 1970-01-01 01:00:00.000000000 +0100
7608 +++ linux-2.4.23/net/ipmi/af_ipmi.c     2004-01-02 23:33:48.187781519 +0100
7609 @@ -0,0 +1,593 @@
7610 +/* 
7611 + * IPMI Socket Glue
7612 + *
7613 + * Author:     Louis Zhuang <louis.zhuang@linux.intel.com>
7614 + * Copyright by Intel Corp., 2003
7615 + */
7616 +#include <linux/module.h>
7617 +#include <linux/config.h>
7618 +#include <linux/kernel.h>
7619 +#include <linux/major.h>
7620 +#include <linux/signal.h>
7621 +#include <linux/sched.h>
7622 +#include <linux/errno.h>
7623 +#include <linux/string.h>
7624 +#include <linux/stat.h>
7625 +#include <linux/socket.h>
7626 +#include <linux/fcntl.h>
7627 +#include <linux/sockios.h>
7628 +#include <linux/net.h>
7629 +#include <linux/in.h>
7630 +#include <linux/fs.h>
7631 +#include <linux/slab.h>
7632 +#include <asm/uaccess.h>
7633 +#include <linux/skbuff.h>
7634 +#include <linux/tcp.h>
7635 +#include <net/sock.h>
7636 +#include <linux/proc_fs.h>
7637 +#include <linux/init.h>
7638 +#include <linux/poll.h>
7639 +#include <linux/smp_lock.h>
7640 +#include <linux/mount.h>
7641 +#include <linux/ipmi.h>
7642 +#include <net/af_ipmi.h>
7643 +#include <linux/rtnetlink.h>
7644 +
7645 +#define IPMI_SOCKINTF_VERSION "v25"
7646 +
7647 +#ifdef CONFIG_DEBUG_KERNEL
7648 +static int debug = 0;
7649 +#define dbg(format, arg...)                                     \
7650 +        do {                                                    \
7651 +                if(debug)                                    \
7652 +                        printk (KERN_DEBUG "%s: " format "\n",  \
7653 +                                __FUNCTION__, ## arg);          \
7654 +        } while(0)
7655 +#else
7656 +#define dbg(format, arg...)
7657 +#endif /* CONFIG_DEBUG_KERNEL */
7658 +
7659 +#define err(format, arg...) \
7660 +                printk(KERN_ERR "%s: " format "\n", \
7661 +                       __FUNCTION__ , ## arg)
7662 +#define info(format, arg...) \
7663 +                printk(KERN_INFO "%s: " format "\n", \
7664 +                       __FUNCTION__ , ## arg)
7665 +#define warn(format, arg...) \
7666 +                printk(KERN_WARNING "%s: " format "\n", \
7667 +                       __FUNCTION__ , ## arg)
7668 +#define trace(format, arg...) \
7669 +                printk(KERN_INFO "%s(" format ")\n", \
7670 +                       __FUNCTION__ , ## arg)
7671 +
7672 +static kmem_cache_t *ipmi_sk_cachep = NULL;
7673 +
7674 +static atomic_t ipmi_nr_socks = ATOMIC_INIT(0);
7675 +
7676 +
7677 +
7678 +/*
7679 + * utility functions
7680 + */
7681 +static inline struct ipmi_sock *to_ipmi_sock(struct sock *sk) 
7682 +{
7683 +       return &sk->protinfo.af_ipmi;
7684 +}
7685 +
7686 +static inline void ipmi_release_sock(struct sock *sk, int embrion)
7687 +{
7688 +       struct ipmi_sock *i = to_ipmi_sock(sk);
7689 +       struct sk_buff   *skb;
7690 +       
7691 +       if (i->user) {
7692 +               ipmi_destroy_user(i->user);
7693 +               i->user = NULL;
7694 +       }
7695 +
7696 +       sock_orphan(sk);
7697 +       sk->shutdown = SHUTDOWN_MASK;
7698 +       sk->state = TCP_CLOSE;
7699 +
7700 +       while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
7701 +               kfree_skb(skb);
7702 +
7703 +       sock_put(sk);
7704 +}
7705 +
7706 +static inline long ipmi_wait_for_queue(struct ipmi_sock *i, long timeo) 
7707 +{
7708 +       
7709 +       DECLARE_WAITQUEUE(wait, current);
7710 +       
7711 +       set_current_state(TASK_INTERRUPTIBLE);
7712 +       add_wait_queue_exclusive(&i->wait, &wait);
7713 +       timeo = schedule_timeout(timeo);
7714 +       set_current_state(TASK_RUNNING);
7715 +       remove_wait_queue(&i->wait, &wait);
7716 +       return timeo;
7717 +}
7718 +
7719 +/*
7720 + * IPMI operation functions
7721 + */
7722 +static void sock_receive_handler(struct ipmi_recv_msg *msg,
7723 +                                void                 *handler_data)
7724 +{
7725 +       struct ipmi_sock *i = (struct ipmi_sock *)handler_data;
7726 +       unsigned long    flags;
7727 +       
7728 +       spin_lock_irqsave(&i->lock, flags);
7729 +       list_add_tail(&msg->link, &i->msg_list);
7730 +       spin_unlock_irqrestore(&i->lock, flags);
7731 +
7732 +       wake_up_interruptible(&i->wait);
7733 +}
7734 +
7735 +/*
7736 + * protocol operation functions
7737 + */
7738 +static int ipmi_release(struct socket *sock)
7739 +{
7740 +       struct sock *sk = sock->sk;
7741 +       
7742 +       if (!sk)
7743 +               return 0;
7744 +
7745 +       sock->sk=NULL;
7746 +       ipmi_release_sock(sk, 0);
7747 +       return 0;
7748 +}
7749 +
7750 +static struct ipmi_user_hndl ipmi_hnd = {
7751 +       .ipmi_recv_hndl = sock_receive_handler
7752 +};
7753 +
7754 +static int ipmi_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
7755 +{
7756 +       struct ipmi_sock *i = to_ipmi_sock(sock->sk);
7757 +       struct sockaddr_ipmi *addr = (struct sockaddr_ipmi *)uaddr;
7758 +       int err = -EINVAL;
7759 +       
7760 +       if (i->user != NULL) {
7761 +               dbg("Cannot bind twice: %p", i->user);
7762 +               return -EINVAL;
7763 +       }
7764 +       
7765 +       err = ipmi_create_user(addr->if_num, &ipmi_hnd, i, &i->user);
7766 +       if (err) {
7767 +               dbg("Cannot create user for the socket: %p", i->user);
7768 +               return err;
7769 +       }
7770 +
7771 +       memcpy(&i->addr, addr, sizeof(i->addr));
7772 +       return 0;
7773 +}
7774 +
7775 +static int ipmi_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
7776 +{
7777 +       struct ipmi_sock *i = to_ipmi_sock(sock->sk);
7778 +       memcpy(uaddr, &i->addr, sizeof(i->addr));
7779 +       return 0;
7780 +}
7781 +
7782 +static unsigned int ipmi_poll(struct file * file, struct socket *sock, poll_table *wait)
7783 +{
7784 +       unsigned int     has_msg = 0;
7785 +       struct ipmi_sock *i = to_ipmi_sock(sock->sk);
7786 +       unsigned long    flags;
7787 +       
7788 +       poll_wait(file, &i->wait, wait);
7789 +       spin_lock_irqsave(&i->lock, flags);
7790 +       if (!list_empty(&i->msg_list))
7791 +               has_msg = 1;
7792 +       spin_unlock_irqrestore(&i->lock, flags);
7793 +
7794 +       if (has_msg)
7795 +               return POLLIN | POLLRDNORM;
7796 +       return 0;
7797 +}
7798 +
7799 +static int ipmi_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
7800 +{
7801 +       struct ipmi_sock    *i = to_ipmi_sock(sock->sk);
7802 +       struct ipmi_cmdspec val; 
7803 +       int                 ival;
7804 +       unsigned int        uival;
7805 +       int                 err;
7806 +       
7807 +       dbg("cmd=%#x, arg=%#lx", cmd, arg);
7808 +       switch(cmd) {
7809 +       case SIOCIPMIREGCMD:
7810 +               err = copy_from_user((void *)&val, (void *)arg,
7811 +                                    sizeof(cmd));
7812 +               if (err) {
7813 +                       err = -EFAULT;
7814 +                       break;
7815 +               }
7816 +               
7817 +               err = ipmi_register_for_cmd(i->user, val.netfn,
7818 +                                           val.cmd);
7819 +               break;
7820 +                       
7821 +       case SIOCIPMIUNREGCMD:
7822 +               err = copy_from_user((void *)&val, (void *)arg,
7823 +                                    sizeof(cmd));
7824 +               if (err) {
7825 +                       err = -EFAULT;
7826 +                       break;
7827 +               }
7828 +               
7829 +               err = ipmi_unregister_for_cmd(i->user, val.netfn,
7830 +                                             val.cmd);
7831 +               break;
7832 +                       
7833 +       case SIOCIPMIGETEVENT:
7834 +               err = copy_from_user((void *)&ival, (void *)arg,
7835 +                                    sizeof(ival));
7836 +               if (err) {
7837 +                       err = -EFAULT;
7838 +                       break;
7839 +               }
7840 +               
7841 +               err = ipmi_set_gets_events(i->user, ival);
7842 +               break;
7843 +                       
7844 +       case SIOCIPMISETADDR:
7845 +               err = copy_from_user((void *)&uival, (void *)arg,
7846 +                                    sizeof(uival));
7847 +               if (err) {
7848 +                       err = -EFAULT;
7849 +                       break;
7850 +               }
7851 +               
7852 +               ipmi_set_my_address(i->user, uival);
7853 +               break;
7854 +                       
7855 +       case SIOCIPMIGETADDR:
7856 +               uival = ipmi_get_my_address(i->user);
7857 +
7858 +               if (copy_to_user((void *) arg, &uival, sizeof(uival))) {
7859 +                       err = -EFAULT;
7860 +                       break;
7861 +               }
7862 +               err = 0;
7863 +               break;
7864 +                       
7865 +       case SIOCIPMISETTIMING:
7866 +       {
7867 +               struct ipmi_timing_parms parms;
7868 +
7869 +               if (copy_from_user(&parms, (void *) arg, sizeof(parms))) {
7870 +                       err = -EFAULT;
7871 +                       break;
7872 +               }
7873 +               
7874 +               i->default_retries = parms.retries;
7875 +               i->default_retry_time_ms = parms.retry_time_ms;
7876 +               err = 0;
7877 +               break;
7878 +       }
7879 +
7880 +       case SIOCIPMIGETTIMING:
7881 +       {
7882 +               struct ipmi_timing_parms parms;
7883 +
7884 +               parms.retries = i->default_retries;
7885 +               parms.retry_time_ms = i->default_retry_time_ms;
7886 +
7887 +               if (copy_to_user((void *) arg, &parms, sizeof(parms))) {
7888 +                       err = -EFAULT;
7889 +                       break;
7890 +               }
7891 +
7892 +               err = 0;
7893 +               break;
7894 +       }
7895 +
7896 +       default:
7897 +               err = dev_ioctl(cmd, (void *)arg);
7898 +               break;
7899 +       }
7900 +       
7901 +       return err;
7902 +}
7903 +
7904 +static int ipmi_recvmsg(struct socket *sock, struct msghdr *msg, int size,
7905 +                       int rflags, struct scm_cookie *scm)
7906 +{
7907 +       struct ipmi_sock     *i = to_ipmi_sock(sock->sk);
7908 +       long                 timeo;
7909 +       struct ipmi_recv_msg *rcvmsg;
7910 +       struct sockaddr_ipmi addr;
7911 +       char                 buf[IPMI_MAX_SOCK_MSG_LENGTH];
7912 +       struct ipmi_sock_msg *smsg = (struct ipmi_sock_msg *)buf; 
7913 +       int                  err;
7914 +       unsigned long        flags;
7915 +
7916 +       timeo = sock_rcvtimeo(sock->sk, rflags & MSG_DONTWAIT);
7917 +
7918 +       while (1) {
7919 +               spin_lock_irqsave(&i->lock, flags);
7920 +               if (!list_empty(&i->msg_list)) 
7921 +                       break;
7922 +               spin_unlock_irqrestore(&i->lock, flags);
7923 +               if (!timeo) {
7924 +                       return -EAGAIN;
7925 +               } else if (signal_pending (current)) {
7926 +                       dbg("Signal pending: %d", 1);
7927 +                       return -EINTR;
7928 +               }
7929 +                               
7930 +               timeo = ipmi_wait_for_queue(i, timeo);
7931 +       }
7932 +
7933 +       rcvmsg = list_entry(i->msg_list.next, struct ipmi_recv_msg, link);
7934 +       list_del(&rcvmsg->link);        
7935 +       spin_unlock_irqrestore(&i->lock, flags);
7936 +
7937 +       memcpy(&addr.ipmi_addr, &rcvmsg->addr, sizeof(addr.ipmi_addr));
7938 +       addr.if_num = i->addr.if_num;
7939 +       addr.sipmi_family = i->addr.sipmi_family;
7940 +       memcpy(msg->msg_name, &addr, sizeof(addr));
7941 +       msg->msg_namelen = (SOCKADDR_IPMI_OVERHEAD
7942 +                           + ipmi_addr_length(rcvmsg->addr.addr_type));
7943 +
7944 +       smsg->recv_type         = rcvmsg->recv_type;
7945 +       smsg->msgid             = rcvmsg->msgid;
7946 +       smsg->netfn             = rcvmsg->msg.netfn;
7947 +       smsg->cmd               = rcvmsg->msg.cmd;
7948 +       smsg->data_len          = rcvmsg->msg.data_len;
7949 +       memcpy(smsg->data, rcvmsg->msg.data, smsg->data_len);
7950 +       
7951 +       ipmi_free_recv_msg(rcvmsg);
7952 +       
7953 +       err = memcpy_toiovec(msg->msg_iov, (void *)smsg, 
7954 +                            sizeof(struct ipmi_sock_msg) + smsg->data_len);
7955 +       if (err) {
7956 +               dbg("Cannot copy data to user: %p", i->user);
7957 +               return err;
7958 +       }
7959 +       
7960 +       dbg("user=%p", i->user);
7961 +       dbg("addr_type=%x, channel=%x",
7962 +           addr.ipmi_addr.addr_type, addr.ipmi_addr.channel);
7963 +       dbg("netfn=%#02x, cmd=%#02x, data=%p, data_len=%x", 
7964 +           smsg->netfn, smsg->cmd, smsg->data, smsg->data_len);
7965 +
7966 +       return (sizeof(struct ipmi_sock_msg) + smsg->data_len);
7967 +}
7968 +
7969 +static int ipmi_sendmsg(struct socket *sock, struct msghdr *msg, int len,
7970 +                       struct scm_cookie *scm)
7971 +{
7972 +       struct ipmi_sock     *i = to_ipmi_sock(sock->sk);
7973 +       struct sockaddr_ipmi *addr = (struct sockaddr_ipmi *)msg->msg_name;
7974 +       struct ipmi_msg      imsg;
7975 +       unsigned char        buf[IPMI_MAX_SOCK_MSG_LENGTH];
7976 +       struct ipmi_sock_msg *smsg = (struct ipmi_sock_msg *)buf;
7977 +       int                  err;
7978 +       struct ipmi_timing_parms tparms;
7979 +       struct cmsghdr           *cmsg;
7980 +
7981 +       err = ipmi_validate_addr(&addr->ipmi_addr,
7982 +                                msg->msg_namelen - SOCKADDR_IPMI_OVERHEAD);
7983 +       if (err) {
7984 +               dbg("Invalid IPMI address: %p", i->user);
7985 +               goto err;
7986 +       }
7987 +       
7988 +       if (len > IPMI_MAX_SOCK_MSG_LENGTH) {
7989 +               err = -EINVAL;
7990 +               dbg("Message too long: %p", i->user);
7991 +               goto err;
7992 +       }
7993 +       
7994 +       if (len < sizeof(struct ipmi_sock_msg)) {
7995 +               err = -EINVAL;
7996 +               dbg("Msg data too small for header: %p", i->user);
7997 +               goto err;
7998 +       }
7999 +
8000 +       err = memcpy_fromiovec((void *)smsg, msg->msg_iov, len);
8001 +       if (err) {
8002 +               dbg("Cannot copy data to kernel: %p", i->user);
8003 +               goto err;
8004 +       }
8005 +       
8006 +       if (len < smsg->data_len+sizeof(struct ipmi_sock_msg)) {
8007 +               err = -EINVAL;
8008 +               dbg("Msg data is out of bound: %p", i->user);
8009 +               goto err;
8010 +       }
8011 +       
8012 +       /* Set defaults. */
8013 +       tparms.retries = i->default_retries;
8014 +       tparms.retry_time_ms = i->default_retry_time_ms;
8015 +
8016 +       for (cmsg=CMSG_FIRSTHDR(msg);
8017 +            cmsg;
8018 +            cmsg = CMSG_NXTHDR(msg, cmsg))
8019 +       {
8020 +               if (cmsg->cmsg_len < sizeof(struct cmsghdr)) {
8021 +                       err = -EINVAL;
8022 +                       dbg("cmsg length too short: %p", i->user);
8023 +                       goto err;
8024 +               }
8025 +
8026 +               if (cmsg->cmsg_level != SOL_SOCKET)
8027 +                       continue;
8028 +
8029 +               if (cmsg->cmsg_type == IPMI_CMSG_TIMING_PARMS) {
8030 +                       struct ipmi_timing_parms *pparms;
8031 +
8032 +                       if (cmsg->cmsg_len != CMSG_LEN(sizeof(*pparms))) {
8033 +                               err = -EINVAL;
8034 +                               dbg("timing parms cmsg not right size: %p",
8035 +                                   i->user);
8036 +                               goto err;
8037 +                       }
8038 +                       pparms = (struct ipmi_timing_parms *) CMSG_DATA(cmsg);
8039 +                       tparms.retries = pparms->retries;
8040 +                       tparms.retry_time_ms = pparms->retry_time_ms;
8041 +               }
8042 +       }
8043 +
8044 +       imsg.netfn      = smsg->netfn;
8045 +       imsg.cmd        = smsg->cmd;
8046 +       imsg.data       = smsg->data;
8047 +       imsg.data_len   = smsg->data_len;
8048 +
8049 +       dbg("user=%p", i->user);
8050 +       dbg("addr_type=%x, channel=%x",
8051 +           addr->ipmi_addr.addr_type, addr->ipmi_addr.channel);
8052 +       dbg("netfn=%#02x, cmd=%#02x, data=%p, data_len=%x", 
8053 +           imsg.netfn, imsg.cmd, imsg.data, imsg.data_len);
8054 +       err = ipmi_request_settime(i->user, &addr->ipmi_addr,
8055 +                                  smsg->msgid, &imsg, 0,
8056 +                                  tparms.retries, tparms.retry_time_ms);
8057 +       if (err) {
8058 +               dbg("Cannot send message: %p", i->user);
8059 +               goto err;
8060 +       }
8061 +       
8062 +err:
8063 +       return err;
8064 +}
8065 +
8066 +static struct proto_ops ipmi_ops = {
8067 +       .family =       PF_IPMI,
8068 +       .release =      ipmi_release,
8069 +       .bind =         ipmi_bind,
8070 +       .connect =      sock_no_connect,
8071 +       .socketpair =   sock_no_socketpair,
8072 +       .accept =       sock_no_accept,
8073 +       .getname =      ipmi_getname,
8074 +       .poll =         ipmi_poll,
8075 +       .ioctl =        ipmi_ioctl,
8076 +       .listen =       sock_no_listen,
8077 +       .shutdown =     sock_no_shutdown,
8078 +       .setsockopt =   sock_no_setsockopt,
8079 +       .getsockopt =   sock_no_getsockopt,
8080 +       .sendmsg =      ipmi_sendmsg,
8081 +       .recvmsg =      ipmi_recvmsg,
8082 +       .mmap =         sock_no_mmap,
8083 +       .sendpage =     sock_no_sendpage
8084 +};
8085 +
8086 +
8087 +static void ipmi_sock_destructor(struct sock *sk)
8088 +{
8089 +       skb_queue_purge(&sk->receive_queue);
8090 +
8091 +       BUG_TRAP(atomic_read(&sk->wmem_alloc) == 0);
8092 +       BUG_TRAP(sk->socket==NULL);
8093 +       if (sk->dead==0) {
8094 +               printk("Attempt to release alive ipmi socket: %p\n", sk);
8095 +               return;
8096 +       }
8097 +
8098 +       atomic_dec(&ipmi_nr_socks);
8099 +       MOD_DEC_USE_COUNT;
8100 +}
8101 +
8102 +/*
8103 + * net protocol functions
8104 + */
8105 +static struct sock *ipmi_socket_create1(struct socket *sock)
8106 +{
8107 +       struct sock *sk;
8108 +
8109 +       if (atomic_read(&ipmi_nr_socks) >= 2*files_stat.max_files)
8110 +               return NULL;
8111 +
8112 +       MOD_INC_USE_COUNT;
8113 +
8114 +       sk = sk_alloc(PF_IPMI, GFP_KERNEL, 1);
8115 +       if (!sk) {
8116 +               MOD_DEC_USE_COUNT;
8117 +               return NULL;
8118 +       }
8119 +       
8120 +       sock_init_data(sock, sk);
8121 +       sock->sk->rcvtimeo = 5*HZ;
8122 +       sock->sk->destruct = ipmi_sock_destructor;
8123 +       spin_lock_init(&sk->protinfo.af_ipmi.lock);
8124 +       INIT_LIST_HEAD(&sk->protinfo.af_ipmi.msg_list);
8125 +       init_waitqueue_head(&sk->protinfo.af_ipmi.wait);
8126 +
8127 +       /* Set to use default values. */
8128 +       sk->protinfo.af_ipmi.default_retries = -1;
8129 +       sk->protinfo.af_ipmi.default_retry_time_ms = 0;
8130 +
8131 +       atomic_inc(&ipmi_nr_socks);
8132 +       return sk;
8133 +}
8134 +
8135 +static int ipmi_socket_create(struct socket *sock, int protocol)
8136 +{
8137 +       if (!capable(CAP_NET_RAW))
8138 +               return -EPERM;
8139 +       if (protocol && protocol != PF_IPMI)
8140 +               return -EPROTONOSUPPORT;
8141 +
8142 +       sock->state = SS_UNCONNECTED;
8143 +
8144 +       switch (sock->type) {
8145 +       case SOCK_RAW:
8146 +               sock->type=SOCK_DGRAM;  
8147 +       case SOCK_DGRAM:
8148 +               sock->ops = &ipmi_ops;
8149 +               break;
8150 +       default:
8151 +               return -EPROTONOSUPPORT;
8152 +       }
8153 +       
8154 +       return ipmi_socket_create1(sock)? 0 : -ENOMEM;
8155 +}
8156 +
8157 +static struct net_proto_family ipmi_family_ops = {
8158 +       .family = PF_IPMI,
8159 +       .create = ipmi_socket_create,
8160 +};
8161 +
8162 +
8163 +/* 
8164 + * init/exit functions
8165 + */
8166 +static int __init ipmi_socket_init(void)
8167 +{
8168 +
8169 +       int err=0;
8170 +       
8171 +       printk(KERN_INFO "ipmi socket interface version "
8172 +              IPMI_SOCKINTF_VERSION "\n");
8173 +
8174 +       ipmi_sk_cachep = kmem_cache_create("ipmi_sock",
8175 +                                          sizeof(struct ipmi_sock), 0,
8176 +                                          SLAB_HWCACHE_ALIGN, 0, 0);
8177 +       if (!ipmi_sk_cachep) {
8178 +               printk(KERN_CRIT "%s: Unable to create ipmi_sock SLAB cache\n", __func__);
8179 +               err = -ENOMEM;
8180 +               goto out;
8181 +       }
8182 +       
8183 +       err = sock_register(&ipmi_family_ops);
8184 +       if (err)
8185 +               kmem_cache_destroy(ipmi_sk_cachep);
8186 +out:
8187 +       return err;
8188 +}
8189 +
8190 +static void __exit ipmi_socket_exit(void)
8191 +{
8192 +       sock_unregister(PF_IPMI);
8193 +       kmem_cache_destroy(ipmi_sk_cachep);
8194 +}
8195 +
8196 +#ifdef CONFIG_DEBUG_KERNEL
8197 +MODULE_PARM(debug, "i");
8198 +#endif
8199 +module_init(ipmi_socket_init);
8200 +module_exit(ipmi_socket_exit);
8201 +
8202 +MODULE_LICENSE("GPL");
8203 diff -urN linux-2.4.23.org/net/ipmi/Makefile linux-2.4.23/net/ipmi/Makefile
8204 --- linux-2.4.23.org/net/ipmi/Makefile  1970-01-01 01:00:00.000000000 +0100
8205 +++ linux-2.4.23/net/ipmi/Makefile      2004-01-02 23:33:48.189781104 +0100
8206 @@ -0,0 +1,7 @@
8207 +
8208 +O_TARGET = ipmi.o
8209 +
8210 +obj-$(CONFIG_IPMI_SOCKET) = af_ipmi.o
8211 +
8212 +include $(TOPDIR)/Rules.make
8213 +
8214 diff -urN linux-2.4.23.org/net/Makefile linux-2.4.23/net/Makefile
8215 --- linux-2.4.23.org/net/Makefile       2004-01-02 23:31:20.022566302 +0100
8216 +++ linux-2.4.23/net/Makefile   2004-01-02 23:34:55.468801116 +0100
8217 @@ -8,7 +8,7 @@
8218  O_TARGET :=    network.o
8219  
8220  mod-subdirs := ipv4/netfilter ipv6/netfilter bridge/netfilter ipx irda \
8221 -       bluetooth atm netlink sched core sctp
8222 +       bluetooth atm netlink sched core sctp ipmi
8223  export-objs := netsyms.o
8224  
8225  subdir-y :=    core ethernet
8226 @@ -54,6 +54,7 @@
8227  subdir-$(CONFIG_DECNET)                += decnet
8228  subdir-$(CONFIG_ECONET)                += econet
8229  subdir-$(CONFIG_VLAN_8021Q)           += 8021q
8230 +subdir-$(CONFIG_IPMI_SOCKET)   += ipmi
8231  
8232  ifeq ($(CONFIG_NETFILTER),y)
8233    mod-subdirs += ipv4/ipvs
This page took 2.167422 seconds and 3 git commands to generate.