]> git.pld-linux.org Git - packages/kernel.git/blob - linux-2.4.23-ipmi-v27.patch
- adapted to current LINUX_2_6
[packages/kernel.git] / linux-2.4.23-ipmi-v27.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       2003-12-06 17:45:52.831977967 +0100
3 +++ linux-2.4.23/Documentation/Configure.help   2003-12-06 17:46:42.774500910 +0100
4 @@ -4226,6 +4226,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 @@ -29334,14 +29341,32 @@
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 Watchdog Timer
51  CONFIG_IPMI_WATCHDOG
52 diff -urN linux-2.4.23.org/Documentation/IPMI.txt linux-2.4.23/Documentation/IPMI.txt
53 --- linux-2.4.23.org/Documentation/IPMI.txt     2003-12-06 12:55:11.829841204 +0100
54 +++ linux-2.4.23/Documentation/IPMI.txt 2003-12-06 17:46:42.792497135 +0100
55 @@ -41,18 +41,29 @@
56  driver, each open file for this device ties in to the message handler
57  as an IPMI user.
58  
59 -ipmi_kcs_drv - A driver for the KCS SMI.  Most system have a KCS
60 -interface for IPMI.
61 +ipmi_si_drv - A driver for various system interfaces.  This supports
62 +KCS, SMIC, and may support BT in the future.  Unless you have your own
63 +custom interface, you probably need to use this.
64 +
65 +ipmi_kcs_drv - A driver for the KCS SI.  Most systems have a KCS
66 +interface for IPMI.  This is deprecated, ipmi_si_drv supports KCS and
67 +SMIC interfaces.
68 +
69 +af_ipmi - A network socket interface to IPMI.  This doesn't take up
70 +a character device in your system.
71  
72  
73  Much documentation for the interface is in the include files.  The
74  IPMI include files are:
75  
76 -ipmi.h - Contains the user interface and IOCTL interface for IPMI.
77 +net/af_ipmi.h - Contains the socket interface.
78 +
79 +linux/ipmi.h - Contains the user interface and IOCTL interface for IPMI.
80  
81 -ipmi_smi.h - Contains the interface for SMI drivers to use.
82 +linux/ipmi_smi.h - Contains the interface for system management interfaces
83 +(things that interface to IPMI controllers) to use.
84  
85 -ipmi_msgdefs.h - General definitions for base IPMI messaging.
86 +linux/ipmi_msgdefs.h - General definitions for base IPMI messaging.
87  
88  
89  Addressing
90 @@ -260,8 +271,66 @@
91  in the order they register, although if an SMI unregisters and then
92  another one registers, all bets are off.
93  
94 -The ipmi_smi.h defines the interface for SMIs, see that for more
95 -details.
96 +The ipmi_smi.h defines the interface for management interfaces, see
97 +that for more details.
98 +
99 +
100 +The SI Driver
101 +-------------
102 +
103 +The SI driver allows up to 4 KCS or SMIC interfaces to be configured
104 +in the system.  By default, scan the ACPI tables for interfaces, and
105 +if it doesn't find any the driver will attempt to register one KCS
106 +interface at the spec-specified I/O port 0xca2 without interrupts.
107 +You can change this at module load time (for a module) with:
108 +
109 +  insmod ipmi_si_drv.o si_type=<type1>,<type2>....
110 +       si_ports=<port1>,<port2>... si_addrs=<addr1>,<addr2>
111 +       si_irqs=<irq1>,<irq2>... si_trydefaults=[0|1]
112 +
113 +Each of these except si_trydefaults is a list, the first item for the
114 +first interface, second item for the second interface, etc.
115 +
116 +The si_type may be either "kcs" or "smic".  If you leave it blank, it
117 +defaults to "kcs".
118 +
119 +If you specify si_addrs as non-zero for an interface, the driver will
120 +use the memory address given as the address of the device.  This
121 +overrides si_ports.
122 +
123 +If you specify si_ports as non-zero for an interface, the driver will
124 +use the I/O port given as the device address.
125 +
126 +If you specify si_irqs as non-zero for an interface, the driver will
127 +attempt to use the given interrupt for the device.
128 +
129 +si_trydefaults sets whether the standard IPMI interface at 0xca2 and
130 +any interfaces specified by ACPE are tried.  By default, the driver
131 +tries it, set this value to zero to turn this off.
132 +
133 +When compiled into the kernel, the addresses can be specified on the
134 +kernel command line as:
135 +
136 +  ipmi_si=[<type>,]<bmc1>:<irq1>,[<type>,]<bmc2>:<irq2>....,[nodefault]
137 +
138 +The type is optional and may be either "kcs" for KCS or "smic" for
139 +SMIC.  If not specified, it defaults to KCS.  The <bmcx> values is
140 +either "p<port>" or "m<addr>" for port or memory addresses.  So for
141 +instance, a KCS interface at port 0xca2 using interrupt 9 and a SMIC
142 +memory interface at address 0xf9827341 with no interrupt would be
143 +specified "ipmi_si=k,p0xca2:9,s,m0xf9827341".  If you specify zero
144 +for in irq or don't specify it, the driver will run polled unless the
145 +software can detect the interrupt to use in the ACPI tables.
146 +
147 +By default, the driver will attempt to detect a KCS device at the
148 +spec-specified 0xca2 address and any address specified by ACPI.  If
149 +you want to turn this off, use the "nodefault" option.
150 +
151 +If you have high-res timers compiled into the kernel, the driver will
152 +use them to provide much better performance.  Note that if you do not
153 +have high-res timers enabled in the kernel and you don't have
154 +interrupts enabled, the driver will run VERY slowly.  Don't blame me,
155 +these interfaces suck.
156  
157  
158  The KCS Driver
159 @@ -323,7 +392,10 @@
160  
161  The timeout is the number of seconds to the action, and the pretimeout
162  is the amount of seconds before the reset that the pre-timeout panic will
163 -occur (if pretimeout is zero, then pretimeout will not be enabled).
164 +occur (if pretimeout is zero, then pretimeout will not be enabled).  Note
165 +that the pretimeout is the time before the final timeout.  So if the
166 +timeout is 50 seconds and the pretimeout is 10 seconds, then the pretimeout
167 +will occur in 40 second (10 seconds before the timeout).
168  
169  The action may be "reset", "power_cycle", or "power_off", and
170  specifies what to do when the timer times out, and defaults to
171 diff -urN linux-2.4.23.org/drivers/char/Config.in linux-2.4.23/drivers/char/Config.in
172 --- linux-2.4.23.org/drivers/char/Config.in     2003-12-06 12:53:22.102691137 +0100
173 +++ linux-2.4.23/drivers/char/Config.in 2003-12-06 17:46:42.890476581 +0100
174 @@ -213,7 +213,9 @@
175  
176  tristate 'IPMI top-level message handler' CONFIG_IPMI_HANDLER
177  dep_mbool '  Generate a panic event to all BMCs on a panic' CONFIG_IPMI_PANIC_EVENT $CONFIG_IPMI_HANDLER
178 +dep_mbool '  Generate a OEM events holding the panic string' CONFIG_IPMI_PANIC_STRING $CONFIG_IPMI_PANIC_EVENT
179  dep_tristate '  Device interface for IPMI' CONFIG_IPMI_DEVICE_INTERFACE $CONFIG_IPMI_HANDLER
180 +dep_tristate '  IPMI SI handler' CONFIG_IPMI_SI $CONFIG_IPMI_HANDLER
181  dep_tristate '  IPMI KCS handler' CONFIG_IPMI_KCS $CONFIG_IPMI_HANDLER
182  dep_tristate '  IPMI Watchdog Timer' CONFIG_IPMI_WATCHDOG $CONFIG_IPMI_HANDLER
183  
184 diff -urN linux-2.4.23.org/drivers/char/ipmi/ipmi_devintf.c linux-2.4.23/drivers/char/ipmi/ipmi_devintf.c
185 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_devintf.c   2003-12-06 12:53:23.036496678 +0100
186 +++ linux-2.4.23/drivers/char/ipmi/ipmi_devintf.c       2003-12-06 17:46:42.918470709 +0100
187 @@ -44,6 +44,8 @@
188  #include <asm/semaphore.h>
189  #include <linux/init.h>
190  
191 +#define IPMI_DEVINTF_VERSION "v27"
192 +
193  struct ipmi_file_private
194  {
195         ipmi_user_t          user;
196 @@ -53,6 +55,8 @@
197         struct fasync_struct *fasync_queue;
198         wait_queue_head_t    wait;
199         struct semaphore     recv_sem;
200 +       int                  default_retries;
201 +       unsigned int         default_retry_time_ms;
202  };
203  
204  static void file_receive_handler(struct ipmi_recv_msg *msg,
205 @@ -105,7 +109,7 @@
206  
207  static struct ipmi_user_hndl ipmi_hndlrs =
208  {
209 -       ipmi_recv_hndl : file_receive_handler
210 +       .ipmi_recv_hndl = file_receive_handler,
211  };
212  
213  static int ipmi_open(struct inode *inode, struct file *file)
214 @@ -138,6 +142,10 @@
215         priv->fasync_queue = NULL;
216         sema_init(&(priv->recv_sem), 1);
217  
218 +       /* Use the low-level defaults. */
219 +       priv->default_retries = -1;
220 +       priv->default_retry_time_ms = 0;
221 +
222         return 0;
223  }
224  
225 @@ -158,6 +166,47 @@
226         return 0;
227  }
228  
229 +static int handle_send_req(ipmi_user_t     user,
230 +                          struct ipmi_req *req,
231 +                          int             retries,
232 +                          unsigned int    retry_time_ms)
233 +{
234 +       int              rv;
235 +       struct ipmi_addr addr;
236 +       unsigned char    msgdata[IPMI_MAX_MSG_LENGTH];
237 +
238 +       if (req->addr_len > sizeof(struct ipmi_addr))
239 +               return -EINVAL;
240 +
241 +       if (copy_from_user(&addr, req->addr, req->addr_len))
242 +               return -EFAULT;
243 +
244 +       rv = ipmi_validate_addr(&addr, req->addr_len);
245 +       if (rv)
246 +               return rv;
247 +
248 +       if (req->msg.data != NULL) {
249 +               if (req->msg.data_len > IPMI_MAX_MSG_LENGTH)
250 +                       return -EMSGSIZE;
251 +
252 +               if (copy_from_user(&msgdata,
253 +                                  req->msg.data,
254 +                                  req->msg.data_len))
255 +                       return -EFAULT;
256 +       } else {
257 +               req->msg.data_len = 0;
258 +       }
259 +       req->msg.data = msgdata;
260 +
261 +       return ipmi_request_settime(user,
262 +                                   &addr,
263 +                                   req->msgid,
264 +                                   &(req->msg),
265 +                                   0,
266 +                                   retries,
267 +                                   retry_time_ms);
268 +}
269 +
270  static int ipmi_ioctl(struct inode  *inode,
271                       struct file   *file,
272                       unsigned int  cmd,
273 @@ -170,54 +219,33 @@
274         {
275         case IPMICTL_SEND_COMMAND:
276         {
277 -               struct ipmi_req    req;
278 -               struct ipmi_addr   addr;
279 -               unsigned char msgdata[IPMI_MAX_MSG_LENGTH];
280 +               struct ipmi_req req;
281  
282                 if (copy_from_user(&req, (void *) data, sizeof(req))) {
283                         rv = -EFAULT;
284                         break;
285                 }
286  
287 -               if (req.addr_len > sizeof(struct ipmi_addr))
288 -               {
289 -                       rv = -EINVAL;
290 -                       break;
291 -               }
292 +               rv = handle_send_req(priv->user,
293 +                                    &req,
294 +                                    priv->default_retries,
295 +                                    priv->default_retry_time_ms);
296 +               break;
297 +       }
298  
299 -               if (copy_from_user(&addr, req.addr, req.addr_len)) {
300 +       case IPMICTL_SEND_COMMAND_SETTIME:
301 +       {
302 +               struct ipmi_req_settime req;
303 +
304 +               if (copy_from_user(&req, (void *) data, sizeof(req))) {
305                         rv = -EFAULT;
306                         break;
307                 }
308  
309 -               rv = ipmi_validate_addr(&addr, req.addr_len);
310 -               if (rv)
311 -                       break;
312 -
313 -               if (req.msg.data != NULL) {
314 -                       if (req.msg.data_len > IPMI_MAX_MSG_LENGTH) {
315 -                               rv = -EMSGSIZE;
316 -                               break;
317 -                       }
318 -
319 -                       if (copy_from_user(&msgdata,
320 -                                          req.msg.data,
321 -                                          req.msg.data_len))
322 -                       {
323 -                               rv = -EFAULT;
324 -                               break;
325 -                       }
326 -               } else {
327 -                       req.msg.data_len = 0;
328 -               }
329 -
330 -               req.msg.data = msgdata;
331 -
332 -               rv = ipmi_request(priv->user,
333 -                                 &addr,
334 -                                 req.msgid,
335 -                                 &(req.msg),
336 -                                 0);
337 +               rv = handle_send_req(priv->user,
338 +                                    &req.req,
339 +                                    req.retries,
340 +                                    req.retry_time_ms);
341                 break;
342         }
343  
344 @@ -416,7 +444,36 @@
345                 rv = 0;
346                 break;
347         }
348 +       case IPMICTL_SET_TIMING_PARMS_CMD:
349 +       {
350 +               struct ipmi_timing_parms parms;
351 +
352 +               if (copy_from_user(&parms, (void *) data, sizeof(parms))) {
353 +                       rv = -EFAULT;
354 +                       break;
355 +               }
356 +
357 +               priv->default_retries = parms.retries;
358 +               priv->default_retry_time_ms = parms.retry_time_ms;
359 +               rv = 0;
360 +               break;
361 +       }
362 +
363 +       case IPMICTL_GET_TIMING_PARMS_CMD:
364 +       {
365 +               struct ipmi_timing_parms parms;
366 +
367 +               parms.retries = priv->default_retries;
368 +               parms.retry_time_ms = priv->default_retry_time_ms;
369  
370 +               if (copy_to_user((void *) data, &parms, sizeof(parms))) {
371 +                       rv = -EFAULT;
372 +                       break;
373 +               }
374 +
375 +               rv = 0;
376 +               break;
377 +       }
378         }
379    
380         return rv;
381 @@ -424,12 +481,12 @@
382  
383  
384  static struct file_operations ipmi_fops = {
385 -       owner:   THIS_MODULE,
386 -       ioctl:   ipmi_ioctl,
387 -       open:    ipmi_open,
388 -       release: ipmi_release,
389 -       fasync:  ipmi_fasync,
390 -       poll:    ipmi_poll
391 +       .owner          = THIS_MODULE,
392 +       .ioctl          = ipmi_ioctl,
393 +       .open           = ipmi_open,
394 +       .release        = ipmi_release,
395 +       .fasync         = ipmi_fasync,
396 +       .poll           = ipmi_poll,
397  };
398  
399  #define DEVICE_NAME     "ipmidev"
400 @@ -468,8 +525,9 @@
401  
402  static struct ipmi_smi_watcher smi_watcher =
403  {
404 -       new_smi  : ipmi_new_smi,
405 -       smi_gone : ipmi_smi_gone
406 +       .owner    = THIS_MODULE,
407 +       .new_smi  = ipmi_new_smi,
408 +       .smi_gone = ipmi_smi_gone,
409  };
410  
411  static __init int init_ipmi_devintf(void)
412 @@ -479,6 +537,9 @@
413         if (ipmi_major < 0)
414                 return -EINVAL;
415  
416 +       printk(KERN_INFO "ipmi device interface version "
417 +              IPMI_DEVINTF_VERSION "\n");
418 +
419         rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
420         if (rv < 0) {
421                 printk(KERN_ERR "ipmi: can't get major %d\n", ipmi_major);
422 @@ -498,9 +559,6 @@
423                 return rv;
424         }
425  
426 -       printk(KERN_INFO "ipmi: device interface at char major %d\n",
427 -              ipmi_major);
428 -
429         return 0;
430  }
431  module_init(init_ipmi_devintf);
432 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
433 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_kcs_intf.c  2003-12-06 12:53:22.989506463 +0100
434 +++ linux-2.4.23/drivers/char/ipmi/ipmi_kcs_intf.c      2003-12-06 17:46:42.974458964 +0100
435 @@ -54,7 +54,7 @@
436  #include <linux/interrupt.h>
437  #include <linux/ipmi_smi.h>
438  #include <asm/io.h>
439 -#include "ipmi_kcs_sm.h"
440 +#include "ipmi_si_sm.h"
441  #include <linux/init.h>
442  
443  /* Measure times between events in the driver. */
444 @@ -72,6 +72,8 @@
445  /* This forces a dependency to the config file for this option. */
446  #endif
447  
448 +extern struct si_sm_handlers kcs_smi_handlers;
449 +
450  enum kcs_intf_state {
451         KCS_NORMAL,
452         KCS_GETTING_FLAGS,
453 @@ -87,7 +89,7 @@
454  struct kcs_info
455  {
456         ipmi_smi_t          intf;
457 -       struct kcs_data     *kcs_sm;
458 +       struct si_sm_data   *kcs_sm;
459         spinlock_t          kcs_lock;
460         spinlock_t          msg_lock;
461         struct list_head    xmit_msgs;
462 @@ -112,8 +114,10 @@
463            out. */
464         int                 run_to_completion;
465  
466 +       struct si_sm_io     io;
467 +
468         /* The I/O port of a KCS interface. */
469 -       int                 port;
470 +       unsigned int        port;
471  
472         /* zero if no irq; */
473         int                 irq;
474 @@ -164,7 +168,7 @@
475         deliver_recv_msg(kcs_info, msg);
476  }
477  
478 -static enum kcs_result start_next_msg(struct kcs_info *kcs_info)
479 +static enum si_sm_result start_next_msg(struct kcs_info *kcs_info)
480  {
481         int              rv;
482         struct list_head *entry = NULL;
483 @@ -185,7 +189,7 @@
484  
485         if (!entry) {
486                 kcs_info->curr_msg = NULL;
487 -               rv = KCS_SM_IDLE;
488 +               rv = SI_SM_IDLE;
489         } else {
490                 int err;
491  
492 @@ -197,14 +201,15 @@
493                 do_gettimeofday(&t);
494                 printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec);
495  #endif
496 -               err = start_kcs_transaction(kcs_info->kcs_sm,
497 -                                          kcs_info->curr_msg->data,
498 -                                          kcs_info->curr_msg->data_size);
499 +               err = kcs_smi_handlers.start_transaction(
500 +                   kcs_info->kcs_sm,
501 +                   kcs_info->curr_msg->data,
502 +                   kcs_info->curr_msg->data_size);
503                 if (err) {
504                         return_hosed_msg(kcs_info);
505                 }
506  
507 -               rv = KCS_CALL_WITHOUT_DELAY;
508 +               rv = SI_SM_CALL_WITHOUT_DELAY;
509         }
510         spin_unlock(&(kcs_info->msg_lock));
511  
512 @@ -220,7 +225,7 @@
513         msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
514         msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
515  
516 -       start_kcs_transaction(kcs_info->kcs_sm, msg, 2);
517 +       kcs_smi_handlers.start_transaction(kcs_info->kcs_sm, msg, 2);
518         kcs_info->kcs_state = KCS_ENABLE_INTERRUPTS1;
519  }
520  
521 @@ -233,7 +238,7 @@
522         msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD;
523         msg[2] = WDT_PRE_TIMEOUT_INT;
524  
525 -       start_kcs_transaction(kcs_info->kcs_sm, msg, 3);
526 +       kcs_smi_handlers.start_transaction(kcs_info->kcs_sm, msg, 3);
527         kcs_info->kcs_state = KCS_CLEARING_FLAGS;
528  }
529  
530 @@ -280,9 +285,10 @@
531                 kcs_info->curr_msg->data[1] = IPMI_GET_MSG_CMD;
532                 kcs_info->curr_msg->data_size = 2;
533  
534 -               start_kcs_transaction(kcs_info->kcs_sm,
535 -                                     kcs_info->curr_msg->data,
536 -                                     kcs_info->curr_msg->data_size);
537 +               kcs_smi_handlers.start_transaction(
538 +                   kcs_info->kcs_sm,
539 +                   kcs_info->curr_msg->data,
540 +                   kcs_info->curr_msg->data_size);
541                 kcs_info->kcs_state = KCS_GETTING_MESSAGES;
542         } else if (kcs_info->msg_flags & EVENT_MSG_BUFFER_FULL) {
543                 /* Events available. */
544 @@ -298,9 +304,10 @@
545                 kcs_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD;
546                 kcs_info->curr_msg->data_size = 2;
547  
548 -               start_kcs_transaction(kcs_info->kcs_sm,
549 -                                     kcs_info->curr_msg->data,
550 -                                     kcs_info->curr_msg->data_size);
551 +               kcs_smi_handlers.start_transaction(
552 +                   kcs_info->kcs_sm,
553 +                   kcs_info->curr_msg->data,
554 +                   kcs_info->curr_msg->data_size);
555                 kcs_info->kcs_state = KCS_GETTING_EVENTS;
556         } else {
557                 kcs_info->kcs_state = KCS_NORMAL;
558 @@ -322,9 +329,10 @@
559                         break;
560                         
561                 kcs_info->curr_msg->rsp_size
562 -                       = kcs_get_result(kcs_info->kcs_sm,
563 -                                        kcs_info->curr_msg->rsp,
564 -                                        IPMI_MAX_MSG_LENGTH);
565 +                       = kcs_smi_handlers.get_result(
566 +                           kcs_info->kcs_sm,
567 +                           kcs_info->curr_msg->rsp,
568 +                           IPMI_MAX_MSG_LENGTH);
569                 
570                 /* Do this here becase deliver_recv_msg() releases the
571                    lock, and a new message can be put in during the
572 @@ -340,7 +348,7 @@
573                 unsigned int  len;
574  
575                 /* We got the flags from the KCS, now handle them. */
576 -               len = kcs_get_result(kcs_info->kcs_sm, msg, 4);
577 +               len = kcs_smi_handlers.get_result(kcs_info->kcs_sm, msg, 4);
578                 if (msg[2] != 0) {
579                         /* Error fetching flags, just give up for
580                            now. */
581 @@ -362,7 +370,7 @@
582                 unsigned char msg[3];
583  
584                 /* We cleared the flags. */
585 -               kcs_get_result(kcs_info->kcs_sm, msg, 3);
586 +               kcs_smi_handlers.get_result(kcs_info->kcs_sm, msg, 3);
587                 if (msg[2] != 0) {
588                         /* Error clearing flags */
589                         printk(KERN_WARNING
590 @@ -379,9 +387,9 @@
591         case KCS_GETTING_EVENTS:
592         {
593                 kcs_info->curr_msg->rsp_size
594 -                       = kcs_get_result(kcs_info->kcs_sm,
595 -                                        kcs_info->curr_msg->rsp,
596 -                                        IPMI_MAX_MSG_LENGTH);
597 +                       = kcs_smi_handlers.get_result(kcs_info->kcs_sm,
598 +                                                     kcs_info->curr_msg->rsp,
599 +                                                     IPMI_MAX_MSG_LENGTH);
600  
601                 /* Do this here becase deliver_recv_msg() releases the
602                    lock, and a new message can be put in during the
603 @@ -404,9 +412,9 @@
604         case KCS_GETTING_MESSAGES:
605         {
606                 kcs_info->curr_msg->rsp_size
607 -                       = kcs_get_result(kcs_info->kcs_sm,
608 -                                        kcs_info->curr_msg->rsp,
609 -                                        IPMI_MAX_MSG_LENGTH);
610 +                       = kcs_smi_handlers.get_result(kcs_info->kcs_sm,
611 +                                                     kcs_info->curr_msg->rsp,
612 +                                                     IPMI_MAX_MSG_LENGTH);
613  
614                 /* Do this here becase deliver_recv_msg() releases the
615                    lock, and a new message can be put in during the
616 @@ -431,7 +439,7 @@
617                 unsigned char msg[4];
618  
619                 /* We got the flags from the KCS, now handle them. */
620 -               kcs_get_result(kcs_info->kcs_sm, msg, 4);
621 +               kcs_smi_handlers.get_result(kcs_info->kcs_sm, msg, 4);
622                 if (msg[2] != 0) {
623                         printk(KERN_WARNING
624                                "ipmi_kcs: Could not enable interrupts"
625 @@ -441,7 +449,8 @@
626                         msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
627                         msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
628                         msg[2] = msg[3] | 1; /* enable msg queue int */
629 -                       start_kcs_transaction(kcs_info->kcs_sm, msg,3);
630 +                       kcs_smi_handlers.start_transaction(
631 +                           kcs_info->kcs_sm, msg,3);
632                         kcs_info->kcs_state = KCS_ENABLE_INTERRUPTS2;
633                 }
634                 break;
635 @@ -452,7 +461,7 @@
636                 unsigned char msg[4];
637  
638                 /* We got the flags from the KCS, now handle them. */
639 -               kcs_get_result(kcs_info->kcs_sm, msg, 4);
640 +               kcs_smi_handlers.get_result(kcs_info->kcs_sm, msg, 4);
641                 if (msg[2] != 0) {
642                         printk(KERN_WARNING
643                                "ipmi_kcs: Could not enable interrupts"
644 @@ -466,9 +475,10 @@
645  
646  /* Called on timeouts and events.  Timeouts should pass the elapsed
647     time, interrupts should pass in zero. */
648 -static enum kcs_result kcs_event_handler(struct kcs_info *kcs_info, int time)
649 +static enum si_sm_result kcs_event_handler(struct kcs_info *kcs_info,
650 +                                          int time)
651  {
652 -       enum kcs_result kcs_result;
653 +       enum si_sm_result kcs_result;
654  
655   restart:
656         /* There used to be a loop here that waited a little while
657 @@ -477,19 +487,19 @@
658            range, which is far too long to wait in an interrupt.  So
659            we just run until the state machine tells us something
660            happened or it needs a delay. */
661 -       kcs_result = kcs_event(kcs_info->kcs_sm, time);
662 +       kcs_result = kcs_smi_handlers.event(kcs_info->kcs_sm, time);
663         time = 0;
664 -       while (kcs_result == KCS_CALL_WITHOUT_DELAY)
665 +       while (kcs_result == SI_SM_CALL_WITHOUT_DELAY)
666         {
667 -               kcs_result = kcs_event(kcs_info->kcs_sm, 0);
668 +               kcs_result = kcs_smi_handlers.event(kcs_info->kcs_sm, 0);
669         }
670  
671 -       if (kcs_result == KCS_TRANSACTION_COMPLETE)
672 +       if (kcs_result == SI_SM_TRANSACTION_COMPLETE)
673         {
674                 handle_transaction_done(kcs_info);
675 -               kcs_result = kcs_event(kcs_info->kcs_sm, 0);
676 +               kcs_result = kcs_smi_handlers.event(kcs_info->kcs_sm, 0);
677         }
678 -       else if (kcs_result == KCS_SM_HOSED)
679 +       else if (kcs_result == SI_SM_HOSED)
680         {
681                 if (kcs_info->curr_msg != NULL) {
682                         /* If we were handling a user message, format
683 @@ -497,12 +507,12 @@
684                             tell it about the error. */
685                         return_hosed_msg(kcs_info);
686                 }
687 -               kcs_result = kcs_event(kcs_info->kcs_sm, 0);
688 +               kcs_result = kcs_smi_handlers.event(kcs_info->kcs_sm, 0);
689                 kcs_info->kcs_state = KCS_NORMAL;
690         }
691  
692         /* We prefer handling attn over new messages. */
693 -       if (kcs_result == KCS_ATTN)
694 +       if (kcs_result == SI_SM_ATTN)
695         {
696                 unsigned char msg[2];
697  
698 @@ -514,19 +524,19 @@
699                 msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
700                 msg[1] = IPMI_GET_MSG_FLAGS_CMD;
701  
702 -               start_kcs_transaction(kcs_info->kcs_sm, msg, 2);
703 +               kcs_smi_handlers.start_transaction(kcs_info->kcs_sm, msg, 2);
704                 kcs_info->kcs_state = KCS_GETTING_FLAGS;
705                 goto restart;
706         }
707  
708         /* If we are currently idle, try to start the next message. */
709 -       if (kcs_result == KCS_SM_IDLE) {
710 +       if (kcs_result == SI_SM_IDLE) {
711                 kcs_result = start_next_msg(kcs_info);
712 -               if (kcs_result != KCS_SM_IDLE)
713 +               if (kcs_result != SI_SM_IDLE)
714                         goto restart;
715          }
716  
717 -       if ((kcs_result == KCS_SM_IDLE)
718 +       if ((kcs_result == SI_SM_IDLE)
719             && (atomic_read(&kcs_info->req_events)))
720         {
721                 /* We are idle and the upper layer requested that I fetch
722 @@ -537,7 +547,7 @@
723                 msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
724                 msg[1] = IPMI_GET_MSG_FLAGS_CMD;
725  
726 -               start_kcs_transaction(kcs_info->kcs_sm, msg, 2);
727 +               kcs_smi_handlers.start_transaction(kcs_info->kcs_sm, msg, 2);
728                 kcs_info->kcs_state = KCS_GETTING_FLAGS;
729                 goto restart;
730         }
731 @@ -549,11 +559,11 @@
732                    struct ipmi_smi_msg *msg,
733                    int                 priority)
734  {
735 -       struct kcs_info *kcs_info = (struct kcs_info *) send_info;
736 -       enum kcs_result result;
737 -       unsigned long   flags;
738 +       struct kcs_info    *kcs_info = (struct kcs_info *) send_info;
739 +       enum si_sm_result  result;
740 +       unsigned long      flags;
741  #ifdef DEBUG_TIMING
742 -       struct timeval t;
743 +       struct timeval     t;
744  #endif
745  
746         spin_lock_irqsave(&(kcs_info->msg_lock), flags);
747 @@ -574,7 +584,7 @@
748  
749                 spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
750                 result = kcs_event_handler(kcs_info, 0);
751 -               while (result != KCS_SM_IDLE) {
752 +               while (result != SI_SM_IDLE) {
753                         udelay(KCS_SHORT_TIMEOUT_USEC);
754                         result = kcs_event_handler(kcs_info,
755                                                    KCS_SHORT_TIMEOUT_USEC);
756 @@ -602,16 +612,16 @@
757  
758  static void set_run_to_completion(void *send_info, int i_run_to_completion)
759  {
760 -       struct kcs_info *kcs_info = (struct kcs_info *) send_info;
761 -       enum kcs_result result;
762 -       unsigned long   flags;
763 +       struct kcs_info    *kcs_info = (struct kcs_info *) send_info;
764 +       enum si_sm_result  result;
765 +       unsigned long      flags;
766  
767         spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
768  
769         kcs_info->run_to_completion = i_run_to_completion;
770         if (i_run_to_completion) {
771                 result = kcs_event_handler(kcs_info, 0);
772 -               while (result != KCS_SM_IDLE) {
773 +               while (result != SI_SM_IDLE) {
774                         udelay(KCS_SHORT_TIMEOUT_USEC);
775                         result = kcs_event_handler(kcs_info,
776                                                    KCS_SHORT_TIMEOUT_USEC);
777 @@ -676,13 +686,13 @@
778  
779  static void kcs_timeout(unsigned long data)
780  {
781 -       struct kcs_info *kcs_info = (struct kcs_info *) data;
782 -       enum kcs_result kcs_result;
783 -       unsigned long   flags;
784 -       unsigned long   jiffies_now;
785 -       unsigned long   time_diff;
786 +       struct kcs_info    *kcs_info = (struct kcs_info *) data;
787 +       enum si_sm_result  kcs_result;
788 +       unsigned long      flags;
789 +       unsigned long      jiffies_now;
790 +       unsigned long      time_diff;
791  #ifdef DEBUG_TIMING
792 -       struct timeval t;
793 +       struct timeval     t;
794  #endif
795  
796         if (kcs_info->stop_operation) {
797 @@ -712,7 +722,7 @@
798         /* If the state machine asks for a short delay, then shorten
799             the timer timeout. */
800  #ifdef CONFIG_HIGH_RES_TIMERS
801 -       if (kcs_result == KCS_CALL_WITH_DELAY) {
802 +       if (kcs_result == SI_SM_CALL_WITH_DELAY) {
803                 kcs_info->kcs_timer.sub_expires
804                         += usec_to_arch_cycles(KCS_SHORT_TIMEOUT_USEC);
805                 while (kcs_info->kcs_timer.sub_expires >= cycles_per_jiffies) {
806 @@ -725,7 +735,7 @@
807         }
808  #else
809         /* If requested, take the shortest delay possible */
810 -       if (kcs_result == KCS_CALL_WITH_DELAY) {
811 +       if (kcs_result == SI_SM_CALL_WITH_DELAY) {
812                 kcs_info->kcs_timer.expires = jiffies + 1;
813         } else {
814                 kcs_info->kcs_timer.expires = jiffies + KCS_TIMEOUT_JIFFIES;
815 @@ -776,12 +786,12 @@
816  extern int kcs_dbg;
817  static int ipmi_kcs_detect_hardware(unsigned int port,
818                                     unsigned char *addr,
819 -                                   struct kcs_data *data)
820 +                                   struct si_sm_data *data)
821  {
822 -       unsigned char   msg[2];
823 -       unsigned char   resp[IPMI_MAX_MSG_LENGTH];
824 -       unsigned long   resp_len;
825 -       enum kcs_result kcs_result;
826 +       unsigned char      msg[2];
827 +       unsigned char      resp[IPMI_MAX_MSG_LENGTH];
828 +       unsigned long      resp_len;
829 +       enum si_sm_result  kcs_result;
830  
831         /* It's impossible for the KCS status register to be all 1's,
832            (assuming a properly functioning, self-initialized BMC)
833 @@ -798,29 +808,30 @@
834            useful info. */
835         msg[0] = IPMI_NETFN_APP_REQUEST << 2;
836         msg[1] = IPMI_GET_DEVICE_ID_CMD;
837 -       start_kcs_transaction(data, msg, 2);
838 +       kcs_smi_handlers.start_transaction(data, msg, 2);
839         
840 -       kcs_result = kcs_event(data, 0);
841 +       kcs_result = kcs_smi_handlers.event(data, 0);
842         for (;;)
843         {
844 -               if (kcs_result == KCS_CALL_WITH_DELAY) {
845 -                       udelay(100);
846 -                       kcs_result = kcs_event(data, 100);
847 +               if (kcs_result == SI_SM_CALL_WITH_DELAY) {
848 +                       schedule_timeout(1);
849 +                       kcs_result = kcs_smi_handlers.event(data, 100);
850                 }
851 -               else if (kcs_result == KCS_CALL_WITHOUT_DELAY)
852 +               else if (kcs_result == SI_SM_CALL_WITHOUT_DELAY)
853                 {
854 -                       kcs_result = kcs_event(data, 0);
855 +                       kcs_result = kcs_smi_handlers.event(data, 0);
856                 }
857                 else
858                         break;
859         }
860 -       if (kcs_result == KCS_SM_HOSED) {
861 +       if (kcs_result == SI_SM_HOSED) {
862                 /* We couldn't get the state machine to run, so whatever's at
863                    the port is probably not an IPMI KCS interface. */
864                 return -ENODEV;
865         }
866         /* Otherwise, we got some data. */
867 -       resp_len = kcs_get_result(data, resp, IPMI_MAX_MSG_LENGTH);
868 +       resp_len = kcs_smi_handlers.get_result(data, resp,
869 +                                              IPMI_MAX_MSG_LENGTH);
870         if (resp_len < 6)
871                 /* That's odd, it should be longer. */
872                 return -EINVAL;
873 @@ -860,6 +871,36 @@
874  MODULE_PARM(kcs_irqs, "1-4i");
875  MODULE_PARM(kcs_ports, "1-4i");
876  
877 +static unsigned char port_inb(struct si_sm_io *io, unsigned int offset)
878 +{
879 +       struct kcs_info *info = io->info;
880 +
881 +       return inb(info->port+offset);
882 +}
883 +
884 +static void port_outb(struct si_sm_io *io, unsigned int offset,
885 +                     unsigned char b)
886 +{
887 +       struct kcs_info *info = io->info;
888 +
889 +       outb(b, info->port+offset);
890 +}
891 +
892 +static unsigned char mem_inb(struct si_sm_io *io, unsigned int offset)
893 +{
894 +       struct kcs_info *info = io->info;
895 +
896 +       return readb(info->addr+offset);
897 +}
898 +
899 +static void mem_outb(struct si_sm_io *io, unsigned int offset,
900 +                    unsigned char b)
901 +{
902 +       struct kcs_info *info = io->info;
903 +
904 +       writeb(b, info->addr+offset);
905 +}
906 +
907  /* Returns 0 if initialized, or negative on an error. */
908  static int init_one_kcs(int kcs_port, 
909                         int irq, 
910 @@ -902,6 +943,9 @@
911                                kcs_port);
912                         return -EIO;
913                 }
914 +               new_kcs->io.outputb = port_outb;
915 +               new_kcs->io.inputb = port_inb;
916 +               new_kcs->io.info = new_kcs;
917         } else {
918                 if (request_mem_region(kcs_physaddr, 2, DEVICE_NAME) == NULL) {
919                         kfree(new_kcs);
920 @@ -917,15 +961,18 @@
921                                kcs_physaddr);
922                         return -EIO;
923                 }
924 +               new_kcs->io.outputb = mem_outb;
925 +               new_kcs->io.inputb = mem_inb;
926 +               new_kcs->io.info = new_kcs;
927         }
928  
929 -       new_kcs->kcs_sm = kmalloc(kcs_size(), GFP_KERNEL);
930 +       new_kcs->kcs_sm = kmalloc(kcs_smi_handlers.size(), GFP_KERNEL);
931         if (!new_kcs->kcs_sm) {
932                 printk(KERN_ERR "ipmi_kcs: out of memory\n");
933                 rv = -ENOMEM;
934                 goto out_err;
935         }
936 -       init_kcs_data(new_kcs->kcs_sm, kcs_port, new_kcs->addr);
937 +       kcs_smi_handlers.init_data(new_kcs->kcs_sm, &(new_kcs->io));
938         spin_lock_init(&(new_kcs->kcs_lock));
939         spin_lock_init(&(new_kcs->msg_lock));
940  
941 @@ -1027,11 +1074,7 @@
942  
943  #ifdef CONFIG_ACPI_INTERPRETER
944  
945 -/* Retrieve the base physical address from ACPI tables.  Originally
946 -   from Hewlett-Packard simple bmc.c, a GPL KCS driver. */
947 -
948  #include <linux/acpi.h>
949 -/* A real hack, but everything's not there yet in 2.4. */
950  #include <acpi/acpi.h>
951  #include <acpi/actypes.h>
952  #include <acpi/actbl.h>
953 @@ -1046,37 +1089,69 @@
954         s8      OEMRevision[4];
955         s8      CreatorID[4];
956         s8      CreatorRevision[4];
957 -       s16     InterfaceType;
958 +       u8      InterfaceType[2];
959         s16     SpecificationRevision;
960 +
961 +       /*
962 +        * Bit 0 - SCI interrupt supported
963 +        * Bit 1 - I/O APIC/SAPIC
964 +        */
965         u8      InterruptType;
966 +
967 +       /* If bit 0 of InterruptType is set, then this is the SCI
968 +           interrupt in the GPEx_STS register. */
969         u8      GPE;
970 +
971         s16     Reserved;
972 -       u64     GlobalSystemInterrupt;
973 -       u8      BaseAddress[12];
974 +
975 +       /* If bit 1 of InterruptType is set, then this is the I/O
976 +           APIC/SAPIC interrupt. */
977 +       u32     GlobalSystemInterrupt;
978 +
979 +       /* The actual register address. */
980 +       struct acpi_generic_address addr;
981 +
982         u8      UID[4];
983 -} __attribute__ ((packed));
984  
985 -static unsigned long acpi_find_bmc(void)
986 +       s8      spmi_id[1]; /* A '\0' terminated array starts here. */
987 +};
988 +
989 +static int acpi_find_bmc(unsigned long *physaddr, int *port)
990  {
991         acpi_status       status;
992 -       struct acpi_table_header *spmi;
993 -       static unsigned long io_base = 0;
994 -
995 -       if (io_base != 0)
996 -               return io_base;
997 +       struct SPMITable  *spmi;
998  
999         status = acpi_get_firmware_table("SPMI", 1,
1000 -                       ACPI_LOGICAL_ADDRESSING, &spmi);
1001 +                                        ACPI_LOGICAL_ADDRESSING,
1002 +                                        (struct acpi_table_header **) &spmi);
1003 +       if (status != AE_OK)
1004 +               goto not_found;
1005 +
1006 +       if (spmi->InterfaceType[0] != 1)
1007 +               /* Not IPMI. */
1008 +               goto not_found;
1009 +
1010 +       if (spmi->InterfaceType[1] != 1)
1011 +               /* Not KCS. */
1012 +               goto not_found;
1013 +
1014 +       if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
1015 +               *physaddr = spmi->addr.address;
1016 +               printk("ipmi_kcs_intf: Found ACPI-specified state machine"
1017 +                      " at memory address 0x%lx\n",
1018 +                      (unsigned long) spmi->addr.address);
1019 +       } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
1020 +               *port = spmi->addr.address;
1021 +               printk("ipmi_kcs_intf: Found ACPI-specified state machine"
1022 +                      " at I/O address 0x%x\n",
1023 +                      (int) spmi->addr.address);
1024 +       } else
1025 +               goto not_found; /* Not an address type we recognise. */
1026  
1027 -       if (status != AE_OK) {
1028 -               printk(KERN_ERR "ipmi_kcs: SPMI table not found.\n");
1029 -               return 0;
1030 -       }
1031 +       return 0;
1032  
1033 -       memcpy(&io_base, ((struct SPMITable *)spmi)->BaseAddress,
1034 -                       sizeof(io_base));
1035 -       
1036 -       return io_base;
1037 + not_found:
1038 +       return -ENODEV;
1039  }
1040  #endif
1041  
1042 @@ -1087,6 +1162,7 @@
1043         int             i = 0;
1044  #ifdef CONFIG_ACPI_INTERPRETER
1045         unsigned long   physaddr = 0;
1046 +       int             port = 0;
1047  #endif
1048  
1049         if (initialized)
1050 @@ -1114,26 +1190,25 @@
1051         /* Only try the defaults if enabled and resources are available
1052            (because they weren't already specified above). */
1053  
1054 -       if (kcs_trydefaults) {
1055 +       if (kcs_trydefaults && (pos == 0)) {
1056 +               rv = -EINVAL;
1057  #ifdef CONFIG_ACPI_INTERPRETER
1058 -               if ((physaddr = acpi_find_bmc())) {
1059 -                       if (!check_mem_region(physaddr, 2)) {
1060 -                               rv = init_one_kcs(0, 
1061 -                                                 0, 
1062 -                                                 physaddr, 
1063 -                                                 &(kcs_infos[pos]));
1064 -                               if (rv == 0)
1065 -                                       pos++;
1066 -                       }
1067 +               if (rv && (acpi_find_bmc(&physaddr, &port) == 0)) {
1068 +                       rv = init_one_kcs(port, 
1069 +                                         0, 
1070 +                                         physaddr, 
1071 +                                         &(kcs_infos[pos]));
1072 +                       if (rv == 0)
1073 +                               pos++;
1074                 }
1075  #endif
1076 -               if (!check_region(DEFAULT_IO_PORT, 2)) {
1077 +               if (rv) {
1078                         rv = init_one_kcs(DEFAULT_IO_PORT, 
1079                                           0, 
1080                                           0, 
1081                                           &(kcs_infos[pos]));
1082                         if (rv == 0)
1083 -                               pos++;
1084 +                           pos++;
1085                 }
1086         }
1087  
1088 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
1089 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_kcs_sm.c    2003-12-06 12:53:23.035496886 +0100
1090 +++ linux-2.4.23/drivers/char/ipmi/ipmi_kcs_sm.c        2003-12-06 17:46:42.982457286 +0100
1091 @@ -37,10 +37,11 @@
1092   * that document.
1093   */
1094  
1095 -#include <asm/io.h>
1096 -#include <asm/string.h>                /* Gets rid of memcpy warning */
1097 +#include <linux/kernel.h> /* For printk. */
1098 +#include <linux/string.h>
1099 +#include "ipmi_si_sm.h"
1100  
1101 -#include "ipmi_kcs_sm.h"
1102 +#define IPMI_KCS_VERSION "v27"
1103  
1104  /* Set this if you want a printout of why the state machine was hosed
1105     when it gets hosed. */
1106 @@ -95,29 +96,28 @@
1107  #define IPMI_ERR_MSG_TRUNCATED 0xc6
1108  #define IPMI_ERR_UNSPECIFIED   0xff
1109  
1110 -struct kcs_data
1111 +struct si_sm_data
1112  {
1113 -       enum kcs_states state;
1114 -       unsigned int    port;
1115 -       unsigned char   *addr;
1116 -       unsigned char   write_data[MAX_KCS_WRITE_SIZE];
1117 -       int             write_pos;
1118 -       int             write_count;
1119 -       int             orig_write_count;
1120 -       unsigned char   read_data[MAX_KCS_READ_SIZE];
1121 -       int             read_pos;
1122 -       int             truncated;
1123 +       enum kcs_states  state;
1124 +       struct si_sm_io *io;
1125 +       unsigned char    write_data[MAX_KCS_WRITE_SIZE];
1126 +       int              write_pos;
1127 +       int              write_count;
1128 +       int              orig_write_count;
1129 +       unsigned char    read_data[MAX_KCS_READ_SIZE];
1130 +       int              read_pos;
1131 +       int              truncated;
1132  
1133         unsigned int  error_retries;
1134         long          ibf_timeout;
1135         long          obf_timeout;
1136  };
1137  
1138 -void init_kcs_data(struct kcs_data *kcs, unsigned int port, unsigned char *addr)
1139 +static unsigned int init_kcs_data(struct si_sm_data *kcs,
1140 +                                 struct si_sm_io *io)
1141  {
1142         kcs->state = KCS_IDLE;
1143 -       kcs->port = port;
1144 -       kcs->addr = addr;
1145 +       kcs->io = io;
1146         kcs->write_pos = 0;
1147         kcs->write_count = 0;
1148         kcs->orig_write_count = 0;
1149 @@ -126,40 +126,29 @@
1150         kcs->truncated = 0;
1151         kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
1152         kcs->obf_timeout = OBF_RETRY_TIMEOUT;
1153 -}
1154  
1155 -/* Remember, init_one_kcs() insured port and addr can't both be set */
1156 +       /* Reserve 2 I/O bytes. */
1157 +       return 2;
1158 +}
1159  
1160 -static inline unsigned char read_status(struct kcs_data *kcs)
1161 +static inline unsigned char read_status(struct si_sm_data *kcs)
1162  {
1163 -        if (kcs->port)
1164 -               return inb(kcs->port + 1);
1165 -        else
1166 -               return readb(kcs->addr + 1);
1167 +       return kcs->io->inputb(kcs->io, 1);
1168  }
1169  
1170 -static inline unsigned char read_data(struct kcs_data *kcs)
1171 +static inline unsigned char read_data(struct si_sm_data *kcs)
1172  {
1173 -        if (kcs->port)
1174 -               return inb(kcs->port + 0);
1175 -        else
1176 -               return readb(kcs->addr + 0);
1177 +       return kcs->io->inputb(kcs->io, 0);
1178  }
1179  
1180 -static inline void write_cmd(struct kcs_data *kcs, unsigned char data)
1181 +static inline void write_cmd(struct si_sm_data *kcs, unsigned char data)
1182  {
1183 -        if (kcs->port)
1184 -               outb(data, kcs->port + 1);
1185 -        else
1186 -               writeb(data, kcs->addr + 1);
1187 +       kcs->io->outputb(kcs->io, 1, data);
1188  }
1189  
1190 -static inline void write_data(struct kcs_data *kcs, unsigned char data)
1191 +static inline void write_data(struct si_sm_data *kcs, unsigned char data)
1192  {
1193 -        if (kcs->port)
1194 -               outb(data, kcs->port + 0);
1195 -        else
1196 -               writeb(data, kcs->addr + 0);
1197 +       kcs->io->outputb(kcs->io, 0, data);
1198  }
1199  
1200  /* Control codes. */
1201 @@ -179,14 +168,14 @@
1202  #define GET_STATUS_OBF(status) ((status) & 0x01)
1203  
1204  
1205 -static inline void write_next_byte(struct kcs_data *kcs)
1206 +static inline void write_next_byte(struct si_sm_data *kcs)
1207  {
1208         write_data(kcs, kcs->write_data[kcs->write_pos]);
1209         (kcs->write_pos)++;
1210         (kcs->write_count)--;
1211  }
1212  
1213 -static inline void start_error_recovery(struct kcs_data *kcs, char *reason)
1214 +static inline void start_error_recovery(struct si_sm_data *kcs, char *reason)
1215  {
1216         (kcs->error_retries)++;
1217         if (kcs->error_retries > MAX_ERROR_RETRIES) {
1218 @@ -199,7 +188,7 @@
1219         }
1220  }
1221  
1222 -static inline void read_next_byte(struct kcs_data *kcs)
1223 +static inline void read_next_byte(struct si_sm_data *kcs)
1224  {
1225         if (kcs->read_pos >= MAX_KCS_READ_SIZE) {
1226                 /* Throw the data away and mark it truncated. */
1227 @@ -212,9 +201,8 @@
1228         write_data(kcs, KCS_READ_BYTE);
1229  }
1230  
1231 -static inline int check_ibf(struct kcs_data *kcs,
1232 -                           unsigned char   status,
1233 -                           long            time)
1234 +static inline int check_ibf(struct si_sm_data *kcs, unsigned char status,
1235 +                           long time)
1236  {
1237         if (GET_STATUS_IBF(status)) {
1238                 kcs->ibf_timeout -= time;
1239 @@ -229,9 +217,8 @@
1240         return 1;
1241  }
1242  
1243 -static inline int check_obf(struct kcs_data *kcs,
1244 -                           unsigned char   status,
1245 -                           long            time)
1246 +static inline int check_obf(struct si_sm_data *kcs, unsigned char status,
1247 +                           long time)
1248  {
1249         if (! GET_STATUS_OBF(status)) {
1250                 kcs->obf_timeout -= time;
1251 @@ -245,13 +232,13 @@
1252         return 1;
1253  }
1254  
1255 -static void clear_obf(struct kcs_data *kcs, unsigned char status)
1256 +static void clear_obf(struct si_sm_data *kcs, unsigned char status)
1257  {
1258         if (GET_STATUS_OBF(status))
1259                 read_data(kcs);
1260  }
1261  
1262 -static void restart_kcs_transaction(struct kcs_data *kcs)
1263 +static void restart_kcs_transaction(struct si_sm_data *kcs)
1264  {
1265         kcs->write_count = kcs->orig_write_count;
1266         kcs->write_pos = 0;
1267 @@ -262,7 +249,8 @@
1268         write_cmd(kcs, KCS_WRITE_START);
1269  }
1270  
1271 -int start_kcs_transaction(struct kcs_data *kcs, char *data, unsigned int size)
1272 +static int start_kcs_transaction(struct si_sm_data *kcs, unsigned char *data,
1273 +                                unsigned int size)
1274  {
1275         if ((size < 2) || (size > MAX_KCS_WRITE_SIZE)) {
1276                 return -1;
1277 @@ -284,7 +272,8 @@
1278         return 0;
1279  }
1280  
1281 -int kcs_get_result(struct kcs_data *kcs, unsigned char *data, int length)
1282 +static int get_kcs_result(struct si_sm_data *kcs, unsigned char *data,
1283 +                         unsigned int length)
1284  {
1285         if (length < kcs->read_pos) {
1286                 kcs->read_pos = length;
1287 @@ -313,7 +302,7 @@
1288  /* This implements the state machine defined in the IPMI manual, see
1289     that for details on how this works.  Divide that flowchart into
1290     sections delimited by "Wait for IBF" and this will become clear. */
1291 -enum kcs_result kcs_event(struct kcs_data *kcs, long time)
1292 +static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
1293  {
1294         unsigned char status;
1295         unsigned char state;
1296 @@ -325,7 +314,7 @@
1297  #endif
1298         /* All states wait for ibf, so just do it here. */
1299         if (!check_ibf(kcs, status, time))
1300 -               return KCS_CALL_WITH_DELAY;
1301 +               return SI_SM_CALL_WITH_DELAY;
1302  
1303         /* Just about everything looks at the KCS state, so grab that, too. */
1304         state = GET_STATUS_STATE(status);
1305 @@ -336,9 +325,9 @@
1306                 clear_obf(kcs, status);
1307  
1308                 if (GET_STATUS_ATN(status))
1309 -                       return KCS_ATTN;
1310 +                       return SI_SM_ATTN;
1311                 else
1312 -                       return KCS_SM_IDLE;
1313 +                       return SI_SM_IDLE;
1314  
1315         case KCS_START_OP:
1316                 if (state != KCS_IDLE) {
1317 @@ -405,7 +394,7 @@
1318  
1319                 if (state == KCS_READ_STATE) {
1320                         if (! check_obf(kcs, status, time))
1321 -                               return KCS_CALL_WITH_DELAY;
1322 +                               return SI_SM_CALL_WITH_DELAY;
1323                         read_next_byte(kcs);
1324                 } else {
1325                         /* We don't implement this exactly like the state
1326 @@ -418,7 +407,7 @@
1327                         clear_obf(kcs, status);
1328                         kcs->orig_write_count = 0;
1329                         kcs->state = KCS_IDLE;
1330 -                       return KCS_TRANSACTION_COMPLETE;
1331 +                       return SI_SM_TRANSACTION_COMPLETE;
1332                 }
1333                 break;
1334  
1335 @@ -441,7 +430,7 @@
1336                         break;
1337                 }
1338                 if (! check_obf(kcs, status, time))
1339 -                       return KCS_CALL_WITH_DELAY;
1340 +                       return SI_SM_CALL_WITH_DELAY;
1341  
1342                 clear_obf(kcs, status);
1343                 write_data(kcs, KCS_READ_BYTE);
1344 @@ -456,14 +445,14 @@
1345                 }
1346  
1347                 if (! check_obf(kcs, status, time))
1348 -                       return KCS_CALL_WITH_DELAY;
1349 +                       return SI_SM_CALL_WITH_DELAY;
1350  
1351                 clear_obf(kcs, status);
1352                 if (kcs->orig_write_count) {
1353                         restart_kcs_transaction(kcs);
1354                 } else {
1355                         kcs->state = KCS_IDLE;
1356 -                       return KCS_TRANSACTION_COMPLETE;
1357 +                       return SI_SM_TRANSACTION_COMPLETE;
1358                 }
1359                 break;
1360                         
1361 @@ -472,14 +461,42 @@
1362         }
1363  
1364         if (kcs->state == KCS_HOSED) {
1365 -               init_kcs_data(kcs, kcs->port, kcs->addr);
1366 -               return KCS_SM_HOSED;
1367 +               init_kcs_data(kcs, kcs->io);
1368 +               return SI_SM_HOSED;
1369         }
1370  
1371 -       return KCS_CALL_WITHOUT_DELAY;
1372 +       return SI_SM_CALL_WITHOUT_DELAY;
1373  }
1374  
1375 -int kcs_size(void)
1376 +static int kcs_size(void)
1377  {
1378 -       return sizeof(struct kcs_data);
1379 +       return sizeof(struct si_sm_data);
1380 +}
1381 +
1382 +static int kcs_detect(struct si_sm_data *kcs)
1383 +{
1384 +       /* It's impossible for the KCS status register to be all 1's,
1385 +          (assuming a properly functioning, self-initialized BMC)
1386 +          but that's what you get from reading a bogus address, so we
1387 +          test that first. */
1388 +       if (read_status(kcs) == 0xff)
1389 +               return 1; 
1390 +
1391 +       return 0;
1392  }
1393 +
1394 +static void kcs_cleanup(struct si_sm_data *kcs)
1395 +{
1396 +}
1397 +
1398 +struct si_sm_handlers kcs_smi_handlers =
1399 +{
1400 +       .version           = IPMI_KCS_VERSION,
1401 +       .init_data         = init_kcs_data,
1402 +       .start_transaction = start_kcs_transaction,
1403 +       .get_result        = get_kcs_result,
1404 +       .event             = kcs_event,
1405 +       .detect            = kcs_detect,
1406 +       .cleanup           = kcs_cleanup,
1407 +       .size              = kcs_size,
1408 +};
1409 diff -urN linux-2.4.23.org/drivers/char/ipmi/ipmi_msghandler.c linux-2.4.23/drivers/char/ipmi/ipmi_msghandler.c
1410 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_msghandler.c        2003-12-06 12:53:23.012501675 +0100
1411 +++ linux-2.4.23/drivers/char/ipmi/ipmi_msghandler.c    2003-12-06 17:46:42.995454560 +0100
1412 @@ -44,16 +44,21 @@
1413  #include <linux/ipmi_smi.h>
1414  #include <linux/notifier.h>
1415  #include <linux/init.h>
1416 +#include <linux/proc_fs.h>
1417 +
1418 +#define IPMI_MSGHANDLER_VERSION "v27"
1419  
1420  struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
1421  static int ipmi_init_msghandler(void);
1422  
1423  static int initialized = 0;
1424  
1425 +static struct proc_dir_entry *proc_ipmi_root = NULL;
1426 +
1427  #define MAX_EVENTS_IN_QUEUE    25
1428  
1429  /* Don't let a message sit in a queue forever, always time it with at lest
1430 -   the max message timer. */
1431 +   the max message timer.  This is in milliseconds. */
1432  #define MAX_MSG_TIMEOUT                60000
1433  
1434  struct ipmi_user
1435 @@ -82,7 +87,8 @@
1436  
1437  struct seq_table
1438  {
1439 -       int                  inuse : 1;
1440 +       unsigned int         inuse : 1;
1441 +       unsigned int         broadcast : 1;
1442  
1443         unsigned long        timeout;
1444         unsigned long        orig_timeout;
1445 @@ -169,6 +175,72 @@
1446         /* My LUN.  This should generally stay the SMS LUN, but just in
1447            case... */
1448         unsigned char my_lun;
1449 +
1450 +       /* The event receiver for my BMC, only really used at panic
1451 +          shutdown as a place to store this. */
1452 +       unsigned char event_receiver;
1453 +       unsigned char event_receiver_lun;
1454 +       unsigned char local_sel_device;
1455 +       unsigned char local_event_generator;
1456 +
1457 +       /* A cheap hack, if this is non-null and a message to an
1458 +          interface comes in with a NULL user, call this routine with
1459 +          it.  Note that the message will still be freed by the
1460 +          caller.  This only works on the system interface. */
1461 +       void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_smi_msg *msg);
1462 +
1463 +       /* Proc FS stuff. */
1464 +       struct proc_dir_entry *proc_dir;
1465 +       char                  proc_dir_name[10];
1466 +
1467 +       spinlock_t   counter_lock; /* For making counters atomic. */
1468 +
1469 +       /* Commands we got that were invalid. */
1470 +       unsigned int sent_invalid_commands;
1471 +
1472 +       /* Commands we sent to the MC. */
1473 +       unsigned int sent_local_commands;
1474 +       /* Responses from the MC that were delivered to a user. */
1475 +       unsigned int handled_local_responses;
1476 +       /* Responses from the MC that were not delivered to a user. */
1477 +       unsigned int unhandled_local_responses;
1478 +
1479 +       /* Commands we sent out to the IPMB bus. */
1480 +       unsigned int sent_ipmb_commands;
1481 +       /* Commands sent on the IPMB that had errors on the SEND CMD */
1482 +       unsigned int sent_ipmb_command_errs;
1483 +       /* Each retransmit increments this count. */
1484 +       unsigned int retransmitted_ipmb_commands;
1485 +       /* When a message times out (runs out of retransmits) this is
1486 +           incremented. */
1487 +       unsigned int timed_out_ipmb_commands;
1488 +
1489 +       /* This is like above, but for broadcasts.  Broadcasts are
1490 +           *not* included in the above count (they are expected to
1491 +           time out). */
1492 +       unsigned int timed_out_ipmb_broadcasts;
1493 +
1494 +       /* Responses I have sent to the IPMB bus. */
1495 +       unsigned int sent_ipmb_responses;
1496 +
1497 +       /* The response was delivered to the user. */
1498 +       unsigned int handled_ipmb_responses;
1499 +       /* The response had invalid data in it. */
1500 +       unsigned int invalid_ipmb_responses;
1501 +       /* The response didn't have anyone waiting for it. */
1502 +       unsigned int unhandled_ipmb_responses;
1503 +
1504 +       /* The command was delivered to the user. */
1505 +       unsigned int handled_commands;
1506 +       /* The command had invalid data in it. */
1507 +       unsigned int invalid_commands;
1508 +       /* The command didn't have anyone waiting for it. */
1509 +       unsigned int unhandled_commands;
1510 +
1511 +       /* Invalid data in an event. */
1512 +       unsigned int invalid_events;
1513 +       /* Events that were received with the proper format. */
1514 +       unsigned int events;
1515  };
1516  
1517  int
1518 @@ -328,7 +400,7 @@
1519  
1520  static void deliver_response(struct ipmi_recv_msg *msg)
1521  {
1522 -    msg->user->handler->ipmi_recv_hndl(msg, msg->user->handler_data);
1523 +       msg->user->handler->ipmi_recv_hndl(msg, msg->user->handler_data);
1524  }
1525  
1526  /* Find the next sequence number not being used and add the given
1527 @@ -338,6 +410,7 @@
1528                          struct ipmi_recv_msg *recv_msg,
1529                          unsigned long        timeout,
1530                          int                  retries,
1531 +                        int                  broadcast,
1532                          unsigned char        *seq,
1533                          long                 *seqid)
1534  {
1535 @@ -360,6 +433,7 @@
1536                 intf->seq_table[i].timeout = MAX_MSG_TIMEOUT;
1537                 intf->seq_table[i].orig_timeout = timeout;
1538                 intf->seq_table[i].retries_left = retries;
1539 +               intf->seq_table[i].broadcast = broadcast;
1540                 intf->seq_table[i].inuse = 1;
1541                 intf->seq_table[i].seqid = NEXT_SEQID(intf->seq_table[i].seqid);
1542                 *seq = i;
1543 @@ -412,8 +486,8 @@
1544  
1545  
1546  /* Start the timer for a specific sequence table entry. */
1547 -static int intf_start_seq_timer(ipmi_smi_t           intf,
1548 -                               long                 msgid)
1549 +static int intf_start_seq_timer(ipmi_smi_t intf,
1550 +                               long       msgid)
1551  {
1552         int           rv = -ENODEV;
1553         unsigned long flags;
1554 @@ -431,9 +505,50 @@
1555         {
1556                 struct seq_table *ent = &(intf->seq_table[seq]);
1557                 ent->timeout = ent->orig_timeout;
1558 +               rv = 0;
1559 +       }
1560 +       spin_unlock_irqrestore(&(intf->seq_lock), flags);
1561 +
1562 +       return rv;
1563 +}
1564 +
1565 +/* Got an error for the send message for a specific sequence number. */
1566 +static int intf_err_seq(ipmi_smi_t   intf,
1567 +                       long         msgid,
1568 +                       unsigned int err)
1569 +{
1570 +       int                  rv = -ENODEV;
1571 +       unsigned long        flags;
1572 +       unsigned char        seq;
1573 +       unsigned long        seqid;
1574 +       struct ipmi_recv_msg *msg = NULL;
1575 +
1576 +
1577 +       GET_SEQ_FROM_MSGID(msgid, seq, seqid);
1578 +
1579 +       spin_lock_irqsave(&(intf->seq_lock), flags);
1580 +       /* We do this verification because the user can be deleted
1581 +           while a message is outstanding. */
1582 +       if ((intf->seq_table[seq].inuse)
1583 +           && (intf->seq_table[seq].seqid == seqid))
1584 +       {
1585 +               struct seq_table *ent = &(intf->seq_table[seq]);
1586 +
1587 +               ent->inuse = 0;
1588 +               msg = ent->recv_msg;
1589 +               rv = 0;
1590         }
1591         spin_unlock_irqrestore(&(intf->seq_lock), flags);
1592  
1593 +       if (msg) {
1594 +               msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
1595 +               msg->msg_data[0] = err;
1596 +               msg->msg.netfn |= 1; /* Convert to a response. */
1597 +               msg->msg.data_len = 1;
1598 +               msg->msg.data = msg->msg_data;
1599 +               deliver_response(msg);
1600 +       }
1601 +
1602         return rv;
1603  }
1604  
1605 @@ -769,7 +884,9 @@
1606                                  struct ipmi_recv_msg *supplied_recv,
1607                                  int                  priority,
1608                                  unsigned char        source_address,
1609 -                                unsigned char        source_lun)
1610 +                                unsigned char        source_lun,
1611 +                                int                  retries,
1612 +                                unsigned int         retry_time_ms)
1613  {
1614         int                  rv = 0;
1615         struct ipmi_smi_msg  *smi_msg;
1616 @@ -797,8 +914,11 @@
1617         }
1618  
1619         if (addr->channel > IPMI_NUM_CHANNELS) {
1620 -           rv = -EINVAL;
1621 -           goto out_err;
1622 +               spin_lock_irqsave(&intf->counter_lock, flags);
1623 +               intf->sent_invalid_commands++;
1624 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
1625 +               rv = -EINVAL;
1626 +               goto out_err;
1627         }
1628  
1629         recv_msg->user = user;
1630 @@ -812,8 +932,12 @@
1631  
1632  
1633                 smi_addr = (struct ipmi_system_interface_addr *) addr;
1634 -               if (smi_addr->lun > 3)
1635 +               if (smi_addr->lun > 3) {
1636 +                       spin_lock_irqsave(&intf->counter_lock, flags);
1637 +                       intf->sent_invalid_commands++;
1638 +                       spin_unlock_irqrestore(&intf->counter_lock, flags);
1639                         return -EINVAL;
1640 +               }
1641  
1642                 memcpy(&recv_msg->addr, smi_addr, sizeof(*smi_addr));
1643  
1644 @@ -824,11 +948,17 @@
1645                 {
1646                         /* We don't let the user do these, since we manage
1647                            the sequence numbers. */
1648 +                       spin_lock_irqsave(&intf->counter_lock, flags);
1649 +                       intf->sent_invalid_commands++;
1650 +                       spin_unlock_irqrestore(&intf->counter_lock, flags);
1651                         rv = -EINVAL;
1652                         goto out_err;
1653                 }
1654  
1655                 if ((msg->data_len + 2) > IPMI_MAX_MSG_LENGTH) {
1656 +                       spin_lock_irqsave(&intf->counter_lock, flags);
1657 +                       intf->sent_invalid_commands++;
1658 +                       spin_unlock_irqrestore(&intf->counter_lock, flags);
1659                         rv = -EMSGSIZE;
1660                         goto out_err;
1661                 }
1662 @@ -840,41 +970,59 @@
1663                 if (msg->data_len > 0)
1664                         memcpy(&(smi_msg->data[2]), msg->data, msg->data_len);
1665                 smi_msg->data_size = msg->data_len + 2;
1666 +               spin_lock_irqsave(&intf->counter_lock, flags);
1667 +               intf->sent_local_commands++;
1668 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
1669         } else if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE)
1670                    || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
1671         {
1672                 struct ipmi_ipmb_addr *ipmb_addr;
1673                 unsigned char         ipmb_seq;
1674                 long                  seqid;
1675 -               int                   broadcast;
1676 -               int                   retries;
1677 +               int                   broadcast = 0;
1678  
1679                 if (addr == NULL) {
1680 +                       spin_lock_irqsave(&intf->counter_lock, flags);
1681 +                       intf->sent_invalid_commands++;
1682 +                       spin_unlock_irqrestore(&intf->counter_lock, flags);
1683                         rv = -EINVAL;
1684                         goto out_err;
1685                 }
1686  
1687 +               if (retries < 0) {
1688 +                   if (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)
1689 +                       retries = 0; /* Don't retry broadcasts. */
1690 +                   else
1691 +                       retries = 4;
1692 +               }
1693                 if (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE) {
1694                     /* Broadcasts add a zero at the beginning of the
1695                        message, but otherwise is the same as an IPMB
1696                        address. */
1697                     addr->addr_type = IPMI_IPMB_ADDR_TYPE;
1698                     broadcast = 1;
1699 -                   retries = 0; /* Don't retry broadcasts. */
1700 -               } else {
1701 -                   broadcast = 0;
1702 -                   retries = 4;
1703                 }
1704  
1705 +
1706 +               /* Default to 1 second retries. */
1707 +               if (retry_time_ms == 0)
1708 +                   retry_time_ms = 1000;
1709 +
1710                 /* 9 for the header and 1 for the checksum, plus
1711                     possibly one for the broadcast. */
1712                 if ((msg->data_len + 10 + broadcast) > IPMI_MAX_MSG_LENGTH) {
1713 +                       spin_lock_irqsave(&intf->counter_lock, flags);
1714 +                       intf->sent_invalid_commands++;
1715 +                       spin_unlock_irqrestore(&intf->counter_lock, flags);
1716                         rv = -EMSGSIZE;
1717                         goto out_err;
1718                 }
1719  
1720                 ipmb_addr = (struct ipmi_ipmb_addr *) addr;
1721                 if (ipmb_addr->lun > 3) {
1722 +                       spin_lock_irqsave(&intf->counter_lock, flags);
1723 +                       intf->sent_invalid_commands++;
1724 +                       spin_unlock_irqrestore(&intf->counter_lock, flags);
1725                         rv = -EINVAL;
1726                         goto out_err;
1727                 }
1728 @@ -884,6 +1032,9 @@
1729                 if (recv_msg->msg.netfn & 0x1) {
1730                         /* It's a response, so use the user's sequence
1731                             from msgid. */
1732 +                       spin_lock_irqsave(&intf->counter_lock, flags);
1733 +                       intf->sent_ipmb_responses++;
1734 +                       spin_unlock_irqrestore(&intf->counter_lock, flags);
1735                         format_ipmb_msg(smi_msg, msg, ipmb_addr, msgid,
1736                                         msgid, broadcast,
1737                                         source_address, source_lun);
1738 @@ -892,13 +1043,17 @@
1739  
1740                         spin_lock_irqsave(&(intf->seq_lock), flags);
1741  
1742 +                       spin_lock(&intf->counter_lock);
1743 +                       intf->sent_ipmb_commands++;
1744 +                       spin_unlock(&intf->counter_lock);
1745 +
1746                         /* Create a sequence number with a 1 second
1747                             timeout and 4 retries. */
1748 -                       /* FIXME - magic number for the timeout. */
1749                         rv = intf_next_seq(intf,
1750                                            recv_msg,
1751 -                                          1000,
1752 +                                          retry_time_ms,
1753                                            retries,
1754 +                                          broadcast,
1755                                            &ipmb_seq,
1756                                            &seqid);
1757                         if (rv) {
1758 @@ -934,16 +1089,19 @@
1759                 }
1760         } else {
1761             /* Unknown address type. */
1762 -           rv = -EINVAL;
1763 -           goto out_err;
1764 +               spin_lock_irqsave(&intf->counter_lock, flags);
1765 +               intf->sent_invalid_commands++;
1766 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
1767 +               rv = -EINVAL;
1768 +               goto out_err;
1769         }
1770  
1771  #if DEBUG_MSGING
1772         {
1773 -           int m;
1774 -           for (m=0; m<smi_msg->data_size; m++)
1775 -               printk(" %2.2x", smi_msg->data[m]);
1776 -           printk("\n");
1777 +               int m;
1778 +               for (m=0; m<smi_msg->data_size; m++)
1779 +                       printk(" %2.2x", smi_msg->data[m]);
1780 +               printk("\n");
1781         }
1782  #endif
1783         intf->handlers->sender(intf->send_info, smi_msg, priority);
1784 @@ -970,7 +1128,29 @@
1785                               NULL, NULL,
1786                               priority,
1787                               user->intf->my_address,
1788 -                             user->intf->my_lun);
1789 +                             user->intf->my_lun,
1790 +                             -1, 0);
1791 +}
1792 +
1793 +int ipmi_request_settime(ipmi_user_t      user,
1794 +                        struct ipmi_addr *addr,
1795 +                        long             msgid,
1796 +                        struct ipmi_msg  *msg,
1797 +                        int              priority,
1798 +                        int              retries,
1799 +                        unsigned int     retry_time_ms)
1800 +{
1801 +       return i_ipmi_request(user,
1802 +                             user->intf,
1803 +                             addr,
1804 +                             msgid,
1805 +                             msg,
1806 +                             NULL, NULL,
1807 +                             priority,
1808 +                             user->intf->my_address,
1809 +                             user->intf->my_lun,
1810 +                             retries,
1811 +                             retry_time_ms);
1812  }
1813  
1814  int ipmi_request_supply_msgs(ipmi_user_t          user,
1815 @@ -990,7 +1170,8 @@
1816                               supplied_recv,
1817                               priority,
1818                               user->intf->my_address,
1819 -                             user->intf->my_lun);
1820 +                             user->intf->my_lun,
1821 +                             -1, 0);
1822  }
1823  
1824  int ipmi_request_with_source(ipmi_user_t      user,
1825 @@ -1009,7 +1190,124 @@
1826                               NULL, NULL,
1827                               priority,
1828                               source_address,
1829 -                             source_lun);
1830 +                             source_lun,
1831 +                             -1, 0);
1832 +}
1833 +
1834 +static int ipmb_file_read_proc(char *page, char **start, off_t off,
1835 +                              int count, int *eof, void *data)
1836 +{
1837 +       char       *out = (char *) page;
1838 +       ipmi_smi_t intf = data;
1839 +
1840 +       return sprintf(out, "%x\n", intf->my_address);
1841 +}
1842 +
1843 +static int version_file_read_proc(char *page, char **start, off_t off,
1844 +                                 int count, int *eof, void *data)
1845 +{
1846 +       char       *out = (char *) page;
1847 +       ipmi_smi_t intf = data;
1848 +
1849 +       return sprintf(out, "%d.%d\n",
1850 +                      intf->version_major, intf->version_minor);
1851 +}
1852 +
1853 +static int stat_file_read_proc(char *page, char **start, off_t off,
1854 +                              int count, int *eof, void *data)
1855 +{
1856 +       char       *out = (char *) page;
1857 +       ipmi_smi_t intf = data;
1858 +
1859 +       out += sprintf(out, "sent_invalid_commands:       %d\n",
1860 +                      intf->sent_invalid_commands);
1861 +       out += sprintf(out, "sent_local_commands:         %d\n",
1862 +                      intf->sent_local_commands);
1863 +       out += sprintf(out, "handled_local_responses:     %d\n",
1864 +                      intf->handled_local_responses);
1865 +       out += sprintf(out, "unhandled_local_responses:   %d\n",
1866 +                      intf->unhandled_local_responses);
1867 +       out += sprintf(out, "sent_ipmb_commands:          %d\n",
1868 +                      intf->sent_ipmb_commands);
1869 +       out += sprintf(out, "sent_ipmb_command_errs:      %d\n",
1870 +                      intf->sent_ipmb_command_errs);
1871 +       out += sprintf(out, "retransmitted_ipmb_commands: %d\n",
1872 +                      intf->retransmitted_ipmb_commands);
1873 +       out += sprintf(out, "timed_out_ipmb_commands:     %d\n",
1874 +                      intf->timed_out_ipmb_commands);
1875 +       out += sprintf(out, "timed_out_ipmb_broadcasts:   %d\n",
1876 +                      intf->timed_out_ipmb_broadcasts);
1877 +       out += sprintf(out, "sent_ipmb_responses:         %d\n",
1878 +                      intf->sent_ipmb_responses);
1879 +       out += sprintf(out, "handled_ipmb_responses:      %d\n",
1880 +                      intf->handled_ipmb_responses);
1881 +       out += sprintf(out, "invalid_ipmb_responses:      %d\n",
1882 +                      intf->invalid_ipmb_responses);
1883 +       out += sprintf(out, "unhandled_ipmb_responses:    %d\n",
1884 +                      intf->unhandled_ipmb_responses);
1885 +       out += sprintf(out, "handled_commands:            %d\n",
1886 +                      intf->handled_commands);
1887 +       out += sprintf(out, "invalid_commands:            %d\n",
1888 +                      intf->invalid_commands);
1889 +       out += sprintf(out, "unhandled_commands:          %d\n",
1890 +                      intf->unhandled_commands);
1891 +       out += sprintf(out, "invalid_events:              %d\n",
1892 +                      intf->invalid_events);
1893 +       out += sprintf(out, "events:                      %d\n",
1894 +                      intf->events);
1895 +
1896 +       return (out - ((char *) page));
1897 +}
1898 +
1899 +int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
1900 +                           read_proc_t *read_proc, write_proc_t *write_proc,
1901 +                           void *data, struct module *owner)
1902 +{
1903 +       struct proc_dir_entry *file;
1904 +       int                   rv = 0;
1905 +
1906 +       file = create_proc_entry(name, 0, smi->proc_dir);
1907 +       if (!file)
1908 +               rv = -ENOMEM;
1909 +       else {
1910 +               file->nlink = 1;
1911 +               file->data = data;
1912 +               file->read_proc = read_proc;
1913 +               file->write_proc = write_proc;
1914 +               file->owner = owner;
1915 +       }
1916 +
1917 +       return rv;
1918 +}
1919 +
1920 +static int add_proc_entries(ipmi_smi_t smi, int num)
1921 +{
1922 +       int rv = 0;
1923 +
1924 +       sprintf(smi->proc_dir_name, "%d", num);
1925 +       smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root);
1926 +       if (!smi->proc_dir)
1927 +               rv = -ENOMEM;
1928 +       else {
1929 +               smi->proc_dir->owner = THIS_MODULE;
1930 +       }
1931 +
1932 +       if (rv == 0)
1933 +               rv = ipmi_smi_add_proc_entry(smi, "stats",
1934 +                                            stat_file_read_proc, NULL,
1935 +                                            smi, THIS_MODULE);
1936 +
1937 +       if (rv == 0)
1938 +               rv = ipmi_smi_add_proc_entry(smi, "ipmb",
1939 +                                            ipmb_file_read_proc, NULL,
1940 +                                            smi, THIS_MODULE);
1941 +
1942 +       if (rv == 0)
1943 +               rv = ipmi_smi_add_proc_entry(smi, "version",
1944 +                                            version_file_read_proc, NULL,
1945 +                                            smi, THIS_MODULE);
1946 +
1947 +       return rv;
1948  }
1949  
1950  int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
1951 @@ -1040,6 +1338,9 @@
1952         new_intf = kmalloc(sizeof(*new_intf), GFP_KERNEL);
1953         if (!new_intf)
1954                 return -ENOMEM;
1955 +       memset(new_intf, 0, sizeof(*new_intf));
1956 +
1957 +       new_intf->proc_dir = NULL;
1958  
1959         rv = -ENOMEM;
1960  
1961 @@ -1069,6 +1370,8 @@
1962                         INIT_LIST_HEAD(&(new_intf->cmd_rcvrs));
1963                         new_intf->all_cmd_rcvr = NULL;
1964  
1965 +                       spin_lock_init(&(new_intf->counter_lock));
1966 +
1967                         spin_lock_irqsave(&interfaces_lock, flags);
1968                         ipmi_interfaces[i] = new_intf;
1969                         spin_unlock_irqrestore(&interfaces_lock, flags);
1970 @@ -1089,6 +1392,9 @@
1971                 /* Well, it went away.  Just return. */
1972                 goto out;
1973  
1974 +       if (rv == 0)
1975 +               rv = add_proc_entries(*intf, i);
1976 +
1977         if (rv == 0) {
1978                 /* Call all the watcher interfaces to tell them that a
1979                    new interface is available. */
1980 @@ -1096,7 +1402,11 @@
1981                 list_for_each(entry, &smi_watchers) {
1982                         struct ipmi_smi_watcher *w;
1983                         w = list_entry(entry, struct ipmi_smi_watcher, link);
1984 -                       w->new_smi(i);
1985 +                       if (try_inc_mod_count(w->owner)) {
1986 +                               w->new_smi(i);
1987 +                               if (w->owner)
1988 +                                       __MOD_DEC_USE_COUNT(w->owner);
1989 +                       }
1990                 }
1991                 up_read(&smi_watchers_sem);
1992         }
1993 @@ -1104,8 +1414,12 @@
1994   out:
1995         up_read(&interfaces_sem);
1996  
1997 -       if (rv)
1998 +       if (rv) {
1999 +               if (new_intf->proc_dir)
2000 +                       remove_proc_entry(new_intf->proc_dir_name,
2001 +                                         proc_ipmi_root);
2002                 kfree(new_intf);
2003 +       }
2004  
2005         return rv;
2006  }
2007 @@ -1163,6 +1477,8 @@
2008         {
2009                 for (i=0; i<MAX_IPMI_INTERFACES; i++) {
2010                         if (ipmi_interfaces[i] == intf) {
2011 +                               remove_proc_entry(intf->proc_dir_name,
2012 +                                                 proc_ipmi_root);
2013                                 spin_lock_irqsave(&interfaces_lock, flags);
2014                                 ipmi_interfaces[i] = NULL;
2015                                 clean_up_interface_data(intf);
2016 @@ -1204,15 +1520,21 @@
2017  {
2018         struct ipmi_ipmb_addr ipmb_addr;
2019         struct ipmi_recv_msg  *recv_msg;
2020 +       unsigned long         flags;
2021  
2022         
2023 -       if (msg->rsp_size < 11)
2024 +       if (msg->rsp_size < 11) {
2025                 /* Message not big enough, just ignore it. */
2026 +               spin_lock_irqsave(&intf->counter_lock, flags);
2027 +               intf->invalid_ipmb_responses++;
2028 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2029                 return 0;
2030 +       }
2031  
2032 -       if (msg->rsp[2] != 0)
2033 +       if (msg->rsp[2] != 0) {
2034                 /* An error getting the response, just ignore it. */
2035                 return 0;
2036 +       }
2037  
2038         ipmb_addr.addr_type = IPMI_IPMB_ADDR_TYPE;
2039         ipmb_addr.slave_addr = msg->rsp[6];
2040 @@ -1231,6 +1553,9 @@
2041         {
2042                 /* We were unable to find the sequence number,
2043                    so just nuke the message. */
2044 +               spin_lock_irqsave(&intf->counter_lock, flags);
2045 +               intf->unhandled_ipmb_responses++;
2046 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2047                 return 0;
2048         }
2049  
2050 @@ -1244,6 +1569,9 @@
2051         recv_msg->msg.data = recv_msg->msg_data;
2052         recv_msg->msg.data_len = msg->rsp_size - 10;
2053         recv_msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
2054 +       spin_lock_irqsave(&intf->counter_lock, flags);
2055 +       intf->handled_ipmb_responses++;
2056 +       spin_unlock_irqrestore(&intf->counter_lock, flags);
2057         deliver_response(recv_msg);
2058  
2059         return 0;
2060 @@ -1252,18 +1580,23 @@
2061  static int handle_get_msg_cmd(ipmi_smi_t          intf,
2062                               struct ipmi_smi_msg *msg)
2063  {
2064 -       struct list_head *entry;
2065 +       struct list_head      *entry;
2066         struct cmd_rcvr       *rcvr;
2067 -       int              rv = 0;
2068 -       unsigned char    netfn;
2069 -       unsigned char    cmd;
2070 -       ipmi_user_t      user = NULL;
2071 +       int                   rv = 0;
2072 +       unsigned char         netfn;
2073 +       unsigned char         cmd;
2074 +       ipmi_user_t           user = NULL;
2075         struct ipmi_ipmb_addr *ipmb_addr;
2076         struct ipmi_recv_msg  *recv_msg;
2077 +       unsigned long         flags;
2078  
2079 -       if (msg->rsp_size < 10)
2080 +       if (msg->rsp_size < 10) {
2081                 /* Message not big enough, just ignore it. */
2082 +               spin_lock_irqsave(&intf->counter_lock, flags);
2083 +               intf->invalid_commands++;
2084 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2085                 return 0;
2086 +       }
2087  
2088         if (msg->rsp[2] != 0) {
2089                 /* An error getting the response, just ignore it. */
2090 @@ -1291,6 +1624,10 @@
2091  
2092         if (user == NULL) {
2093                 /* We didn't find a user, deliver an error response. */
2094 +               spin_lock_irqsave(&intf->counter_lock, flags);
2095 +               intf->unhandled_commands++;
2096 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2097 +
2098                 msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
2099                 msg->data[1] = IPMI_SEND_MSG_CMD;
2100                 msg->data[2] = msg->rsp[3];
2101 @@ -1311,6 +1648,10 @@
2102                             causes it to not be freed or queued. */
2103         } else {
2104                 /* Deliver the message to the user. */
2105 +               spin_lock_irqsave(&intf->counter_lock, flags);
2106 +               intf->handled_commands++;
2107 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2108 +
2109                 recv_msg = ipmi_alloc_recv_msg();
2110                 if (! recv_msg) {
2111                         /* We couldn't allocate memory for the
2112 @@ -1374,6 +1715,9 @@
2113  
2114         if (msg->rsp_size < 19) {
2115                 /* Message is too small to be an IPMB event. */
2116 +               spin_lock_irqsave(&intf->counter_lock, flags);
2117 +               intf->invalid_events++;
2118 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2119                 return 0;
2120         }
2121  
2122 @@ -1386,6 +1730,10 @@
2123  
2124         spin_lock_irqsave(&(intf->events_lock), flags);
2125  
2126 +       spin_lock(&intf->counter_lock);
2127 +       intf->events++;
2128 +       spin_unlock(&intf->counter_lock);
2129 +
2130         /* Allocate and fill in one message for every user that is getting
2131            events. */
2132         list_for_each(entry, &(intf->users)) {
2133 @@ -1459,6 +1807,7 @@
2134         struct ipmi_recv_msg *recv_msg;
2135         int                  found = 0;
2136         struct list_head     *entry;
2137 +       unsigned long        flags;
2138  
2139         recv_msg = (struct ipmi_recv_msg *) msg->user_data;
2140  
2141 @@ -1474,11 +1823,20 @@
2142         }
2143  
2144         if (!found) {
2145 +               /* Special handling for NULL users. */
2146 +               if (!recv_msg->user && intf->null_user_handler)
2147 +                       intf->null_user_handler(intf, msg);
2148                 /* The user for the message went away, so give up. */
2149 +               spin_lock_irqsave(&intf->counter_lock, flags);
2150 +               intf->unhandled_local_responses++;
2151 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2152                 ipmi_free_recv_msg(recv_msg);
2153         } else {
2154                 struct ipmi_system_interface_addr *smi_addr;
2155  
2156 +               spin_lock_irqsave(&intf->counter_lock, flags);
2157 +               intf->handled_local_responses++;
2158 +               spin_unlock_irqrestore(&intf->counter_lock, flags);
2159                 recv_msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
2160                 recv_msg->msgid = msg->msgid;
2161                 smi_addr = ((struct ipmi_system_interface_addr *)
2162 @@ -1505,7 +1863,7 @@
2163  static int handle_new_recv_msg(ipmi_smi_t          intf,
2164                                struct ipmi_smi_msg *msg)
2165  {
2166 -       int requeue;
2167 +       int           requeue;
2168  
2169         if (msg->rsp_size < 2) {
2170                 /* Message is too small to be correct. */
2171 @@ -1551,10 +1909,30 @@
2172            working on it. */
2173         read_lock(&(intf->users_lock));
2174  
2175 -       if ((msg->data_size >= 2) && (msg->data[1] == IPMI_SEND_MSG_CMD)) {
2176 +       if ((msg->data_size >= 2)
2177 +           && (msg->data[0] == (IPMI_NETFN_APP_REQUEST << 2))
2178 +           && (msg->data[1] == IPMI_SEND_MSG_CMD)) {
2179                 /* This is the local response to a send, start the
2180                     timer for these. */
2181 -               intf_start_seq_timer(intf, msg->msgid);
2182 +
2183 +               /* Check for errors, if we get certain errors (ones
2184 +                   that mean basically we can try again later), we
2185 +                   ignore them and start the timer.  Otherwise we
2186 +                   report the error immediately. */
2187 +               if ((msg->rsp_size >= 3) && (msg->rsp[2] != 0)
2188 +                   && (msg->rsp[2] != IPMI_NODE_BUSY_ERR)
2189 +                   && (msg->rsp[2] != IPMI_LOST_ARBITRATION_ERR))
2190 +               {
2191 +                       /* Got an error sending the message, handle it. */
2192 +                       spin_lock_irqsave(&intf->counter_lock, flags);
2193 +                       intf->sent_ipmb_command_errs++;
2194 +                       spin_unlock_irqrestore(&intf->counter_lock, flags);
2195 +                       intf_err_seq(intf, msg->msgid, msg->rsp[2]);
2196 +               } else {
2197 +                       /* The message was sent, start the timer. */
2198 +                       intf_start_seq_timer(intf, msg->msgid);
2199 +               }
2200 +
2201                 ipmi_free_smi_msg(msg);
2202                 goto out_unlock;
2203         }
2204 @@ -1699,6 +2077,12 @@
2205                                 ent->inuse = 0;
2206                                 msg = ent->recv_msg;
2207                                 list_add_tail(&(msg->link), &timeouts);
2208 +                               spin_lock(&intf->counter_lock);
2209 +                               if (ent->broadcast)
2210 +                                       intf->timed_out_ipmb_broadcasts++;
2211 +                               else
2212 +                                       intf->timed_out_ipmb_commands++;
2213 +                               spin_unlock(&intf->counter_lock);
2214                         } else {
2215                                 /* More retries, send again. */
2216  
2217 @@ -1708,6 +2092,9 @@
2218                                 ent->retries_left--;
2219                                 send_from_recv_msg(intf, ent->recv_msg, NULL,
2220                                                    j, ent->seqid);
2221 +                               spin_lock(&intf->counter_lock);
2222 +                               intf->retransmitted_ipmb_commands++;
2223 +                               spin_unlock(&intf->counter_lock);
2224                         }
2225                 }
2226                 spin_unlock_irqrestore(&(intf->seq_lock), flags);
2227 @@ -1740,13 +2127,16 @@
2228  
2229  static struct timer_list ipmi_timer;
2230  
2231 -/* Call every 100 ms. */
2232 +/* Call every ~100 ms. */
2233  #define IPMI_TIMEOUT_TIME      100
2234 -#define IPMI_TIMEOUT_JIFFIES   (IPMI_TIMEOUT_TIME/(1000/HZ))
2235  
2236 -/* Request events from the queue every second.  Hopefully, in the
2237 -   future, IPMI will add a way to know immediately if an event is
2238 -   in the queue. */
2239 +/* How many jiffies does it take to get to the timeout time. */
2240 +#define IPMI_TIMEOUT_JIFFIES   ((IPMI_TIMEOUT_TIME * HZ) / 1000)
2241 +
2242 +/* Request events from the queue every second (this is the number of
2243 +   IPMI_TIMEOUT_TIMES between event requests).  Hopefully, in the
2244 +   future, IPMI will add a way to know immediately if an event is in
2245 +   the queue and this silliness can go away. */
2246  #define IPMI_REQUEST_EV_TIME   (1000 / (IPMI_TIMEOUT_TIME))
2247  
2248  static volatile int stop_operation = 0;
2249 @@ -1822,18 +2212,48 @@
2250  {
2251  }
2252  
2253 -static void send_panic_events(void)
2254 +#ifdef CONFIG_IPMI_PANIC_STRING
2255 +static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
2256 +{
2257 +       if ((msg->rsp[0] == (IPMI_NETFN_SENSOR_EVENT_RESPONSE << 2))
2258 +           && (msg->rsp[1] == IPMI_GET_EVENT_RECEIVER_CMD)
2259 +           && (msg->rsp[2] == IPMI_CC_NO_ERROR))
2260 +       {
2261 +               /* A get event receiver command, save it. */
2262 +               intf->event_receiver = msg->rsp[3];
2263 +               intf->event_receiver_lun = msg->rsp[4] & 0x3;
2264 +       }
2265 +}
2266 +
2267 +static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
2268 +{
2269 +       if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2))
2270 +           && (msg->rsp[1] == IPMI_GET_DEVICE_ID_CMD)
2271 +           && (msg->rsp[2] == IPMI_CC_NO_ERROR))
2272 +       {
2273 +               /* A get device id command, save if we are an event
2274 +                  receiver or generator. */
2275 +               intf->local_sel_device = (msg->rsp[8] >> 2) & 1;
2276 +               intf->local_event_generator = (msg->rsp[8] >> 5) & 1;
2277 +       }
2278 +}
2279 +#endif
2280 +
2281 +static void send_panic_events(char *str)
2282  {
2283         struct ipmi_msg                   msg;
2284         ipmi_smi_t                        intf;
2285 -       unsigned char                     data[8];
2286 +       unsigned char                     data[16];
2287         int                               i;
2288 -       struct ipmi_system_interface_addr addr;
2289 +       struct ipmi_system_interface_addr *si;
2290 +       struct ipmi_addr                  addr;
2291         struct ipmi_smi_msg               smi_msg;
2292         struct ipmi_recv_msg              recv_msg;
2293  
2294 -       addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
2295 -       addr.channel = IPMI_BMC_CHANNEL;
2296 +       si = (struct ipmi_system_interface_addr *) &addr;
2297 +       si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
2298 +       si->channel = IPMI_BMC_CHANNEL;
2299 +       si->lun = 0;
2300  
2301         /* Fill in an event telling that we have failed. */
2302         msg.netfn = 0x04; /* Sensor or Event. */
2303 @@ -1846,12 +2266,13 @@
2304         data[4] = 0x6f; /* Sensor specific, IPMI table 36-1 */
2305         data[5] = 0xa1; /* Runtime stop OEM bytes 2 & 3. */
2306  
2307 -       /* These used to have the first three bytes of the panic string,
2308 -          but not only is that not terribly useful, it's not available
2309 -          any more. */
2310 -       data[3] = 0;
2311 -       data[6] = 0;
2312 -       data[7] = 0;
2313 +       /* Put a few breadcrums in.  Hopefully later we can add more things
2314 +          to make the panic events more useful. */
2315 +       if (str) {
2316 +               data[3] = str[0];
2317 +               data[6] = str[1];
2318 +               data[7] = str[2];
2319 +       }
2320  
2321         smi_msg.done = dummy_smi_done_handler;
2322         recv_msg.done = dummy_recv_done_handler;
2323 @@ -1862,18 +2283,147 @@
2324                 if (intf == NULL)
2325                         continue;
2326  
2327 +               /* Send the event announcing the panic. */
2328                 intf->handlers->set_run_to_completion(intf->send_info, 1);
2329                 i_ipmi_request(NULL,
2330                                intf,
2331 -                              (struct ipmi_addr *) &addr,
2332 +                              &addr,
2333                                0,
2334                                &msg,
2335                                &smi_msg,
2336                                &recv_msg,
2337                                0,
2338                                intf->my_address,
2339 -                              intf->my_lun);
2340 +                              intf->my_lun,
2341 +                              0, 1); /* Don't retry, and don't wait. */
2342         }
2343 +
2344 +#ifdef CONFIG_IPMI_PANIC_STRING
2345 +       /* On every interface, dump a bunch of OEM event holding the
2346 +          string. */
2347 +       if (!str) 
2348 +               return;
2349 +
2350 +       for (i=0; i<MAX_IPMI_INTERFACES; i++) {
2351 +               char                  *p = str;
2352 +               struct ipmi_ipmb_addr *ipmb;
2353 +               int                   j;
2354 +
2355 +               intf = ipmi_interfaces[i];
2356 +               if (intf == NULL)
2357 +                       continue;
2358 +
2359 +               /* First job here is to figure out where to send the
2360 +                  OEM events.  There's no way in IPMI to send OEM
2361 +                  events using an event send command, so we have to
2362 +                  find the SEL to put them in and stick them in
2363 +                  there. */
2364 +
2365 +               /* Get capabilities from the get device id. */
2366 +               intf->local_sel_device = 0;
2367 +               intf->local_event_generator = 0;
2368 +               intf->event_receiver = 0;
2369 +
2370 +               /* Request the device info from the local MC. */
2371 +               msg.netfn = IPMI_NETFN_APP_REQUEST;
2372 +               msg.cmd = IPMI_GET_DEVICE_ID_CMD;
2373 +               msg.data = NULL;
2374 +               msg.data_len = 0;
2375 +               intf->null_user_handler = device_id_fetcher;
2376 +               i_ipmi_request(NULL,
2377 +                              intf,
2378 +                              &addr,
2379 +                              0,
2380 +                              &msg,
2381 +                              &smi_msg,
2382 +                              &recv_msg,
2383 +                              0,
2384 +                              intf->my_address,
2385 +                              intf->my_lun,
2386 +                              0, 1); /* Don't retry, and don't wait. */
2387 +
2388 +               if (intf->local_event_generator) {
2389 +                       /* Request the event receiver from the local MC. */
2390 +                       msg.netfn = IPMI_NETFN_SENSOR_EVENT_REQUEST;
2391 +                       msg.cmd = IPMI_GET_EVENT_RECEIVER_CMD;
2392 +                       msg.data = NULL;
2393 +                       msg.data_len = 0;
2394 +                       intf->null_user_handler = event_receiver_fetcher;
2395 +                       i_ipmi_request(NULL,
2396 +                                      intf,
2397 +                                      &addr,
2398 +                                      0,
2399 +                                      &msg,
2400 +                                      &smi_msg,
2401 +                                      &recv_msg,
2402 +                                      0,
2403 +                                      intf->my_address,
2404 +                                      intf->my_lun,
2405 +                                      0, 1); /* no retry, and no wait. */
2406 +               }
2407 +               intf->null_user_handler = NULL;
2408 +
2409 +               /* Validate the event receiver.  The low bit must not
2410 +                  be 1 (it must be a valid IPMB address), it cannot
2411 +                  be zero, and it must not be my address. */
2412 +                if (((intf->event_receiver & 1) == 0)
2413 +                   && (intf->event_receiver != 0)
2414 +                   && (intf->event_receiver != intf->my_address))
2415 +               {
2416 +                       /* The event receiver is valid, send an IPMB
2417 +                          message. */
2418 +                       ipmb = (struct ipmi_ipmb_addr *) &addr;
2419 +                       ipmb->addr_type = IPMI_IPMB_ADDR_TYPE;
2420 +                       ipmb->channel = 0; /* FIXME - is this right? */
2421 +                       ipmb->lun = intf->event_receiver_lun;
2422 +                       ipmb->slave_addr = intf->event_receiver;
2423 +               } else if (intf->local_sel_device) {
2424 +                       /* The event receiver was not valid (or was
2425 +                          me), but I am an SEL device, just dump it
2426 +                          in my SEL. */
2427 +                       si = (struct ipmi_system_interface_addr *) &addr;
2428 +                       si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
2429 +                       si->channel = IPMI_BMC_CHANNEL;
2430 +                       si->lun = 0;
2431 +               } else
2432 +                       continue; /* No where to send the event. */
2433 +
2434 +               
2435 +               msg.netfn = IPMI_NETFN_STORAGE_REQUEST; /* Storage. */
2436 +               msg.cmd = IPMI_ADD_SEL_ENTRY_CMD;
2437 +               msg.data = data;
2438 +               msg.data_len = 16;
2439 +
2440 +               j = 0;
2441 +               while (*p) {
2442 +                       int size = strlen(p);
2443 +
2444 +                       if (size > 11)
2445 +                               size = 11;
2446 +                       data[0] = 0;
2447 +                       data[1] = 0;
2448 +                       data[2] = 0xf0; /* OEM event without timestamp. */
2449 +                       data[3] = intf->my_address;
2450 +                       data[4] = j++; /* sequence # */
2451 +                       /* Always give 11 bytes, so strncpy will fill
2452 +                          it with zeroes for me. */
2453 +                       strncpy(data+5, p, 11);
2454 +                       p += size;
2455 +
2456 +                       i_ipmi_request(NULL,
2457 +                                      intf,
2458 +                                      &addr,
2459 +                                      0,
2460 +                                      &msg,
2461 +                                      &smi_msg,
2462 +                                      &recv_msg,
2463 +                                      0,
2464 +                                      intf->my_address,
2465 +                                      intf->my_lun,
2466 +                                      0, 1); /* no retry, and no wait. */
2467 +               }
2468 +       }       
2469 +#endif /* CONFIG_IPMI_PANIC_STRING */
2470  }
2471  #endif /* CONFIG_IPMI_PANIC_EVENT */
2472  
2473 @@ -1900,7 +2450,7 @@
2474         }
2475  
2476  #ifdef CONFIG_IPMI_PANIC_EVENT
2477 -       send_panic_events();
2478 +       send_panic_events(ptr);
2479  #endif
2480  
2481         return NOTIFY_DONE;
2482 @@ -1912,7 +2462,6 @@
2483         200   /* priority: INT_MAX >= x >= 0 */
2484  };
2485  
2486 -
2487  static __init int ipmi_init_msghandler(void)
2488  {
2489         int i;
2490 @@ -1920,10 +2469,21 @@
2491         if (initialized)
2492                 return 0;
2493  
2494 +       printk(KERN_INFO "ipmi message handler version "
2495 +              IPMI_MSGHANDLER_VERSION "\n");
2496 +
2497         for (i=0; i<MAX_IPMI_INTERFACES; i++) {
2498                 ipmi_interfaces[i] = NULL;
2499         }
2500  
2501 +       proc_ipmi_root = proc_mkdir("ipmi", 0);
2502 +       if (!proc_ipmi_root) {
2503 +           printk("Unable to create IPMI proc dir\n");
2504 +           return -ENOMEM;
2505 +       }
2506 +
2507 +       proc_ipmi_root->owner = THIS_MODULE;
2508 +
2509         init_timer(&ipmi_timer);
2510         ipmi_timer.data = 0;
2511         ipmi_timer.function = ipmi_timeout;
2512 @@ -1934,8 +2494,6 @@
2513  
2514         initialized = 1;
2515  
2516 -       printk(KERN_INFO "ipmi: message handler initialized\n");
2517 -
2518         return 0;
2519  }
2520  
2521 @@ -1980,6 +2538,7 @@
2522  EXPORT_SYMBOL(ipmi_destroy_user);
2523  EXPORT_SYMBOL(ipmi_get_version);
2524  EXPORT_SYMBOL(ipmi_request);
2525 +EXPORT_SYMBOL(ipmi_request_settime);
2526  EXPORT_SYMBOL(ipmi_request_supply_msgs);
2527  EXPORT_SYMBOL(ipmi_request_with_source);
2528  EXPORT_SYMBOL(ipmi_register_smi);
2529 @@ -2001,3 +2560,4 @@
2530  EXPORT_SYMBOL(ipmi_get_my_address);
2531  EXPORT_SYMBOL(ipmi_set_my_LUN);
2532  EXPORT_SYMBOL(ipmi_get_my_LUN);
2533 +EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
2534 diff -urN linux-2.4.23.org/drivers/char/ipmi/ipmi_si.c linux-2.4.23/drivers/char/ipmi/ipmi_si.c
2535 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_si.c        1970-01-01 01:00:00.000000000 +0100
2536 +++ linux-2.4.23/drivers/char/ipmi/ipmi_si.c    2003-12-06 17:46:43.002453092 +0100
2537 @@ -0,0 +1,1729 @@
2538 +/*
2539 + * ipmi_si.c
2540 + *
2541 + * The interface to the IPMI driver for the system interfaces (KCS, SMIC,
2542 + * BT in the future).
2543 + *
2544 + * Author: MontaVista Software, Inc.
2545 + *         Corey Minyard <minyard@mvista.com>
2546 + *         source@mvista.com
2547 + *
2548 + * Copyright 2002 MontaVista Software Inc.
2549 + *
2550 + *  This program is free software; you can redistribute it and/or modify it
2551 + *  under the terms of the GNU General Public License as published by the
2552 + *  Free Software Foundation; either version 2 of the License, or (at your
2553 + *  option) any later version.
2554 + *
2555 + *
2556 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
2557 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2558 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2559 + *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2560 + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2561 + *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
2562 + *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2563 + *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
2564 + *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
2565 + *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2566 + *
2567 + *  You should have received a copy of the GNU General Public License along
2568 + *  with this program; if not, write to the Free Software Foundation, Inc.,
2569 + *  675 Mass Ave, Cambridge, MA 02139, USA.
2570 + */
2571 +
2572 +/*
2573 + * This file holds the "policy" for the interface to the SMI state
2574 + * machine.  It does the configuration, handles timers and interrupts,
2575 + * and drives the real SMI state machine.
2576 + */
2577 +
2578 +#include <linux/config.h>
2579 +#include <linux/module.h>
2580 +#include <asm/system.h>
2581 +#include <linux/sched.h>
2582 +#include <linux/timer.h>
2583 +#include <linux/errno.h>
2584 +#include <linux/spinlock.h>
2585 +#include <linux/slab.h>
2586 +#include <linux/delay.h>
2587 +#include <linux/list.h>
2588 +#include <linux/ioport.h>
2589 +#ifdef CONFIG_HIGH_RES_TIMERS
2590 +#include <linux/hrtime.h>
2591 +# if defined(schedule_next_int)
2592 +/* Old high-res timer code, do translations. */
2593 +#  define get_arch_cycles(a) quick_update_jiffies_sub(a) 
2594 +#  define arch_cycles_per_jiffy cycles_per_jiffies
2595 +# endif
2596 +static inline void add_usec_to_timer(struct timer_list *t, long v)
2597 +{
2598 +       t->sub_expires += nsec_to_arch_cycle(v * 1000);
2599 +       while (t->sub_expires >= arch_cycles_per_jiffy)
2600 +       {
2601 +               t->expires++;
2602 +               t->sub_expires -= arch_cycles_per_jiffy;
2603 +       }
2604 +}
2605 +#endif
2606 +#include <linux/interrupt.h>
2607 +#include <linux/ipmi_smi.h>
2608 +#include <asm/io.h>
2609 +#include "ipmi_si_sm.h"
2610 +#include <linux/init.h>
2611 +
2612 +#define IPMI_SI_VERSION "v27"
2613 +
2614 +/* Measure times between events in the driver. */
2615 +#undef DEBUG_TIMING
2616 +
2617 +/* Call every 10 ms when nothing is going on. */
2618 +#define SI_TIMEOUT_TIME_USEC   10000
2619 +#define SI_USEC_PER_JIFFY      (1000000/HZ)
2620 +#define SI_TIMEOUT_JIFFIES     (SI_TIMEOUT_TIME_USEC/SI_USEC_PER_JIFFY)
2621 +#define SI_SHORT_TIMEOUT_USEC  250 /* .25ms when the SM request a
2622 +                                       short timeout */
2623 +
2624 +enum si_intf_state {
2625 +       SI_NORMAL,
2626 +       SI_GETTING_FLAGS,
2627 +       SI_GETTING_EVENTS,
2628 +       SI_CLEARING_FLAGS,
2629 +       SI_CLEARING_FLAGS_THEN_SET_IRQ,
2630 +       SI_GETTING_MESSAGES,
2631 +       SI_ENABLE_INTERRUPTS1,
2632 +       SI_ENABLE_INTERRUPTS2
2633 +       /* FIXME - add watchdog stuff. */
2634 +};
2635 +
2636 +enum si_type {
2637 +       SI_KCS, SI_SMIC, SI_BT
2638 +};
2639 +
2640 +struct smi_info
2641 +{
2642 +       ipmi_smi_t             intf;
2643 +       struct si_sm_data      *si_sm;
2644 +       struct si_sm_handlers  *handlers;
2645 +       enum si_type           si_type;
2646 +       spinlock_t             si_lock;
2647 +       spinlock_t             msg_lock;
2648 +       struct list_head       xmit_msgs;
2649 +       struct list_head       hp_xmit_msgs;
2650 +       struct ipmi_smi_msg    *curr_msg;
2651 +       enum si_intf_state     si_state;
2652 +
2653 +       /* Used to handle the various types of I/O that can occur with
2654 +           IPMI */
2655 +       struct si_sm_io io;
2656 +       int (*io_setup)(struct smi_info *info);
2657 +       void (*io_cleanup)(struct smi_info *info);
2658 +       int (*irq_setup)(struct smi_info *info);
2659 +       void (*irq_cleanup)(struct smi_info *info);
2660 +       unsigned int io_size;
2661 +
2662 +       /* Flags from the last GET_MSG_FLAGS command, used when an ATTN
2663 +          is set to hold the flags until we are done handling everything
2664 +          from the flags. */
2665 +#define RECEIVE_MSG_AVAIL      0x01
2666 +#define EVENT_MSG_BUFFER_FULL  0x02
2667 +#define WDT_PRE_TIMEOUT_INT    0x08
2668 +       unsigned char       msg_flags;
2669 +
2670 +       /* If set to true, this will request events the next time the
2671 +          state machine is idle. */
2672 +       atomic_t            req_events;
2673 +
2674 +       /* If true, run the state machine to completion on every send
2675 +          call.  Generally used after a panic to make sure stuff goes
2676 +          out. */
2677 +       int                 run_to_completion;
2678 +
2679 +       /* The I/O port of an SI interface. */
2680 +       int                 port;
2681 +
2682 +       /* zero if no irq; */
2683 +       int                 irq;
2684 +
2685 +       /* The physical and remapped memory addresses of a SI interface. */
2686 +       unsigned long       physaddr;
2687 +       unsigned char       *addr;
2688 +
2689 +       /* The timer for this si. */
2690 +       struct timer_list   si_timer;
2691 +
2692 +       /* The time (in jiffies) the last timeout occurred at. */
2693 +       unsigned long       last_timeout_jiffies;
2694 +
2695 +       /* Used to gracefully stop the timer without race conditions. */
2696 +       volatile int        stop_operation;
2697 +       volatile int        timer_stopped;
2698 +
2699 +       /* The driver will disable interrupts when it gets into a
2700 +          situation where it cannot handle messages due to lack of
2701 +          memory.  Once that situation clears up, it will re-enable
2702 +          interrupts. */
2703 +       int interrupt_disabled;
2704 +
2705 +       unsigned char ipmi_si_dev_rev;
2706 +       unsigned char ipmi_si_fw_rev_major;
2707 +       unsigned char ipmi_si_fw_rev_minor;
2708 +       unsigned char ipmi_version_major;
2709 +       unsigned char ipmi_version_minor;
2710 +
2711 +       /* Counters and things for the proc filesystem. */
2712 +       spinlock_t count_lock;
2713 +       unsigned long short_timeouts;
2714 +       unsigned long long_timeouts;
2715 +       unsigned long timeout_restarts;
2716 +       unsigned long idles;
2717 +       unsigned long interrupts;
2718 +       unsigned long attentions;
2719 +       unsigned long flag_fetches;
2720 +       unsigned long hosed_count;
2721 +       unsigned long complete_transactions;
2722 +       unsigned long events;
2723 +       unsigned long watchdog_pretimeouts;
2724 +       unsigned long incoming_messages;
2725 +};
2726 +
2727 +static void si_restart_short_timer(struct smi_info *smi_info);
2728 +
2729 +static void deliver_recv_msg(struct smi_info *smi_info,
2730 +                            struct ipmi_smi_msg *msg)
2731 +{
2732 +       /* Deliver the message to the upper layer with the lock
2733 +           released. */
2734 +       spin_unlock(&(smi_info->si_lock));
2735 +       ipmi_smi_msg_received(smi_info->intf, msg);
2736 +       spin_lock(&(smi_info->si_lock));
2737 +}
2738 +
2739 +static void return_hosed_msg(struct smi_info *smi_info)
2740 +{
2741 +       struct ipmi_smi_msg *msg = smi_info->curr_msg;
2742 +
2743 +       /* Make it a reponse */
2744 +       msg->rsp[0] = msg->data[0] | 4;
2745 +       msg->rsp[1] = msg->data[1];
2746 +       msg->rsp[2] = 0xFF; /* Unknown error. */
2747 +       msg->rsp_size = 3;
2748 +                       
2749 +       smi_info->curr_msg = NULL;
2750 +       deliver_recv_msg(smi_info, msg);
2751 +}
2752 +
2753 +static enum si_sm_result start_next_msg(struct smi_info *smi_info)
2754 +{
2755 +       int              rv;
2756 +       struct list_head *entry = NULL;
2757 +#ifdef DEBUG_TIMING
2758 +       struct timeval t;
2759 +#endif
2760 +
2761 +       /* No need to save flags, we aleady have interrupts off and we
2762 +          already hold the SMI lock. */
2763 +       spin_lock(&(smi_info->msg_lock));
2764 +       
2765 +       /* Pick the high priority queue first. */
2766 +       if (! list_empty(&(smi_info->hp_xmit_msgs))) {
2767 +               entry = smi_info->hp_xmit_msgs.next;
2768 +       } else if (! list_empty(&(smi_info->xmit_msgs))) {
2769 +               entry = smi_info->xmit_msgs.next;
2770 +       }
2771 +
2772 +       if (!entry) {
2773 +               smi_info->curr_msg = NULL;
2774 +               rv = SI_SM_IDLE;
2775 +       } else {
2776 +               int err;
2777 +
2778 +               list_del(entry);
2779 +               smi_info->curr_msg = list_entry(entry,
2780 +                                               struct ipmi_smi_msg,
2781 +                                               link);
2782 +#ifdef DEBUG_TIMING
2783 +               do_gettimeofday(&t);
2784 +               printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec);
2785 +#endif
2786 +               err = smi_info->handlers->start_transaction(
2787 +                       smi_info->si_sm,
2788 +                       smi_info->curr_msg->data,
2789 +                       smi_info->curr_msg->data_size);
2790 +               if (err) {
2791 +                       return_hosed_msg(smi_info);
2792 +               }
2793 +
2794 +               rv = SI_SM_CALL_WITHOUT_DELAY;
2795 +       }
2796 +       spin_unlock(&(smi_info->msg_lock));
2797 +
2798 +       return rv;
2799 +}
2800 +
2801 +static void start_enable_irq(struct smi_info *smi_info)
2802 +{
2803 +       unsigned char msg[2];
2804 +
2805 +       /* If we are enabling interrupts, we have to tell the
2806 +          BMC to use them. */
2807 +       msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
2808 +       msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
2809 +
2810 +       smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
2811 +       smi_info->si_state = SI_ENABLE_INTERRUPTS1;
2812 +}
2813 +
2814 +static void start_clear_flags(struct smi_info *smi_info)
2815 +{
2816 +       unsigned char msg[3];
2817 +
2818 +       /* Make sure the watchdog pre-timeout flag is not set at startup. */
2819 +       msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
2820 +       msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD;
2821 +       msg[2] = WDT_PRE_TIMEOUT_INT;
2822 +
2823 +       smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3);
2824 +       smi_info->si_state = SI_CLEARING_FLAGS;
2825 +}
2826 +
2827 +/* When we have a situtaion where we run out of memory and cannot
2828 +   allocate messages, we just leave them in the BMC and run the system
2829 +   polled until we can allocate some memory.  Once we have some
2830 +   memory, we will re-enable the interrupt. */
2831 +static inline void disable_si_irq(struct smi_info *smi_info)
2832 +{
2833 +       if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
2834 +               disable_irq_nosync(smi_info->irq);
2835 +               smi_info->interrupt_disabled = 1;
2836 +       }
2837 +}
2838 +
2839 +static inline void enable_si_irq(struct smi_info *smi_info)
2840 +{
2841 +       if ((smi_info->irq) && (smi_info->interrupt_disabled)) {
2842 +               enable_irq(smi_info->irq);
2843 +               smi_info->interrupt_disabled = 0;
2844 +       }
2845 +}
2846 +
2847 +static void handle_flags(struct smi_info *smi_info)
2848 +{
2849 +       if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) {
2850 +               /* Watchdog pre-timeout */
2851 +               spin_lock(&smi_info->count_lock);
2852 +               smi_info->watchdog_pretimeouts++;
2853 +               spin_unlock(&smi_info->count_lock);
2854 +
2855 +               start_clear_flags(smi_info);
2856 +               smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT;
2857 +               spin_unlock(&(smi_info->si_lock));
2858 +               ipmi_smi_watchdog_pretimeout(smi_info->intf);
2859 +               spin_lock(&(smi_info->si_lock));
2860 +       } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) {
2861 +               /* Messages available. */
2862 +               smi_info->curr_msg = ipmi_alloc_smi_msg();
2863 +               if (!smi_info->curr_msg) {
2864 +                       disable_si_irq(smi_info);
2865 +                       smi_info->si_state = SI_NORMAL;
2866 +                       return;
2867 +               }
2868 +               enable_si_irq(smi_info);
2869 +
2870 +               smi_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
2871 +               smi_info->curr_msg->data[1] = IPMI_GET_MSG_CMD;
2872 +               smi_info->curr_msg->data_size = 2;
2873 +
2874 +               smi_info->handlers->start_transaction(
2875 +                       smi_info->si_sm,
2876 +                       smi_info->curr_msg->data,
2877 +                       smi_info->curr_msg->data_size);
2878 +               smi_info->si_state = SI_GETTING_MESSAGES;
2879 +       } else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) {
2880 +               /* Events available. */
2881 +               smi_info->curr_msg = ipmi_alloc_smi_msg();
2882 +               if (!smi_info->curr_msg) {
2883 +                       disable_si_irq(smi_info);
2884 +                       smi_info->si_state = SI_NORMAL;
2885 +                       return;
2886 +               }
2887 +               enable_si_irq(smi_info);
2888 +
2889 +               smi_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
2890 +               smi_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD;
2891 +               smi_info->curr_msg->data_size = 2;
2892 +
2893 +               smi_info->handlers->start_transaction(
2894 +                       smi_info->si_sm,
2895 +                       smi_info->curr_msg->data,
2896 +                       smi_info->curr_msg->data_size);
2897 +               smi_info->si_state = SI_GETTING_EVENTS;
2898 +       } else {
2899 +               smi_info->si_state = SI_NORMAL;
2900 +       }
2901 +}
2902 +
2903 +static void handle_transaction_done(struct smi_info *smi_info)
2904 +{
2905 +       struct ipmi_smi_msg *msg;
2906 +#ifdef DEBUG_TIMING
2907 +       struct timeval t;
2908 +
2909 +       do_gettimeofday(&t);
2910 +       printk("**Done: %d.%9.9d\n", t.tv_sec, t.tv_usec);
2911 +#endif
2912 +       switch (smi_info->si_state) {
2913 +       case SI_NORMAL:
2914 +               if (!smi_info->curr_msg)
2915 +                       break;
2916 +                       
2917 +               smi_info->curr_msg->rsp_size
2918 +                       = smi_info->handlers->get_result(
2919 +                               smi_info->si_sm,
2920 +                               smi_info->curr_msg->rsp,
2921 +                               IPMI_MAX_MSG_LENGTH);
2922 +               
2923 +               /* Do this here becase deliver_recv_msg() releases the
2924 +                  lock, and a new message can be put in during the
2925 +                  time the lock is released. */
2926 +               msg = smi_info->curr_msg;
2927 +               smi_info->curr_msg = NULL;
2928 +               deliver_recv_msg(smi_info, msg);
2929 +               break;
2930 +               
2931 +       case SI_GETTING_FLAGS:
2932 +       {
2933 +               unsigned char msg[4];
2934 +               unsigned int  len;
2935 +
2936 +               /* We got the flags from the SMI, now handle them. */
2937 +               len = smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
2938 +               if (msg[2] != 0) {
2939 +                       /* Error fetching flags, just give up for
2940 +                          now. */
2941 +                       smi_info->si_state = SI_NORMAL;
2942 +               } else if (len < 3) {
2943 +                       /* Hmm, no flags.  That's technically illegal, but
2944 +                          don't use uninitialized data. */
2945 +                       smi_info->si_state = SI_NORMAL;
2946 +               } else {
2947 +                       smi_info->msg_flags = msg[3];
2948 +                       handle_flags(smi_info);
2949 +               }
2950 +               break;
2951 +       }
2952 +
2953 +       case SI_CLEARING_FLAGS:
2954 +       case SI_CLEARING_FLAGS_THEN_SET_IRQ:
2955 +       {
2956 +               unsigned char msg[3];
2957 +
2958 +               /* We cleared the flags. */
2959 +               smi_info->handlers->get_result(smi_info->si_sm, msg, 3);
2960 +               if (msg[2] != 0) {
2961 +                       /* Error clearing flags */
2962 +                       printk(KERN_WARNING
2963 +                              "ipmi_smi: Error clearing flags: %2.2x\n",
2964 +                              msg[2]);
2965 +               }
2966 +               if (smi_info->si_state == SI_CLEARING_FLAGS_THEN_SET_IRQ)
2967 +                       start_enable_irq(smi_info);
2968 +               else
2969 +                       smi_info->si_state = SI_NORMAL;
2970 +               break;
2971 +       }
2972 +
2973 +       case SI_GETTING_EVENTS:
2974 +       {
2975 +               smi_info->curr_msg->rsp_size
2976 +                       = smi_info->handlers->get_result(
2977 +                               smi_info->si_sm,
2978 +                               smi_info->curr_msg->rsp,
2979 +                               IPMI_MAX_MSG_LENGTH);
2980 +
2981 +               /* Do this here becase deliver_recv_msg() releases the
2982 +                  lock, and a new message can be put in during the
2983 +                  time the lock is released. */
2984 +               msg = smi_info->curr_msg;
2985 +               smi_info->curr_msg = NULL;
2986 +               if (msg->rsp[2] != 0) {
2987 +                       /* Error getting event, probably done. */
2988 +                       msg->done(msg);
2989 +
2990 +                       /* Take off the event flag. */
2991 +                       smi_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
2992 +               } else {
2993 +                       spin_lock(&smi_info->count_lock);
2994 +                       smi_info->events++;
2995 +                       spin_unlock(&smi_info->count_lock);
2996 +
2997 +                       deliver_recv_msg(smi_info, msg);
2998 +               }
2999 +               handle_flags(smi_info);
3000 +               break;
3001 +       }
3002 +
3003 +       case SI_GETTING_MESSAGES:
3004 +       {
3005 +               smi_info->curr_msg->rsp_size
3006 +                       = smi_info->handlers->get_result(
3007 +                               smi_info->si_sm,
3008 +                               smi_info->curr_msg->rsp,
3009 +                               IPMI_MAX_MSG_LENGTH);
3010 +
3011 +               /* Do this here becase deliver_recv_msg() releases the
3012 +                  lock, and a new message can be put in during the
3013 +                  time the lock is released. */
3014 +               msg = smi_info->curr_msg;
3015 +               smi_info->curr_msg = NULL;
3016 +               if (msg->rsp[2] != 0) {
3017 +                       /* Error getting event, probably done. */
3018 +                       msg->done(msg);
3019 +
3020 +                       /* Take off the msg flag. */
3021 +                       smi_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
3022 +               } else {
3023 +                       spin_lock(&smi_info->count_lock);
3024 +                       smi_info->incoming_messages++;
3025 +                       spin_unlock(&smi_info->count_lock);
3026 +
3027 +                       deliver_recv_msg(smi_info, msg);
3028 +               }
3029 +               handle_flags(smi_info);
3030 +               break;
3031 +       }
3032 +
3033 +       case SI_ENABLE_INTERRUPTS1:
3034 +       {
3035 +               unsigned char msg[4];
3036 +
3037 +               /* We got the flags from the SMI, now handle them. */
3038 +               smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
3039 +               if (msg[2] != 0) {
3040 +                       printk(KERN_WARNING
3041 +                              "ipmi_smi: Could not enable interrupts"
3042 +                              ", failed get, using polled mode.\n");
3043 +                       smi_info->si_state = SI_NORMAL;
3044 +               } else {
3045 +                       msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
3046 +                       msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
3047 +                       msg[2] = msg[3] | 1; /* enable msg queue int */
3048 +                       smi_info->handlers->start_transaction(
3049 +                               smi_info->si_sm, msg, 3);
3050 +                       smi_info->si_state = SI_ENABLE_INTERRUPTS2;
3051 +               }
3052 +               break;
3053 +       }
3054 +
3055 +       case SI_ENABLE_INTERRUPTS2:
3056 +       {
3057 +               unsigned char msg[4];
3058 +
3059 +               /* We got the flags from the SMI, now handle them. */
3060 +               smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
3061 +               if (msg[2] != 0) {
3062 +                       printk(KERN_WARNING
3063 +                              "ipmi_smi: Could not enable interrupts"
3064 +                              ", failed set, using polled mode.\n");
3065 +               }
3066 +               smi_info->si_state = SI_NORMAL;
3067 +               break;
3068 +       }
3069 +       }
3070 +}
3071 +
3072 +/* Called on timeouts and events.  Timeouts should pass the elapsed
3073 +   time, interrupts should pass in zero. */
3074 +static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
3075 +                                          int time)
3076 +{
3077 +       enum si_sm_result si_sm_result;
3078 +
3079 + restart:
3080 +       /* There used to be a loop here that waited a little while
3081 +          (around 25us) before giving up.  That turned out to be
3082 +          pointless, the minimum delays I was seeing were in the 300us
3083 +          range, which is far too long to wait in an interrupt.  So
3084 +          we just run until the state machine tells us something
3085 +          happened or it needs a delay. */
3086 +       si_sm_result = smi_info->handlers->event(smi_info->si_sm, time);
3087 +       time = 0;
3088 +       while (si_sm_result == SI_SM_CALL_WITHOUT_DELAY)
3089 +       {
3090 +               si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
3091 +       }
3092 +
3093 +       if (si_sm_result == SI_SM_TRANSACTION_COMPLETE)
3094 +       {
3095 +               spin_lock(&smi_info->count_lock);
3096 +               smi_info->complete_transactions++;
3097 +               spin_unlock(&smi_info->count_lock);
3098 +
3099 +               handle_transaction_done(smi_info);
3100 +               si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
3101 +       }
3102 +       else if (si_sm_result == SI_SM_HOSED)
3103 +       {
3104 +               spin_lock(&smi_info->count_lock);
3105 +               smi_info->hosed_count++;
3106 +               spin_unlock(&smi_info->count_lock);
3107 +
3108 +               if (smi_info->curr_msg != NULL) {
3109 +                       /* If we were handling a user message, format
3110 +                           a response to send to the upper layer to
3111 +                           tell it about the error. */
3112 +                       return_hosed_msg(smi_info);
3113 +               }
3114 +               si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
3115 +               smi_info->si_state = SI_NORMAL;
3116 +       }
3117 +
3118 +       /* We prefer handling attn over new messages. */
3119 +       if (si_sm_result == SI_SM_ATTN)
3120 +       {
3121 +               unsigned char msg[2];
3122 +
3123 +               spin_lock(&smi_info->count_lock);
3124 +               smi_info->attentions++;
3125 +               spin_unlock(&smi_info->count_lock);
3126 +
3127 +               /* Got a attn, send down a get message flags to see
3128 +                   what's causing it.  It would be better to handle
3129 +                   this in the upper layer, but due to the way
3130 +                   interrupts work with the SMI, that's not really
3131 +                   possible. */
3132 +               msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
3133 +               msg[1] = IPMI_GET_MSG_FLAGS_CMD;
3134 +
3135 +               smi_info->handlers->start_transaction(
3136 +                       smi_info->si_sm, msg, 2);
3137 +               smi_info->si_state = SI_GETTING_FLAGS;
3138 +               goto restart;
3139 +       }
3140 +
3141 +       /* If we are currently idle, try to start the next message. */
3142 +       if (si_sm_result == SI_SM_IDLE) {
3143 +               spin_lock(&smi_info->count_lock);
3144 +               smi_info->idles++;
3145 +               spin_unlock(&smi_info->count_lock);
3146 +
3147 +               si_sm_result = start_next_msg(smi_info);
3148 +               if (si_sm_result != SI_SM_IDLE)
3149 +                       goto restart;
3150 +        }
3151 +
3152 +       if ((si_sm_result == SI_SM_IDLE)
3153 +           && (atomic_read(&smi_info->req_events)))
3154 +       {
3155 +               /* We are idle and the upper layer requested that I fetch
3156 +                  events, so do so. */
3157 +               unsigned char msg[2];
3158 +
3159 +               spin_lock(&smi_info->count_lock);
3160 +               smi_info->flag_fetches++;
3161 +               spin_unlock(&smi_info->count_lock);
3162 +
3163 +               atomic_set(&smi_info->req_events, 0);
3164 +               msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
3165 +               msg[1] = IPMI_GET_MSG_FLAGS_CMD;
3166 +
3167 +               smi_info->handlers->start_transaction(
3168 +                       smi_info->si_sm, msg, 2);
3169 +               smi_info->si_state = SI_GETTING_FLAGS;
3170 +               goto restart;
3171 +       }
3172 +
3173 +       return si_sm_result;
3174 +}
3175 +
3176 +static void sender(void                *send_info,
3177 +                  struct ipmi_smi_msg *msg,
3178 +                  int                 priority)
3179 +{
3180 +       struct smi_info   *smi_info = (struct smi_info *) send_info;
3181 +       enum si_sm_result result;
3182 +       unsigned long     flags;
3183 +#ifdef DEBUG_TIMING
3184 +       struct timeval    t;
3185 +#endif
3186 +
3187 +       spin_lock_irqsave(&(smi_info->msg_lock), flags);
3188 +#ifdef DEBUG_TIMING
3189 +       do_gettimeofday(&t);
3190 +       printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec);
3191 +#endif
3192 +
3193 +       if (smi_info->run_to_completion) {
3194 +               /* If we are running to completion, then throw it in
3195 +                  the list and run transactions until everything is
3196 +                  clear.  Priority doesn't matter here. */
3197 +               list_add_tail(&(msg->link), &(smi_info->xmit_msgs));
3198 +
3199 +               /* We have to release the msg lock and claim the smi
3200 +                  lock in this case, because of race conditions. */
3201 +               spin_unlock_irqrestore(&(smi_info->msg_lock), flags);
3202 +
3203 +               spin_lock_irqsave(&(smi_info->si_lock), flags);
3204 +               result = smi_event_handler(smi_info, 0);
3205 +               while (result != SI_SM_IDLE) {
3206 +                       udelay(SI_SHORT_TIMEOUT_USEC);
3207 +                       result = smi_event_handler(smi_info,
3208 +                                                  SI_SHORT_TIMEOUT_USEC);
3209 +               }
3210 +               spin_unlock_irqrestore(&(smi_info->si_lock), flags);
3211 +               return;
3212 +       } else {
3213 +               if (priority > 0) {
3214 +                       list_add_tail(&(msg->link), &(smi_info->hp_xmit_msgs));
3215 +               } else {
3216 +                       list_add_tail(&(msg->link), &(smi_info->xmit_msgs));
3217 +               }
3218 +       }
3219 +       spin_unlock_irqrestore(&(smi_info->msg_lock), flags);
3220 +
3221 +       spin_lock_irqsave(&(smi_info->si_lock), flags);
3222 +       if ((smi_info->si_state == SI_NORMAL)
3223 +           && (smi_info->curr_msg == NULL))
3224 +       {
3225 +               start_next_msg(smi_info);
3226 +               si_restart_short_timer(smi_info);
3227 +       }
3228 +       spin_unlock_irqrestore(&(smi_info->si_lock), flags);
3229 +}
3230 +
3231 +static void set_run_to_completion(void *send_info, int i_run_to_completion)
3232 +{
3233 +       struct smi_info   *smi_info = (struct smi_info *) send_info;
3234 +       enum si_sm_result result;
3235 +       unsigned long     flags;
3236 +
3237 +       spin_lock_irqsave(&(smi_info->si_lock), flags);
3238 +
3239 +       smi_info->run_to_completion = i_run_to_completion;
3240 +       if (i_run_to_completion) {
3241 +               result = smi_event_handler(smi_info, 0);
3242 +               while (result != SI_SM_IDLE) {
3243 +                       udelay(SI_SHORT_TIMEOUT_USEC);
3244 +                       result = smi_event_handler(smi_info,
3245 +                                                  SI_SHORT_TIMEOUT_USEC);
3246 +               }
3247 +       }
3248 +
3249 +       spin_unlock_irqrestore(&(smi_info->si_lock), flags);
3250 +}
3251 +
3252 +static void request_events(void *send_info)
3253 +{
3254 +       struct smi_info *smi_info = (struct smi_info *) send_info;
3255 +
3256 +       atomic_set(&smi_info->req_events, 1);
3257 +}
3258 +
3259 +static int new_user(void *send_info)
3260 +{
3261 +       if (!try_inc_mod_count(THIS_MODULE))
3262 +               return -EBUSY;
3263 +       return 0;
3264 +}
3265 +
3266 +static void user_left(void *send_info)
3267 +{
3268 +       MOD_DEC_USE_COUNT;
3269 +}
3270 +
3271 +static int initialized = 0;
3272 +
3273 +/* Must be called with interrupts off and with the si_lock held. */
3274 +static void si_restart_short_timer(struct smi_info *smi_info)
3275 +{
3276 +#if defined(CONFIG_HIGH_RES_TIMERS)
3277 +       unsigned long flags;
3278 +       unsigned long jiffies_now;
3279 +
3280 +       if (del_timer(&(smi_info->si_timer))) {
3281 +               /* If we don't delete the timer, then it will go off
3282 +                  immediately, anyway.  So we only process if we
3283 +                  actually delete the timer. */
3284 +
3285 +               /* We already have irqsave on, so no need for it
3286 +                   here. */
3287 +               read_lock(&xtime_lock);
3288 +               jiffies_now = jiffies;
3289 +               smi_info->si_timer.expires = jiffies_now;
3290 +               smi_info->si_timer.sub_expires = get_arch_cycles(jiffies_now);
3291 +               read_unlock(&xtime_lock);
3292 +
3293 +               add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC);
3294 +
3295 +               add_timer(&(smi_info->si_timer));
3296 +               spin_lock_irqsave(&smi_info->count_lock, flags);
3297 +               smi_info->timeout_restarts++;
3298 +               spin_unlock_irqrestore(&smi_info->count_lock, flags);
3299 +       }
3300 +#endif
3301 +}
3302 +
3303 +static void smi_timeout(unsigned long data)
3304 +{
3305 +       struct smi_info   *smi_info = (struct smi_info *) data;
3306 +       enum si_sm_result smi_result;
3307 +       unsigned long     flags;
3308 +       unsigned long     jiffies_now;
3309 +       unsigned long     time_diff;
3310 +#ifdef DEBUG_TIMING
3311 +       struct timeval    t;
3312 +#endif
3313 +
3314 +       if (smi_info->stop_operation) {
3315 +               smi_info->timer_stopped = 1;
3316 +               return;
3317 +       }
3318 +
3319 +       spin_lock_irqsave(&(smi_info->si_lock), flags);
3320 +#ifdef DEBUG_TIMING
3321 +       do_gettimeofday(&t);
3322 +       printk("**Timer: %d.%9.9d\n", t.tv_sec, t.tv_usec);
3323 +#endif
3324 +       jiffies_now = jiffies;
3325 +       time_diff = ((jiffies_now - smi_info->last_timeout_jiffies)
3326 +                    * SI_USEC_PER_JIFFY);
3327 +       smi_result = smi_event_handler(smi_info, time_diff);
3328 +
3329 +       spin_unlock_irqrestore(&(smi_info->si_lock), flags);
3330 +
3331 +       smi_info->last_timeout_jiffies = jiffies_now;
3332 +
3333 +       if ((smi_info->irq) && (! smi_info->interrupt_disabled)) {
3334 +               /* Running with interrupts, only do long timeouts. */
3335 +               smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
3336 +               spin_lock_irqsave(&smi_info->count_lock, flags);
3337 +               smi_info->long_timeouts++;
3338 +               spin_unlock_irqrestore(&smi_info->count_lock, flags);
3339 +               goto do_add_timer;
3340 +       }
3341 +
3342 +       /* If the state machine asks for a short delay, then shorten
3343 +           the timer timeout. */
3344 +       if (smi_result == SI_SM_CALL_WITH_DELAY) {
3345 +               spin_lock_irqsave(&smi_info->count_lock, flags);
3346 +               smi_info->short_timeouts++;
3347 +               spin_unlock_irqrestore(&smi_info->count_lock, flags);
3348 +#if defined(CONFIG_HIGH_RES_TIMERS)
3349 +               add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC);
3350 +#else
3351 +               smi_info->si_timer.expires = jiffies + 1;
3352 +#endif
3353 +       } else {
3354 +               spin_lock_irqsave(&smi_info->count_lock, flags);
3355 +               smi_info->long_timeouts++;
3356 +               spin_unlock_irqrestore(&smi_info->count_lock, flags);
3357 +               smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
3358 +#if defined(CONFIG_HIGH_RES_TIMERS)
3359 +               smi_info->si_timer.sub_expires = 0;
3360 +#endif
3361 +       }
3362 +
3363 + do_add_timer:
3364 +       add_timer(&(smi_info->si_timer));
3365 +}
3366 +
3367 +static void si_irq_handler(int irq, void *data, struct pt_regs *regs)
3368 +{
3369 +       struct smi_info *smi_info = (struct smi_info *) data;
3370 +       unsigned long   flags;
3371 +#ifdef DEBUG_TIMING
3372 +       struct timeval  t;
3373 +#endif
3374 +
3375 +       spin_lock_irqsave(&(smi_info->si_lock), flags);
3376 +
3377 +       spin_lock(&smi_info->count_lock);
3378 +       smi_info->interrupts++;
3379 +       spin_unlock(&smi_info->count_lock);
3380 +
3381 +       if (smi_info->stop_operation)
3382 +               goto out;
3383 +
3384 +#ifdef DEBUG_TIMING
3385 +       do_gettimeofday(&t);
3386 +       printk("**Interrupt: %d.%9.9d\n", t.tv_sec, t.tv_usec);
3387 +#endif
3388 +       smi_event_handler(smi_info, 0);
3389 + out:
3390 +       spin_unlock_irqrestore(&(smi_info->si_lock), flags);
3391 +}
3392 +
3393 +static struct ipmi_smi_handlers handlers =
3394 +{
3395 +       sender:                sender,
3396 +       request_events:        request_events,
3397 +       new_user:              new_user,
3398 +       user_left:             user_left,
3399 +       set_run_to_completion: set_run_to_completion
3400 +};
3401 +
3402 +/* There can be 4 IO ports passed in (with or without IRQs), 4 addresses,
3403 +   a default IO port, and 1 ACPI/SPMI address.  That sets SI_MAX_DRIVERS */
3404 +
3405 +#define SI_MAX_PARMS 4
3406 +#define SI_MAX_DRIVERS ((SI_MAX_PARMS * 2) + 2)
3407 +static struct smi_info *smi_infos[SI_MAX_DRIVERS] =
3408 +{ NULL, NULL, NULL, NULL };
3409 +
3410 +#define DEVICE_NAME "ipmi_si"
3411 +
3412 +#define DEFAULT_KCS_IO_PORT 0xca2
3413 +#define DEFAULT_SMIC_IO_PORT 0xca9
3414 +
3415 +static int           si_trydefaults = 1;
3416 +static char          *si_type[SI_MAX_PARMS] = { NULL, NULL, NULL, NULL };
3417 +static unsigned long si_addrs[SI_MAX_PARMS] = { 0, 0, 0, 0 };
3418 +static unsigned int  si_ports[SI_MAX_PARMS] = { 0, 0, 0, 0 };
3419 +static int           si_irqs[SI_MAX_PARMS] = { 0, 0, 0, 0 };
3420 +
3421 +
3422 +MODULE_PARM(si_trydefaults, "i");
3423 +MODULE_PARM(si_type, "1-4s");
3424 +MODULE_PARM(si_addrs, "1-4l");
3425 +MODULE_PARM(si_irqs, "1-4i");
3426 +MODULE_PARM(si_ports, "1-4i");
3427 +
3428 +
3429 +static int std_irq_setup(struct smi_info *info)
3430 +{
3431 +       int rv;
3432 +
3433 +       if (!info->irq)
3434 +               return 0;
3435 +
3436 +       rv = request_irq(info->irq,
3437 +                        si_irq_handler,
3438 +                        SA_INTERRUPT,
3439 +                        DEVICE_NAME,
3440 +                        info);
3441 +       if (rv) {
3442 +               printk(KERN_WARNING
3443 +                      "ipmi_smi: %s unable to claim interrupt %d,"
3444 +                      " running polled\n",
3445 +                      DEVICE_NAME, info->irq);
3446 +               info->irq = 0;
3447 +       } else {
3448 +               printk("  Using irq %d\n", info->irq);
3449 +       }
3450 +
3451 +       return rv;
3452 +}
3453 +
3454 +static void std_irq_cleanup(struct smi_info *info)
3455 +{
3456 +       if (!info->irq)
3457 +               return;
3458 +
3459 +       free_irq(info->irq, info);
3460 +}
3461 +
3462 +static unsigned char port_inb(struct si_sm_io *io, unsigned int offset)
3463 +{
3464 +       unsigned int *addr = io->info;
3465 +
3466 +       return inb((*addr)+offset);
3467 +}
3468 +
3469 +static void port_outb(struct si_sm_io *io, unsigned int offset,
3470 +                     unsigned char b)
3471 +{
3472 +       unsigned int *addr = io->info;
3473 +
3474 +       outb(b, (*addr)+offset);
3475 +}
3476 +
3477 +static int port_setup(struct smi_info *info)
3478 +{
3479 +       unsigned int *addr = info->io.info;
3480 +
3481 +       if (!addr || (!*addr))
3482 +               return -ENODEV;
3483 +
3484 +       if (request_region(*addr, info->io_size, DEVICE_NAME) == NULL)
3485 +               return -EIO;
3486 +       return 0;
3487 +}
3488 +
3489 +static void port_cleanup(struct smi_info *info)
3490 +{
3491 +       unsigned int *addr = info->io.info;
3492 +
3493 +       if (addr && (*addr)) 
3494 +               release_region (*addr, info->io_size);
3495 +       kfree(info);
3496 +}
3497 +
3498 +static int try_init_port(int intf_num, struct smi_info **new_info)
3499 +{
3500 +       struct smi_info *info;
3501 +
3502 +       if (!si_ports[intf_num])
3503 +               return -ENODEV;
3504 +
3505 +       info = kmalloc(sizeof(*info), GFP_KERNEL);
3506 +       if (!info) {
3507 +               printk("ipmi_smi: Could not allocate SMI data\n");
3508 +               return -ENOMEM;
3509 +       }
3510 +       memset(info, 0, sizeof(*info));
3511 +
3512 +       info->io_setup = port_setup;
3513 +       info->io_cleanup = port_cleanup;
3514 +       info->io.inputb = port_inb;
3515 +       info->io.outputb = port_outb;
3516 +       info->io.info = &(si_ports[intf_num]);
3517 +       info->irq = 0;
3518 +       info->irq_setup = NULL;
3519 +       *new_info = info;
3520 +
3521 +       printk("ipmi_smi: Trying state machine at I/O address 0x%x\n",
3522 +              si_ports[intf_num]);
3523 +       return 0;
3524 +}
3525 +
3526 +static unsigned char mem_inb(struct si_sm_io *io, unsigned int offset)
3527 +{
3528 +       return readb((io->addr)+offset);
3529 +}
3530 +
3531 +static void mem_outb(struct si_sm_io *io, unsigned int offset,
3532 +                    unsigned char b)
3533 +{
3534 +       writeb(b, (io->addr)+offset);
3535 +}
3536 +
3537 +static int mem_setup(struct smi_info *info)
3538 +{
3539 +       unsigned long *addr = info->io.info;
3540 +
3541 +       if (!addr || (!*addr))
3542 +               return -ENODEV;
3543 +
3544 +       if (request_mem_region(*addr, info->io_size, DEVICE_NAME) == NULL)
3545 +               return -EIO;
3546 +       info->io.addr = ioremap(*addr, info->io_size);
3547 +       if (info->io.addr == NULL) {
3548 +               release_mem_region(*addr, info->io_size);
3549 +               return -EIO;
3550 +       }
3551 +       return 0;
3552 +}
3553 +
3554 +static void mem_cleanup(struct smi_info *info)
3555 +{
3556 +       unsigned int *addr = info->io.info;
3557 +
3558 +       if (addr) {
3559 +               iounmap(info->addr);
3560 +               release_mem_region(*addr, info->io_size);
3561 +       }
3562 +       kfree(info);
3563 +}
3564 +
3565 +static int try_init_mem(int intf_num, struct smi_info **new_info)
3566 +{
3567 +       struct smi_info *info;
3568 +
3569 +       if (!si_addrs[intf_num])
3570 +               return -ENODEV;
3571 +
3572 +       info = kmalloc(sizeof(*info), GFP_KERNEL);
3573 +       if (!info) {
3574 +               printk("ipmi_smi: Could not allocate SMI data\n");
3575 +               return -ENOMEM;
3576 +       }
3577 +       memset(info, 0, sizeof(*info));
3578 +
3579 +       info->io_setup = mem_setup;
3580 +       info->io_cleanup = mem_cleanup;
3581 +       info->io.inputb = mem_inb;
3582 +       info->io.outputb = mem_outb;
3583 +       info->io.info = &(si_addrs[intf_num]);
3584 +       info->irq = 0;
3585 +       info->irq_setup = NULL;
3586 +       *new_info = info;
3587 +
3588 +       printk("ipmi_smi: Trying state machine at memory address 0x%lx\n",
3589 +              si_addrs[intf_num]);
3590 +       return 0;
3591 +}
3592 +
3593 +
3594 +#ifdef CONFIG_ACPI_INTERPRETER
3595 +
3596 +#include <linux/acpi.h>
3597 +#include <acpi/acpi.h>
3598 +#include <acpi/actypes.h>
3599 +#include <acpi/actbl.h>
3600 +
3601 +/* Once we get an ACPI failure, we don't try any more, because we go
3602 +   through the tables sequentially.  Once we don't find a table, there
3603 +   are no more. */
3604 +static int acpi_failure = 0;
3605 +
3606 +/* For GPE-type interrupts. */
3607 +void ipmi_acpi_gpe(void *context)
3608 +{
3609 +       struct smi_info *smi_info = context;
3610 +       unsigned long   flags;
3611 +#ifdef DEBUG_TIMING
3612 +       struct timeval t;
3613 +#endif
3614 +
3615 +       spin_lock_irqsave(&(smi_info->si_lock), flags);
3616 +
3617 +       spin_lock(&smi_info->count_lock);
3618 +       smi_info->interrupts++;
3619 +       spin_unlock(&smi_info->count_lock);
3620 +
3621 +       if (smi_info->stop_operation)
3622 +               goto out;
3623 +
3624 +#ifdef DEBUG_TIMING
3625 +       do_gettimeofday(&t);
3626 +       printk("**ACPI_GPE: %d.%9.9d\n", t.tv_sec, t.tv_usec);
3627 +#endif
3628 +       smi_event_handler(smi_info, 0);
3629 + out:
3630 +       spin_unlock_irqrestore(&(smi_info->si_lock), flags);
3631 +}
3632 +
3633 +static int acpi_gpe_irq_setup(struct smi_info *info)
3634 +{
3635 +       acpi_status status;
3636 +
3637 +       if (!info->irq)
3638 +               return 0;
3639 +
3640 +       /* FIXME - is level triggered right? */
3641 +       status = acpi_install_gpe_handler(NULL,
3642 +                                         info->irq,
3643 +                                         ACPI_EVENT_LEVEL_TRIGGERED,
3644 +                                         ipmi_acpi_gpe,
3645 +                                         info);
3646 +       if (status != AE_OK) {
3647 +               printk(KERN_WARNING
3648 +                      "ipmi_smi: %s unable to claim ACPI GPE %d,"
3649 +                      " running polled\n",
3650 +                      DEVICE_NAME, info->irq);
3651 +               info->irq = 0;
3652 +               return -EINVAL;
3653 +       } else {
3654 +               printk("  Using ACPI GPE %d\n", info->irq);
3655 +               return 0;
3656 +       }
3657 +
3658 +}
3659 +
3660 +static void acpi_gpe_irq_cleanup(struct smi_info *info)
3661 +{
3662 +       if (!info->irq)
3663 +               return;
3664 +
3665 +       acpi_remove_gpe_handler(NULL, info->irq, ipmi_acpi_gpe);
3666 +}
3667 +
3668 +/*
3669 + * Defined at
3670 + * http://h21007.www2.hp.com/dspp/files/unprotected/devresource/Docs/TechPapers/IA64/hpspmi.pdf
3671 + */
3672 +struct SPMITable {
3673 +       s8      Signature[4];
3674 +       u32     Length;
3675 +       u8      Revision;
3676 +       u8      Checksum;
3677 +       s8      OEMID[6];
3678 +       s8      OEMTableID[8];
3679 +       s8      OEMRevision[4];
3680 +       s8      CreatorID[4];
3681 +       s8      CreatorRevision[4];
3682 +       u8      InterfaceType[2];
3683 +       s16     SpecificationRevision;
3684 +
3685 +       /*
3686 +        * Bit 0 - SCI interrupt supported
3687 +        * Bit 1 - I/O APIC/SAPIC
3688 +        */
3689 +       u8      InterruptType;
3690 +
3691 +       /* If bit 0 of InterruptType is set, then this is the SCI
3692 +           interrupt in the GPEx_STS register. */
3693 +       u8      GPE;
3694 +
3695 +       s16     Reserved;
3696 +
3697 +       /* If bit 1 of InterruptType is set, then this is the I/O
3698 +           APIC/SAPIC interrupt. */
3699 +       u32     GlobalSystemInterrupt;
3700 +
3701 +       /* The actual register address. */
3702 +       struct acpi_generic_address addr;
3703 +
3704 +       u8      UID[4];
3705 +
3706 +       s8      spmi_id[1]; /* A '\0' terminated array starts here. */
3707 +};
3708 +
3709 +static int try_init_acpi(int intf_num, struct smi_info **new_info)
3710 +{
3711 +       struct smi_info  *info;
3712 +       acpi_status      status;
3713 +       struct SPMITable *spmi;
3714 +       char             *io_type;
3715 +
3716 +       if (acpi_failure)
3717 +               return -ENODEV;
3718 +
3719 +       status = acpi_get_firmware_table("SPMI", intf_num+1,
3720 +                                        ACPI_LOGICAL_ADDRESSING,
3721 +                                        (struct acpi_table_header **) &spmi);
3722 +       if (status != AE_OK) {
3723 +               acpi_failure = 1;
3724 +               return -ENODEV;
3725 +       }
3726 +
3727 +       if (spmi->InterfaceType[0] != 1)
3728 +           return -ENODEV;
3729 +
3730 +       /* Figure out the interface type. */
3731 +       switch (spmi->InterfaceType[1])
3732 +       {
3733 +       case 1: /* KCS */
3734 +               si_type[intf_num] = "kcs";
3735 +               break;
3736 +
3737 +       case 2: /* SMIC */
3738 +               si_type[intf_num] = "smic";
3739 +               break;
3740 +
3741 +       case 3: /* BT */
3742 +               si_type[intf_num] = "bt";
3743 +               break;
3744 +
3745 +       default:
3746 +               printk("ipmi_smi: Unknown ACPI SMI type.\n");
3747 +               return -EIO;
3748 +       } 
3749 +
3750 +       info = kmalloc(sizeof(*info), GFP_KERNEL);
3751 +       if (!info) {
3752 +               printk("ipmi_smi: Could not allocate SMI data\n");
3753 +               return -ENOMEM;
3754 +       }
3755 +       memset(info, 0, sizeof(*info));
3756 +
3757 +       if (spmi->InterruptType & 1) {
3758 +               /* We've got a GPE interrupt. */
3759 +               info->irq = spmi->GPE;
3760 +               info->irq_setup = acpi_gpe_irq_setup;
3761 +               info->irq_cleanup = acpi_gpe_irq_cleanup;
3762 +       } else if (spmi->InterruptType & 2) {
3763 +               /* We've got an APIC/SAPIC interrupt. */
3764 +               info->irq = spmi->GlobalSystemInterrupt;
3765 +               info->irq_setup = std_irq_setup;
3766 +               info->irq_cleanup = std_irq_cleanup;
3767 +       } else {
3768 +               /* Use the default interrupt setting. */
3769 +               info->irq = 0;
3770 +               info->irq_setup = NULL;
3771 +       }
3772 +
3773 +       if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
3774 +               io_type = "memory";
3775 +               info->io_setup = mem_setup;
3776 +               info->io_cleanup = mem_cleanup;
3777 +               si_addrs[intf_num] = spmi->addr.address;
3778 +               info->io.inputb = mem_inb;
3779 +               info->io.outputb = mem_outb;
3780 +               info->io.info = &(si_addrs[intf_num]);
3781 +       } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
3782 +               io_type = "I/O";
3783 +               info->io_setup = port_setup;
3784 +               info->io_cleanup = port_cleanup;
3785 +               si_ports[intf_num] = spmi->addr.address;
3786 +               info->io.inputb = port_inb;
3787 +               info->io.outputb = port_outb;
3788 +               info->io.info = &(si_ports[intf_num]);
3789 +       } else {
3790 +               kfree(info);
3791 +               printk("ipmi_smi: Unknown ACPI I/O Address type.\n");
3792 +               return -EIO;
3793 +       }
3794 +
3795 +       *new_info = info;
3796 +
3797 +       printk("ipmi_smi: Found ACPI-specified state machine at %s"
3798 +              " address 0x%lx\n",
3799 +              io_type, (unsigned long) spmi->addr.address);
3800 +       return 0;
3801 +}
3802 +#endif
3803 +
3804 +static int try_get_dev_id(struct smi_info *smi_info)
3805 +{
3806 +       unsigned char      msg[2];
3807 +       unsigned char      resp[IPMI_MAX_MSG_LENGTH];
3808 +       unsigned long      resp_len;
3809 +       enum si_sm_result smi_result;
3810 +
3811 +       /* Do a Get Device ID command, since it comes back with some
3812 +          useful info. */
3813 +       msg[0] = IPMI_NETFN_APP_REQUEST << 2;
3814 +       msg[1] = IPMI_GET_DEVICE_ID_CMD;
3815 +       smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
3816 +       
3817 +       smi_result = smi_info->handlers->event(smi_info->si_sm, 0);
3818 +       for (;;)
3819 +       {
3820 +               if (smi_result == SI_SM_CALL_WITH_DELAY) {
3821 +                       schedule_timeout(1);
3822 +                       smi_result = smi_info->handlers->event(
3823 +                               smi_info->si_sm, 100);
3824 +               }
3825 +               else if (smi_result == SI_SM_CALL_WITHOUT_DELAY)
3826 +               {
3827 +                       smi_result = smi_info->handlers->event(
3828 +                               smi_info->si_sm, 0);
3829 +               }
3830 +               else
3831 +                       break;
3832 +       }
3833 +       if (smi_result == SI_SM_HOSED)
3834 +               /* We couldn't get the state machine to run, so whatever's at
3835 +                  the port is probably not an IPMI SMI interface. */
3836 +               return -ENODEV;
3837 +
3838 +       /* Otherwise, we got some data. */
3839 +       resp_len = smi_info->handlers->get_result(smi_info->si_sm,
3840 +                                                 resp, IPMI_MAX_MSG_LENGTH);
3841 +       if (resp_len < 6)
3842 +               /* That's odd, it should be longer. */
3843 +               return -EINVAL;
3844 +       
3845 +       if ((resp[1] != IPMI_GET_DEVICE_ID_CMD) || (resp[2] != 0))
3846 +               /* That's odd, it shouldn't be able to fail. */
3847 +               return -EINVAL;
3848 +
3849 +       /* Record info from the get device id, in case we need it. */
3850 +       smi_info->ipmi_si_dev_rev = resp[4] & 0xf;
3851 +       smi_info->ipmi_si_fw_rev_major = resp[5] & 0x7f;
3852 +       smi_info->ipmi_si_fw_rev_minor = resp[6];
3853 +       smi_info->ipmi_version_major = resp[7] & 0xf;
3854 +       smi_info->ipmi_version_minor = resp[7] >> 4;
3855 +
3856 +       return 0;
3857 +}
3858 +
3859 +extern struct si_sm_handlers kcs_smi_handlers;
3860 +extern struct si_sm_handlers smic_smi_handlers;
3861 +
3862 +static int type_file_read_proc(char *page, char **start, off_t off,
3863 +                              int count, int *eof, void *data)
3864 +{
3865 +       char            *out = (char *) page;
3866 +       struct smi_info *smi = data;
3867 +
3868 +       switch (smi->si_type) {
3869 +           case SI_KCS:
3870 +               return sprintf(out, "kcs\n");
3871 +           case SI_SMIC:
3872 +               return sprintf(out, "smic\n");
3873 +           case SI_BT:
3874 +               return sprintf(out, "bt\n");
3875 +           default:
3876 +               return 0;
3877 +       }
3878 +}
3879 +
3880 +static int stat_file_read_proc(char *page, char **start, off_t off,
3881 +                              int count, int *eof, void *data)
3882 +{
3883 +       char            *out = (char *) page;
3884 +       struct smi_info *smi = data;
3885 +
3886 +       out += sprintf(out, "interrupts_enabled:    %d\n",
3887 +                      smi->irq && !smi->interrupt_disabled);
3888 +       out += sprintf(out, "short_timeouts:        %ld\n",
3889 +                      smi->short_timeouts);
3890 +       out += sprintf(out, "long_timeouts:         %ld\n",
3891 +                      smi->long_timeouts);
3892 +       out += sprintf(out, "timeout_restarts:      %ld\n",
3893 +                      smi->timeout_restarts);
3894 +       out += sprintf(out, "idles:                 %ld\n",
3895 +                      smi->idles);
3896 +       out += sprintf(out, "interrupts:            %ld\n",
3897 +                      smi->interrupts);
3898 +       out += sprintf(out, "attentions:            %ld\n",
3899 +                      smi->attentions);
3900 +       out += sprintf(out, "flag_fetches:          %ld\n",
3901 +                      smi->flag_fetches);
3902 +       out += sprintf(out, "hosed_count:           %ld\n",
3903 +                      smi->hosed_count);
3904 +       out += sprintf(out, "complete_transactions: %ld\n",
3905 +                      smi->complete_transactions);
3906 +       out += sprintf(out, "events:                %ld\n",
3907 +                      smi->events);
3908 +       out += sprintf(out, "watchdog_pretimeouts:  %ld\n",
3909 +                      smi->watchdog_pretimeouts);
3910 +       out += sprintf(out, "incoming_messages:     %ld\n",
3911 +                      smi->incoming_messages);
3912 +
3913 +       return (out - ((char *) page));
3914 +}
3915 +
3916 +/* Returns 0 if initialized, or negative on an error. */
3917 +static int init_one_smi(int intf_num, struct smi_info **smi)
3918 +{
3919 +       int             rv;
3920 +       struct smi_info *new_smi;
3921 +
3922 +
3923 +       rv = try_init_mem(intf_num, &new_smi);
3924 +       if (rv)
3925 +               rv = try_init_port(intf_num, &new_smi);
3926 +#ifdef CONFIG_ACPI_INTERPRETER
3927 +       if ((rv) && (si_trydefaults)) {
3928 +               rv = try_init_acpi(intf_num, &new_smi);
3929 +       }
3930 +#endif
3931 +
3932 +       if (rv)
3933 +               return rv;
3934 +
3935 +       /* So we know not to free it unless we have allocated one. */
3936 +       new_smi->intf = NULL;
3937 +       new_smi->si_sm = NULL;
3938 +       new_smi->handlers = 0;
3939 +
3940 +       if (!new_smi->irq_setup) {
3941 +               new_smi->irq = si_irqs[intf_num];
3942 +               new_smi->irq_setup = std_irq_setup;
3943 +               new_smi->irq_cleanup = std_irq_cleanup;
3944 +       }
3945 +
3946 +       /* Default to KCS if no type is specified. */
3947 +       if (si_type[intf_num] == NULL) {
3948 +               if (si_trydefaults)
3949 +                       si_type[intf_num] = "kcs";
3950 +               else {
3951 +                       rv = -EINVAL;
3952 +                       goto out_err;
3953 +               }
3954 +       }
3955 +
3956 +       /* Set up the state machine to use. */
3957 +       if (strcmp(si_type[intf_num], "kcs") == 0) {
3958 +               new_smi->handlers = &kcs_smi_handlers;
3959 +               new_smi->si_type = SI_KCS;
3960 +       } else if (strcmp(si_type[intf_num], "smic") == 0) {
3961 +               new_smi->handlers = &smic_smi_handlers;
3962 +               new_smi->si_type = SI_SMIC;
3963 +       } else {
3964 +               /* No support for anything else yet. */
3965 +               rv = -EIO;
3966 +               goto out_err;
3967 +       }
3968 +
3969 +       /* Allocate the state machine's data and initialize it. */
3970 +       new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL);
3971 +       if (!new_smi->si_sm) {
3972 +               printk(" Could not allocate state machine memory\n");
3973 +               rv = -ENOMEM;
3974 +               goto out_err;
3975 +       }
3976 +       new_smi->io_size = new_smi->handlers->init_data(new_smi->si_sm,
3977 +                                                       &new_smi->io);
3978 +
3979 +       /* Now that we know the I/O size, we can set up the I/O. */
3980 +       rv = new_smi->io_setup(new_smi);
3981 +       if (rv) {
3982 +               printk(" Could not set up I/O space\n");
3983 +               goto out_err;
3984 +       }
3985 +       
3986 +       spin_lock_init(&(new_smi->si_lock));
3987 +       spin_lock_init(&(new_smi->msg_lock));
3988 +       spin_lock_init(&(new_smi->count_lock));
3989 +
3990 +       /* Do low-level detection first. */
3991 +       if (new_smi->handlers->detect(new_smi->si_sm)) {
3992 +               rv = -ENODEV;
3993 +               goto out_err;
3994 +       }
3995 +
3996 +       /* Attempt a get device id command.  If it fails, we probably
3997 +           don't have a SMI here. */
3998 +       rv = try_get_dev_id(new_smi);
3999 +       if (rv)
4000 +               goto out_err;
4001 +
4002 +       /* Try to claim any interrupts. */
4003 +       new_smi->irq_setup(new_smi);
4004 +
4005 +       INIT_LIST_HEAD(&(new_smi->xmit_msgs));
4006 +       INIT_LIST_HEAD(&(new_smi->hp_xmit_msgs));
4007 +       new_smi->curr_msg = NULL;
4008 +       atomic_set(&new_smi->req_events, 0);
4009 +       new_smi->run_to_completion = 0;
4010 +
4011 +       rv = ipmi_register_smi(&handlers,
4012 +                              new_smi,
4013 +                              new_smi->ipmi_version_major,
4014 +                              new_smi->ipmi_version_minor,
4015 +                              &(new_smi->intf));
4016 +       if (rv) {
4017 +               printk(KERN_ERR 
4018 +                      "ipmi_smi: Unable to register device: error %d\n",
4019 +                      rv);
4020 +               goto out_err;
4021 +       }
4022 +
4023 +       rv = ipmi_smi_add_proc_entry(new_smi->intf, "type",
4024 +                                    type_file_read_proc, NULL,
4025 +                                    new_smi, THIS_MODULE);
4026 +       if (rv) {
4027 +               printk(KERN_ERR 
4028 +                      "ipmi_smi: Unable to create proc entry: %d\n",
4029 +                      rv);
4030 +               goto out_err;
4031 +       }
4032 +
4033 +       rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats",
4034 +                                    stat_file_read_proc, NULL,
4035 +                                    new_smi, THIS_MODULE);
4036 +       if (rv) {
4037 +               printk(KERN_ERR 
4038 +                      "ipmi_smi: Unable to create proc entry: %d\n",
4039 +                      rv);
4040 +               goto out_err;
4041 +       }
4042 +
4043 +       start_clear_flags(new_smi);
4044 +
4045 +       /* IRQ is defined to be set when non-zero. */
4046 +       if (new_smi->irq)
4047 +               new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ;
4048 +
4049 +       new_smi->interrupt_disabled = 0;
4050 +       new_smi->timer_stopped = 0;
4051 +       new_smi->stop_operation = 0;
4052 +
4053 +       init_timer(&(new_smi->si_timer));
4054 +       new_smi->si_timer.data = (long) new_smi;
4055 +       new_smi->si_timer.function = smi_timeout;
4056 +       new_smi->last_timeout_jiffies = jiffies;
4057 +       new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
4058 +       add_timer(&(new_smi->si_timer));
4059 +
4060 +       *smi = new_smi;
4061 +
4062 +       printk(" IPMI %s interface initialized\n", si_type[intf_num]);
4063 +
4064 +       return 0;
4065 +
4066 + out_err:
4067 +       if (new_smi->intf)
4068 +               ipmi_unregister_smi(new_smi->intf);
4069 +
4070 +       new_smi->irq_cleanup(new_smi);
4071 +       if (new_smi->si_sm) {
4072 +               if (new_smi->handlers)
4073 +                       new_smi->handlers->cleanup(new_smi->si_sm);
4074 +               kfree(new_smi->si_sm);
4075 +       }
4076 +       new_smi->io_cleanup(new_smi);
4077 +       return rv;
4078 +}
4079 +
4080 +static __init int init_ipmi_si(void)
4081 +{
4082 +       int             rv = 0;
4083 +       int             pos = 0;
4084 +       int             i = 0;
4085 +
4086 +       if (initialized)
4087 +               return 0;
4088 +       initialized = 1;
4089 +
4090 +       printk(KERN_INFO "IPMI System Interface driver version "
4091 +              IPMI_SI_VERSION);
4092 +       if (kcs_smi_handlers.version)
4093 +               printk(", KCS version %s", kcs_smi_handlers.version);
4094 +       if (smic_smi_handlers.version)
4095 +               printk(", SMIC version %s", smic_smi_handlers.version);
4096 +       printk("\n");
4097 +
4098 +       rv = init_one_smi(0, &(smi_infos[pos]));
4099 +       if (rv && !si_ports[0] && si_trydefaults) {
4100 +               /* If we are trying defaults and the initial port is
4101 +                   not set, then set it. */
4102 +               si_type[0] = "kcs";
4103 +               si_ports[0] = DEFAULT_KCS_IO_PORT;
4104 +               rv = init_one_smi(0, &(smi_infos[pos]));
4105 +               if (rv) {
4106 +                       /* No KCS - try SMIC */
4107 +                       si_type[0] = "smic";
4108 +                       si_ports[0] = DEFAULT_SMIC_IO_PORT;
4109 +                       rv = init_one_smi(0, &(smi_infos[pos]));
4110 +               }
4111 +       }
4112 +       if (rv == 0)
4113 +               pos++;
4114 +
4115 +       for (i=1; i < SI_MAX_PARMS; i++) {
4116 +               rv = init_one_smi(i, &(smi_infos[pos]));
4117 +               if (rv == 0)
4118 +                       pos++;
4119 +       }
4120 +
4121 +       if (smi_infos[0] == NULL) {
4122 +               printk("ipmi_smi: Unable to find any SMI interfaces\n");
4123 +               return -ENODEV;
4124 +       } 
4125 +
4126 +       return 0;
4127 +}
4128 +module_init(init_ipmi_si);
4129 +
4130 +#ifdef MODULE
4131 +void __exit cleanup_one_si(struct smi_info *to_clean)
4132 +{
4133 +       int           rv;
4134 +       unsigned long flags;
4135 +
4136 +       if (! to_clean)
4137 +               return;
4138 +
4139 +       /* Tell the timer and interrupt handlers that we are shutting
4140 +          down. */
4141 +       spin_lock_irqsave(&(to_clean->si_lock), flags);
4142 +       spin_lock(&(to_clean->msg_lock));
4143 +
4144 +       to_clean->stop_operation = 1;
4145 +
4146 +       to_clean->irq_cleanup(to_clean);
4147 +
4148 +       spin_unlock(&(to_clean->msg_lock));
4149 +       spin_unlock_irqrestore(&(to_clean->si_lock), flags);
4150 +
4151 +       /* Wait for the timer to stop.  This avoids problems with race
4152 +          conditions removing the timer here.  Hopefully this will be
4153 +          long enough to avoid problems with interrupts still
4154 +          running. */
4155 +       schedule_timeout(2);
4156 +       while (!to_clean->timer_stopped) {
4157 +               schedule_timeout(1);
4158 +       }
4159 +
4160 +       rv = ipmi_unregister_smi(to_clean->intf);
4161 +       if (rv) {
4162 +               printk(KERN_ERR 
4163 +                      "ipmi_smi: Unable to unregister device: errno=%d\n",
4164 +                      rv);
4165 +       }
4166 +
4167 +       to_clean->handlers->cleanup(to_clean->si_sm);
4168 +
4169 +       kfree(to_clean->si_sm);
4170 +
4171 +       to_clean->io_cleanup(to_clean);
4172 +}
4173 +
4174 +static __exit void cleanup_ipmi_si(void)
4175 +{
4176 +       int i;
4177 +
4178 +       if (!initialized)
4179 +               return;
4180 +
4181 +       for (i=0; i<SI_MAX_DRIVERS; i++) {
4182 +               cleanup_one_si(smi_infos[i]);
4183 +       }
4184 +}
4185 +module_exit(cleanup_ipmi_si);
4186 +#else
4187 +
4188 +/* Unfortunately, cmdline::get_options() only returns integers, not
4189 +   longs.  Since we need ulongs (64-bit physical addresses) parse the 
4190 +   comma-separated list manually.  Arguments can be one of these forms:
4191 +   m0xaabbccddeeff     A physical memory address without an IRQ
4192 +   m0xaabbccddeeff:cc  A physical memory address with an IRQ
4193 +   p0xaabb             An IO port without an IRQ
4194 +   p0xaabb:cc          An IO port with an IRQ
4195 +   nodefaults          Suppress trying the default IO port or ACPI address 
4196 +
4197 +   For example, to pass one IO port with an IRQ, one address, and 
4198 +   suppress the use of the default IO port and ACPI address,
4199 +   use this option string: ipmi_smi=p0xCA2:5,m0xFF5B0022,nodefaults
4200 +
4201 +   Remember, ipmi_si_setup() is passed the string after the equal sign. */
4202 +
4203 +static int __init ipmi_si_setup(char *str)
4204 +{
4205 +       unsigned long val;
4206 +       char *cur, *colon;
4207 +       int pos;
4208 +
4209 +       pos = 0;
4210 +       
4211 +       cur = strsep(&str, ",");
4212 +       while ((cur) && (*cur) && (pos < SI_MAX_PARMS)) {
4213 +               switch (*cur) {
4214 +               case 'n':
4215 +                       if (strcmp(cur, "nodefaults") == 0)
4216 +                               si_trydefaults = 0;
4217 +                       else
4218 +                               printk(KERN_INFO 
4219 +                                      "ipmi_si: bad parameter value %s\n",
4220 +                                      cur);
4221 +                       break;
4222 +
4223 +               case 'k': /* KCS */
4224 +                       si_type[pos] = "kcs";
4225 +                       break;
4226 +               
4227 +               case 's': /* SMIC */
4228 +                       si_type[pos] = "smic";
4229 +                       break;
4230 +               
4231 +               case 'b': /* BT */
4232 +                       si_type[pos] = "bt";
4233 +                       break;
4234 +               
4235 +               case 'm':
4236 +               case 'p':
4237 +                       val = simple_strtoul(cur + 1,
4238 +                                            &colon,
4239 +                                            0);
4240 +                       if (*cur == 'p')
4241 +                               si_ports[pos] = val;
4242 +                       else
4243 +                               si_addrs[pos] = val;
4244 +                       if (*colon == ':') {
4245 +                               val = simple_strtoul(colon + 1,
4246 +                                                    &colon,
4247 +                                                    0);
4248 +                               si_irqs[pos] = val;
4249 +                       }
4250 +                       pos++;
4251 +                       break;
4252 +
4253 +               default:
4254 +                       printk(KERN_INFO 
4255 +                              "ipmi_si: bad parameter value %s\n",
4256 +                              cur);
4257 +               }
4258 +               cur = strsep(&str, ",");
4259 +       }
4260 +
4261 +       return 1;
4262 +}
4263 +__setup("ipmi_si=", ipmi_si_setup);
4264 +#endif
4265 +
4266 +MODULE_LICENSE("GPL");
4267 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
4268 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_si_sm.h     1970-01-01 01:00:00.000000000 +0100
4269 +++ linux-2.4.23/drivers/char/ipmi/ipmi_si_sm.h 2003-12-06 17:46:43.004452672 +0100
4270 @@ -0,0 +1,112 @@
4271 +/*
4272 + * ipmi_si_sm.h
4273 + *
4274 + * State machine interface for low-level IPMI system management
4275 + * interface state machines.  This code is the interface between
4276 + * the ipmi_smi code (that handles the policy of a KCS, SMIC, or
4277 + * BT interface) and the actual low-level state machine.
4278 + *
4279 + * Author: MontaVista Software, Inc.
4280 + *         Corey Minyard <minyard@mvista.com>
4281 + *         source@mvista.com
4282 + *
4283 + * Copyright 2002 MontaVista Software Inc.
4284 + *
4285 + *  This program is free software; you can redistribute it and/or modify it
4286 + *  under the terms of the GNU General Public License as published by the
4287 + *  Free Software Foundation; either version 2 of the License, or (at your
4288 + *  option) any later version.
4289 + *
4290 + *
4291 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
4292 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
4293 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
4294 + *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
4295 + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
4296 + *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
4297 + *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
4298 + *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
4299 + *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
4300 + *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4301 + *
4302 + *  You should have received a copy of the GNU General Public License along
4303 + *  with this program; if not, write to the Free Software Foundation, Inc.,
4304 + *  675 Mass Ave, Cambridge, MA 02139, USA.
4305 + */
4306 +
4307 +/* This is defined by the state machines themselves, it is an opaque
4308 +   data type for them to use. */
4309 +struct si_sm_data;
4310 +
4311 +/* The structure for doing I/O in the state machine.  The state
4312 +   machine doesn't have the actual I/O routines, they are done through
4313 +   this interface. */
4314 +struct si_sm_io
4315 +{
4316 +       unsigned char (*inputb)(struct si_sm_io *io, unsigned int offset);
4317 +       void (*outputb)(struct si_sm_io *io,
4318 +                       unsigned int  offset,
4319 +                       unsigned char b);
4320 +
4321 +       /* Generic info used by the actual handling routines, the
4322 +           state machine shouldn't touch these. */
4323 +       void *info;
4324 +       void *addr;
4325 +};
4326 +
4327 +/* Results of SMI events. */
4328 +enum si_sm_result
4329 +{
4330 +       SI_SM_CALL_WITHOUT_DELAY, /* Call the driver again immediately */
4331 +       SI_SM_CALL_WITH_DELAY,  /* Delay some before calling again. */
4332 +       SI_SM_TRANSACTION_COMPLETE, /* A transaction is finished. */
4333 +       SI_SM_IDLE,             /* The SM is in idle state. */
4334 +       SI_SM_HOSED,            /* The hardware violated the state machine. */
4335 +       SI_SM_ATTN              /* The hardware is asserting attn and the
4336 +                                  state machine is idle. */
4337 +};
4338 +
4339 +/* Handlers for the SMI state machine. */
4340 +struct si_sm_handlers
4341 +{
4342 +       /* Put the version number of the state machine here so the
4343 +           upper layer can print it. */
4344 +       char *version;
4345 +
4346 +       /* Initialize the data and return the amount of I/O space to
4347 +           reserve for the space. */
4348 +       unsigned int (*init_data)(struct si_sm_data *smi,
4349 +                                 struct si_sm_io   *io);
4350 +
4351 +       /* Start a new transaction in the state machine.  This will
4352 +          return -2 if the state machine is not idle, -1 if the size
4353 +          is invalid (to large or too small), or 0 if the transaction
4354 +          is successfully completed. */
4355 +       int (*start_transaction)(struct si_sm_data *smi,
4356 +                                unsigned char *data, unsigned int size);
4357 +
4358 +       /* Return the results after the transaction.  This will return
4359 +          -1 if the buffer is too small, zero if no transaction is
4360 +          present, or the actual length of the result data. */
4361 +       int (*get_result)(struct si_sm_data *smi,
4362 +                         unsigned char *data, unsigned int length);
4363 +
4364 +       /* Call this periodically (for a polled interface) or upon
4365 +          receiving an interrupt (for a interrupt-driven interface).
4366 +          If interrupt driven, you should probably poll this
4367 +          periodically when not in idle state.  This should be called
4368 +          with the time that passed since the last call, if it is
4369 +          significant.  Time is in microseconds. */
4370 +       enum si_sm_result (*event)(struct si_sm_data *smi, long time);
4371 +
4372 +       /* Attempt to detect an SMI.  Returns 0 on success or nonzero
4373 +           on failure. */
4374 +       int (*detect)(struct si_sm_data *smi);
4375 +
4376 +       /* The interface is shutting down, so clean it up. */
4377 +       void (*cleanup)(struct si_sm_data *smi);
4378 +
4379 +       /* Return the size of the SMI structure in bytes. */
4380 +       int (*size)(void);
4381 +};
4382 +
4383 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
4384 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_smic_sm.c   1970-01-01 01:00:00.000000000 +0100
4385 +++ linux-2.4.23/drivers/char/ipmi/ipmi_smic_sm.c       2003-12-06 17:46:43.024448478 +0100
4386 @@ -0,0 +1,601 @@
4387 +/*
4388 + * ipmi_smic_sm.c
4389 + *
4390 + * The state-machine driver for an IPMI SMIC driver
4391 + *
4392 + * It started as a copy of Corey Minyard's driver for the KSC interface
4393 + * and the kernel patch "mmcdev-patch-245" by HP
4394 + *
4395 + * modified by:        Hannes Schulz <schulz@schwaar.com>
4396 + *             ipmi@schwaar.com
4397 + *
4398 + *
4399 + * Corey Minyard's driver for the KSC interface has the following
4400 + * copyright notice:
4401 + *   Copyright 2002 MontaVista Software Inc.
4402 + *
4403 + * the kernel patch "mmcdev-patch-245" by HP has the following
4404 + * copyright notice:
4405 + * (c) Copyright 2001 Grant Grundler (c) Copyright
4406 + * 2001 Hewlett-Packard Company
4407 + * 
4408 + *
4409 + *  This program is free software; you can redistribute it and/or modify it
4410 + *  under the terms of the GNU General Public License as published by the
4411 + *  Free Software Foundation; either version 2 of the License, or (at your
4412 + *  option) any later version.
4413 + *
4414 + *
4415 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
4416 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
4417 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
4418 + *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
4419 + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
4420 + *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
4421 + *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
4422 + *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
4423 + *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
4424 + *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4425 + *
4426 + *  You should have received a copy of the GNU General Public License along
4427 + *  with this program; if not, write to the Free Software Foundation, Inc.,
4428 + *  675 Mass Ave, Cambridge, MA 02139, USA.  */
4429 +
4430 +#include <linux/kernel.h> /* For printk. */
4431 +#include <linux/string.h>
4432 +#include "ipmi_si_sm.h"
4433 +
4434 +#define IPMI_SMIC_VERSION "v27"
4435 +
4436 +/* smic_debug is a bit-field 
4437 + *     SMIC_DEBUG_ENABLE -     turned on for now 
4438 + *     SMIC_DEBUG_MSG -        commands and their responses
4439 + *     SMIC_DEBUG_STATES -     state machine
4440 +*/
4441 +#define SMIC_DEBUG_STATES      4
4442 +#define SMIC_DEBUG_MSG         2
4443 +#define        SMIC_DEBUG_ENABLE       1
4444 +
4445 +static int smic_debug = 1;
4446 +
4447 +enum smic_states {
4448 +       SMIC_IDLE,
4449 +       SMIC_START_OP,
4450 +       SMIC_OP_OK,
4451 +       SMIC_WRITE_START,
4452 +       SMIC_WRITE_NEXT,
4453 +       SMIC_WRITE_END,
4454 +       SMIC_WRITE2READ,
4455 +       SMIC_READ_START,
4456 +       SMIC_READ_NEXT,
4457 +       SMIC_READ_END,
4458 +       SMIC_HOSED
4459 +};
4460 +
4461 +#define MAX_SMIC_READ_SIZE 80
4462 +#define MAX_SMIC_WRITE_SIZE 80
4463 +#define SMIC_MAX_ERROR_RETRIES 3
4464 +
4465 +/* Timeouts in microseconds. */
4466 +#define SMIC_RETRY_TIMEOUT 100000
4467 +#define IPMI_ERR_MSG_TRUNCATED 0xc6
4468 +#define IPMI_ERR_UNSPECIFIED   0xff
4469 +
4470 +
4471 +/* SMIC Flags Register Bits */
4472 +#define SMIC_RX_DATA_READY     0x80
4473 +#define SMIC_TX_DATA_READY     0x40
4474 +#define SMIC_SMI               0x10
4475 +#define SMIC_EVM_DATA_AVAIL    0x08
4476 +#define SMIC_SMS_DATA_AVAIL    0x04
4477 +#define SMIC_FLAG_BSY          0x01
4478 +
4479 +/* SMIC Error Codes */
4480 +#define        EC_NO_ERROR             0x00
4481 +#define        EC_ABORTED              0x01
4482 +#define        EC_ILLEGAL_CONTROL      0x02
4483 +#define        EC_NO_RESPONSE          0x03
4484 +#define        EC_ILLEGAL_COMMAND      0x04
4485 +#define        EC_BUFFER_FULL          0x05
4486 +
4487 +struct si_sm_data
4488 +{
4489 +       enum smic_states state;
4490 +       struct si_sm_io *io;
4491 +        unsigned char   write_data[MAX_SMIC_WRITE_SIZE];
4492 +        int             write_pos;
4493 +        int             write_count;
4494 +        int             orig_write_count;
4495 +        unsigned char   read_data[MAX_SMIC_READ_SIZE];
4496 +        int             read_pos;
4497 +        int             truncated;
4498 +        unsigned int    error_retries;
4499 +        long            smic_timeout;
4500 +};
4501 +
4502 +static unsigned int init_smic_data (struct si_sm_data *smic,
4503 +                                   struct si_sm_io *io)
4504 +{
4505 +       smic->state = SMIC_IDLE;
4506 +       smic->io = io;
4507 +       smic->write_pos = 0;
4508 +       smic->write_count = 0;
4509 +       smic->orig_write_count = 0;
4510 +       smic->read_pos = 0;
4511 +       smic->error_retries = 0;
4512 +       smic->truncated = 0;
4513 +       smic->smic_timeout = SMIC_RETRY_TIMEOUT;
4514 +
4515 +       /* We use 3 bytes of I/O. */
4516 +       return 3;
4517 +}
4518 +
4519 +static int start_smic_transaction(struct si_sm_data *smic,
4520 +                                 unsigned char *data, unsigned int size)
4521 +{
4522 +       unsigned int i;
4523 +
4524 +       if ((size < 2) || (size > MAX_SMIC_WRITE_SIZE)) {
4525 +               return -1;
4526 +       }
4527 +       if ((smic->state != SMIC_IDLE) && (smic->state != SMIC_HOSED)) {
4528 +               return -2;
4529 +       }
4530 +       if (smic_debug & SMIC_DEBUG_MSG) {
4531 +               printk(KERN_INFO "start_smic_transaction -");
4532 +               for (i = 0; i < size; i ++) {
4533 +                       printk (" %02x", (unsigned char) (data [i]));
4534 +               }
4535 +               printk ("\n");
4536 +       }
4537 +       smic->error_retries = 0;
4538 +       memcpy(smic->write_data, data, size);
4539 +       smic->write_count = size;
4540 +       smic->orig_write_count = size;
4541 +       smic->write_pos = 0;
4542 +       smic->read_pos = 0;
4543 +       smic->state = SMIC_START_OP;
4544 +       smic->smic_timeout = SMIC_RETRY_TIMEOUT;
4545 +       return 0;
4546 +}
4547 +
4548 +static int smic_get_result(struct si_sm_data *smic,
4549 +                          unsigned char *data, unsigned int length)
4550 +{
4551 +       int i;
4552 +
4553 +       if (smic_debug & SMIC_DEBUG_MSG) {
4554 +               printk (KERN_INFO "smic_get result -");
4555 +               for (i = 0; i < smic->read_pos; i ++) {
4556 +                       printk (" %02x", (smic->read_data [i]));
4557 +               }
4558 +               printk ("\n");
4559 +       }
4560 +       if (length < smic->read_pos) {
4561 +               smic->read_pos = length;
4562 +               smic->truncated = 1;
4563 +       }
4564 +       memcpy(data, smic->read_data, smic->read_pos);
4565 +
4566 +       if ((length >= 3) && (smic->read_pos < 3)) {
4567 +               data[2] = IPMI_ERR_UNSPECIFIED;
4568 +               smic->read_pos = 3;
4569 +       }
4570 +       if (smic->truncated) {
4571 +               data[2] = IPMI_ERR_MSG_TRUNCATED;
4572 +               smic->truncated = 0;
4573 +       }
4574 +       return smic->read_pos;
4575 +}
4576 +
4577 +static inline unsigned char read_smic_flags(struct si_sm_data *smic)
4578 +{
4579 +       return smic->io->inputb(smic->io, 2);
4580 +}
4581 +
4582 +static inline unsigned char read_smic_status(struct si_sm_data *smic)
4583 +{
4584 +       return smic->io->inputb(smic->io, 1);
4585 +}
4586 +
4587 +static inline unsigned char read_smic_data(struct si_sm_data *smic)
4588 +{
4589 +       return smic->io->inputb(smic->io, 0);
4590 +}
4591 +
4592 +static inline void write_smic_flags(struct si_sm_data *smic,
4593 +                                   unsigned char   flags)
4594 +{
4595 +       smic->io->outputb(smic->io, 2, flags);
4596 +}
4597 +
4598 +static inline void write_smic_control(struct si_sm_data *smic,
4599 +                                     unsigned char   control)
4600 +{
4601 +       smic->io->outputb(smic->io, 1, control);
4602 +}
4603 +
4604 +static inline void write_si_sm_data (struct si_sm_data *smic,
4605 +                                  unsigned char   data)
4606 +{
4607 +       smic->io->outputb(smic->io, 0, data);
4608 +}
4609 +
4610 +static inline void start_error_recovery(struct si_sm_data *smic, char *reason)
4611 +{
4612 +       (smic->error_retries)++;
4613 +       if (smic->error_retries > SMIC_MAX_ERROR_RETRIES) {
4614 +               if (smic_debug & SMIC_DEBUG_ENABLE) {
4615 +                       printk(KERN_WARNING
4616 +                              "ipmi_smic_drv: smic hosed: %s\n", reason);
4617 +               }       
4618 +               smic->state = SMIC_HOSED;
4619 +       } else {
4620 +               smic->write_count = smic->orig_write_count;
4621 +               smic->write_pos = 0;
4622 +               smic->read_pos = 0;
4623 +               smic->state = SMIC_START_OP;
4624 +               smic->smic_timeout = SMIC_RETRY_TIMEOUT;
4625 +       }
4626 +}
4627 +
4628 +static inline void write_next_byte(struct si_sm_data *smic)
4629 +{
4630 +       write_si_sm_data(smic, smic->write_data[smic->write_pos]);
4631 +       (smic->write_pos)++;
4632 +       (smic->write_count)--;
4633 +}
4634 +
4635 +static inline void read_next_byte (struct si_sm_data *smic)
4636 +{
4637 +       if (smic->read_pos >= MAX_SMIC_READ_SIZE) {
4638 +               read_smic_data (smic);
4639 +               smic->truncated = 1;
4640 +       } else {
4641 +               smic->read_data[smic->read_pos] = read_smic_data(smic); 
4642 +               (smic->read_pos)++;
4643 +       }
4644 +}
4645 +
4646 +/*  SMIC Control/Status Code Components */
4647 +#define        SMIC_GET_STATUS         0x00    /* Control form's name */
4648 +#define        SMIC_READY              0x00    /* Status  form's name */
4649 +#define        SMIC_WR_START           0x01    /* Unified Control/Status names... */
4650 +#define        SMIC_WR_NEXT            0x02
4651 +#define        SMIC_WR_END             0x03
4652 +#define        SMIC_RD_START           0x04
4653 +#define        SMIC_RD_NEXT            0x05
4654 +#define        SMIC_RD_END             0x06
4655 +#define        SMIC_CODE_MASK          0x0f
4656 +
4657 +#define        SMIC_CONTROL            0x00
4658 +#define        SMIC_STATUS             0x80
4659 +#define        SMIC_CS_MASK            0x80
4660 +
4661 +#define        SMIC_SMS                0x40
4662 +#define        SMIC_SMM                0x60
4663 +#define        SMIC_STREAM_MASK        0x60
4664 +
4665 +/*  SMIC Control Codes */
4666 +#define        SMIC_CC_SMS_GET_STATUS  (SMIC_CONTROL|SMIC_SMS|SMIC_GET_STATUS)
4667 +#define        SMIC_CC_SMS_WR_START    (SMIC_CONTROL|SMIC_SMS|SMIC_WR_START)
4668 +#define        SMIC_CC_SMS_WR_NEXT     (SMIC_CONTROL|SMIC_SMS|SMIC_WR_NEXT)
4669 +#define        SMIC_CC_SMS_WR_END      (SMIC_CONTROL|SMIC_SMS|SMIC_WR_END)
4670 +#define        SMIC_CC_SMS_RD_START    (SMIC_CONTROL|SMIC_SMS|SMIC_RD_START)
4671 +#define        SMIC_CC_SMS_RD_NEXT     (SMIC_CONTROL|SMIC_SMS|SMIC_RD_NEXT)
4672 +#define        SMIC_CC_SMS_RD_END      (SMIC_CONTROL|SMIC_SMS|SMIC_RD_END)
4673 +
4674 +#define        SMIC_CC_SMM_GET_STATUS  (SMIC_CONTROL|SMIC_SMM|SMIC_GET_STATUS)
4675 +#define        SMIC_CC_SMM_WR_START    (SMIC_CONTROL|SMIC_SMM|SMIC_WR_START)
4676 +#define        SMIC_CC_SMM_WR_NEXT     (SMIC_CONTROL|SMIC_SMM|SMIC_WR_NEXT)
4677 +#define        SMIC_CC_SMM_WR_END      (SMIC_CONTROL|SMIC_SMM|SMIC_WR_END)
4678 +#define        SMIC_CC_SMM_RD_START    (SMIC_CONTROL|SMIC_SMM|SMIC_RD_START)
4679 +#define        SMIC_CC_SMM_RD_NEXT     (SMIC_CONTROL|SMIC_SMM|SMIC_RD_NEXT)
4680 +#define        SMIC_CC_SMM_RD_END      (SMIC_CONTROL|SMIC_SMM|SMIC_RD_END)
4681 +
4682 +/*  SMIC Status Codes */
4683 +#define        SMIC_SC_SMS_READY       (SMIC_STATUS|SMIC_SMS|SMIC_READY)
4684 +#define        SMIC_SC_SMS_WR_START    (SMIC_STATUS|SMIC_SMS|SMIC_WR_START)
4685 +#define        SMIC_SC_SMS_WR_NEXT     (SMIC_STATUS|SMIC_SMS|SMIC_WR_NEXT)
4686 +#define        SMIC_SC_SMS_WR_END      (SMIC_STATUS|SMIC_SMS|SMIC_WR_END)
4687 +#define        SMIC_SC_SMS_RD_START    (SMIC_STATUS|SMIC_SMS|SMIC_RD_START)
4688 +#define        SMIC_SC_SMS_RD_NEXT     (SMIC_STATUS|SMIC_SMS|SMIC_RD_NEXT)
4689 +#define        SMIC_SC_SMS_RD_END      (SMIC_STATUS|SMIC_SMS|SMIC_RD_END)
4690 +
4691 +#define        SMIC_SC_SMM_READY       (SMIC_STATUS|SMIC_SMM|SMIC_READY)
4692 +#define        SMIC_SC_SMM_WR_START    (SMIC_STATUS|SMIC_SMM|SMIC_WR_START)
4693 +#define        SMIC_SC_SMM_WR_NEXT     (SMIC_STATUS|SMIC_SMM|SMIC_WR_NEXT)
4694 +#define        SMIC_SC_SMM_WR_END      (SMIC_STATUS|SMIC_SMM|SMIC_WR_END)
4695 +#define        SMIC_SC_SMM_RD_START    (SMIC_STATUS|SMIC_SMM|SMIC_RD_START)
4696 +#define        SMIC_SC_SMM_RD_NEXT     (SMIC_STATUS|SMIC_SMM|SMIC_RD_NEXT)
4697 +#define        SMIC_SC_SMM_RD_END      (SMIC_STATUS|SMIC_SMM|SMIC_RD_END)
4698 +
4699 +/* these are the control/status codes we actually use
4700 +       SMIC_CC_SMS_GET_STATUS  0x40
4701 +       SMIC_CC_SMS_WR_START    0x41
4702 +       SMIC_CC_SMS_WR_NEXT     0x42
4703 +       SMIC_CC_SMS_WR_END      0x43
4704 +       SMIC_CC_SMS_RD_START    0x44
4705 +       SMIC_CC_SMS_RD_NEXT     0x45
4706 +       SMIC_CC_SMS_RD_END      0x46
4707 +
4708 +       SMIC_SC_SMS_READY       0xC0
4709 +       SMIC_SC_SMS_WR_START    0xC1
4710 +       SMIC_SC_SMS_WR_NEXT     0xC2
4711 +       SMIC_SC_SMS_WR_END      0xC3
4712 +       SMIC_SC_SMS_RD_START    0xC4
4713 +       SMIC_SC_SMS_RD_NEXT     0xC5
4714 +       SMIC_SC_SMS_RD_END      0xC6
4715 +*/
4716 +
4717 +static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
4718 +{
4719 +       unsigned char status;
4720 +       unsigned char flags;
4721 +       unsigned char data;
4722 +
4723 +       if (smic->state == SMIC_HOSED) {
4724 +               init_smic_data(smic, smic->io);
4725 +               return SI_SM_HOSED;
4726 +       }
4727 +       if (smic->state != SMIC_IDLE) {
4728 +               if (smic_debug & SMIC_DEBUG_STATES) {
4729 +                       printk(KERN_INFO
4730 +                              "smic_event - smic->smic_timeout = %ld,"
4731 +                              " time = %ld\n",
4732 +                              smic->smic_timeout, time);
4733 +               }
4734 +/* FIXME: smic_event is sometimes called with time > SMIC_RETRY_TIMEOUT */
4735 +               if (time < SMIC_RETRY_TIMEOUT) {
4736 +                       smic->smic_timeout -= time;
4737 +                       if (smic->smic_timeout < 0) {
4738 +                               start_error_recovery(smic, "smic timed out.");
4739 +                               return SI_SM_CALL_WITH_DELAY;
4740 +                       }
4741 +               }
4742 +       }
4743 +       flags = read_smic_flags(smic);
4744 +       if (flags & SMIC_FLAG_BSY)
4745 +               return SI_SM_CALL_WITH_DELAY;
4746 +
4747 +       status = read_smic_status (smic);
4748 +       if (smic_debug & SMIC_DEBUG_STATES)
4749 +               printk(KERN_INFO
4750 +                      "smic_event - state = %d, flags = 0x%02x,"
4751 +                      " status = 0x%02x\n",
4752 +                      smic->state, flags, status);
4753 +
4754 +       switch (smic->state) {
4755 +       case SMIC_IDLE:
4756 +               /* in IDLE we check for available messages */
4757 +               if (flags & (SMIC_SMI |
4758 +                            SMIC_EVM_DATA_AVAIL | SMIC_SMS_DATA_AVAIL))
4759 +               {
4760 +                       return SI_SM_ATTN;
4761 +               }
4762 +               return SI_SM_IDLE;
4763 +
4764 +       case SMIC_START_OP:
4765 +               /* sanity check whether smic is really idle */
4766 +               write_smic_control(smic, SMIC_CC_SMS_GET_STATUS);
4767 +               write_smic_flags(smic, flags | SMIC_FLAG_BSY);
4768 +               smic->state = SMIC_OP_OK;
4769 +               break;
4770 +
4771 +       case SMIC_OP_OK:
4772 +               if (status != SMIC_SC_SMS_READY) {
4773 +                               /* this should not happen */
4774 +                       start_error_recovery(smic,
4775 +                                            "state = SMIC_OP_OK,"
4776 +                                            " status != SMIC_SC_SMS_READY");
4777 +                       return SI_SM_CALL_WITH_DELAY;
4778 +               }
4779 +               /* OK so far; smic is idle let us start ... */
4780 +               write_smic_control(smic, SMIC_CC_SMS_WR_START);
4781 +               write_next_byte(smic);
4782 +               write_smic_flags(smic, flags | SMIC_FLAG_BSY);
4783 +               smic->state = SMIC_WRITE_START;
4784 +               break;
4785 +
4786 +       case SMIC_WRITE_START:
4787 +               if (status != SMIC_SC_SMS_WR_START) {
4788 +                       start_error_recovery(smic,
4789 +                                            "state = SMIC_WRITE_START, "
4790 +                                            "status != SMIC_SC_SMS_WR_START");
4791 +                       return SI_SM_CALL_WITH_DELAY;
4792 +               }
4793 +               /* we must not issue WR_(NEXT|END) unless
4794 +                   TX_DATA_READY is set */
4795 +               if (flags & SMIC_TX_DATA_READY) {
4796 +                       if (smic->write_count == 1) {
4797 +                               /* last byte */
4798 +                               write_smic_control(smic, SMIC_CC_SMS_WR_END);
4799 +                               smic->state = SMIC_WRITE_END;
4800 +                       } else {
4801 +                               write_smic_control(smic, SMIC_CC_SMS_WR_NEXT);
4802 +                               smic->state = SMIC_WRITE_NEXT;
4803 +                       }
4804 +                       write_next_byte(smic);
4805 +                       write_smic_flags(smic, flags | SMIC_FLAG_BSY);
4806 +               }
4807 +               else {
4808 +                       return SI_SM_CALL_WITH_DELAY;
4809 +               }
4810 +               break;
4811 +
4812 +       case SMIC_WRITE_NEXT:
4813 +               if (status != SMIC_SC_SMS_WR_NEXT) {
4814 +                       start_error_recovery(smic,
4815 +                                            "state = SMIC_WRITE_NEXT, "
4816 +                                            "status != SMIC_SC_SMS_WR_NEXT");
4817 +                       return SI_SM_CALL_WITH_DELAY;
4818 +               }
4819 +               /* this is the same code as in SMIC_WRITE_START */
4820 +               if (flags & SMIC_TX_DATA_READY) {
4821 +                       if (smic->write_count == 1) {
4822 +                               write_smic_control(smic, SMIC_CC_SMS_WR_END);
4823 +                               smic->state = SMIC_WRITE_END;
4824 +                       }
4825 +                       else {
4826 +                               write_smic_control(smic, SMIC_CC_SMS_WR_NEXT);
4827 +                               smic->state = SMIC_WRITE_NEXT;
4828 +                       }
4829 +                       write_next_byte(smic);
4830 +                       write_smic_flags(smic, flags | SMIC_FLAG_BSY);
4831 +               }
4832 +               else {
4833 +                       return SI_SM_CALL_WITH_DELAY;
4834 +               }
4835 +               break;
4836 +
4837 +       case SMIC_WRITE_END:
4838 +               if (status != SMIC_SC_SMS_WR_END) {
4839 +                       start_error_recovery (smic,
4840 +                                             "state = SMIC_WRITE_END, "
4841 +                                             "status != SMIC_SC_SMS_WR_END");
4842 +                       return SI_SM_CALL_WITH_DELAY;
4843 +               }
4844 +               /* data register holds an error code */
4845 +               data = read_smic_data(smic);
4846 +               if (data != 0) {
4847 +                       if (smic_debug & SMIC_DEBUG_ENABLE) {
4848 +                               printk(KERN_INFO
4849 +                                      "SMIC_WRITE_END: data = %02x\n", data);
4850 +                       }
4851 +                       start_error_recovery(smic,
4852 +                                            "state = SMIC_WRITE_END, "
4853 +                                            "data != SUCCESS");
4854 +                       return SI_SM_CALL_WITH_DELAY;
4855 +               } else {
4856 +                       smic->state = SMIC_WRITE2READ;
4857 +               }
4858 +               break;
4859 +
4860 +       case SMIC_WRITE2READ:
4861 +               /* we must wait for RX_DATA_READY to be set before we
4862 +                   can continue */
4863 +               if (flags & SMIC_RX_DATA_READY) {
4864 +                       write_smic_control(smic, SMIC_CC_SMS_RD_START);
4865 +                       write_smic_flags(smic, flags | SMIC_FLAG_BSY);
4866 +                       smic->state = SMIC_READ_START;
4867 +               } else {
4868 +                       return SI_SM_CALL_WITH_DELAY;
4869 +               }
4870 +               break;
4871 +
4872 +       case SMIC_READ_START:
4873 +               if (status != SMIC_SC_SMS_RD_START) {
4874 +                       start_error_recovery(smic,
4875 +                                            "state = SMIC_READ_START, "
4876 +                                            "status != SMIC_SC_SMS_RD_START");
4877 +                       return SI_SM_CALL_WITH_DELAY;
4878 +               }
4879 +               if (flags & SMIC_RX_DATA_READY) {
4880 +                       read_next_byte(smic);
4881 +                       write_smic_control(smic, SMIC_CC_SMS_RD_NEXT);
4882 +                       write_smic_flags(smic, flags | SMIC_FLAG_BSY);
4883 +                       smic->state = SMIC_READ_NEXT;
4884 +               } else {
4885 +                       return SI_SM_CALL_WITH_DELAY;
4886 +               }
4887 +               break;
4888 +
4889 +       case SMIC_READ_NEXT:
4890 +               switch (status) {
4891 +               /* smic tells us that this is the last byte to be read
4892 +                   --> clean up */
4893 +               case SMIC_SC_SMS_RD_END:
4894 +                       read_next_byte(smic);
4895 +                       write_smic_control(smic, SMIC_CC_SMS_RD_END);
4896 +                       write_smic_flags(smic, flags | SMIC_FLAG_BSY);
4897 +                       smic->state = SMIC_READ_END;
4898 +                       break;
4899 +               case SMIC_SC_SMS_RD_NEXT:
4900 +                       if (flags & SMIC_RX_DATA_READY) {
4901 +                               read_next_byte(smic);
4902 +                               write_smic_control(smic, SMIC_CC_SMS_RD_NEXT);
4903 +                               write_smic_flags(smic, flags | SMIC_FLAG_BSY);
4904 +                               smic->state = SMIC_READ_NEXT;
4905 +                       } else {
4906 +                               return SI_SM_CALL_WITH_DELAY;
4907 +                       }
4908 +                       break;
4909 +               default:
4910 +                       start_error_recovery(
4911 +                               smic,
4912 +                               "state = SMIC_READ_NEXT, "
4913 +                               "status != SMIC_SC_SMS_RD_(NEXT|END)");
4914 +                       return SI_SM_CALL_WITH_DELAY;
4915 +               }
4916 +               break;
4917 +
4918 +       case SMIC_READ_END:
4919 +               if (status != SMIC_SC_SMS_READY) {
4920 +                       start_error_recovery(smic,
4921 +                                            "state = SMIC_READ_END, "
4922 +                                            "status != SMIC_SC_SMS_READY");
4923 +                       return SI_SM_CALL_WITH_DELAY;
4924 +               }
4925 +               data = read_smic_data(smic);
4926 +               /* data register holds an error code */
4927 +               if (data != 0) {
4928 +                       if (smic_debug & SMIC_DEBUG_ENABLE) {
4929 +                               printk(KERN_INFO
4930 +                                      "SMIC_READ_END: data = %02x\n", data);
4931 +                       }
4932 +                       start_error_recovery(smic,
4933 +                                            "state = SMIC_READ_END, "
4934 +                                            "data != SUCCESS");
4935 +                       return SI_SM_CALL_WITH_DELAY;
4936 +               } else {
4937 +                       smic->state = SMIC_IDLE;
4938 +                       return SI_SM_TRANSACTION_COMPLETE;
4939 +               }
4940 +
4941 +       case SMIC_HOSED:
4942 +               init_smic_data(smic, smic->io);
4943 +               return SI_SM_HOSED;
4944 +
4945 +       default:
4946 +               if (smic_debug & SMIC_DEBUG_ENABLE) {
4947 +                       printk(KERN_WARNING "smic->state = %d\n", smic->state);
4948 +                       start_error_recovery(smic, "state = UNKNOWN");
4949 +                       return SI_SM_CALL_WITH_DELAY;
4950 +               }
4951 +       }
4952 +       smic->smic_timeout = SMIC_RETRY_TIMEOUT;
4953 +       return SI_SM_CALL_WITHOUT_DELAY;
4954 +}
4955 +
4956 +static int smic_detect(struct si_sm_data *smic)
4957 +{
4958 +       /* It's impossible for the SMIC fnags register to be all 1's,
4959 +          (assuming a properly functioning, self-initialized BMC)
4960 +          but that's what you get from reading a bogus address, so we
4961 +          test that first. */
4962 +       if (read_smic_flags(smic) == 0xff)
4963 +               return 1; 
4964 +
4965 +       return 0;
4966 +}
4967 +
4968 +static void smic_cleanup(struct si_sm_data *kcs)
4969 +{
4970 +}
4971 +
4972 +static int smic_size(void)
4973 +{
4974 +       return sizeof(struct si_sm_data);
4975 +}
4976 +
4977 +struct si_sm_handlers smic_smi_handlers =
4978 +{
4979 +       .version           = IPMI_SMIC_VERSION,
4980 +       .init_data         = init_smic_data,
4981 +       .start_transaction = start_smic_transaction,
4982 +       .get_result        = smic_get_result,
4983 +       .event             = smic_event,
4984 +       .detect            = smic_detect,
4985 +       .cleanup           = smic_cleanup,
4986 +       .size              = smic_size,
4987 +};
4988 diff -urN linux-2.4.23.org/drivers/char/ipmi/ipmi_watchdog.c linux-2.4.23/drivers/char/ipmi/ipmi_watchdog.c
4989 --- linux-2.4.23.org/drivers/char/ipmi/ipmi_watchdog.c  2003-12-06 12:53:23.003503549 +0100
4990 +++ linux-2.4.23/drivers/char/ipmi/ipmi_watchdog.c      2003-12-06 17:46:43.041444912 +0100
4991 @@ -50,6 +50,8 @@
4992  #include <asm/apic.h>
4993  #endif
4994  
4995 +#define IPMI_WATCHDOG_VERSION "v27"
4996 +
4997  /*
4998   * The IPMI command/response information for the watchdog timer.
4999   */
5000 @@ -153,10 +155,18 @@
5001  static char pretimeout_since_last_heartbeat = 0;
5002  
5003  MODULE_PARM(timeout, "i");
5004 +MODULE_PARM_DESC(timeout, "Timeout value in seconds.");
5005  MODULE_PARM(pretimeout, "i");
5006 +MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds.");
5007  MODULE_PARM(action, "s");
5008 +MODULE_PARM_DESC(action, "Timeout action. One of: "
5009 +                "reset, none, power_cycle, power_off.");
5010  MODULE_PARM(preaction, "s");
5011 +MODULE_PARM_DESC(preaction, "Pretimeout action.  One of: "
5012 +                "pre_none, pre_smi, pre_nmi, pre_int.");
5013  MODULE_PARM(preop, "s");
5014 +MODULE_PARM_DESC(preop, "Pretimeout driver operation.  One of: "
5015 +                "preop_none, preop_panic, preop_give_data.");
5016  
5017  /* Default state of the timer. */
5018  static unsigned char ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
5019 @@ -899,6 +909,7 @@
5020  
5021  static struct ipmi_smi_watcher smi_watcher =
5022  {
5023 +       .owner    = THIS_MODULE,
5024         .new_smi  = ipmi_new_smi,
5025         .smi_gone = ipmi_smi_gone
5026  };
5027 @@ -907,6 +918,9 @@
5028  {
5029         int rv;
5030  
5031 +       printk(KERN_INFO "IPMI watchdog driver version "
5032 +              IPMI_WATCHDOG_VERSION "\n");
5033 +
5034         if (strcmp(action, "reset") == 0) {
5035                 action_val = WDOG_TIMEOUT_RESET;
5036         } else if (strcmp(action, "none") == 0) {
5037 @@ -995,9 +1009,6 @@
5038         register_reboot_notifier(&wdog_reboot_notifier);
5039         notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier);
5040  
5041 -       printk(KERN_INFO "IPMI watchdog by "
5042 -              "Corey Minyard (minyard@mvista.com)\n");
5043 -
5044         return 0;
5045  }
5046  
5047 diff -urN linux-2.4.23.org/drivers/char/ipmi/Makefile linux-2.4.23/drivers/char/ipmi/Makefile
5048 --- linux-2.4.23.org/drivers/char/ipmi/Makefile 2003-12-06 12:53:23.043495221 +0100
5049 +++ linux-2.4.23/drivers/char/ipmi/Makefile     2003-12-06 17:46:43.064440089 +0100
5050 @@ -6,11 +6,13 @@
5051  
5052  export-objs    := ipmi_msghandler.o ipmi_watchdog.o
5053  
5054 -list-multi := ipmi_kcs_drv.o
5055 +list-multi := ipmi_kcs_drv.o ipmi_si_drv.o
5056  ipmi_kcs_drv-objs := ipmi_kcs_sm.o ipmi_kcs_intf.o
5057 +ipmi_si_drv-objs := ipmi_si.o ipmi_kcs_sm.o ipmi_smic_sm.o
5058  
5059  obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o
5060  obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o
5061 +obj-$(CONFIG_IPMI_SI) += ipmi_si_drv.o
5062  obj-$(CONFIG_IPMI_KCS) += ipmi_kcs_drv.o
5063  obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
5064  
5065 @@ -18,3 +20,6 @@
5066  
5067  ipmi_kcs_drv.o:        $(ipmi_kcs_drv-objs)
5068         $(LD) -r -o $@ $(ipmi_kcs_drv-objs) 
5069 +
5070 +ipmi_si_drv.o: $(ipmi_si_drv-objs)
5071 +       $(LD) -r -o $@ $(ipmi_si_drv-objs) 
5072 diff -urN linux-2.4.23.org/include/linux/ipmi.h linux-2.4.23/include/linux/ipmi.h
5073 --- linux-2.4.23.org/include/linux/ipmi.h       2003-12-06 12:52:27.330097221 +0100
5074 +++ linux-2.4.23/include/linux/ipmi.h   2003-12-06 17:46:43.115429392 +0100
5075 @@ -160,6 +160,7 @@
5076   * The in-kernel interface.
5077   */
5078  #include <linux/list.h>
5079 +#include <linux/module.h>
5080  
5081  /* Opaque type for a IPMI message user.  One of these is needed to
5082     send and receive messages. */
5083 @@ -221,7 +222,12 @@
5084                      void                  *handler_data,
5085                      ipmi_user_t           *user);
5086  
5087 -/* Destroy the given user of the IPMI layer. */
5088 +/* Destroy the given user of the IPMI layer.  Note that after this
5089 +   function returns, the system is guaranteed to not call any
5090 +   callbacks for the user.  Thus as long as you destroy all the users
5091 +   before you unload a module, you will be safe.  And if you destroy
5092 +   the users before you destroy the callback structures, it should be
5093 +   safe, too. */
5094  int ipmi_destroy_user(ipmi_user_t user);
5095  
5096  /* Get the IPMI version of the BMC we are talking to. */
5097 @@ -261,6 +267,27 @@
5098                  int              priority);
5099  
5100  /*
5101 + * Like ipmi_request, but lets you specify the number of retries and
5102 + * the retry time.  The retries is the number of times the message
5103 + * will be resent if no reply is received.  If set to -1, the default
5104 + * value will be used.  The retry time is the time in milliseconds
5105 + * between retries.  If set to zero, the default value will be
5106 + * used.
5107 + *
5108 + * Don't use this unless you *really* have to.  It's primarily for the
5109 + * IPMI over LAN converter; since the LAN stuff does its own retries,
5110 + * it makes no sense to do it here.  However, this can be used if you
5111 + * have unusual requirements.
5112 + */
5113 +int ipmi_request_settime(ipmi_user_t      user,
5114 +                        struct ipmi_addr *addr,
5115 +                        long             msgid,
5116 +                        struct ipmi_msg  *msg,
5117 +                        int              priority,
5118 +                        int              max_retries,
5119 +                        unsigned int     retry_time_ms);
5120 +
5121 +/*
5122   * Like ipmi_request, but lets you specify the slave return address.
5123   */
5124  int ipmi_request_with_source(ipmi_user_t      user,
5125 @@ -331,6 +358,10 @@
5126  {
5127         struct list_head link;
5128  
5129 +       /* You must set the owner to the current module, if you are in
5130 +          a module (generally just set it to "THIS_MODULE"). */
5131 +       struct module *owner;
5132 +
5133         /* These two are called with read locks held for the interface
5134            the watcher list.  So you can add and remove users from the
5135            IPMI interface, send messages, etc., but you cannot add
5136 @@ -422,6 +453,29 @@
5137  #define IPMICTL_SEND_COMMAND           _IOR(IPMI_IOC_MAGIC, 13,        \
5138                                              struct ipmi_req)
5139  
5140 +/* Messages sent to the interface with timing parameters are this
5141 +   format. */
5142 +struct ipmi_req_settime
5143 +{
5144 +       struct ipmi_req req;
5145 +
5146 +       /* See ipmi_request_settime() above for details on these
5147 +           values. */
5148 +       int          retries;
5149 +       unsigned int retry_time_ms;
5150 +};
5151 +/*
5152 + * Send a message to the interfaces with timing parameters.  error values
5153 + * are:
5154 + *   - EFAULT - an address supplied was invalid.
5155 + *   - EINVAL - The address supplied was not valid, or the command
5156 + *              was not allowed.
5157 + *   - EMSGSIZE - The message to was too large.
5158 + *   - ENOMEM - Buffers could not be allocated for the command.
5159 + */
5160 +#define IPMICTL_SEND_COMMAND_SETTIME   _IOR(IPMI_IOC_MAGIC, 21,        \
5161 +                                            struct ipmi_req_settime)
5162 +
5163  /* Messages received from the interface are this format. */
5164  struct ipmi_recv
5165  {
5166 @@ -513,4 +567,18 @@
5167  #define IPMICTL_SET_MY_LUN_CMD         _IOR(IPMI_IOC_MAGIC, 19, unsigned int)
5168  #define IPMICTL_GET_MY_LUN_CMD         _IOR(IPMI_IOC_MAGIC, 20, unsigned int)
5169  
5170 +/*
5171 + * Get/set the default timing values for an interface.  You shouldn't
5172 + * generally mess with these.
5173 + */
5174 +struct ipmi_timing_parms
5175 +{
5176 +       int          retries;
5177 +       unsigned int retry_time_ms;
5178 +};
5179 +#define IPMICTL_SET_TIMING_PARMS_CMD   _IOR(IPMI_IOC_MAGIC, 22, \
5180 +                                            struct ipmi_timing_parms)
5181 +#define IPMICTL_GET_TIMING_PARMS_CMD   _IOR(IPMI_IOC_MAGIC, 23, \
5182 +                                            struct ipmi_timing_parms)
5183 +
5184  #endif /* __LINUX_IPMI_H */
5185 diff -urN linux-2.4.23.org/include/linux/ipmi_msgdefs.h linux-2.4.23/include/linux/ipmi_msgdefs.h
5186 --- linux-2.4.23.org/include/linux/ipmi_msgdefs.h       2003-12-06 12:52:27.323098678 +0100
5187 +++ linux-2.4.23/include/linux/ipmi_msgdefs.h   2003-12-06 17:46:43.148422471 +0100
5188 @@ -37,22 +37,34 @@
5189  /* Various definitions for IPMI messages used by almost everything in
5190     the IPMI stack. */
5191  
5192 -#define IPMI_NETFN_APP_REQUEST 0x06
5193 -#define IPMI_NETFN_APP_RESPONSE        0x07
5194 -
5195 -#define IPMI_BMC_SLAVE_ADDR    0x20
5196 +/* NetFNs and commands used inside the IPMI stack. */
5197
5198 +#define IPMI_NETFN_SENSOR_EVENT_REQUEST                0x04
5199 +#define IPMI_NETFN_SENSOR_EVENT_RESPONSE       0x05
5200 +#define IPMI_GET_EVENT_RECEIVER_CMD    0x01
5201  
5202 +#define IPMI_NETFN_APP_REQUEST                 0x06
5203 +#define IPMI_NETFN_APP_RESPONSE                        0x07
5204  #define IPMI_GET_DEVICE_ID_CMD         0x01
5205 -
5206  #define IPMI_CLEAR_MSG_FLAGS_CMD       0x30
5207  #define IPMI_GET_MSG_FLAGS_CMD         0x31
5208  #define IPMI_SEND_MSG_CMD              0x34
5209  #define IPMI_GET_MSG_CMD               0x33
5210 -
5211  #define IPMI_SET_BMC_GLOBAL_ENABLES_CMD        0x2e
5212  #define IPMI_GET_BMC_GLOBAL_ENABLES_CMD        0x2f
5213  #define IPMI_READ_EVENT_MSG_BUFFER_CMD 0x35
5214  
5215 +#define IPMI_NETFN_STORAGE_REQUEST             0x0a
5216 +#define IPMI_NETFN_STORAGE_RESPONSE            0x0b
5217 +#define IPMI_ADD_SEL_ENTRY_CMD         0x44
5218 +
5219 +/* The default slave address */
5220 +#define IPMI_BMC_SLAVE_ADDR    0x20
5221 +
5222  #define IPMI_MAX_MSG_LENGTH    80
5223  
5224 +#define IPMI_CC_NO_ERROR       0
5225 +#define IPMI_NODE_BUSY_ERR             0xc0
5226 +#define IPMI_LOST_ARBITRATION_ERR      0x81
5227 +
5228  #endif /* __LINUX_IPMI_MSGDEFS_H */
5229 diff -urN linux-2.4.23.org/include/linux/ipmi_smi.h linux-2.4.23/include/linux/ipmi_smi.h
5230 --- linux-2.4.23.org/include/linux/ipmi_smi.h   2003-12-06 12:52:27.322098886 +0100
5231 +++ linux-2.4.23/include/linux/ipmi_smi.h       2003-12-06 17:46:43.162419535 +0100
5232 @@ -35,6 +35,8 @@
5233  #define __LINUX_IPMI_SMI_H
5234  
5235  #include <linux/ipmi_msgdefs.h>
5236 +#include <linux/proc_fs.h>
5237 +#include <linux/module.h>
5238  
5239  /* This files describes the interface for IPMI system management interface
5240     drivers to bind into the IPMI message handler. */
5241 @@ -141,4 +143,11 @@
5242         msg->done(msg);
5243  }
5244  
5245 +/* Allow the lower layer to add things to the proc filesystem
5246 +   directory for this interface.  Note that the entry will
5247 +   automatically be dstroyed when the interface is destroyed. */
5248 +int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
5249 +                           read_proc_t *read_proc, write_proc_t *write_proc,
5250 +                           void *data, struct module *owner);
5251 +
5252  #endif /* __LINUX_IPMI_SMI_H */
5253 diff -urN linux-2.4.23.org/include/linux/net.h linux-2.4.23/include/linux/net.h
5254 --- linux-2.4.23.org/include/linux/net.h        2003-12-06 12:52:26.841199031 +0100
5255 +++ linux-2.4.23/include/linux/net.h    2003-12-06 17:46:43.181415550 +0100
5256 @@ -24,7 +24,7 @@
5257  
5258  struct poll_table_struct;
5259  
5260 -#define NPROTO         32              /* should be enough for now..   */
5261 +#define NPROTO         64              /* should be enough for now..   */
5262  
5263  
5264  #define SYS_SOCKET     1               /* sys_socket(2)                */
5265 diff -urN linux-2.4.23.org/include/linux/socket.h linux-2.4.23/include/linux/socket.h
5266 --- linux-2.4.23.org/include/linux/socket.h     2003-12-06 12:52:26.722223807 +0100
5267 +++ linux-2.4.23/include/linux/socket.h 2003-12-06 17:46:43.201411356 +0100
5268 @@ -175,7 +175,8 @@
5269  #define AF_WANPIPE     25      /* Wanpipe API Sockets */
5270  #define AF_LLC         26      /* Linux LLC                    */
5271  #define AF_BLUETOOTH   31      /* Bluetooth sockets            */
5272 -#define AF_MAX         32      /* For now.. */
5273 +#define AF_IPMI                32      /* IPMI sockers                 */
5274 +#define AF_MAX         33      /* For now.. */
5275  
5276  /* Protocol families, same as address families. */
5277  #define PF_UNSPEC      AF_UNSPEC
5278 @@ -207,6 +208,7 @@
5279  #define PF_WANPIPE     AF_WANPIPE
5280  #define PF_LLC         AF_LLC
5281  #define PF_BLUETOOTH   AF_BLUETOOTH
5282 +#define PF_IPMI                AF_IPMI
5283  #define PF_MAX         AF_MAX
5284  
5285  /* Maximum queue length specifiable by listen.  */
5286 diff -urN linux-2.4.23.org/include/net/af_ipmi.h linux-2.4.23/include/net/af_ipmi.h
5287 --- linux-2.4.23.org/include/net/af_ipmi.h      1970-01-01 01:00:00.000000000 +0100
5288 +++ linux-2.4.23/include/net/af_ipmi.h  2003-12-06 17:46:43.228405693 +0100
5289 @@ -0,0 +1,66 @@
5290 +#ifndef _NET_IPMI_H
5291 +#define _NET_IPMI_H
5292 +
5293 +#include <linux/ipmi.h>
5294 +
5295 +/*
5296 + * This is ipmi address for socket
5297 + */
5298 +struct sockaddr_ipmi {
5299 +       sa_family_t      sipmi_family; /* AF_IPMI */
5300 +       int              if_num; /* IPMI interface number */
5301 +       struct ipmi_addr ipmi_addr;
5302 +};
5303 +#define SOCKADDR_IPMI_OVERHEAD (sizeof(struct sockaddr_ipmi) \
5304 +                               - sizeof(struct ipmi_addr))
5305 +
5306 +/* A msg_control item, this takes a 'struct ipmi_timing_parms' */
5307 +#define IPMI_CMSG_TIMING_PARMS 0x01
5308 +
5309 +/* 
5310 + * This is ipmi message for socket
5311 + */
5312 +struct ipmi_sock_msg {
5313 +       int                   recv_type;
5314 +       long                  msgid;
5315 +
5316 +       unsigned char         netfn;
5317 +       unsigned char         cmd;
5318 +       int                   data_len;
5319 +       unsigned char         data[0];
5320 +};
5321 +
5322 +#define IPMI_MAX_SOCK_MSG_LENGTH (sizeof(struct ipmi_sock_msg)+IPMI_MAX_MSG_LENGTH)
5323 +
5324 +/* Register/unregister to receive specific commands.  Uses struct
5325 +   ipmi_cmdspec from linux/ipmi.h */
5326 +#define SIOCIPMIREGCMD         (SIOCPROTOPRIVATE + 0)
5327 +#define SIOCIPMIUNREGCMD       (SIOCPROTOPRIVATE + 1)
5328 +
5329 +/* Register to receive events.  Takes an integer */
5330 +#define SIOCIPMIGETEVENT       (SIOCPROTOPRIVATE + 2)
5331 +
5332 +/* Set the default timing parameters for the socket.  Takes a struct
5333 +   ipmi_timing_parms from linux/ipmi.h */
5334 +#define SIOCIPMISETTIMING      (SIOCPROTOPRIVATE + 3)
5335 +#define SIOCIPMIGETTIMING      (SIOCPROTOPRIVATE + 4)
5336 +
5337 +/* Set/Get the IPMB address of the MC we are connected to, takes an
5338 +   unsigned int. */
5339 +#define SIOCIPMISETADDR                (SIOCPROTOPRIVATE + 5)
5340 +#define SIOCIPMIGETADDR                (SIOCPROTOPRIVATE + 6)
5341 +
5342 +/* Socket information for IPMI for protinfo. */
5343 +struct ipmi_sock {
5344 +       ipmi_user_t user;
5345 +       struct sockaddr_ipmi addr;
5346 +       struct list_head msg_list;
5347 +       
5348 +       wait_queue_head_t wait; 
5349 +       spinlock_t lock;
5350 +
5351 +       int          default_retries;
5352 +       unsigned int default_retry_time_ms;
5353 +};
5354 +
5355 +#endif/*_NET_IPMI_H*/
5356 diff -urN linux-2.4.23.org/include/net/sock.h linux-2.4.23/include/net/sock.h
5357 --- linux-2.4.23.org/include/net/sock.h 2003-12-06 12:52:36.719142002 +0100
5358 +++ linux-2.4.23/include/net/sock.h     2003-12-06 17:46:43.247401708 +0100
5359 @@ -98,6 +98,10 @@
5360  #include <net/irda/irda.h>
5361  #endif
5362  
5363 +#if defined(CONFIG_IPMI_SOCKET) || defined(CONFIG_IPMI_SOCKET_MODULE)
5364 +#include <net/af_ipmi.h>
5365 +#endif
5366 +
5367  #if defined(CONFIG_ATM) || defined(CONFIG_ATM_MODULE)
5368  struct atm_vcc;
5369  #endif
5370 @@ -673,6 +677,9 @@
5371  #if defined(CONFIG_WAN_ROUTER) || defined(CONFIG_WAN_ROUTER_MODULE)
5372                 struct wanpipe_opt      *af_wanpipe;
5373  #endif
5374 +#if defined(CONFIG_IPMI_SOCKET) || defined(CONFIG_IPMI_SOCKET_MODULE)
5375 +              struct ipmi_sock        af_ipmi;
5376 +#endif
5377         } protinfo;             
5378  
5379  
5380 diff -urN linux-2.4.23.org/LOG linux-2.4.23/LOG
5381 --- linux-2.4.23.org/LOG        1970-01-01 01:00:00.000000000 +0100
5382 +++ linux-2.4.23/LOG    2003-12-06 17:46:43.371375702 +0100
5383 @@ -0,0 +1,38 @@
5384 +patching file Documentation/Configure.help
5385 +Hunk #1 succeeded at 4226 (offset 974 lines).
5386 +Hunk #2 succeeded at 29341 (offset 1959 lines).
5387 +patching file Documentation/IPMI.txt
5388 +patching file drivers/char/Config.in
5389 +Hunk #1 succeeded at 213 (offset 9 lines).
5390 +patching file drivers/char/ipmi/ipmi_devintf.c
5391 +patching file drivers/char/ipmi/ipmi_kcs_intf.c
5392 +patching file drivers/char/ipmi/ipmi_kcs_sm.c
5393 +patching file drivers/char/ipmi/ipmi_msghandler.c
5394 +patching file drivers/char/ipmi/ipmi_si.c
5395 +patching file drivers/char/ipmi/ipmi_si_sm.h
5396 +patching file drivers/char/ipmi/ipmi_smic_sm.c
5397 +patching file drivers/char/ipmi/ipmi_watchdog.c
5398 +patching file drivers/char/ipmi/Makefile
5399 +patching file include/linux/ipmi.h
5400 +patching file include/linux/ipmi_msgdefs.h
5401 +patching file include/linux/ipmi_smi.h
5402 +patching file include/linux/net.h
5403 +patching file include/linux/socket.h
5404 +Hunk #1 succeeded at 175 (offset 2 lines).
5405 +Hunk #2 succeeded at 208 (offset 2 lines).
5406 +patching file include/net/af_ipmi.h
5407 +patching file include/net/sock.h
5408 +Hunk #1 succeeded at 98 (offset 3 lines).
5409 +Hunk #2 succeeded at 677 (offset 6 lines).
5410 +patching file kernel/panic.c
5411 +Reversed (or previously applied) patch detected!  Assume -R? [n] 
5412 +Apply anyway? [n] 
5413 +Skipping patch.
5414 +1 out of 1 hunk ignored -- saving rejects to file kernel/panic.c.rej
5415 +patching file net/Config.in
5416 +patching file net/ipmi/af_ipmi.c
5417 +patching file net/ipmi/Makefile
5418 +patching file net/Makefile
5419 +Hunk #1 FAILED at 7.
5420 +Hunk #2 succeeded at 47 with fuzz 2 (offset 2 lines).
5421 +1 out of 2 hunks FAILED -- saving rejects to file net/Makefile.rej
5422 diff -urN linux-2.4.23.org/net/Config.in linux-2.4.23/net/Config.in
5423 --- linux-2.4.23.org/net/Config.in      2003-12-06 12:52:51.579047508 +0100
5424 +++ linux-2.4.23/net/Config.in  2003-12-06 17:46:43.327384930 +0100
5425 @@ -16,6 +16,7 @@
5426  fi
5427  bool 'Socket Filtering'  CONFIG_FILTER
5428  tristate 'Unix domain sockets' CONFIG_UNIX
5429 +tristate 'IPMI sockets' CONFIG_IPMI_SOCKET
5430  bool 'TCP/IP networking' CONFIG_INET
5431  if [ "$CONFIG_INET" = "y" ]; then
5432     source net/ipv4/Config.in
5433 diff -urN linux-2.4.23.org/net/ipmi/af_ipmi.c linux-2.4.23/net/ipmi/af_ipmi.c
5434 --- linux-2.4.23.org/net/ipmi/af_ipmi.c 1970-01-01 01:00:00.000000000 +0100
5435 +++ linux-2.4.23/net/ipmi/af_ipmi.c     2003-12-06 17:46:43.330384301 +0100
5436 @@ -0,0 +1,593 @@
5437 +/* 
5438 + * IPMI Socket Glue
5439 + *
5440 + * Author:     Louis Zhuang <louis.zhuang@linux.intel.com>
5441 + * Copyright by Intel Corp., 2003
5442 + */
5443 +#include <linux/module.h>
5444 +#include <linux/config.h>
5445 +#include <linux/kernel.h>
5446 +#include <linux/major.h>
5447 +#include <linux/signal.h>
5448 +#include <linux/sched.h>
5449 +#include <linux/errno.h>
5450 +#include <linux/string.h>
5451 +#include <linux/stat.h>
5452 +#include <linux/socket.h>
5453 +#include <linux/fcntl.h>
5454 +#include <linux/sockios.h>
5455 +#include <linux/net.h>
5456 +#include <linux/in.h>
5457 +#include <linux/fs.h>
5458 +#include <linux/slab.h>
5459 +#include <asm/uaccess.h>
5460 +#include <linux/skbuff.h>
5461 +#include <linux/tcp.h>
5462 +#include <net/sock.h>
5463 +#include <linux/proc_fs.h>
5464 +#include <linux/init.h>
5465 +#include <linux/poll.h>
5466 +#include <linux/smp_lock.h>
5467 +#include <linux/mount.h>
5468 +#include <linux/ipmi.h>
5469 +#include <net/af_ipmi.h>
5470 +#include <linux/rtnetlink.h>
5471 +
5472 +#define IPMI_SOCKINTF_VERSION "v25"
5473 +
5474 +#ifdef CONFIG_DEBUG_KERNEL
5475 +static int debug = 0;
5476 +#define dbg(format, arg...)                                     \
5477 +        do {                                                    \
5478 +                if(debug)                                    \
5479 +                        printk (KERN_DEBUG "%s: " format "\n",  \
5480 +                                __FUNCTION__, ## arg);          \
5481 +        } while(0)
5482 +#else
5483 +#define dbg(format, arg...)
5484 +#endif /* CONFIG_DEBUG_KERNEL */
5485 +
5486 +#define err(format, arg...) \
5487 +                printk(KERN_ERR "%s: " format "\n", \
5488 +                       __FUNCTION__ , ## arg)
5489 +#define info(format, arg...) \
5490 +                printk(KERN_INFO "%s: " format "\n", \
5491 +                       __FUNCTION__ , ## arg)
5492 +#define warn(format, arg...) \
5493 +                printk(KERN_WARNING "%s: " format "\n", \
5494 +                       __FUNCTION__ , ## arg)
5495 +#define trace(format, arg...) \
5496 +                printk(KERN_INFO "%s(" format ")\n", \
5497 +                       __FUNCTION__ , ## arg)
5498 +
5499 +static kmem_cache_t *ipmi_sk_cachep = NULL;
5500 +
5501 +static atomic_t ipmi_nr_socks = ATOMIC_INIT(0);
5502 +
5503 +
5504 +
5505 +/*
5506 + * utility functions
5507 + */
5508 +static inline struct ipmi_sock *to_ipmi_sock(struct sock *sk) 
5509 +{
5510 +       return &sk->protinfo.af_ipmi;
5511 +}
5512 +
5513 +static inline void ipmi_release_sock(struct sock *sk, int embrion)
5514 +{
5515 +       struct ipmi_sock *i = to_ipmi_sock(sk);
5516 +       struct sk_buff   *skb;
5517 +       
5518 +       if (i->user) {
5519 +               ipmi_destroy_user(i->user);
5520 +               i->user = NULL;
5521 +       }
5522 +
5523 +       sock_orphan(sk);
5524 +       sk->shutdown = SHUTDOWN_MASK;
5525 +       sk->state = TCP_CLOSE;
5526 +
5527 +       while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
5528 +               kfree_skb(skb);
5529 +
5530 +       sock_put(sk);
5531 +}
5532 +
5533 +static inline long ipmi_wait_for_queue(struct ipmi_sock *i, long timeo) 
5534 +{
5535 +       
5536 +       DECLARE_WAITQUEUE(wait, current);
5537 +       
5538 +       set_current_state(TASK_INTERRUPTIBLE);
5539 +       add_wait_queue_exclusive(&i->wait, &wait);
5540 +       timeo = schedule_timeout(timeo);
5541 +       set_current_state(TASK_RUNNING);
5542 +       remove_wait_queue(&i->wait, &wait);
5543 +       return timeo;
5544 +}
5545 +
5546 +/*
5547 + * IPMI operation functions
5548 + */
5549 +static void sock_receive_handler(struct ipmi_recv_msg *msg,
5550 +                                void                 *handler_data)
5551 +{
5552 +       struct ipmi_sock *i = (struct ipmi_sock *)handler_data;
5553 +       unsigned long    flags;
5554 +       
5555 +       spin_lock_irqsave(&i->lock, flags);
5556 +       list_add_tail(&msg->link, &i->msg_list);
5557 +       spin_unlock_irqrestore(&i->lock, flags);
5558 +
5559 +       wake_up_interruptible(&i->wait);
5560 +}
5561 +
5562 +/*
5563 + * protocol operation functions
5564 + */
5565 +static int ipmi_release(struct socket *sock)
5566 +{
5567 +       struct sock *sk = sock->sk;
5568 +       
5569 +       if (!sk)
5570 +               return 0;
5571 +
5572 +       sock->sk=NULL;
5573 +       ipmi_release_sock(sk, 0);
5574 +       return 0;
5575 +}
5576 +
5577 +static struct ipmi_user_hndl ipmi_hnd = {
5578 +       .ipmi_recv_hndl = sock_receive_handler
5579 +};
5580 +
5581 +static int ipmi_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
5582 +{
5583 +       struct ipmi_sock *i = to_ipmi_sock(sock->sk);
5584 +       struct sockaddr_ipmi *addr = (struct sockaddr_ipmi *)uaddr;
5585 +       int err = -EINVAL;
5586 +       
5587 +       if (i->user != NULL) {
5588 +               dbg("Cannot bind twice: %p", i->user);
5589 +               return -EINVAL;
5590 +       }
5591 +       
5592 +       err = ipmi_create_user(addr->if_num, &ipmi_hnd, i, &i->user);
5593 +       if (err) {
5594 +               dbg("Cannot create user for the socket: %p", i->user);
5595 +               return err;
5596 +       }
5597 +
5598 +       memcpy(&i->addr, addr, sizeof(i->addr));
5599 +       return 0;
5600 +}
5601 +
5602 +static int ipmi_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
5603 +{
5604 +       struct ipmi_sock *i = to_ipmi_sock(sock->sk);
5605 +       memcpy(uaddr, &i->addr, sizeof(i->addr));
5606 +       return 0;
5607 +}
5608 +
5609 +static unsigned int ipmi_poll(struct file * file, struct socket *sock, poll_table *wait)
5610 +{
5611 +       unsigned int     has_msg = 0;
5612 +       struct ipmi_sock *i = to_ipmi_sock(sock->sk);
5613 +       unsigned long    flags;
5614 +       
5615 +       poll_wait(file, &i->wait, wait);
5616 +       spin_lock_irqsave(&i->lock, flags);
5617 +       if (!list_empty(&i->msg_list))
5618 +               has_msg = 1;
5619 +       spin_unlock_irqrestore(&i->lock, flags);
5620 +
5621 +       if (has_msg)
5622 +               return POLLIN | POLLRDNORM;
5623 +       return 0;
5624 +}
5625 +
5626 +static int ipmi_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
5627 +{
5628 +       struct ipmi_sock    *i = to_ipmi_sock(sock->sk);
5629 +       struct ipmi_cmdspec val; 
5630 +       int                 ival;
5631 +       unsigned int        uival;
5632 +       int                 err;
5633 +       
5634 +       dbg("cmd=%#x, arg=%#lx", cmd, arg);
5635 +       switch(cmd) {
5636 +       case SIOCIPMIREGCMD:
5637 +               err = copy_from_user((void *)&val, (void *)arg,
5638 +                                    sizeof(cmd));
5639 +               if (err) {
5640 +                       err = -EFAULT;
5641 +                       break;
5642 +               }
5643 +               
5644 +               err = ipmi_register_for_cmd(i->user, val.netfn,
5645 +                                           val.cmd);
5646 +               break;
5647 +                       
5648 +       case SIOCIPMIUNREGCMD:
5649 +               err = copy_from_user((void *)&val, (void *)arg,
5650 +                                    sizeof(cmd));
5651 +               if (err) {
5652 +                       err = -EFAULT;
5653 +                       break;
5654 +               }
5655 +               
5656 +               err = ipmi_unregister_for_cmd(i->user, val.netfn,
5657 +                                             val.cmd);
5658 +               break;
5659 +                       
5660 +       case SIOCIPMIGETEVENT:
5661 +               err = copy_from_user((void *)&ival, (void *)arg,
5662 +                                    sizeof(ival));
5663 +               if (err) {
5664 +                       err = -EFAULT;
5665 +                       break;
5666 +               }
5667 +               
5668 +               err = ipmi_set_gets_events(i->user, ival);
5669 +               break;
5670 +                       
5671 +       case SIOCIPMISETADDR:
5672 +               err = copy_from_user((void *)&uival, (void *)arg,
5673 +                                    sizeof(uival));
5674 +               if (err) {
5675 +                       err = -EFAULT;
5676 +                       break;
5677 +               }
5678 +               
5679 +               ipmi_set_my_address(i->user, uival);
5680 +               break;
5681 +                       
5682 +       case SIOCIPMIGETADDR:
5683 +               uival = ipmi_get_my_address(i->user);
5684 +
5685 +               if (copy_to_user((void *) arg, &uival, sizeof(uival))) {
5686 +                       err = -EFAULT;
5687 +                       break;
5688 +               }
5689 +               err = 0;
5690 +               break;
5691 +                       
5692 +       case SIOCIPMISETTIMING:
5693 +       {
5694 +               struct ipmi_timing_parms parms;
5695 +
5696 +               if (copy_from_user(&parms, (void *) arg, sizeof(parms))) {
5697 +                       err = -EFAULT;
5698 +                       break;
5699 +               }
5700 +               
5701 +               i->default_retries = parms.retries;
5702 +               i->default_retry_time_ms = parms.retry_time_ms;
5703 +               err = 0;
5704 +               break;
5705 +       }
5706 +
5707 +       case SIOCIPMIGETTIMING:
5708 +       {
5709 +               struct ipmi_timing_parms parms;
5710 +
5711 +               parms.retries = i->default_retries;
5712 +               parms.retry_time_ms = i->default_retry_time_ms;
5713 +
5714 +               if (copy_to_user((void *) arg, &parms, sizeof(parms))) {
5715 +                       err = -EFAULT;
5716 +                       break;
5717 +               }
5718 +
5719 +               err = 0;
5720 +               break;
5721 +       }
5722 +
5723 +       default:
5724 +               err = dev_ioctl(cmd, (void *)arg);
5725 +               break;
5726 +       }
5727 +       
5728 +       return err;
5729 +}
5730 +
5731 +static int ipmi_recvmsg(struct socket *sock, struct msghdr *msg, int size,
5732 +                       int rflags, struct scm_cookie *scm)
5733 +{
5734 +       struct ipmi_sock     *i = to_ipmi_sock(sock->sk);
5735 +       long                 timeo;
5736 +       struct ipmi_recv_msg *rcvmsg;
5737 +       struct sockaddr_ipmi addr;
5738 +       char                 buf[IPMI_MAX_SOCK_MSG_LENGTH];
5739 +       struct ipmi_sock_msg *smsg = (struct ipmi_sock_msg *)buf; 
5740 +       int                  err;
5741 +       unsigned long        flags;
5742 +
5743 +       timeo = sock_rcvtimeo(sock->sk, rflags & MSG_DONTWAIT);
5744 +
5745 +       while (1) {
5746 +               spin_lock_irqsave(&i->lock, flags);
5747 +               if (!list_empty(&i->msg_list)) 
5748 +                       break;
5749 +               spin_unlock_irqrestore(&i->lock, flags);
5750 +               if (!timeo) {
5751 +                       return -EAGAIN;
5752 +               } else if (signal_pending (current)) {
5753 +                       dbg("Signal pending: %d", 1);
5754 +                       return -EINTR;
5755 +               }
5756 +                               
5757 +               timeo = ipmi_wait_for_queue(i, timeo);
5758 +       }
5759 +
5760 +       rcvmsg = list_entry(i->msg_list.next, struct ipmi_recv_msg, link);
5761 +       list_del(&rcvmsg->link);        
5762 +       spin_unlock_irqrestore(&i->lock, flags);
5763 +
5764 +       memcpy(&addr.ipmi_addr, &rcvmsg->addr, sizeof(addr.ipmi_addr));
5765 +       addr.if_num = i->addr.if_num;
5766 +       addr.sipmi_family = i->addr.sipmi_family;
5767 +       memcpy(msg->msg_name, &addr, sizeof(addr));
5768 +       msg->msg_namelen = (SOCKADDR_IPMI_OVERHEAD
5769 +                           + ipmi_addr_length(rcvmsg->addr.addr_type));
5770 +
5771 +       smsg->recv_type         = rcvmsg->recv_type;
5772 +       smsg->msgid             = rcvmsg->msgid;
5773 +       smsg->netfn             = rcvmsg->msg.netfn;
5774 +       smsg->cmd               = rcvmsg->msg.cmd;
5775 +       smsg->data_len          = rcvmsg->msg.data_len;
5776 +       memcpy(smsg->data, rcvmsg->msg.data, smsg->data_len);
5777 +       
5778 +       ipmi_free_recv_msg(rcvmsg);
5779 +       
5780 +       err = memcpy_toiovec(msg->msg_iov, (void *)smsg, 
5781 +                            sizeof(struct ipmi_sock_msg) + smsg->data_len);
5782 +       if (err) {
5783 +               dbg("Cannot copy data to user: %p", i->user);
5784 +               return err;
5785 +       }
5786 +       
5787 +       dbg("user=%p", i->user);
5788 +       dbg("addr_type=%x, channel=%x",
5789 +           addr.ipmi_addr.addr_type, addr.ipmi_addr.channel);
5790 +       dbg("netfn=%#02x, cmd=%#02x, data=%p, data_len=%x", 
5791 +           smsg->netfn, smsg->cmd, smsg->data, smsg->data_len);
5792 +
5793 +       return (sizeof(struct ipmi_sock_msg) + smsg->data_len);
5794 +}
5795 +
5796 +static int ipmi_sendmsg(struct socket *sock, struct msghdr *msg, int len,
5797 +                       struct scm_cookie *scm)
5798 +{
5799 +       struct ipmi_sock     *i = to_ipmi_sock(sock->sk);
5800 +       struct sockaddr_ipmi *addr = (struct sockaddr_ipmi *)msg->msg_name;
5801 +       struct ipmi_msg      imsg;
5802 +       unsigned char        buf[IPMI_MAX_SOCK_MSG_LENGTH];
5803 +       struct ipmi_sock_msg *smsg = (struct ipmi_sock_msg *)buf;
5804 +       int                  err;
5805 +       struct ipmi_timing_parms tparms;
5806 +       struct cmsghdr           *cmsg;
5807 +
5808 +       err = ipmi_validate_addr(&addr->ipmi_addr,
5809 +                                msg->msg_namelen - SOCKADDR_IPMI_OVERHEAD);
5810 +       if (err) {
5811 +               dbg("Invalid IPMI address: %p", i->user);
5812 +               goto err;
5813 +       }
5814 +       
5815 +       if (len > IPMI_MAX_SOCK_MSG_LENGTH) {
5816 +               err = -EINVAL;
5817 +               dbg("Message too long: %p", i->user);
5818 +               goto err;
5819 +       }
5820 +       
5821 +       if (len < sizeof(struct ipmi_sock_msg)) {
5822 +               err = -EINVAL;
5823 +               dbg("Msg data too small for header: %p", i->user);
5824 +               goto err;
5825 +       }
5826 +
5827 +       err = memcpy_fromiovec((void *)smsg, msg->msg_iov, len);
5828 +       if (err) {
5829 +               dbg("Cannot copy data to kernel: %p", i->user);
5830 +               goto err;
5831 +       }
5832 +       
5833 +       if (len < smsg->data_len+sizeof(struct ipmi_sock_msg)) {
5834 +               err = -EINVAL;
5835 +               dbg("Msg data is out of bound: %p", i->user);
5836 +               goto err;
5837 +       }
5838 +       
5839 +       /* Set defaults. */
5840 +       tparms.retries = i->default_retries;
5841 +       tparms.retry_time_ms = i->default_retry_time_ms;
5842 +
5843 +       for (cmsg=CMSG_FIRSTHDR(msg);
5844 +            cmsg;
5845 +            cmsg = CMSG_NXTHDR(msg, cmsg))
5846 +       {
5847 +               if (cmsg->cmsg_len < sizeof(struct cmsghdr)) {
5848 +                       err = -EINVAL;
5849 +                       dbg("cmsg length too short: %p", i->user);
5850 +                       goto err;
5851 +               }
5852 +
5853 +               if (cmsg->cmsg_level != SOL_SOCKET)
5854 +                       continue;
5855 +
5856 +               if (cmsg->cmsg_type == IPMI_CMSG_TIMING_PARMS) {
5857 +                       struct ipmi_timing_parms *pparms;
5858 +
5859 +                       if (cmsg->cmsg_len != CMSG_LEN(sizeof(*pparms))) {
5860 +                               err = -EINVAL;
5861 +                               dbg("timing parms cmsg not right size: %p",
5862 +                                   i->user);
5863 +                               goto err;
5864 +                       }
5865 +                       pparms = (struct ipmi_timing_parms *) CMSG_DATA(cmsg);
5866 +                       tparms.retries = pparms->retries;
5867 +                       tparms.retry_time_ms = pparms->retry_time_ms;
5868 +               }
5869 +       }
5870 +
5871 +       imsg.netfn      = smsg->netfn;
5872 +       imsg.cmd        = smsg->cmd;
5873 +       imsg.data       = smsg->data;
5874 +       imsg.data_len   = smsg->data_len;
5875 +
5876 +       dbg("user=%p", i->user);
5877 +       dbg("addr_type=%x, channel=%x",
5878 +           addr->ipmi_addr.addr_type, addr->ipmi_addr.channel);
5879 +       dbg("netfn=%#02x, cmd=%#02x, data=%p, data_len=%x", 
5880 +           imsg.netfn, imsg.cmd, imsg.data, imsg.data_len);
5881 +       err = ipmi_request_settime(i->user, &addr->ipmi_addr,
5882 +                                  smsg->msgid, &imsg, 0,
5883 +                                  tparms.retries, tparms.retry_time_ms);
5884 +       if (err) {
5885 +               dbg("Cannot send message: %p", i->user);
5886 +               goto err;
5887 +       }
5888 +       
5889 +err:
5890 +       return err;
5891 +}
5892 +
5893 +static struct proto_ops ipmi_ops = {
5894 +       .family =       PF_IPMI,
5895 +       .release =      ipmi_release,
5896 +       .bind =         ipmi_bind,
5897 +       .connect =      sock_no_connect,
5898 +       .socketpair =   sock_no_socketpair,
5899 +       .accept =       sock_no_accept,
5900 +       .getname =      ipmi_getname,
5901 +       .poll =         ipmi_poll,
5902 +       .ioctl =        ipmi_ioctl,
5903 +       .listen =       sock_no_listen,
5904 +       .shutdown =     sock_no_shutdown,
5905 +       .setsockopt =   sock_no_setsockopt,
5906 +       .getsockopt =   sock_no_getsockopt,
5907 +       .sendmsg =      ipmi_sendmsg,
5908 +       .recvmsg =      ipmi_recvmsg,
5909 +       .mmap =         sock_no_mmap,
5910 +       .sendpage =     sock_no_sendpage
5911 +};
5912 +
5913 +
5914 +static void ipmi_sock_destructor(struct sock *sk)
5915 +{
5916 +       skb_queue_purge(&sk->receive_queue);
5917 +
5918 +       BUG_TRAP(atomic_read(&sk->wmem_alloc) == 0);
5919 +       BUG_TRAP(sk->socket==NULL);
5920 +       if (sk->dead==0) {
5921 +               printk("Attempt to release alive ipmi socket: %p\n", sk);
5922 +               return;
5923 +       }
5924 +
5925 +       atomic_dec(&ipmi_nr_socks);
5926 +       MOD_DEC_USE_COUNT;
5927 +}
5928 +
5929 +/*
5930 + * net protocol functions
5931 + */
5932 +static struct sock *ipmi_socket_create1(struct socket *sock)
5933 +{
5934 +       struct sock *sk;
5935 +
5936 +       if (atomic_read(&ipmi_nr_socks) >= 2*files_stat.max_files)
5937 +               return NULL;
5938 +
5939 +       MOD_INC_USE_COUNT;
5940 +
5941 +       sk = sk_alloc(PF_IPMI, GFP_KERNEL, 1);
5942 +       if (!sk) {
5943 +               MOD_DEC_USE_COUNT;
5944 +               return NULL;
5945 +       }
5946 +       
5947 +       sock_init_data(sock, sk);
5948 +       sock->sk->rcvtimeo = 5*HZ;
5949 +       sock->sk->destruct = ipmi_sock_destructor;
5950 +       spin_lock_init(&sk->protinfo.af_ipmi.lock);
5951 +       INIT_LIST_HEAD(&sk->protinfo.af_ipmi.msg_list);
5952 +       init_waitqueue_head(&sk->protinfo.af_ipmi.wait);
5953 +
5954 +       /* Set to use default values. */
5955 +       sk->protinfo.af_ipmi.default_retries = -1;
5956 +       sk->protinfo.af_ipmi.default_retry_time_ms = 0;
5957 +
5958 +       atomic_inc(&ipmi_nr_socks);
5959 +       return sk;
5960 +}
5961 +
5962 +static int ipmi_socket_create(struct socket *sock, int protocol)
5963 +{
5964 +       if (!capable(CAP_NET_RAW))
5965 +               return -EPERM;
5966 +       if (protocol && protocol != PF_IPMI)
5967 +               return -EPROTONOSUPPORT;
5968 +
5969 +       sock->state = SS_UNCONNECTED;
5970 +
5971 +       switch (sock->type) {
5972 +       case SOCK_RAW:
5973 +               sock->type=SOCK_DGRAM;  
5974 +       case SOCK_DGRAM:
5975 +               sock->ops = &ipmi_ops;
5976 +               break;
5977 +       default:
5978 +               return -EPROTONOSUPPORT;
5979 +       }
5980 +       
5981 +       return ipmi_socket_create1(sock)? 0 : -ENOMEM;
5982 +}
5983 +
5984 +static struct net_proto_family ipmi_family_ops = {
5985 +       .family = PF_IPMI,
5986 +       .create = ipmi_socket_create,
5987 +};
5988 +
5989 +
5990 +/* 
5991 + * init/exit functions
5992 + */
5993 +static int __init ipmi_socket_init(void)
5994 +{
5995 +
5996 +       int err=0;
5997 +       
5998 +       printk(KERN_INFO "ipmi socket interface version "
5999 +              IPMI_SOCKINTF_VERSION "\n");
6000 +
6001 +       ipmi_sk_cachep = kmem_cache_create("ipmi_sock",
6002 +                                          sizeof(struct ipmi_sock), 0,
6003 +                                          SLAB_HWCACHE_ALIGN, 0, 0);
6004 +       if (!ipmi_sk_cachep) {
6005 +               printk(KERN_CRIT "%s: Unable to create ipmi_sock SLAB cache\n", __func__);
6006 +               err = -ENOMEM;
6007 +               goto out;
6008 +       }
6009 +       
6010 +       err = sock_register(&ipmi_family_ops);
6011 +       if (err)
6012 +               kmem_cache_destroy(ipmi_sk_cachep);
6013 +out:
6014 +       return err;
6015 +}
6016 +
6017 +static void __exit ipmi_socket_exit(void)
6018 +{
6019 +       sock_unregister(PF_IPMI);
6020 +       kmem_cache_destroy(ipmi_sk_cachep);
6021 +}
6022 +
6023 +#ifdef CONFIG_DEBUG_KERNEL
6024 +MODULE_PARM(debug, "i");
6025 +#endif
6026 +module_init(ipmi_socket_init);
6027 +module_exit(ipmi_socket_exit);
6028 +
6029 +MODULE_LICENSE("GPL");
6030 diff -urN linux-2.4.23.org/net/ipmi/Makefile linux-2.4.23/net/ipmi/Makefile
6031 --- linux-2.4.23.org/net/ipmi/Makefile  1970-01-01 01:00:00.000000000 +0100
6032 +++ linux-2.4.23/net/ipmi/Makefile      2003-12-06 17:46:43.353379477 +0100
6033 @@ -0,0 +1,7 @@
6034 +
6035 +O_TARGET = ipmi.o
6036 +
6037 +obj-$(CONFIG_IPMI_SOCKET) = af_ipmi.o
6038 +
6039 +include $(TOPDIR)/Rules.make
6040 +
6041 diff -urN linux-2.4.23.org/net/Makefile linux-2.4.23/net/Makefile
6042 --- linux-2.4.23.org/net/Makefile       2003-12-06 12:52:51.596043969 +0100
6043 +++ linux-2.4.23/net/Makefile   2003-12-06 17:48:04.493359735 +0100
6044 @@ -8,7 +8,7 @@
6045  O_TARGET :=    network.o
6046  
6047  mod-subdirs := ipv4/netfilter ipv6/netfilter bridge/netfilter ipx irda \
6048 -       bluetooth atm netlink sched core sctp
6049 +       bluetooth atm netlink sched core sctp ipmi
6050  export-objs := netsyms.o
6051  
6052  subdir-y :=    core ethernet
6053 @@ -47,6 +47,7 @@
6054  subdir-$(CONFIG_DECNET)                += decnet
6055  subdir-$(CONFIG_ECONET)                += econet
6056  subdir-$(CONFIG_VLAN_8021Q)           += 8021q
6057 +subdir-$(CONFIG_IPMI_SOCKET)   += ipmi
6058  
6059  ifeq ($(CONFIG_NETFILTER),y)
6060    mod-subdirs += ipv4/ipvs
This page took 0.48004 seconds and 3 git commands to generate.