1 2 /* 3 * IBM ASM Service Processor Device Driver 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 * 19 * Copyright (C) IBM Corporation, 2004 20 * 21 * Author: Max Asb�ck <amax@us.ibm.com> 22 * 23 */ 24 25 #include <linux/kernel.h> 26 #include <linux/types.h> 27 #include <linux/errno.h> 28 #include <linux/list.h> 29 #include <linux/wait.h> 30 #include <linux/spinlock.h> 31 #include <linux/slab.h> 32 #include <linux/config.h> 33 #include <linux/module.h> 34 #include <linux/version.h> 35 #include <linux/interrupt.h> 36 #include <linux/device.h> 37 38 /* Driver identification */ 39 #define DRIVER_NAME "ibmasm" 40 #define DRIVER_VERSION "0.4" 41 #define DRIVER_AUTHOR "Max Asbock" 42 #define DRIVER_DESC "IBM ASM Service Processor Driver" 43 44 #define err(msg) printk(KERN_ERR "%s: " msg "\n", DRIVER_NAME) 45 #define info(msg) printk(KERN_INFO "%s: " msg "\n", DRIVER_NAME) 46 47 48 #define IBMASM_CMD_PENDING 0 49 #define IBMASM_CMD_COMPLETE 1 50 #define IBMASM_CMD_FAILED 2 51 52 #define IBMASM_CMD_TIMEOUT_NORMAL 45 53 #define IBMASM_CMD_TIMEOUT_EXTRA 240 54 55 #define IBMASM_CMD_MAX_BUFFER_SIZE 0x8000 56 57 #define REVERSE_HEARTBEAT_TIMEOUT 120 58 59 #define HEARTBEAT_BUFFER_SIZE 0x400 60 61 #ifdef IA64 62 #define IBMASM_DRIVER_VPD "Lin64 6.08 " 63 #else 64 #define IBMASM_DRIVER_VPD "Lin32 6.08 " 65 #endif 66 67 #define SYSTEM_STATE_OS_UP 5 68 #define SYSTEM_STATE_OS_DOWN 4 69 70 #define IBMASM_NAME_SIZE 16 71 72 #define IBMASM_NUM_EVENTS 10 73 #define IBMASM_EVENT_MAX_SIZE 2048u 74 75 76 struct command { 77 struct list_head queue_node; 78 wait_queue_head_t wait; 79 unsigned char *buffer; 80 size_t buffer_size; 81 int status; 82 struct kobject kobj; 83 }; 84 #define to_command(c) container_of(c, struct command, kobj) 85 86 static inline void command_put(struct command *cmd) 87 { 88 kobject_put(&cmd->kobj); 89 } 90 91 static inline void command_get(struct command *cmd) 92 { 93 kobject_get(&cmd->kobj); 94 } 95 96 97 struct ibmasm_event { 98 unsigned int serial_number; 99 unsigned int data_size; 100 unsigned char data[IBMASM_EVENT_MAX_SIZE]; 101 }; 102 103 struct event_buffer { 104 struct ibmasm_event events[IBMASM_NUM_EVENTS]; 105 unsigned int next_serial_number; 106 unsigned int next_index; 107 struct list_head readers; 108 }; 109 110 struct event_reader { 111 int cancelled; 112 unsigned int next_serial_number; 113 wait_queue_head_t wait; 114 struct list_head node; 115 unsigned int data_size; 116 unsigned char data[IBMASM_EVENT_MAX_SIZE]; 117 }; 118 119 struct reverse_heartbeat { 120 wait_queue_head_t wait; 121 unsigned int stopped; 122 }; 123 124 125 /* remote console events */ 126 struct mouse_event { 127 long x; 128 long y; 129 unsigned char buttons; 130 unsigned char transitions; 131 }; 132 133 struct keyboard_event { 134 unsigned long key_code; 135 unsigned char key_down; 136 }; 137 138 struct remote_event { 139 unsigned long type; 140 union { 141 struct mouse_event mouse; 142 struct keyboard_event keyboard; 143 } data; 144 }; 145 146 #define DRIVER_REMOTE_QUEUE_SIZE 240 147 148 struct remote_queue { 149 struct remote_event *start; 150 struct remote_event *end; 151 struct remote_event *reader; 152 struct remote_event *writer; 153 unsigned int size; 154 int open; 155 wait_queue_head_t wait; 156 }; 157 158 159 struct service_processor { 160 struct list_head node; 161 spinlock_t lock; 162 void __iomem *base_address; 163 unsigned int irq; 164 struct command *current_command; 165 struct command *heartbeat; 166 struct list_head command_queue; 167 struct event_buffer *event_buffer; 168 char dirname[IBMASM_NAME_SIZE]; 169 char devname[IBMASM_NAME_SIZE]; 170 unsigned int number; 171 struct remote_queue remote_queue; 172 int serial_line; 173 struct device *dev; 174 }; 175 176 /* command processing */ 177 extern struct command *ibmasm_new_command(size_t buffer_size); 178 extern void ibmasm_exec_command(struct service_processor *sp, struct command *cmd); 179 extern void ibmasm_wait_for_response(struct command *cmd, int timeout); 180 extern void ibmasm_receive_command_response(struct service_processor *sp, void *response, size_t size); 181 182 /* event processing */ 183 extern int ibmasm_event_buffer_init(struct service_processor *sp); 184 extern void ibmasm_event_buffer_exit(struct service_processor *sp); 185 extern void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int data_size); 186 extern void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader); 187 extern void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader); 188 extern int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader); 189 extern void ibmasm_cancel_next_event(struct event_reader *reader); 190 191 /* heartbeat - from SP to OS */ 192 extern void ibmasm_register_panic_notifier(void); 193 extern void ibmasm_unregister_panic_notifier(void); 194 extern int ibmasm_heartbeat_init(struct service_processor *sp); 195 extern void ibmasm_heartbeat_exit(struct service_processor *sp); 196 extern void ibmasm_receive_heartbeat(struct service_processor *sp, void *message, size_t size); 197 198 /* reverse heartbeat - from OS to SP */ 199 extern void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb); 200 extern int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb); 201 extern void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb); 202 203 /* dot commands */ 204 extern void ibmasm_receive_message(struct service_processor *sp, void *data, int data_size); 205 extern int ibmasm_send_driver_vpd(struct service_processor *sp); 206 extern int ibmasm_send_os_state(struct service_processor *sp, int os_state); 207 208 /* low level message processing */ 209 extern int ibmasm_send_i2o_message(struct service_processor *sp); 210 extern irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id, struct pt_regs *regs); 211 212 /* remote console */ 213 extern void ibmasm_handle_mouse_interrupt(struct service_processor *sp); 214 extern int ibmasm_init_remote_queue(struct service_processor *sp); 215 extern void ibmasm_free_remote_queue(struct service_processor *sp); 216 extern void ibmasm_advance_reader(struct remote_queue *q, unsigned int n); 217 extern size_t ibmasm_events_available(struct remote_queue *q); 218 219 /* file system */ 220 extern int ibmasmfs_register(void); 221 extern void ibmasmfs_unregister(void); 222 extern void ibmasmfs_add_sp(struct service_processor *sp); 223 224 /* uart */ 225 #ifdef CONFIG_SERIAL_8250 226 extern void ibmasm_register_uart(struct service_processor *sp); 227 extern void ibmasm_unregister_uart(struct service_processor *sp); 228 #else 229 #define ibmasm_register_uart(sp) do { } while(0) 230 #define ibmasm_unregister_uart(sp) do { } while(0) 231 #endif 232