]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.x-IBM-RAS-service-procesor-1of2-lkml.patch
- obsolete
[packages/kernel.git] / 2.6.x-IBM-RAS-service-procesor-1of2-lkml.patch
1 diff -urN linux-2.6.1/drivers/Kconfig linux-2.6.1-ibmasm/drivers/Kconfig
2 --- linux-2.6.1/drivers/Kconfig 2004-01-08 23:00:03.000000000 -0800
3 +++ linux-2.6.1-ibmasm/drivers/Kconfig  2004-01-14 13:21:36.000000000 -0800
4 @@ -38,7 +38,7 @@
5  
6  source "drivers/char/Kconfig"
7  
8 -# source "drivers/misc/Kconfig"
9 +source "drivers/misc/Kconfig"
10  
11  source "drivers/media/Kconfig"
12  
13 diff -urN linux-2.6.1/drivers/misc/ibmasm/command.c linux-2.6.1-ibmasm/drivers/misc/ibmasm/command.c
14 --- linux-2.6.1/drivers/misc/ibmasm/command.c   1969-12-31 16:00:00.000000000 -0800
15 +++ linux-2.6.1-ibmasm/drivers/misc/ibmasm/command.c    2004-01-22 11:57:28.000000000 -0800
16 @@ -0,0 +1,175 @@
17 +
18 +/*
19 + * IBM ASM Service Processor Device Driver
20 + *
21 + * This program is free software; you can redistribute it and/or modify
22 + * it under the terms of the GNU General Public License as published by
23 + * the Free Software Foundation; either version 2 of the License, or
24 + * (at your option) any later version.
25 + *
26 + * This program is distributed in the hope that it will be useful,
27 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29 + * GNU General Public License for more details.
30 + *
31 + * You should have received a copy of the GNU General Public License
32 + * along with this program; if not, write to the Free Software
33 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 + *
35 + * Copyright (C) IBM Corporation, 2004
36 + *
37 + * Author: Max Asböck <amax@us.ibm.com> 
38 + *
39 + */
40 +
41 +#include "ibmasm.h"
42 +
43 +static void exec_next_command(struct service_processor *sp);
44 +static void free_command(struct kobject *kobj);
45 +
46 +static struct kobj_type ibmasm_cmd_kobj_type = {
47 +       .release = free_command,
48 +};
49 +
50 +
51 +struct command *ibmasm_new_command(size_t buffer_size)
52 +{
53 +       struct command *cmd;
54 +
55 +       if (buffer_size > IBMASM_CMD_MAX_BUFFER_SIZE)
56 +               return NULL;
57 +
58 +       cmd = kmalloc(sizeof(struct command), GFP_KERNEL);
59 +       if (cmd == NULL)
60 +               return NULL;
61 +
62 +       memset(cmd, 0, sizeof(*cmd));
63 +
64 +       cmd->buffer = kmalloc(buffer_size, GFP_KERNEL);
65 +       if (cmd->buffer == NULL) {
66 +               kfree(cmd);
67 +               return NULL;
68 +       }
69 +       memset(cmd->buffer, 0, buffer_size);
70 +       cmd->buffer_size = buffer_size;
71 +
72 +       kobject_init(&cmd->kobj);
73 +       cmd->kobj.ktype = &ibmasm_cmd_kobj_type;
74 +
75 +       cmd->status = IBMASM_CMD_PENDING;
76 +       init_waitqueue_head(&cmd->wait);
77 +       INIT_LIST_HEAD(&cmd->queue_node);
78 +
79 +       return cmd;
80 +}
81 +
82 +static void free_command(struct kobject *kobj)
83 +{
84 +       struct command *cmd = to_command(kobj);
85
86 +       list_del(&cmd->queue_node);
87 +       kfree(cmd->buffer);
88 +       kfree(cmd);
89 +}
90 +
91 +static void enqueue_command(struct service_processor *sp, struct command *cmd)
92 +{
93 +       list_add_tail(&cmd->queue_node, &sp->command_queue);
94 +}
95 +
96 +static struct command *dequeue_command(struct service_processor *sp)
97 +{
98 +       struct command *cmd;
99 +       struct list_head *next;
100 +
101 +       if ( list_empty(&sp->command_queue) )
102 +               return NULL;
103 +
104 +       next = sp->command_queue.next;
105 +       list_del_init(next);
106 +       cmd = list_entry(next, struct command, queue_node);
107 +
108 +       return cmd;
109 +}
110 +
111 +static inline void do_exec_command(struct service_processor *sp)
112 +{
113 +       if ( ibmasm_send_i2o_message(sp) ) {
114 +               sp->current_command->status = IBMASM_CMD_FAILED;
115 +               exec_next_command(sp);
116 +       }
117 +}
118 +       
119 +/**
120 + * exec_command
121 + * send a command to a service processor
122 + * Commands are executed sequentially. One command (sp->current_command)
123 + * is sent to the service processor. Once the interrupt handler gets a
124 + * message of type command_response, the message is copied into
125 + * the current commands buffer, 
126 + */
127 +void ibmasm_exec_command(struct service_processor *sp, struct command *cmd)
128 +{
129 +       unsigned long flags;
130 +
131 +       spin_lock_irqsave(&sp->lock, flags);
132 +
133 +       if ( !sp->current_command ) {
134 +               command_get(cmd);
135 +               sp->current_command = cmd;
136 +               spin_unlock_irqrestore(&sp->lock, flags);
137 +
138 +               do_exec_command(sp);
139 +       } else {
140 +               enqueue_command(sp, cmd);
141 +               spin_unlock_irqrestore(&sp->lock, flags);
142 +       }
143 +}
144 +
145 +static void exec_next_command(struct service_processor *sp)
146 +{
147 +       unsigned long flags;
148 +
149 +       wake_up(&sp->current_command->wait);
150 +       command_put(sp->current_command);
151 +
152 +       spin_lock_irqsave(&sp->lock, flags);
153 +       sp->current_command = dequeue_command(sp);
154 +       if ( sp->current_command ) {
155 +               command_get(sp->current_command);
156 +               spin_unlock_irqrestore(&sp->lock, flags);
157 +               do_exec_command(sp);
158 +       } else {
159 +               spin_unlock_irqrestore(&sp->lock, flags);
160 +       }
161 +}
162 +
163 +/** 
164 + * Sleep until a command has failed or a response has been received
165 + * and the command status been updated by the interrupt handler.
166 + * (see receive_response).
167 + */
168 +void ibmasm_wait_for_response(struct command *cmd, int timeout)
169 +{
170 +       wait_event_interruptible_timeout(cmd->wait,
171 +                               cmd->status == IBMASM_CMD_COMPLETE ||
172 +                               cmd->status == IBMASM_CMD_FAILED,
173 +                               timeout * HZ);
174 +}
175 +
176 +/**
177 + * receive_command_response
178 + * called by the interrupt handler when a dot command of type command_response
179 + * was received.
180 + */
181 +void ibmasm_receive_command_response(struct service_processor *sp, void *response, size_t size)
182 +{
183 +       struct command *cmd = sp->current_command;
184 +
185 +       if (!sp->current_command) 
186 +               return; 
187 +
188 +       memcpy(cmd->buffer, response, min(size, cmd->buffer_size));
189 +       cmd->status = IBMASM_CMD_COMPLETE;
190 +       exec_next_command(sp);
191 +}
192 diff -urN linux-2.6.1/drivers/misc/ibmasm/dot_command.c linux-2.6.1-ibmasm/drivers/misc/ibmasm/dot_command.c
193 --- linux-2.6.1/drivers/misc/ibmasm/dot_command.c       1969-12-31 16:00:00.000000000 -0800
194 +++ linux-2.6.1-ibmasm/drivers/misc/ibmasm/dot_command.c        2004-01-22 11:10:20.000000000 -0800
195 @@ -0,0 +1,146 @@
196 +/*
197 + * IBM ASM Service Processor Device Driver
198 + *
199 + * This program is free software; you can redistribute it and/or modify
200 + * it under the terms of the GNU General Public License as published by
201 + * the Free Software Foundation; either version 2 of the License, or
202 + * (at your option) any later version.
203 + *
204 + * This program is distributed in the hope that it will be useful,
205 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
206 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
207 + * GNU General Public License for more details.
208 + *
209 + * You should have received a copy of the GNU General Public License
210 + * along with this program; if not, write to the Free Software
211 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
212 + *
213 + * Copyright (C) IBM Corporation, 2004
214 + *
215 + * Author: Max Asböck <amax@us.ibm.com> 
216 + *
217 + */
218 +
219 +#include "ibmasm.h"
220 +#include "dot_command.h"
221 +
222 +/**
223 + * Dispatch an incoming message to the specific handler for the message.
224 + * Called from interrupt context.
225 + */
226 +void ibmasm_receive_message(struct service_processor *sp, void *message, int message_size)
227 +{
228 +       u32 size;
229 +       struct dot_command_header *header = (struct dot_command_header *)message;
230 +
231 +       size = get_dot_command_size(message);
232 +       if (size > message_size)
233 +               size = message_size;
234 +
235 +       switch (header->type) {
236 +       case sp_event: 
237 +               ibmasm_receive_event(sp, message, size);
238 +               break;
239 +       case sp_command_response:
240 +               ibmasm_receive_command_response(sp, message, size); 
241 +               break;
242 +       case sp_heartbeat:
243 +               ibmasm_receive_heartbeat(sp, message, size);
244 +               break;
245 +       default:
246 +               dev_err(sp->dev, "Received unknown message from service processor\n");
247 +       }
248 +}
249 +
250 +
251 +#define INIT_BUFFER_SIZE 32
252 +
253 +
254 +/**
255 + * send the 4.3.5.10 dot command (driver VPD) to the service processor
256 + */
257 +int ibmasm_send_driver_vpd(struct service_processor *sp)
258 +{
259 +       struct command *command;
260 +       struct dot_command_header *header;
261 +       u8 *vpd_command;
262 +       u8 *vpd_data;
263 +       int result = 0;
264 +
265 +       command = ibmasm_new_command(INIT_BUFFER_SIZE);
266 +       if (command == NULL)
267 +               return -ENOMEM;
268 +
269 +       header = (struct dot_command_header *)command->buffer;
270 +       header->type                = sp_write;
271 +       header->command_size        = 4;
272 +       header->data_size           = 16;
273 +       header->status              = 0;
274 +       header->reserved            = 0;
275 +
276 +       vpd_command = command->buffer + sizeof(struct dot_command_header);
277 +       vpd_command[0] = 0x4;
278 +       vpd_command[1] = 0x3;
279 +       vpd_command[2] = 0x5;
280 +       vpd_command[3] = 0xa;
281 +
282 +       vpd_data = vpd_command + header->command_size;
283 +       vpd_data[0] = 0;
284 +       strcat(vpd_data, IBMASM_DRIVER_VPD);
285 +       vpd_data[10] = 0;
286 +       vpd_data[15] = 0;
287 +       
288 +       ibmasm_exec_command(sp, command);
289 +       ibmasm_wait_for_response(command, IBMASM_CMD_TIMEOUT_NORMAL);
290 +
291 +       if (command->status != IBMASM_CMD_COMPLETE)
292 +               result = -ENODEV;
293 +
294 +       command_put(command);
295 +
296 +       return result;
297 +}
298 +
299 +struct os_state_command {
300 +       struct dot_command_header       header;
301 +       unsigned char                   command[3];
302 +       unsigned char                   data;
303 +};
304 +
305 +/**
306 + * send the 4.3.6 dot command (os state) to the service processor
307 + * During driver init this function is called with os state "up".
308 + * This causes the service processor to start sending heartbeats the
309 + * driver.
310 + * During driver exit the function is called with os state "down", 
311 + * causing the service processor to stop the heartbeats.
312 + */
313 +int ibmasm_send_os_state(struct service_processor *sp, int os_state)
314 +{
315 +       struct command *cmd;
316 +       struct os_state_command *os_state_cmd;
317 +       int result = 0;
318 +
319 +       cmd = ibmasm_new_command(sizeof(struct os_state_command));
320 +       if (cmd == NULL)
321 +               return -ENOMEM;
322 +
323 +       os_state_cmd = (struct os_state_command *)cmd->buffer;
324 +       os_state_cmd->header.type               = sp_write;
325 +       os_state_cmd->header.command_size       = 3;
326 +       os_state_cmd->header.data_size          = 1;
327 +       os_state_cmd->header.status             = 0;
328 +       os_state_cmd->command[0]                = 4;
329 +       os_state_cmd->command[1]                = 3;
330 +       os_state_cmd->command[2]                = 6;
331 +       os_state_cmd->data                      = os_state;
332 +
333 +       ibmasm_exec_command(sp, cmd);
334 +       ibmasm_wait_for_response(cmd, IBMASM_CMD_TIMEOUT_NORMAL);
335 +
336 +       if (cmd->status != IBMASM_CMD_COMPLETE)
337 +               result = -ENODEV;
338 +
339 +       command_put(cmd);
340 +       return result;
341 +}
342 diff -urN linux-2.6.1/drivers/misc/ibmasm/dot_command.h linux-2.6.1-ibmasm/drivers/misc/ibmasm/dot_command.h
343 --- linux-2.6.1/drivers/misc/ibmasm/dot_command.h       1969-12-31 16:00:00.000000000 -0800
344 +++ linux-2.6.1-ibmasm/drivers/misc/ibmasm/dot_command.h        2004-01-23 15:40:55.000000000 -0800
345 @@ -0,0 +1,78 @@
346 +/*
347 + * IBM ASM Service Processor Device Driver
348 + *
349 + * This program is free software; you can redistribute it and/or modify
350 + * it under the terms of the GNU General Public License as published by
351 + * the Free Software Foundation; either version 2 of the License, or
352 + * (at your option) any later version.
353 + *
354 + * This program is distributed in the hope that it will be useful,
355 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
356 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
357 + * GNU General Public License for more details.
358 + *
359 + * You should have received a copy of the GNU General Public License
360 + * along with this program; if not, write to the Free Software
361 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
362 + *
363 + * Copyright (C) IBM Corporation, 2004
364 + *
365 + * Author: Max Asböck <amax@us.ibm.com> 
366 + *
367 + */
368 +
369 +#ifndef __DOT_COMMAND_H__
370 +#define __DOT_COMMAND_H__
371 +
372 +/*
373 + * dot commands are the protocol used to communicate with the service
374 + * processor.
375 + * They consist of header, a command of variable length and data of
376 + * variable length.
377 + */
378 +
379 +/* dot command types */
380 +#define sp_write               0
381 +#define sp_write_next          1
382 +#define sp_read                        2
383 +#define sp_read_next           3
384 +#define sp_command_response    4
385 +#define sp_event               5
386 +#define sp_heartbeat           6
387 +
388 +#pragma pack(1)
389 +struct dot_command_header {
390 +       u8      type;
391 +       u8      command_size;
392 +       u16     data_size;
393 +       u8      status;
394 +       u8      reserved;
395 +};
396 +#pragma pack()
397 +
398 +static inline size_t get_dot_command_size(void *buffer)
399 +{
400 +       struct dot_command_header *cmd = (struct dot_command_header *)buffer;
401 +       return sizeof(struct dot_command_header) + cmd->command_size + cmd->data_size;
402 +}
403 +
404 +static inline unsigned int get_dot_command_timeout(void *buffer)
405 +{
406 +       struct dot_command_header *header = (struct dot_command_header *)buffer;
407 +       unsigned char *cmd = buffer + sizeof(struct dot_command_header);
408 +
409 +       /* dot commands 6.3.1, 7.1 and 8.x need a longer timeout */
410 +
411 +       if (header->command_size == 3) {
412 +               if ( (cmd[0] == 6) && (cmd[1] == 3) && (cmd[2] == 1) )
413 +                       return IBMASM_CMD_TIMEOUT_EXTRA;
414 +       } else if (header->command_size == 2) {
415 +               if ( (cmd[0] == 7) && (cmd[1] == 1) )
416 +                       return IBMASM_CMD_TIMEOUT_EXTRA;
417 +               if (cmd[0] == 8)
418 +                       return IBMASM_CMD_TIMEOUT_EXTRA;
419 +       }
420 +       return IBMASM_CMD_TIMEOUT_NORMAL;
421 +}
422 +
423 +#endif /* __DOT_COMMAND_H__ */
424 diff -urN linux-2.6.1/drivers/misc/ibmasm/event.c linux-2.6.1-ibmasm/drivers/misc/ibmasm/event.c
425 --- linux-2.6.1/drivers/misc/ibmasm/event.c     1969-12-31 16:00:00.000000000 -0800
426 +++ linux-2.6.1-ibmasm/drivers/misc/ibmasm/event.c      2004-01-20 11:16:29.000000000 -0800
427 @@ -0,0 +1,172 @@
428 +
429 +/*
430 + * IBM ASM Service Processor Device Driver
431 + *
432 + * This program is free software; you can redistribute it and/or modify
433 + * it under the terms of the GNU General Public License as published by
434 + * the Free Software Foundation; either version 2 of the License, or
435 + * (at your option) any later version.
436 + *
437 + * This program is distributed in the hope that it will be useful,
438 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
439 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
440 + * GNU General Public License for more details.
441 + *
442 + * You should have received a copy of the GNU General Public License
443 + * along with this program; if not, write to the Free Software
444 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
445 + *
446 + * Copyright (C) IBM Corporation, 2004
447 + *
448 + * Author: Max Asböck <amax@us.ibm.com> 
449 + *
450 + */
451 +
452 +#include "ibmasm.h"
453 +
454 +/*
455 + * ASM service processor event handling routines.
456 + *
457 + * Events are signalled to the device drivers through interrupts.
458 + * They have the format of dot commands, with the type field set to
459 + * sp_event.
460 + * The driver does not interpret the events, it simply stores them in a
461 + * circular buffer.
462 + */
463 +
464 +
465 +static void wake_up_event_readers(struct service_processor *sp)
466 +{
467 +       struct event_reader *reader;
468 +       struct list_head *entry;
469 +
470 +       list_for_each(entry, &sp->event_buffer->readers) {
471 +               reader = list_entry(entry, struct event_reader, node);
472 +               wake_up_interruptible(&reader->wait);
473 +       }
474 +}
475 +
476 +/**
477 + * receive_event
478 + * Called by the interrupt handler when a dot command of type sp_event is
479 + * received.
480 + * Store the event in the circular event buffer, wake up any sleeping
481 + * event readers.
482 + * There is no reader marker in the buffer, therefore readers are
483 + * responsible for keeping up with the writer, or they will loose events.
484 + */ 
485 +void ibmasm_receive_event(struct service_processor *sp, void *data, size_t data_size)
486 +{
487 +       struct event_buffer *buffer = sp->event_buffer;
488 +       struct ibmasm_event *event;
489 +       unsigned long flags;
490 +
491 +       data_size = min(data_size, IBMASM_EVENT_MAX_SIZE);
492 +
493 +       spin_lock_irqsave(&sp->lock, flags);
494 +       /* copy the event into the next slot in the circular buffer */
495 +       event = &buffer->events[buffer->next_index];
496 +       memcpy(event->data, data, data_size);
497 +       event->data_size = data_size;
498 +       event->serial_number = buffer->next_serial_number;
499 +
500 +       /* advance indices in the buffer */
501 +       buffer->next_index = ++(buffer->next_index) % IBMASM_NUM_EVENTS;
502 +       buffer->next_serial_number++;
503 +       spin_unlock_irqrestore(&sp->lock, flags);
504 +
505 +       wake_up_event_readers(sp);
506 +}
507 +
508 +static inline int event_available(struct event_buffer *b, struct event_reader *r)
509 +{
510 +       return  (r->next_serial_number < b->next_serial_number);
511 +}
512 +
513 +/**
514 + * get_next_event
515 + * Called by event readers (initiated from user space through the file
516 + * system). 
517 + * Sleeps until a new event is available.
518 + */
519 +int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader)
520 +{
521 +       struct event_buffer *buffer = sp->event_buffer;
522 +       struct ibmasm_event *event;
523 +       unsigned int index;
524 +       unsigned long flags;
525 +
526 +       if ( wait_event_interruptible(reader->wait, event_available(buffer, reader)) )
527 +               return -ERESTARTSYS;
528 +
529 +       if (!event_available(buffer, reader))
530 +               return 0;
531 +
532 +       spin_lock_irqsave(&sp->lock, flags);
533 +
534 +       index = buffer->next_index;
535 +       event = &buffer->events[index];
536 +       while (event->serial_number < reader->next_serial_number) {
537 +               index = (index + 1) % IBMASM_NUM_EVENTS;
538 +               event = &buffer->events[index];
539 +       }
540 +       memcpy(reader->data, event->data, event->data_size);
541 +       reader->data_size = event->data_size;
542 +       reader->next_serial_number = event->serial_number + 1;
543 +
544 +       spin_unlock_irqrestore(&sp->lock, flags);
545 +
546 +       return event->data_size;
547 +}
548 +
549 +void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader)
550 +{
551 +       unsigned long flags;
552 +
553 +       reader->next_serial_number = sp->event_buffer->next_serial_number;
554 +       init_waitqueue_head(&reader->wait);
555 +       spin_lock_irqsave(&sp->lock, flags);
556 +       list_add(&reader->node, &sp->event_buffer->readers);
557 +       spin_unlock_irqrestore(&sp->lock, flags);
558 +}
559 +
560 +void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader)
561 +{
562 +       unsigned long flags;
563 +
564 +       wake_up_interruptible(&reader->wait);
565 +
566 +       spin_lock_irqsave(&sp->lock, flags);
567 +       list_del(&reader->node);
568 +       spin_unlock_irqrestore(&sp->lock, flags);
569 +}
570 +
571 +int ibmasm_event_buffer_init(struct service_processor *sp)
572 +{
573 +       struct event_buffer *buffer;
574 +       struct ibmasm_event *event;
575 +       int i;
576 +
577 +       buffer = kmalloc(sizeof(struct event_buffer), GFP_KERNEL);
578 +       if (!buffer)
579 +               return 1;
580 +
581 +       buffer->next_index = 0;
582 +       buffer->next_serial_number = 1;
583 +
584 +       event = buffer->events;
585 +       for (i=0; i<IBMASM_NUM_EVENTS; i++, event++)
586 +               event->serial_number = 0;
587 +
588 +       INIT_LIST_HEAD(&buffer->readers);
589 +
590 +       sp->event_buffer = buffer;
591 +
592 +       return 0;
593 +}
594 +
595 +void ibmasm_event_buffer_exit(struct service_processor *sp)
596 +{
597 +       wake_up_event_readers(sp);
598 +       kfree(sp->event_buffer);
599 +}
600 diff -urN linux-2.6.1/drivers/misc/ibmasm/heartbeat.c linux-2.6.1-ibmasm/drivers/misc/ibmasm/heartbeat.c
601 --- linux-2.6.1/drivers/misc/ibmasm/heartbeat.c 1969-12-31 16:00:00.000000000 -0800
602 +++ linux-2.6.1-ibmasm/drivers/misc/ibmasm/heartbeat.c  2004-01-22 11:09:09.000000000 -0800
603 @@ -0,0 +1,91 @@
604 +
605 +/*
606 + * IBM ASM Service Processor Device Driver
607 + *
608 + * This program is free software; you can redistribute it and/or modify
609 + * it under the terms of the GNU General Public License as published by
610 + * the Free Software Foundation; either version 2 of the License, or
611 + * (at your option) any later version.
612 + *
613 + * This program is distributed in the hope that it will be useful,
614 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
615 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
616 + * GNU General Public License for more details.
617 + *
618 + * You should have received a copy of the GNU General Public License
619 + * along with this program; if not, write to the Free Software
620 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
621 + *
622 + * Copyright (C) IBM Corporation, 2004
623 + *
624 + * Author: Max Asböck <amax@us.ibm.com> 
625 + *
626 + */
627 +
628 +#include <linux/notifier.h>
629 +#include "ibmasm.h"
630 +#include "dot_command.h"
631 +
632 +static int suspend_heartbeats = 0;
633 +
634 +/*
635 + * Once the driver indicates to the service processor that it is running
636 + * - see send_os_state() - the service processor sends periodic heartbeats
637 + * to the driver. The driver must respond to the heartbeats or else the OS
638 + * will be rebooted.
639 + * In the case of a panic the interrupt handler continues to work and thus
640 + * continues to respond to heartbeats, making the service processor believe
641 + * the OS is still running and thus preventing a reboot.
642 + * To prevent this from happening a callback is added the panic_notifier_list.
643 + * Before responding to a heartbeat the driver checks if a panic has happened,
644 + * if yes it suspends heartbeat, causing the service processor to reboot as
645 + * expected.
646 + */
647 +static int panic_happened(struct notifier_block *n, unsigned long val, void *v)
648 +{
649 +       suspend_heartbeats = 1;
650 +       return 0;
651 +}
652 +
653 +static struct notifier_block panic_notifier = { panic_happened, NULL, 1 };
654 +
655 +void ibmasm_register_panic_notifier(void)
656 +{
657 +       notifier_chain_register(&panic_notifier_list, &panic_notifier);
658 +}
659 +
660 +void ibmasm_unregister_panic_notifier(void)
661 +{
662 +       notifier_chain_unregister(&panic_notifier_list, &panic_notifier);
663 +}
664 +
665 +
666 +int ibmasm_heartbeat_init(struct service_processor *sp)
667 +{
668 +       sp->heartbeat = ibmasm_new_command(HEARTBEAT_BUFFER_SIZE);
669 +       if (sp->heartbeat == NULL)
670 +               return -ENOMEM;
671 +
672 +       return 0;
673 +}
674 +
675 +void ibmasm_heartbeat_exit(struct service_processor *sp)
676 +{
677 +       command_put(sp->heartbeat);
678 +}
679 +
680 +void ibmasm_receive_heartbeat(struct service_processor *sp,  void *message, size_t size)
681 +{
682 +       struct command *cmd = sp->heartbeat;
683 +       struct dot_command_header *header = (struct dot_command_header *)cmd->buffer;
684 +
685 +       if (suspend_heartbeats)
686 +               return;
687 +
688 +       /* return the received dot command to sender */
689 +       cmd->status = IBMASM_CMD_PENDING;
690 +       size = min(size, cmd->buffer_size);
691 +       memcpy(cmd->buffer, message, size);
692 +       header->type = sp_write;
693 +       ibmasm_exec_command(sp, cmd);
694 +}
695 diff -urN linux-2.6.1/drivers/misc/ibmasm/i2o.h linux-2.6.1-ibmasm/drivers/misc/ibmasm/i2o.h
696 --- linux-2.6.1/drivers/misc/ibmasm/i2o.h       1969-12-31 16:00:00.000000000 -0800
697 +++ linux-2.6.1-ibmasm/drivers/misc/ibmasm/i2o.h        2004-01-23 15:41:15.000000000 -0800
698 @@ -0,0 +1,77 @@
699 +/*
700 + * IBM ASM Service Processor Device Driver
701 + *
702 + * This program is free software; you can redistribute it and/or modify
703 + * it under the terms of the GNU General Public License as published by
704 + * the Free Software Foundation; either version 2 of the License, or
705 + * (at your option) any later version.
706 + *
707 + * This program is distributed in the hope that it will be useful,
708 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
709 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
710 + * GNU General Public License for more details.
711 + *
712 + * You should have received a copy of the GNU General Public License
713 + * along with this program; if not, write to the Free Software
714 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
715 + *
716 + * Copyright (C) IBM Corporation, 2004
717 + *
718 + * Author: Max Asböck <amax@us.ibm.com> 
719 + *
720 + */
721 +
722 +#pragma pack(1)
723 +struct i2o_header {
724 +       u8      version;
725 +       u8      message_flags;
726 +       u16     message_size;
727 +       u8      target;           
728 +       u8      initiator_and_target;
729 +       u8      initiator;        
730 +       u8      function;
731 +       u32     initiator_context;
732 +};
733 +#pragma pack()
734 +
735 +#define I2O_HEADER_TEMPLATE \
736 +      { .version              = 0x01, \
737 +       .message_flags        = 0x00, \
738 +       .function             = 0xFF, \
739 +       .initiator            = 0x00, \
740 +       .initiator_and_target = 0x40, \
741 +       .target               = 0x00, \
742 +       .initiator_context    = 0x0 }
743 +
744 +#define I2O_MESSAGE_SIZE       0x1000
745 +#define I2O_COMMAND_SIZE       (I2O_MESSAGE_SIZE - sizeof(struct i2o_header))
746 +
747 +#pragma pack(1)
748 +struct i2o_message {
749 +       struct i2o_header       header;
750 +       void                    *data;
751 +};
752 +#pragma pack()
753 +
754 +static inline unsigned short outgoing_message_size(unsigned int data_size)
755 +{
756 +       unsigned int size;
757 +       unsigned short i2o_size;
758 +
759 +       if (data_size > I2O_COMMAND_SIZE)
760 +               data_size = I2O_COMMAND_SIZE;
761 +
762 +       size = sizeof(struct i2o_header) + data_size;
763 +
764 +       i2o_size = size / sizeof(u32);
765 +       
766 +       if (size % sizeof(u32))
767 +              i2o_size++;
768 +
769 +       return i2o_size;
770 +}      
771 +
772 +static inline u32 incoming_data_size(struct i2o_message *i2o_message)
773 +{
774 +       return (sizeof(u32) * i2o_message->header.message_size);
775 +}
776 diff -urN linux-2.6.1/drivers/misc/ibmasm/ibmasm.h linux-2.6.1-ibmasm/drivers/misc/ibmasm/ibmasm.h
777 --- linux-2.6.1/drivers/misc/ibmasm/ibmasm.h    1969-12-31 16:00:00.000000000 -0800
778 +++ linux-2.6.1-ibmasm/drivers/misc/ibmasm/ibmasm.h     2004-01-26 10:05:25.000000000 -0800
779 @@ -0,0 +1,227 @@
780 +
781 +/*
782 + * IBM ASM Service Processor Device Driver
783 + *
784 + * This program is free software; you can redistribute it and/or modify
785 + * it under the terms of the GNU General Public License as published by
786 + * the Free Software Foundation; either version 2 of the License, or
787 + * (at your option) any later version.
788 + *
789 + * This program is distributed in the hope that it will be useful,
790 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
791 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
792 + * GNU General Public License for more details.
793 + *
794 + * You should have received a copy of the GNU General Public License
795 + * along with this program; if not, write to the Free Software
796 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
797 + *
798 + * Copyright (C) IBM Corporation, 2004
799 + *
800 + * Author: Max Asböck <amax@us.ibm.com> 
801 + *
802 + */
803 +
804 +#include <linux/kernel.h>
805 +#include <linux/types.h>
806 +#include <linux/errno.h>
807 +#include <linux/list.h>
808 +#include <linux/wait.h>
809 +#include <linux/spinlock.h>
810 +#include <linux/slab.h>
811 +#include <linux/config.h>
812 +#include <linux/module.h>
813 +#include <linux/version.h>
814 +#include <linux/interrupt.h>
815 +#include <linux/device.h>
816 +
817 +/* Driver identification */
818 +#define DRIVER_NAME    "ibmasm"
819 +#define DRIVER_VERSION  "0.3"
820 +#define DRIVER_AUTHOR   "Max Asbock"
821 +#define DRIVER_DESC     "IBM ASM Service Processor Driver"
822 +
823 +#define err(msg) printk(KERN_ERR "%s: " msg "\n", DRIVER_NAME)
824 +#define info(msg) printk(KERN_INFO "%s: " msg "\n", DRIVER_NAME)
825 +
826 +
827 +#define IBMASM_CMD_PENDING     0       
828 +#define IBMASM_CMD_COMPLETE    1       
829 +#define IBMASM_CMD_FAILED      2
830 +
831 +#define IBMASM_CMD_TIMEOUT_NORMAL      45
832 +#define IBMASM_CMD_TIMEOUT_EXTRA       240
833 +
834 +#define IBMASM_CMD_MAX_BUFFER_SIZE     0x4000
835 +
836 +#define REVERSE_HEARTBEAT_TIMEOUT      120
837 +
838 +#define HEARTBEAT_BUFFER_SIZE          0x400
839 +
840 +#ifdef IA64
841 +#define IBMASM_DRIVER_VPD "Lin64 6.08      "
842 +#else
843 +#define IBMASM_DRIVER_VPD "Lin32 6.08      "
844 +#endif
845 +
846 +#define SYSTEM_STATE_OS_UP      5
847 +#define SYSTEM_STATE_OS_DOWN    4
848 +
849 +#define IBMASM_IOCTL_MAGIC     'f'
850 +#define IBMASM_IO_CANCEL       _IO(IBMASM_IOCTL_MAGIC, 0)
851 +
852 +#define IBMASM_NAME_SIZE       16
853 +
854 +#define IBMASM_NUM_EVENTS      10
855 +#define IBMASM_EVENT_MAX_SIZE  2048u
856 +
857 +
858 +struct command {
859 +       struct list_head        queue_node;
860 +       wait_queue_head_t       wait;
861 +       unsigned char           *buffer;
862 +       size_t                  buffer_size;
863 +       int                     status;
864 +       struct kobject          kobj;
865 +};
866 +#define to_command(c) container_of(c, struct command, kobj)
867 +
868 +static inline void command_put(struct command *cmd)
869 +{
870 +        kobject_put(&cmd->kobj);
871 +}
872 +
873 +static inline void command_get(struct command *cmd)
874 +{
875 +        kobject_get(&cmd->kobj);
876 +}
877 +
878 +
879 +struct ibmasm_event {
880 +       unsigned int    serial_number;
881 +       unsigned int    data_size;
882 +       unsigned char   data[IBMASM_EVENT_MAX_SIZE];
883 +};
884 +
885 +struct event_buffer {
886 +       struct ibmasm_event     events[IBMASM_NUM_EVENTS];
887 +       unsigned int            next_serial_number;
888 +       unsigned int            next_index;
889 +       struct list_head        readers;
890 +};
891 +
892 +struct event_reader {
893 +       unsigned int            next_serial_number;
894 +       wait_queue_head_t       wait;
895 +       struct list_head        node;
896 +       unsigned int            data_size;
897 +       unsigned char           data[IBMASM_EVENT_MAX_SIZE];
898 +};
899 +
900 +struct reverse_heartbeat {
901 +       wait_queue_head_t       wait;
902 +       unsigned int            stopped;
903 +};
904 +
905 +
906 +/* remote console events */
907 +struct mouse_event {
908 +       long            x;
909 +       long            y;
910 +       unsigned char   buttons;
911 +       unsigned char   transitions;
912 +};
913 +
914 +struct keyboard_event {
915 +       unsigned long   key_code;
916 +       unsigned char   key_down;
917 +};
918 +
919 +struct remote_event {
920 +       unsigned long   type;
921 +       union {
922 +               struct mouse_event      mouse;
923 +               struct keyboard_event   keyboard;
924 +       } data;
925 +};
926 +
927 +#define DRIVER_REMOTE_QUEUE_SIZE 240
928 +
929 +struct remote_queue {
930 +       struct remote_event     *start;
931 +       struct remote_event     *end;
932 +       struct remote_event     *reader;
933 +       struct remote_event     *writer;
934 +       unsigned int            size;
935 +       int                     open;
936 +       wait_queue_head_t       wait;
937 +};
938 +
939 +
940 +struct service_processor {
941 +       struct list_head        node;
942 +       spinlock_t              lock;
943 +       void                    *base_address;
944 +       unsigned int            irq;
945 +       struct command          *current_command;
946 +       struct command          *heartbeat;
947 +       struct list_head        command_queue;
948 +       struct event_buffer     *event_buffer;
949 +       char                    dirname[IBMASM_NAME_SIZE];
950 +       char                    devname[IBMASM_NAME_SIZE];
951 +       unsigned int            number;
952 +       struct remote_queue     remote_queue;
953 +       int                     serial_line;
954 +       struct device           *dev;
955 +};
956 +
957 +/* command processing */
958 +extern struct command *ibmasm_new_command(size_t buffer_size);
959 +extern void ibmasm_exec_command(struct service_processor *sp, struct command *cmd);
960 +extern void ibmasm_wait_for_response(struct command *cmd, int timeout);
961 +extern void ibmasm_receive_command_response(struct service_processor *sp, void *response,  size_t size);
962 +
963 +/* event processing */
964 +extern int ibmasm_event_buffer_init(struct service_processor *sp);
965 +extern void ibmasm_event_buffer_exit(struct service_processor *sp);
966 +extern void ibmasm_receive_event(struct service_processor *sp, void *data,  size_t data_size);
967 +extern void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader);
968 +extern void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader);
969 +extern int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader);
970 +
971 +/* heartbeat - from SP to OS */
972 +extern void ibmasm_register_panic_notifier(void);
973 +extern void ibmasm_unregister_panic_notifier(void);
974 +extern int ibmasm_heartbeat_init(struct service_processor *sp);
975 +extern void ibmasm_heartbeat_exit(struct service_processor *sp);
976 +extern void ibmasm_receive_heartbeat(struct service_processor *sp,  void *message, size_t size);
977 +
978 +/* reverse heartbeat - from OS to SP */
979 +extern void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);
980 +extern int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);
981 +extern void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb);
982 +
983 +/* dot commands */
984 +extern void ibmasm_receive_message(struct service_processor *sp, void *data, int data_size);
985 +extern int ibmasm_send_driver_vpd(struct service_processor *sp);
986 +extern int ibmasm_send_os_state(struct service_processor *sp, int os_state);
987 +
988 +/* low level message processing */
989 +extern int ibmasm_send_i2o_message(struct service_processor *sp);
990 +extern irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id, struct pt_regs *regs);
991 +
992 +/* remote console */
993 +extern void ibmasm_handle_mouse_interrupt(struct service_processor *sp);
994 +extern int ibmasm_init_remote_queue(struct service_processor *sp);
995 +extern void ibmasm_free_remote_queue(struct service_processor *sp);
996 +extern void ibmasm_advance_reader(struct remote_queue *q, unsigned int n);
997 +extern size_t ibmasm_events_available(struct remote_queue *q);
998 +
999 +/* file system */
1000 +extern int ibmasmfs_register(void);
1001 +extern void ibmasmfs_unregister(void);
1002 +extern void ibmasmfs_add_sp(struct service_processor *sp);
1003 +
1004 +/* uart */
1005 +extern void ibmasm_register_uart(struct service_processor *sp);
1006 +extern void ibmasm_unregister_uart(struct service_processor *sp);
1007 diff -urN linux-2.6.1/drivers/misc/ibmasm/lowlevel.c linux-2.6.1-ibmasm/drivers/misc/ibmasm/lowlevel.c
1008 --- linux-2.6.1/drivers/misc/ibmasm/lowlevel.c  1969-12-31 16:00:00.000000000 -0800
1009 +++ linux-2.6.1-ibmasm/drivers/misc/ibmasm/lowlevel.c   2004-01-14 16:41:31.000000000 -0800
1010 @@ -0,0 +1,81 @@
1011 +/*
1012 + * IBM ASM Service Processor Device Driver
1013 + *
1014 + * This program is free software; you can redistribute it and/or modify
1015 + * it under the terms of the GNU General Public License as published by
1016 + * the Free Software Foundation; either version 2 of the License, or
1017 + * (at your option) any later version.
1018 + *
1019 + * This program is distributed in the hope that it will be useful,
1020 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1021 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1022 + * GNU General Public License for more details.
1023 + *
1024 + * You should have received a copy of the GNU General Public License
1025 + * along with this program; if not, write to the Free Software
1026 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1027 + *
1028 + * Copyright (C) IBM Corporation, 2004
1029 + *
1030 + * Author: Max Asböck <amax@us.ibm.com> 
1031 + *
1032 + */
1033 +
1034 +#include "ibmasm.h"
1035 +#include "lowlevel.h"
1036 +#include "i2o.h"
1037 +#include "dot_command.h"
1038 +#include "remote.h"
1039 +
1040 +static struct i2o_header header = I2O_HEADER_TEMPLATE;
1041 +
1042 +
1043 +int ibmasm_send_i2o_message(struct service_processor *sp)
1044 +{
1045 +       u32 mfa;
1046 +       unsigned int command_size;
1047 +       struct i2o_message *message;
1048 +       struct command *command = sp->current_command;
1049 +
1050 +       mfa = get_mfa_inbound(sp->base_address);
1051 +       if ( !mfa )
1052 +               return 1;
1053 +
1054 +       command_size = get_dot_command_size(command->buffer);
1055 +       header.message_size = outgoing_message_size(command_size);
1056 +
1057 +       message = get_i2o_message(sp->base_address, mfa);
1058 +
1059 +       memcpy(&message->header, &header, sizeof(struct i2o_header));
1060 +       memcpy(&message->data, command->buffer, command_size);
1061 +
1062 +       set_mfa_inbound(sp->base_address, mfa);
1063 +
1064 +       return 0;
1065 +}
1066 +
1067 +irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id, struct pt_regs *regs)
1068 +{
1069 +       u32     mfa;
1070 +       struct service_processor *sp = (struct service_processor *)dev_id;
1071 +       void *base_address = sp->base_address;
1072 +
1073 +       if (!sp_interrupt_pending(base_address))
1074 +               return IRQ_NONE;
1075 +
1076 +       if ( mouse_interrupt_pending(sp) ) {
1077 +               ibmasm_handle_mouse_interrupt(sp);
1078 +               mfa = get_mfa_outbound(base_address);
1079 +               clear_mouse_interrupt(sp);
1080 +               set_mfa_outbound(base_address, mfa);
1081 +               return IRQ_HANDLED;
1082 +       }
1083 +
1084 +       mfa = get_mfa_outbound(base_address);
1085 +       if ( valid_mfa(mfa) ) {
1086 +               struct i2o_message *msg = get_i2o_message(base_address, mfa);
1087 +               ibmasm_receive_message(sp, &msg->data, incoming_data_size(msg));
1088 +       }
1089 +       set_mfa_outbound(base_address, mfa);
1090 +       return IRQ_HANDLED;
1091 +}
1092 diff -urN linux-2.6.1/drivers/misc/ibmasm/lowlevel.h linux-2.6.1-ibmasm/drivers/misc/ibmasm/lowlevel.h
1093 --- linux-2.6.1/drivers/misc/ibmasm/lowlevel.h  1969-12-31 16:00:00.000000000 -0800
1094 +++ linux-2.6.1-ibmasm/drivers/misc/ibmasm/lowlevel.h   2004-01-14 16:41:42.000000000 -0800
1095 @@ -0,0 +1,137 @@
1096 +/*
1097 + * IBM ASM Service Processor Device Driver
1098 + *
1099 + * This program is free software; you can redistribute it and/or modify
1100 + * it under the terms of the GNU General Public License as published by
1101 + * the Free Software Foundation; either version 2 of the License, or
1102 + * (at your option) any later version.
1103 + *
1104 + * This program is distributed in the hope that it will be useful,
1105 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1106 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1107 + * GNU General Public License for more details.
1108 + *
1109 + * You should have received a copy of the GNU General Public License
1110 + * along with this program; if not, write to the Free Software
1111 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1112 + *
1113 + * Copyright (C) IBM Corporation, 2004
1114 + *
1115 + * Author: Max Asböck <amax@us.ibm.com> 
1116 + *
1117 + */
1118 +
1119 +/* Condor service processor specific hardware definitions */
1120 +
1121 +#ifndef __IBMASM_CONDOR_H__
1122 +#define __IBMASM_CONDOR_H__
1123 +
1124 +#include <asm/io.h>
1125 +
1126 +#define VENDORID_IBM   0x1014
1127 +#define DEVICEID_RSA   0x010F
1128 +
1129 +#define GET_MFA_ADDR(x)  (x & 0xFFFFFF00)
1130 +
1131 +#define MAILBOX_FULL(x)  (x & 0x00000001)
1132 +
1133 +#define NO_MFAS_AVAILABLE     0xFFFFFFFF
1134 +
1135 +
1136 +#define INBOUND_QUEUE_PORT   0x40  /* contains address of next free MFA */
1137 +#define OUTBOUND_QUEUE_PORT  0x44  /* contains address of posted MFA    */
1138 +
1139 +#define SP_INTR_MASK   0x00000008
1140 +#define UART_INTR_MASK 0x00000010
1141 +
1142 +#define INTR_STATUS_REGISTER   0x13A0
1143 +#define INTR_CONTROL_REGISTER  0x13A4
1144 +
1145 +#define SCOUT_COM_A_BASE         0x0000
1146 +#define SCOUT_COM_B_BASE         0x0100   
1147 +#define SCOUT_COM_C_BASE         0x0200   
1148 +#define SCOUT_COM_D_BASE         0x0300   
1149 +
1150 +static inline int sp_interrupt_pending(void *base_address)
1151 +{
1152 +       return SP_INTR_MASK & readl(base_address + INTR_STATUS_REGISTER);
1153 +}
1154 +
1155 +static inline int uart_interrupt_pending(void *base_address)
1156 +{
1157 +       return UART_INTR_MASK & readl(base_address + INTR_STATUS_REGISTER);
1158 +}
1159 +
1160 +static inline void ibmasm_enable_interrupts(void *base_address, int mask)
1161 +{
1162 +       void *ctrl_reg = base_address + INTR_CONTROL_REGISTER;
1163 +       writel( readl(ctrl_reg) & ~mask, ctrl_reg);
1164 +}
1165 +
1166 +static inline void ibmasm_disable_interrupts(void *base_address, int mask)
1167 +{
1168 +       void *ctrl_reg = base_address + INTR_CONTROL_REGISTER;
1169 +       writel( readl(ctrl_reg) | mask, ctrl_reg);
1170 +}
1171 +
1172 +static inline void enable_sp_interrupts(void *base_address)
1173 +{
1174 +       ibmasm_enable_interrupts(base_address, SP_INTR_MASK);
1175 +}
1176 +
1177 +static inline void disable_sp_interrupts(void *base_address)
1178 +{
1179 +       ibmasm_disable_interrupts(base_address, SP_INTR_MASK);
1180 +}
1181 +
1182 +static inline void enable_uart_interrupts(void *base_address)
1183 +{
1184 +       ibmasm_enable_interrupts(base_address, UART_INTR_MASK); 
1185 +}
1186 +
1187 +static inline void disable_uart_interrupts(void *base_address)
1188 +{
1189 +       ibmasm_disable_interrupts(base_address, UART_INTR_MASK); 
1190 +}
1191 +
1192 +#define valid_mfa(mfa) ( (mfa) != NO_MFAS_AVAILABLE )
1193 +
1194 +static inline u32 get_mfa_outbound(void *base_address)
1195 +{
1196 +       int retry;
1197 +       u32 mfa;
1198 +
1199 +       for (retry=0; retry<=10; retry++) {
1200 +               mfa = readl(base_address + OUTBOUND_QUEUE_PORT);
1201 +               if ( valid_mfa(mfa) )
1202 +                       break;
1203 +       }
1204 +       return mfa;
1205 +}
1206 +
1207 +static inline void set_mfa_outbound(void *base_address, u32 mfa)
1208 +{
1209 +       writel(mfa, base_address + OUTBOUND_QUEUE_PORT);
1210 +}
1211 +
1212 +static inline u32 get_mfa_inbound(void *base_address)
1213 +{
1214 +       u32 mfa = readl(base_address + INBOUND_QUEUE_PORT);
1215 +
1216 +       if ( MAILBOX_FULL(mfa) )
1217 +               return 0;
1218 +
1219 +       return mfa;
1220 +}
1221 +
1222 +static inline void set_mfa_inbound(void *base_address, u32 mfa)
1223 +{
1224 +       writel(mfa, base_address + INBOUND_QUEUE_PORT);
1225 +}
1226 +
1227 +static inline struct i2o_message *get_i2o_message(void *base_address, u32 mfa)
1228 +{
1229 +       return (struct i2o_message *)(GET_MFA_ADDR(mfa) + base_address);
1230 +}
1231 +
1232 +#endif /* __IBMASM_CONDOR_H__ */
1233 diff -urN linux-2.6.1/drivers/misc/ibmasm/Makefile linux-2.6.1-ibmasm/drivers/misc/ibmasm/Makefile
1234 --- linux-2.6.1/drivers/misc/ibmasm/Makefile    1969-12-31 16:00:00.000000000 -0800
1235 +++ linux-2.6.1-ibmasm/drivers/misc/ibmasm/Makefile     2004-01-14 14:50:21.000000000 -0800
1236 @@ -0,0 +1,13 @@
1237 +
1238 +obj-$(CONFIG_IBM_ASM) := ibmasm.o
1239 +
1240 +ibmasm-objs := module.o      \
1241 +               ibmasmfs.o    \
1242 +               event.o       \
1243 +               command.o     \
1244 +               remote.o      \
1245 +               heartbeat.o   \
1246 +               r_heartbeat.o \
1247 +               dot_command.o \
1248 +               lowlevel.o    \
1249 +               uart.o
1250 diff -urN linux-2.6.1/drivers/misc/ibmasm/module.c linux-2.6.1-ibmasm/drivers/misc/ibmasm/module.c
1251 --- linux-2.6.1/drivers/misc/ibmasm/module.c    1969-12-31 16:00:00.000000000 -0800
1252 +++ linux-2.6.1-ibmasm/drivers/misc/ibmasm/module.c     2004-01-20 13:05:38.000000000 -0800
1253 @@ -0,0 +1,212 @@
1254 +
1255 +/*
1256 + * IBM ASM Service Processor Device Driver
1257 + *
1258 + * This program is free software; you can redistribute it and/or modify
1259 + * it under the terms of the GNU General Public License as published by
1260 + * the Free Software Foundation; either version 2 of the License, or
1261 + * (at your option) any later version.
1262 + *
1263 + * This program is distributed in the hope that it will be useful,
1264 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1265 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1266 + * GNU General Public License for more details.
1267 + *
1268 + * You should have received a copy of the GNU General Public License
1269 + * along with this program; if not, write to the Free Software
1270 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1271 + *
1272 + * Copyright (C) IBM Corporation, 2004
1273 + *
1274 + * Author: Max Asböck <amax@us.ibm.com> 
1275 + *
1276 + * This driver is based on code originally written by Pete Reynolds 
1277 + * and others.
1278 + *
1279 + */
1280 +
1281 +/*
1282 + * The ASM device driver does the following things:
1283 + *
1284 + * 1) When loaded it sends a message to the service processor,
1285 + * indicating that an OS is * running. This causes the service processor
1286 + * to send periodic heartbeats to the OS. 
1287 + *
1288 + * 2) Answers the periodic heartbeats sent by the service processor.
1289 + * Failure to do so would result in system reboot.
1290 + *
1291 + * 3) Acts as a pass through for dot commands sent from user applications.
1292 + * The interface for this is the ibmasmfs file system. 
1293 + *
1294 + * 4) Allows user applications to register for event notification. Events
1295 + * are sent to the driver through interrupts. They can be read from user
1296 + * space through the ibmasmfs file system.
1297 + *
1298 + * 5) Allows user space applications to send heartbeats to the service
1299 + * processor (aka reverse heartbeats). Again this happens through ibmasmfs.
1300 + *
1301 + * 6) Handles remote mouse and keyboard event interrupts and makes them
1302 + * available to user applications through ibmasmfs.
1303 + *
1304 + */
1305 +
1306 +#include <linux/pci.h>
1307 +#include <linux/init.h>
1308 +#include "ibmasm.h"
1309 +#include "lowlevel.h"
1310 +#include "remote.h"
1311 +
1312 +
1313 +static int __init ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
1314 +{
1315 +       int result = 0;
1316 +       struct service_processor *sp;
1317 +
1318 +       sp = kmalloc(sizeof(struct service_processor), GFP_KERNEL);
1319 +       if (sp == NULL) {
1320 +               dev_err(&pdev->dev, "Failed to allocate memory\n");
1321 +               return -ENOMEM;
1322 +       }
1323 +       memset(sp, 0, sizeof(struct service_processor));
1324 +
1325 +       pci_set_drvdata(pdev, (void *)sp);
1326 +       sp->dev = &pdev->dev;
1327 +       sp->number = pdev->bus->number;
1328 +       snprintf(sp->dirname, IBMASM_NAME_SIZE, "%d", sp->number);
1329 +       snprintf(sp->devname, IBMASM_NAME_SIZE, "%s%d", DRIVER_NAME, sp->number);
1330 +
1331 +       if (ibmasm_event_buffer_init(sp)) {
1332 +               dev_err(sp->dev, "Failed to allocate event buffer\n");
1333 +               result =  -ENOMEM;
1334 +               goto error_eventbuffer;
1335 +       }
1336 +
1337 +       if (ibmasm_heartbeat_init(sp)) {
1338 +               dev_err(sp->dev, "Failed to allocate heartbeat command\n");
1339 +               result =  -ENOMEM;
1340 +               goto error_heartbeat;
1341 +       }
1342 +
1343 +       sp->irq = pdev->irq;
1344 +       sp->base_address = ioremap(pci_resource_start(pdev, 0), 
1345 +                                       pci_resource_len(pdev, 0));
1346 +       if (sp->base_address == 0) {
1347 +               dev_err(sp->dev, "Failed to ioremap pci memory\n");
1348 +               result =  -ENODEV;
1349 +               goto error_ioremap;
1350 +       }
1351 +
1352 +       result = ibmasm_init_remote_queue(sp);
1353 +       if (result) {
1354 +               dev_err(sp->dev, "Failed to initialize remote queue\n");
1355 +               goto error_remote_queue;
1356 +       }
1357 +
1358 +       sp->lock = SPIN_LOCK_UNLOCKED;
1359 +       INIT_LIST_HEAD(&sp->command_queue);
1360 +
1361 +       result = request_irq(sp->irq, ibmasm_interrupt_handler, SA_SHIRQ, sp->devname, (void*)sp);
1362 +       if (result) {
1363 +               dev_err(sp->dev, "Failed to register interrupt handler\n");
1364 +               goto error_request_irq;
1365 +       }
1366 +
1367 +       enable_sp_interrupts(sp->base_address);
1368 +       disable_mouse_interrupts(sp);
1369 +
1370 +       result = ibmasm_send_driver_vpd(sp);
1371 +       if (result) {
1372 +               dev_err(sp->dev, "Failed to send driver VPD to service processor\n");
1373 +               goto error_send_message;
1374 +       }
1375 +       result = ibmasm_send_os_state(sp, SYSTEM_STATE_OS_UP);
1376 +       if (result) {
1377 +               dev_err(sp->dev, "Failed to send OS state to service processor\n");
1378 +               goto error_send_message;
1379 +       }
1380 +       ibmasmfs_add_sp(sp);
1381 +
1382 +       ibmasm_register_uart(sp);
1383 +
1384 +       return 0;
1385 +
1386 +error_send_message:
1387 +       disable_sp_interrupts(sp->base_address);
1388 +       free_irq(sp->irq, (void *)sp);
1389 +error_request_irq:
1390 +       ibmasm_free_remote_queue(sp);
1391 +error_remote_queue:
1392 +       iounmap(sp->base_address);
1393 +error_ioremap:
1394 +       ibmasm_heartbeat_exit(sp);
1395 +error_heartbeat:
1396 +       ibmasm_event_buffer_exit(sp);
1397 +error_eventbuffer:
1398 +       kfree(sp);
1399 +
1400 +       return result;
1401 +}
1402 +
1403 +static void __exit ibmasm_remove_one(struct pci_dev *pdev)
1404 +{
1405 +       struct service_processor *sp = (struct service_processor *)pci_get_drvdata(pdev);
1406 +
1407 +       ibmasm_unregister_uart(sp);
1408 +       ibmasm_send_os_state(sp, SYSTEM_STATE_OS_DOWN);
1409 +       disable_sp_interrupts(sp->base_address);
1410 +       disable_mouse_interrupts(sp);
1411 +       free_irq(sp->irq, (void *)sp);
1412 +       ibmasm_heartbeat_exit(sp);
1413 +       ibmasm_free_remote_queue(sp);
1414 +       iounmap(sp->base_address);
1415 +       ibmasm_event_buffer_exit(sp);
1416 +       kfree(sp);
1417 +}
1418 +
1419 +static struct pci_device_id ibmasm_pci_table[] =
1420 +{
1421 +       { PCI_DEVICE(VENDORID_IBM, DEVICEID_RSA) },
1422 +       {},
1423 +};
1424 +
1425 +static struct pci_driver ibmasm_driver = {
1426 +       .name           = DRIVER_NAME,
1427 +       .id_table       = ibmasm_pci_table,
1428 +       .probe          = ibmasm_init_one,
1429 +       .remove         = __devexit_p(ibmasm_remove_one),
1430 +};
1431 +
1432 +static void __exit ibmasm_exit (void)
1433 +{
1434 +       ibmasm_unregister_panic_notifier();
1435 +       ibmasmfs_unregister();
1436 +       pci_unregister_driver(&ibmasm_driver);
1437 +       info(DRIVER_DESC " version " DRIVER_VERSION " unloaded");
1438 +}
1439 +
1440 +static int __init ibmasm_init(void)
1441 +{
1442 +       int result;
1443 +
1444 +       result = ibmasmfs_register();
1445 +       if (result) {
1446 +               err("Failed to register ibmasmfs file system");
1447 +               return result;
1448 +       }
1449 +       result = pci_register_driver(&ibmasm_driver);
1450 +       if (result <= 0) {
1451 +               pci_unregister_driver(&ibmasm_driver);
1452 +               ibmasmfs_unregister();
1453 +               return -ENODEV;
1454 +       }
1455 +       ibmasm_register_panic_notifier();
1456 +       info(DRIVER_DESC " version " DRIVER_VERSION " loaded");
1457 +       return 0;
1458 +}
1459 +
1460 +module_init(ibmasm_init);
1461 +module_exit(ibmasm_exit);
1462 +
1463 +MODULE_AUTHOR(DRIVER_AUTHOR);
1464 +MODULE_DESCRIPTION(DRIVER_DESC);
1465 +MODULE_LICENSE("GPL");
1466 diff -urN linux-2.6.1/drivers/misc/ibmasm/remote.c linux-2.6.1-ibmasm/drivers/misc/ibmasm/remote.c
1467 --- linux-2.6.1/drivers/misc/ibmasm/remote.c    1969-12-31 16:00:00.000000000 -0800
1468 +++ linux-2.6.1-ibmasm/drivers/misc/ibmasm/remote.c     2004-01-14 16:42:01.000000000 -0800
1469 @@ -0,0 +1,156 @@
1470 +
1471 +/*
1472 + * IBM ASM Service Processor Device Driver
1473 + *
1474 + * This program is free software; you can redistribute it and/or modify
1475 + * it under the terms of the GNU General Public License as published by
1476 + * the Free Software Foundation; either version 2 of the License, or
1477 + * (at your option) any later version.
1478 + *
1479 + * This program is distributed in the hope that it will be useful,
1480 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1481 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1482 + * GNU General Public License for more details.
1483 + *
1484 + * You should have received a copy of the GNU General Public License
1485 + * along with this program; if not, write to the Free Software
1486 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1487 + *
1488 + * Copyright (C) IBM Corporation, 2004
1489 + *
1490 + * Author: Max Asböck <amax@us.ibm.com> 
1491 + *
1492 + */
1493 +
1494 +/* Remote mouse and keyboard event handling functions */
1495 +
1496 +#include "ibmasm.h"
1497 +#include "remote.h"
1498 +
1499 +int ibmasm_init_remote_queue(struct service_processor *sp)
1500 +{
1501 +       struct remote_queue *q = &sp->remote_queue;
1502 +
1503 +       disable_mouse_interrupts(sp);
1504 +
1505 +       q->open = 0;
1506 +       q->size = 0;
1507 +
1508 +       q->start = kmalloc(DRIVER_REMOTE_QUEUE_SIZE * sizeof(struct remote_event), GFP_KERNEL);
1509 +        if (q->start == 0)
1510 +                return -ENOMEM;
1511 +
1512 +       q->end = q->start + DRIVER_REMOTE_QUEUE_SIZE;
1513 +       q->reader = q->start;
1514 +       q->writer = q->start;
1515 +       q->size = DRIVER_REMOTE_QUEUE_SIZE;
1516 +       init_waitqueue_head(&q->wait);
1517 +
1518 +       return 0;
1519 +}
1520 +
1521 +void ibmasm_free_remote_queue(struct service_processor *sp)
1522 +{
1523 +       if (sp->remote_queue.start)
1524 +               kfree(sp->remote_queue.start);
1525 +}
1526 +
1527 +void ibmasm_advance_reader(struct remote_queue *q, unsigned int n)
1528 +{
1529 +       q->reader += n;
1530 +       if (q->reader >= q->end)
1531 +               q->reader -= q->size;
1532 +}
1533 +
1534 +size_t ibmasm_events_available(struct remote_queue *q)
1535 +{
1536 +       ssize_t diff = q->writer - q->reader;
1537 +
1538 +       if (diff >= 0)
1539 +               return diff;
1540 +       else
1541 +               return (q->end - q->reader);
1542 +}
1543 +       
1544 +
1545 +static int space_free(struct remote_queue *q)
1546 +{
1547 +       if (q->reader == q->writer)
1548 +               return q->size - 1;
1549 +
1550 +       return ( (q->reader + q->size - q->writer) % q->size ) - 1;
1551 +}
1552 +
1553 +static void set_mouse_event(struct remote_input *input, struct mouse_event *mouse)
1554 +{
1555 +       static char last_buttons = 0;
1556 +
1557 +       mouse->x = input->data.mouse.x;
1558 +       mouse->y = input->data.mouse.y;
1559 +
1560 +       if (input->mouse_buttons == REMOTE_MOUSE_DOUBLE_CLICK) {
1561 +               mouse->buttons = REMOTE_MOUSE_DOUBLE_CLICK;
1562 +               last_buttons = 0;
1563 +               return;
1564 +       }
1565 +       mouse->transitions = last_buttons ^ input->mouse_buttons;
1566 +       mouse->buttons = input->mouse_buttons;
1567 +
1568 +       last_buttons = input->mouse_buttons;
1569 +}
1570 +
1571 +static void set_keyboard_event(struct remote_input *input, struct keyboard_event *keyboard)
1572 +{
1573 +       keyboard->key_code = input->data.keyboard.key_code;
1574 +       keyboard->key_down = input->data.keyboard.key_down;
1575 +}
1576 +
1577 +static int add_to_driver_queue(struct remote_queue *q, struct remote_input *input)
1578 +{
1579 +       struct remote_event *event = q->writer;
1580 +
1581 +       if ( space_free(q) < 1 ) {
1582 +               return 1;
1583 +       }
1584 +
1585 +       switch(input->type) {
1586 +       case (INPUT_TYPE_MOUSE):
1587 +               event->type = INPUT_TYPE_MOUSE;
1588 +               set_mouse_event(input, &event->data.mouse);
1589 +               break;
1590 +       case (INPUT_TYPE_KEYBOARD):
1591 +               event->type = INPUT_TYPE_KEYBOARD;
1592 +               set_keyboard_event(input, &event->data.keyboard);
1593 +               break;
1594 +       default:
1595 +               return 0;
1596 +       }
1597 +       event->type = input->type;
1598 +
1599 +       q->writer++;
1600 +       if (q->writer == q->end)
1601 +               q->writer = q->start;
1602 +
1603 +       return 0;
1604 +}
1605 +       
1606 +
1607 +void ibmasm_handle_mouse_interrupt(struct service_processor *sp)
1608 +{
1609 +       unsigned long reader;
1610 +       unsigned long writer;
1611 +       struct remote_input input;
1612 +
1613 +       reader = get_queue_reader(sp);
1614 +       writer = get_queue_writer(sp);
1615 +
1616 +       while (reader != writer) {
1617 +               memcpy(&input, (void *)get_queue_entry(sp, reader), sizeof(struct remote_input));
1618 +
1619 +               if ( add_to_driver_queue(&sp->remote_queue, &input) )
1620 +                       break;
1621 +
1622 +               reader = advance_queue_reader(sp, reader);
1623 +       }
1624 +       wake_up_interruptible(&sp->remote_queue.wait);
1625 +}
1626 diff -urN linux-2.6.1/drivers/misc/ibmasm/remote.h linux-2.6.1-ibmasm/drivers/misc/ibmasm/remote.h
1627 --- linux-2.6.1/drivers/misc/ibmasm/remote.h    1969-12-31 16:00:00.000000000 -0800
1628 +++ linux-2.6.1-ibmasm/drivers/misc/ibmasm/remote.h     2004-01-14 16:42:14.000000000 -0800
1629 @@ -0,0 +1,119 @@
1630 +
1631 +/*
1632 + * IBM ASM Service Processor Device Driver
1633 + *
1634 + * This program is free software; you can redistribute it and/or modify
1635 + * it under the terms of the GNU General Public License as published by
1636 + * the Free Software Foundation; either version 2 of the License, or
1637 + * (at your option) any later version.
1638 + *
1639 + * This program is distributed in the hope that it will be useful,
1640 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1641 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1642 + * GNU General Public License for more details.
1643 + *
1644 + * You should have received a copy of the GNU General Public License
1645 + * along with this program; if not, write to the Free Software
1646 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1647 + *
1648 + * Copyright (C) IBM Corporation, 2004
1649 + *
1650 + * Author: Max Asböck <amax@us.ibm.com> 
1651 + *
1652 + * Orignally written by Pete Reynolds
1653 + */
1654 +
1655 +#ifndef _IBMASM_REMOTE_H_
1656 +#define _IBMASM_REMOTE_H_
1657 +
1658 +#include <asm/io.h>
1659 +
1660 +/* pci offsets */
1661 +#define CONDOR_MOUSE_DATA              0x000AC000
1662 +#define CONDOR_MOUSE_ISR_CONTROL       0x00
1663 +#define CONDOR_MOUSE_ISR_STATUS                0x04
1664 +#define CONDOR_MOUSE_Q_READER          0x08
1665 +#define CONDOR_MOUSE_Q_WRITER          0x0C
1666 +#define CONDOR_MOUSE_Q_BEGIN           0x10
1667 +#define CONDOR_MOUSE_MAX_X             0x14
1668 +#define CONDOR_MOUSE_MAX_Y             0x18
1669 +
1670 +#define CONDOR_INPUT_DESKTOP_INFO      0x1F0
1671 +#define CONDOR_INPUT_DISPLAY_RESX      0x1F4
1672 +#define CONDOR_INPUT_DISPLAY_RESY      0x1F8
1673 +#define CONDOR_INPUT_DISPLAY_BITS      0x1FC
1674 +#define CONDOR_OUTPUT_VNC_STATUS       0x200
1675 +
1676 +#define CONDOR_MOUSE_INTR_STATUS_MASK  0x00000001
1677 +
1678 +#define INPUT_TYPE_MOUSE       0x1
1679 +#define INPUT_TYPE_KEYBOARD    0x2
1680 +
1681 +
1682 +/* mouse button states received from SP */
1683 +#define REMOTE_MOUSE_DOUBLE_CLICK      0xF0
1684 +#define REMOTE_MOUSE_BUTTON_LEFT       0x01
1685 +#define REMOTE_MOUSE_BUTTON_MIDDLE     0x02
1686 +#define REMOTE_MOUSE_BUTTON_RIGHT      0x04
1687 +
1688 +
1689 +struct mouse_input {
1690 +       unsigned short  y;
1691 +       unsigned short  x;
1692 +};
1693 +
1694 +
1695 +struct keyboard_input {
1696 +       unsigned short  key_code;
1697 +       unsigned char   key_flag;
1698 +       unsigned char   key_down;
1699 +};
1700 +
1701 +
1702 +
1703 +struct remote_input { 
1704 +       union {
1705 +               struct mouse_input      mouse;
1706 +               struct keyboard_input   keyboard;
1707 +       } data;
1708 +
1709 +       unsigned char   type;
1710 +       unsigned char   pad1;
1711 +       unsigned char   mouse_buttons;
1712 +       unsigned char   pad3;
1713 +};
1714 +
1715 +#define mouse_addr(sp)                 sp->base_address + CONDOR_MOUSE_DATA
1716 +#define display_width(sp)      mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESX
1717 +#define display_height(sp)     mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESY
1718 +#define display_depth(sp)      mouse_addr(sp) + CONDOR_INPUT_DISPLAY_BITS
1719 +#define vnc_status(sp)         mouse_addr(sp) + CONDOR_OUTPUT_VNC_STATUS
1720 +
1721 +#define mouse_interrupt_pending(sp)    readl(mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS)
1722 +#define clear_mouse_interrupt(sp)      writel(0, mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS)
1723 +#define enable_mouse_interrupts(sp)    writel(1, mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL)
1724 +#define disable_mouse_interrupts(sp)   writel(0, mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL)
1725 +
1726 +/* remote input queue operations */
1727 +#define REMOTE_QUEUE_SIZE      60
1728 +
1729 +#define get_queue_writer(sp)   readl(mouse_addr(sp) + CONDOR_MOUSE_Q_WRITER)
1730 +#define get_queue_reader(sp)   readl(mouse_addr(sp) + CONDOR_MOUSE_Q_READER)
1731 +#define set_queue_reader(sp, reader)   writel(reader, mouse_addr(sp) + CONDOR_MOUSE_Q_READER)
1732 +
1733 +#define queue_begin    mouse_addr(sp) + CONDOR_MOUSE_Q_BEGIN
1734 +
1735 +#define get_queue_entry(sp, read_index) \
1736 +       queue_begin + read_index * sizeof(struct remote_input)
1737 +
1738 +static inline int advance_queue_reader(struct service_processor *sp, unsigned long reader)
1739 +{
1740 +       reader++;
1741 +       if (reader == REMOTE_QUEUE_SIZE)
1742 +               reader = 0;
1743 +
1744 +       set_queue_reader(sp, reader);
1745 +       return reader;
1746 +}
1747 +
1748 +#endif /* _IBMASM_REMOTE_H_ */
1749 diff -urN linux-2.6.1/drivers/misc/ibmasm/r_heartbeat.c linux-2.6.1-ibmasm/drivers/misc/ibmasm/r_heartbeat.c
1750 --- linux-2.6.1/drivers/misc/ibmasm/r_heartbeat.c       1969-12-31 16:00:00.000000000 -0800
1751 +++ linux-2.6.1-ibmasm/drivers/misc/ibmasm/r_heartbeat.c        2004-01-22 11:08:48.000000000 -0800
1752 @@ -0,0 +1,95 @@
1753 +
1754 +/*
1755 + * This program is free software; you can redistribute it and/or modify
1756 + * it under the terms of the GNU General Public License as published by
1757 + * the Free Software Foundation; either version 2 of the License, or
1758 + * (at your option) any later version.
1759 + *
1760 + * This program is distributed in the hope that it will be useful,
1761 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1762 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1763 + * GNU General Public License for more details.
1764 + *
1765 + * You should have received a copy of the GNU General Public License
1766 + * along with this program; if not, write to the Free Software
1767 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1768 + *
1769 + * Copyright (C) IBM Corporation, 2004
1770 + *
1771 + * Author: Max Asböck <amax@us.ibm.com> 
1772 + *
1773 + */
1774 +
1775 +#include "ibmasm.h"
1776 +#include "dot_command.h"
1777 +
1778 +/*
1779 + * Reverse Heartbeat, i.e. heartbeats sent from the driver to the
1780 + * service processor.
1781 + * These heartbeats are initiated by user level programs.
1782 + */
1783 +
1784 +/* the reverse heartbeat dot command */
1785 +static struct {
1786 +       struct dot_command_header       header;
1787 +       unsigned char                   command[3];
1788 +} rhb_dot_cmd = {
1789 +       .header = {
1790 +               .type =         sp_read,
1791 +               .command_size = 3,
1792 +               .data_size =    0,
1793 +               .status =       0
1794 +       },
1795 +       .command = { 4, 3, 6 }
1796 +};
1797 +
1798 +void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb)
1799 +{
1800 +       init_waitqueue_head(&rhb->wait);
1801 +       rhb->stopped = 0;
1802 +}
1803 +
1804 +/**
1805 + * start_reverse_heartbeat
1806 + * Loop forever, sending a reverse heartbeat dot command to the service
1807 + * processor, then sleeping. The loop comes to an end if the service
1808 + * processor fails to respond 3 times or we were interrupted.
1809 + */
1810 +int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb)
1811 +{
1812 +       struct command *cmd;
1813 +       int times_failed = 0;
1814 +
1815 +       cmd = ibmasm_new_command(sizeof rhb_dot_cmd);
1816 +       if (!cmd)
1817 +               return -ENOMEM;
1818 +
1819 +       while ( times_failed < 3 && !rhb->stopped ) {
1820 +               memcpy(cmd->buffer, (void *)&rhb_dot_cmd, sizeof rhb_dot_cmd);
1821 +               cmd->status = IBMASM_CMD_PENDING;
1822 +               ibmasm_exec_command(sp, cmd);
1823 +               ibmasm_wait_for_response(cmd, IBMASM_CMD_TIMEOUT_NORMAL);
1824 +
1825 +               if (cmd->status != IBMASM_CMD_COMPLETE)
1826 +                       times_failed++;
1827 +
1828 +               wait_event_interruptible_timeout(rhb->wait, 
1829 +                       rhb->stopped,
1830 +                       REVERSE_HEARTBEAT_TIMEOUT * HZ);        
1831 +               if (signal_pending(current)) {
1832 +                       command_put(cmd);
1833 +                       return -EINTR;
1834 +               }
1835 +       }
1836 +       command_put(cmd);
1837 +       if (rhb->stopped)
1838 +               return -EINTR;
1839 +
1840 +       return 1;
1841 +}
1842 +
1843 +void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb)
1844 +{
1845 +       rhb->stopped = 1;
1846 +       wake_up_interruptible(&rhb->wait);
1847 +}
1848 diff -urN linux-2.6.1/drivers/misc/ibmasm/uart.c linux-2.6.1-ibmasm/drivers/misc/ibmasm/uart.c
1849 --- linux-2.6.1/drivers/misc/ibmasm/uart.c      1969-12-31 16:00:00.000000000 -0800
1850 +++ linux-2.6.1-ibmasm/drivers/misc/ibmasm/uart.c       2004-01-19 14:02:56.000000000 -0800
1851 @@ -0,0 +1,72 @@
1852 +
1853 +/*
1854 + * IBM ASM Service Processor Device Driver
1855 + *
1856 + * This program is free software; you can redistribute it and/or modify
1857 + * it under the terms of the GNU General Public License as published by
1858 + * the Free Software Foundation; either version 2 of the License, or
1859 + * (at your option) any later version.
1860 + *
1861 + * This program is distributed in the hope that it will be useful,
1862 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1863 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1864 + * GNU General Public License for more details.
1865 + *
1866 + * You should have received a copy of the GNU General Public License
1867 + * along with this program; if not, write to the Free Software
1868 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1869 + *
1870 + * Copyright (C) IBM Corporation, 2004
1871 + *
1872 + * Author: Max Asböck <amax@us.ibm.com> 
1873 + *
1874 + */
1875 +
1876 +#include <linux/termios.h>
1877 +#include <linux/tty.h>
1878 +#include <linux/serial_core.h>
1879 +#include <linux/serial.h>
1880 +#include <linux/serial_reg.h>
1881 +#include "ibmasm.h"
1882 +#include "lowlevel.h"
1883 +
1884 +
1885 +void ibmasm_register_uart(struct service_processor *sp)
1886 +{
1887 +       struct serial_struct serial;
1888 +       unsigned char *iomem_base;
1889 +
1890 +       iomem_base = sp->base_address + SCOUT_COM_B_BASE;
1891 +
1892 +       /* read the uart scratch register to determine if the UART
1893 +        * is dedicated to the service processor or if the OS can use it
1894 +        */
1895 +       if ( 0 == readl(iomem_base + UART_SCR) ) {
1896 +               dev_info(sp->dev, "IBM SP UART not registered, owned by service processor\n");
1897 +               sp->serial_line = -1;
1898 +               return;
1899 +       }
1900 +
1901 +       memset(&serial, 0, sizeof(serial));
1902 +       serial.irq              = sp->irq;
1903 +       serial.baud_base        = 3686400 / 16;
1904 +       serial.flags            = UPF_AUTOPROBE | UPF_SHARE_IRQ;
1905 +       serial.io_type          = UPIO_MEM;
1906 +       serial.iomem_base       = iomem_base;
1907 +
1908 +       sp->serial_line = register_serial(&serial);
1909 +       if (sp->serial_line < 0) {
1910 +               dev_err(sp->dev, "Failed to register serial port\n");
1911 +               return;
1912 +       }
1913 +       enable_uart_interrupts(sp->base_address);
1914 +}
1915 +
1916 +void ibmasm_unregister_uart(struct service_processor *sp)
1917 +{
1918 +       if (sp->serial_line < 0)
1919 +               return;
1920 +
1921 +       disable_uart_interrupts(sp->base_address);
1922 +       unregister_serial(sp->serial_line);
1923 +}
1924 diff -urN linux-2.6.1/drivers/misc/Kconfig linux-2.6.1-ibmasm/drivers/misc/Kconfig
1925 --- linux-2.6.1/drivers/misc/Kconfig    2004-01-08 22:59:18.000000000 -0800
1926 +++ linux-2.6.1-ibmasm/drivers/misc/Kconfig     2004-01-15 10:00:13.000000000 -0800
1927 @@ -4,5 +4,21 @@
1928  
1929  menu "Misc devices"
1930  
1931 +config IBM_ASM
1932 +       tristate "Device driver for IBM RSA service processor"
1933 +       default n
1934 +       ---help---
1935 +         This option enables device driver support for in-band access to the
1936 +         IBM RSA (Condor) service processor in eServer xSeries systems.
1937 +         The ibmasm device driver allows user space application to access
1938 +         ASM (Advanced Systems Management) functions on the service
1939 +         processor. The driver is meant to be used in conjunction with
1940 +         a user space API.
1941 +         The ibmasm driver also enables the OS to use the UART on the
1942 +          service processor board as a regular serial port.
1943 +         
1944 +
1945 +         If unsure, say N.
1946 +
1947  endmenu
1948  
1949 diff -urN linux-2.6.1/drivers/misc/Makefile linux-2.6.1-ibmasm/drivers/misc/Makefile
1950 --- linux-2.6.1/drivers/misc/Makefile   2004-01-08 23:00:03.000000000 -0800
1951 +++ linux-2.6.1-ibmasm/drivers/misc/Makefile    2004-01-14 17:15:39.000000000 -0800
1952 @@ -1,4 +1,6 @@
1953  #
1954  # Makefile for misc devices that really don't fit anywhere else.
1955  #
1956 -obj- := misc.o # Dummy rule to force built-in.o to be made
1957 +obj- := misc.o  # Dummy rule to force built-in.o to be made
1958 +
1959 +obj-$(CONFIG_IBM_ASM)  += ibmasm/
This page took 0.173086 seconds and 3 git commands to generate.