Index: oldkernel/linux/drivers/char/ipmi_kcs.c diff -u linux/drivers/char/ipmi_kcs.c:1.1 linux/drivers/char/ipmi_kcs.c:1.2 --- linux/drivers/char/ipmi_kcs.c:1.1 Thu Jun 1 17:01:59 2000 +++ linux/drivers/char/ipmi_kcs.c Mon Jul 10 16:23:53 2000 @@ -1,25 +1,25 @@ /* - * Intelligent Platform Management Interface driver for Linux 2.1.x + * Intelligent Platform Management Interface driver for Linux 2.2.x * - * (c) Copyright 1999 San Mehat ,All Rights Reserved. - * http://www.valinux.com + * (c) Copyright 2000 San Mehat , All Rights Reserved. + * http://www.valinux.com * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Neither San Mehat nor VA Linux Systems admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither San Mehat nor VA Linux Systems admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. * - * (c) Copyright 1999 San Mehat + * (c) Copyright 1999 San Mehat * - * Release 0.04. - Initial Release - * - * Release 0.05. - Fixed ring buffer bugs... better buffer handling + * Release 0.04. - Initial Release + * + * Release 0.05. - Fixed ring buffer bugs... better buffer handling * - * Release 0.06. - Changed polling freq to 1/10 sec + * Release 0.06. - Changed polling freq to 1/10 sec * * Release 0.07. - Integrated watchdog commands into IOCTL's and added * support for blinking front panel LED @@ -38,6 +38,20 @@ * * Release 0.10. - Modified kcs_write routine so once a write is complete * if the interface isn't in a 'READ STATE' it's okay. + * + * Release 0.12. - Added Intel Nightshade MB fixups since NS boards don't + * support pre-timeout NMI support + * - FRU download support added + * - /proc/ipmi created with fru data and driver status + * Release 0.13. - Added ioctl for setting asset tag + * - Fixed bug in /proc + * - Added asset tag max length field + * Release 1.00 - Added intelligent proc reading so that asset tag is + * refreshed whenever /proc/ipmi is read + * - Code cleanup + * - When asset tag is set with data whoes size is < maximum, + * pad the rest out with NULLs + * */ #include @@ -61,6 +75,10 @@ #include #include +#ifdef CONFIG_PROC_FS +#include +#endif + /* function prototypes */ static int kcs_send_message(unsigned char *buf, int length); static int kcs_read_message(int *msglen, unsigned char *buf); @@ -69,7 +87,7 @@ static int add_data_to_ringbuffer(unsigned char *data, int length); static int remove_data_from_ringbuffer(unsigned char *data, int length); -static int watchdog_set(unsigned char args); +static int watchdog_set(unsigned char args, int disable); static int watchdog_ping(void); static int panel_set(unsigned char state); static int read_sensor(struct sensor_request *sensor); @@ -83,34 +101,93 @@ static ssize_t kcs_write(struct file *file, const char *buf, size_t count, loff_t *ppos); static long long kcs_llseek(struct file *file, long long offset, int origin); static int kcs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg); + unsigned long arg); +static int load_fru(void); +static int refresh_asset(void); +static void decode_string(unsigned char type, + unsigned char language_code, + unsigned char *source, + char *target, + int size); +static int asset_set(unsigned char *tag, int len); +static int add_sel_entry(struct sel_entry_request *req); +static int watchdog_get(void); +static int get_deviceid(void); +#ifdef CONFIG_PROC_FS +static int ipmi_get_info(char *, char **, off_t, int, int); +#endif + /* static globals */ -static struct timer_list poll_timer; -static int kcs_is_open=0; -static struct wait_queue *wq = NULL; -static int head; -static int tail; -static unsigned char *buffer; +static struct timer_list poll_timer; +static int kcs_is_open=0; +static int internal_cmd = 0; +static struct wait_queue *wq = NULL; +static int head; +static int tail; +static unsigned char *buffer; +static unsigned char *fru_buffer; +static int driver_major = 1; +static int driver_minor = 0; + +#define BOARD_AREA_NUM_FIELDS 4 +#define BOARD_MANUFACTURER 0 +#define BOARD_PRODUCT_NAME 1 +#define BOARD_SERIAL 2 +#define BOARD_PART 3 +static char board_area[BOARD_AREA_NUM_FIELDS][64]; + +#define PRODUCT_AREA_NUM_FIELDS 6 +#define PRODUCT_MANUFACTURER 0 +#define PRODUCT_NAME 1 +#define PRODUCT_PART 2 +#define PRODUCT_VERSION 3 +#define PRODUCT_SERIAL 4 +#define PRODUCT_ASSET 5 +static char product_area[PRODUCT_AREA_NUM_FIELDS][64]; + +static int asset_offset = -1; +static int asset_length = 0; +static char asset_lang = 0; + +static time_t watchdog_last_pet; +static int watchdog_active = 0; +static GET_WATCHDOG_RESPONSE wd_status; +static DEVICE_ID_RESPONSE dev_id; + +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry ipmi_proc_entry = { + 0, + 4, + "ipmi", + S_IFREG | S_IRUGO, + 1, + 0, + 0, + 0, + 0, + ipmi_get_info + }; +#endif static struct file_operations kcs_fops = { - kcs_llseek, - kcs_read, - kcs_write, - NULL, /* No Readdir */ - NULL, /* No Select */ - kcs_ioctl, - NULL, /* No mmap */ - kcs_open, - NULL, /* flush */ - kcs_release + kcs_llseek, + kcs_read, + kcs_write, + NULL, /* No Readdir */ + NULL, /* No Select */ + kcs_ioctl, + NULL, /* No mmap */ + kcs_open, + NULL, /* flush */ + kcs_release }; static struct miscdevice kcs_miscdev= { - IPMI_KCS_MINOR, - "ipmi_kcs", - &kcs_fops + IPMI_KCS_MINOR, + "ipmi_kcs", + &kcs_fops }; #define POLL_FREQ ((HZ/10)) @@ -119,280 +196,733 @@ static long long kcs_llseek(struct file *file, long long offset, int origin) { - return -ESPIPE; + return -ESPIPE; } static ssize_t kcs_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { - unsigned char tmp_buffer[MAX_ISA_LENGTH]; - int rc; + unsigned char tmp_buffer[MAX_ISA_LENGTH]; + int rc; - if (!count) - return(0); - if (count > MAX_ISA_LENGTH) - return -EFBIG; - copy_from_user(&tmp_buffer[0], buf, count); - if ((rc = kcs_send_message(&tmp_buffer[0],count))<0) - { - printk("kcs_write(): Unable to send message\n"); - return(rc); - } - return(0); + if (!count) + return(0); + if (count > MAX_ISA_LENGTH) + return -EFBIG; + copy_from_user(&tmp_buffer[0], buf, count); + if ((rc = kcs_send_message(&tmp_buffer[0],count))<0) + { + printk("[IPMI_KCS] Unable to send message\n"); + return(rc); + } + return(0); } static ssize_t kcs_read(struct file *file, char *buf, size_t count, loff_t *ptr) { - unsigned char tmp_buffer[MAX_ISA_LENGTH]; - int rc; + unsigned char tmp_buffer[MAX_ISA_LENGTH]; + int rc; - /* Can't seek (pread) on this device */ - if (ptr != &file->f_pos) - return -ESPIPE; - - if (count > MAX_ISA_LENGTH) - count = MAX_ISA_LENGTH; - - switch(MINOR(file->f_dentry->d_inode->i_rdev)) - { - case IPMI_KCS_MINOR: - /* Check to see if theres any data to be read */ - if (head == tail) - { - if (file->f_flags & O_NONBLOCK) - { - return -EAGAIN; - } - else - { - interruptible_sleep_on(&wq); - } - } - /* If we're here theres data to be read */ - if ((rc = remove_data_from_ringbuffer(&tmp_buffer[0], count))<0) - { - printk("kcs_read(): ring buffer remove failure\n"); - return -EIO; - } - copy_to_user(buf, &tmp_buffer[0], rc); - return(rc); - break; - default: - return -EINVAL; - } + /* Can't seek (pread) on this device */ + if (ptr != &file->f_pos) + return -ESPIPE; + + if (count > MAX_ISA_LENGTH) + count = MAX_ISA_LENGTH; + + switch(MINOR(file->f_dentry->d_inode->i_rdev)) + { + case IPMI_KCS_MINOR: + /* Check to see if theres any data to be read */ + if (head == tail) + { + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + else + interruptible_sleep_on(&wq); + } + /* If we're here theres data to be read */ + if ((rc = remove_data_from_ringbuffer(&tmp_buffer[0], count))<0) + { + printk("[IPMI_KCS] Ring buffer remove failure\n"); + return -EIO; + } + copy_to_user(buf, &tmp_buffer[0], rc); + return(rc); + break; + default: + return -EINVAL; + } } -static int kcs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static int kcs_ioctl(struct inode *inode, + struct file *file, + unsigned int cmd, + unsigned long arg) +{ + unsigned char argument; + + switch(cmd) + { + case IOCTL_WATCHDOG_SET: + if (!arg) + return(-EINVAL); + if (copy_from_user(&argument, (void *) arg, sizeof(unsigned char))) + return(-EFAULT); + return(watchdog_set(argument, 0)); + break; + case IOCTL_WATCHDOG_PING: + if (arg) + return(-EINVAL); + return(watchdog_ping()); + break; + case IOCTL_PANEL_LED_SET_BLINK: + if (!arg) + return(-EINVAL); + if (copy_from_user(&argument, (void *) arg, sizeof(unsigned char))) + return(-EFAULT); + if ((argument != 0x00) && (argument != 0x01)) + return(-EINVAL); + return(panel_set(argument)); + break; + case IOCTL_READ_SENSOR: + { + struct sensor_request req; + int rc; + + if (!arg) + return(-EINVAL); + if (copy_from_user(&req, (void *) arg, sizeof(req))) + return(-EFAULT); + rc = read_sensor(&req); + if (copy_to_user((struct sensor_request *)arg, &req, sizeof(req))) + return(-EFAULT); + return(rc); + } + case IOCTL_SET_ASSET_TAG: + { + struct asset_tag_request req; + int rc; + char *tag; + int tag_len; + + if (!arg) + return(-EINVAL); + if (copy_from_user(&req, (void *) arg, sizeof(req))) + return(-EFAULT); + tag_len = req.buffer_len; + if (tag_len <= 0) + return(-EFAULT); + if (tag_len > PAGE_SIZE) + return(-EOVERFLOW); + if (!(tag = kmalloc(PAGE_SIZE, GFP_KERNEL))) + return(-ENOMEM); + if (copy_from_user(tag, (void *) req.buffer, tag_len)) + { + kfree(tag); + return(-EFAULT); + } + rc = asset_set(tag, tag_len); + kfree(tag); + return(rc); + } + case IOCTL_REFRESH_FRU: + { + int rc; + + memset(board_area, 0, sizeof(board_area)); + memset(product_area, 0, sizeof(product_area)); + rc = load_fru(); + return(rc); + } + case IOCTL_ADD_SEL_ENTRY: + { + struct sel_entry_request req; + int rc; + + if (!arg) + return(-EINVAL); + if (copy_from_user(&req, (void *) arg, sizeof(req))) + return(-EFAULT); + + rc = add_sel_entry(&req); + return(rc); + } + default: + return -EINVAL; + } + return (0); +} + +static int add_sel_entry(struct sel_entry_request *req) { - unsigned char argument; + ADD_SEL_CMD cmd; + unsigned char reply[MAX_ISA_LENGTH]; - switch(cmd) - { - case IOCTL_WATCHDOG_SET: - if (!arg) - return(-EINVAL); - if (copy_from_user(&argument, (void *) arg, sizeof(unsigned char))) - return(-EFAULT); - return(watchdog_set(argument)); - break; - case IOCTL_WATCHDOG_PING: - if (arg) - return(-EINVAL); - return(watchdog_ping()); - break; - case IOCTL_PANEL_LED_SET_BLINK: - if (!arg) - return(-EINVAL); - if (copy_from_user(&argument, (void *) arg, sizeof(unsigned char))) - return(-EFAULT); - if ((argument != 0x00) && (argument != 0x01)) - return(-EINVAL); - return(panel_set(argument)); - break; - case IOCTL_READ_SENSOR: - { - struct sensor_request req; - int rc; - - if (!arg) - return(-EINVAL); - if (copy_from_user(&req, (void *) arg, sizeof(req))) - return(-EFAULT); - rc = read_sensor(&req); - if (copy_to_user((struct sensor_request *)arg, &req, sizeof(req))) - return(-EFAULT); - return(rc); - } - default: - return -EINVAL; - } - return (0); + memset(&cmd, 0, sizeof(cmd)); + + cmd.lun = 0; + cmd.netfn = STORAGE_REQUEST; + cmd.cmd = CMD_ADD_SEL_ENTRY; + cmd.record_id = 0x1234; + cmd.timestamp = 0x1234; + cmd.mfid = VALINUX_MFID; + + memcpy(&cmd.data, &req->data[0], 6); + if (ipmi_kcs_dispatch_internal((void *) &cmd, + sizeof(cmd), + (void *) + &reply)<0) + { + return(-EIO); + } + if (reply[2] != (unsigned char) 0x00) + { + printk("[IPMI_KCS] Command failed (rc = 0x%.2x)\n", + reply[2]); + return(-EIO); + } + return(0); } static int read_sensor(struct sensor_request *sensor) { - SENSOR_CMD pkt; + SENSOR_CMD pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.netfn=0x04; - pkt.lun=0x00; - pkt.cmd=0x2d; - pkt.sensor_number=sensor->sensor_number; - - if ((sensor->result_length =ipmi_kcs_dispatch_internal((void *) &pkt, - sizeof(pkt), - (void *) &sensor->result_buffer[0]))<0) - { - printk("read_sensor(): IPMI command timed out for reply\n"); - return -EIO; - } - if (sensor->result_buffer[2] != 0x00) - { - printk("read_sensor(): IPMI command failed (rc = 0x%.2x)\n", - sensor->result_buffer[2]); - return -EIO; - } - return(0); -} - -static int watchdog_set(unsigned char args) -{ - IPMI_KCS_SET_WATCHDOG pkt; - unsigned char reply[MAX_ISA_LENGTH]; - - memset(&pkt, 0, sizeof(pkt)); - pkt.netfn=0x06; - pkt.lun=0x0; - pkt.cmd=0x24; - pkt.timer_use = 0x04; - - if (args & WATCHDOG_ACTION_REBOOT) - pkt.timeout_action = 0x03; - if (args & WATCHDOG_ACTION_NMI) - pkt.pre_irq = 0x02; - - pkt.pretimeout_interval = 10; - pkt.tuefc_biosfrb2=0x00; - pkt.tuefc_biospost=0x0; - pkt.tuefc_osload=0x00; - pkt.tuefc_smsos=0x01; - pkt.initial_count = (30 * 10); - if (ipmi_kcs_dispatch_internal((void *) &pkt, sizeof(pkt), (void *) &reply)<0) - { - printk("watchdog_set(): IPMI command timed out for reply\n"); - return(-EIO); - } - if (reply[2] != 0x00) - { - printk("watchdog_set(): IPMI command failed (rc = 0x%.2x)\n",reply[2]); - return(-EIO); - } - return(0); + memset(&pkt, 0, sizeof(pkt)); + pkt.netfn=0x04; + pkt.lun=0x00; + pkt.cmd=0x2d; + pkt.sensor_number=sensor->sensor_number; + + if ((sensor->result_length =ipmi_kcs_dispatch_internal((void *) &pkt, + sizeof(pkt), + (void *) &sensor->result_buffer[0]))<0) + { + return -EIO; + } + if (sensor->result_buffer[2] != 0x00) + { + printk("[IPMI_KCS] Command failed (rc = 0x%.2x)\n", + sensor->result_buffer[2]); + return -EIO; + } + return(0); } -static int watchdog_ping(void) +static int refresh_asset() { - IPMI_KCS_RESET_WATCHDOG pkt; - unsigned char reply[MAX_ISA_LENGTH]; + FRU_DATA_REQ data_req; + unsigned char reply[MAX_ISA_LENGTH], num; + TL *tl; + int brtl; + int fru_pos; + + /* Get the type/length byte */ + data_req.lun = 0; + data_req.netfn = STORAGE_REQUEST; + data_req.cmd = CMD_READ_FRU_INV_DATA; + data_req.offset = asset_offset; + data_req.count = 1; + + internal_cmd = 1; + if (ipmi_kcs_dispatch_internal((void *) &data_req, + sizeof(data_req), + (void *) + &reply)<0) + { + return(-EIO); + } + internal_cmd = 0; + if (reply[2] != 0x00) + { + printk("[IPMI_KCS] Unable to download TL (0x%.2x)\n",reply[2]); + return(-EIO); + } + if (reply[3] != 1) + { + printk("[IPMI_KCS] TL download size != 1 (%d)\n",reply[3]); + return(-EIO); + } + /* + * If the stored length != asset length + * the FRU has probably been externally reloaded.. + * so reload the entire FRU + */ + tl = (TL *) &reply[4]; + if (tl->num_bytes != asset_length) + { + printk("[IPMI_KCS] TL size (%d) != asset size (%d), redownloading FRU\n", + tl->num_bytes, + asset_length); + load_fru(); + return(0); + } + brtl = tl->num_bytes; + fru_pos = asset_offset+1; /* Skip the type length byte */ + while(brtl) + { + data_req.lun = 0; + data_req.netfn = STORAGE_REQUEST; + data_req.cmd = CMD_READ_FRU_INV_DATA; + data_req.offset = fru_pos; + data_req.count = ((brtl < 16) ? brtl : 16); + + internal_cmd = 1; + if (ipmi_kcs_dispatch_internal((void *) &data_req, + sizeof(data_req), + (void *) + &reply)<0) + { + return(-EIO); + } + internal_cmd = 0; + if (reply[2] != 0x00) + { + printk("[IPMI_KCS] Unable to refresh asset tag (0x%.2x)\n",reply[2]); + return(-EIO); + } + num = reply[3]; + memcpy(&fru_buffer[fru_pos], &reply[4], num); + fru_pos += num; + brtl -= num; + } + tl = (TL *) &fru_buffer[asset_offset]; + decode_string(tl->type_code, + asset_lang, + &fru_buffer[(asset_offset+1)], + product_area[PRODUCT_ASSET], + tl->num_bytes); + product_area[PRODUCT_ASSET][tl->num_bytes] = 0; + return(0); +} - memset(&pkt, 0, sizeof(pkt)); - pkt.netfn = 0x06; - pkt.lun = 0x00; - pkt.cmd = 0x22; - - if (ipmi_kcs_dispatch_internal((void *) &pkt, sizeof(pkt), (void *) &reply)<0) - { - printk("watchdog_ping(): IPMI command timed out for reply\n"); - return(-EIO); - } - if (reply[2] != 0x00) - { - printk("watchdog_ping(): IPMI command failed (rc = 0x%.2x)\n",reply[2]); - return(-EIO); - } - return(0); +static int load_fru() +{ + FRU_COMMON_HEADER *cmn_hdr; + FRU_DATA_REQ data_req; + KCS_GENERIC_CMD inv_info_req; + FRU_AREA_INFO *inv_info_resp; + unsigned char reply[MAX_ISA_LENGTH], num, *p, lang; + int i,fru_pos,brtl,fru_size; + TL *tl; + + memset(&inv_info_req, 0, sizeof(inv_info_req)); + memset(&reply, 0, sizeof(reply)); + inv_info_req.lun = 0; + inv_info_req.netfn = STORAGE_REQUEST; + inv_info_req.cmd = CMD_GET_FRU_INV_AREA_INFO; + + internal_cmd = 1; + if (ipmi_kcs_dispatch_internal((void *) &inv_info_req, + sizeof(inv_info_req), + (void *) + &reply)<0) + { + return(-EIO); + } + internal_cmd = 0; + inv_info_resp = (FRU_AREA_INFO *) &reply[2]; + +#if 0 + printk("[IPMI_KCS] FRU is %d bytes (mode %d)\n", + inv_info_resp->size, + inv_info_resp->accessmode); +#endif + brtl = inv_info_resp->size; + fru_pos = 0; + fru_size = inv_info_resp->size; + if (fru_size > PAGE_SIZE) + { + printk("[IPMI_KCS] FRU too large\n"); + return(-ENOBUFS); + } + + data_req.lun = 0; + data_req.netfn = STORAGE_REQUEST; + data_req.cmd = CMD_READ_FRU_INV_DATA; + data_req.offset = 0; + data_req.count = 16; + while(brtl) + { +#if 0 + printk("Downloading fru hunk size %d offset %d\n", + data_req.count, + data_req.offset); +#endif + internal_cmd = 1; + if (ipmi_kcs_dispatch_internal((void *) &data_req, + sizeof(data_req), + (void *) + &reply)<0) + { + return(-EIO); + } + internal_cmd = 0; + if (reply[2] != 0x00) + { + printk("[IPMI_KCS] Unable to download fru (0x%.2x)\n",reply[2]); + return(-EIO); + } + num = reply[3]; + + memcpy(&fru_buffer[fru_pos], &reply[4], num); + + fru_pos += num; + brtl -= num; + if (brtl == 0) + break; + if (brtl <= 16) + data_req.count = brtl; + else + data_req.count = 16; + data_req.offset = fru_pos; + } + + cmn_hdr = (FRU_COMMON_HEADER *) &fru_buffer[0]; + if (cmn_hdr->board_area_offset) + { + p = &fru_buffer[(cmn_hdr->board_area_offset * 8)]; + lang = p[2]; + p +=6; + for (i=0; i < BOARD_AREA_NUM_FIELDS; i++) + { + tl = (TL *) p; + p++; + decode_string(tl->type_code, lang, p, board_area[i], tl->num_bytes); + board_area[i][tl->num_bytes] = 0; + p += tl->num_bytes; + } + } + if (cmn_hdr->product_info_offset) + { + p = &fru_buffer[(cmn_hdr->product_info_offset * 8)]; + lang = p[2]; + p +=3; + + for (i=0; i < PRODUCT_AREA_NUM_FIELDS; i++) + { + tl = (TL *) p; + if (i == PRODUCT_ASSET) + { + asset_offset = (p - fru_buffer); + asset_length = tl->num_bytes; + asset_lang = lang; + } + p++; + decode_string(tl->type_code, lang, p, product_area[i], tl->num_bytes); + product_area[i][tl->num_bytes] = 0; + p += tl->num_bytes; + } + } +#if 0 + for (i=0; i < BOARD_AREA_NUM_FIELDS; i++) + printk("Field %d = %s\n",i,board_area[i]); + for (i=0; i < PRODUCT_AREA_NUM_FIELDS; i++) + printk("Field %d = %s\n",i,product_area[i]); +#endif + return(0); +} + +static int asset_set(unsigned char *tag, int len) +{ + unsigned short *fru_write_offset; + KCS_GENERIC_CMD *cmd; + TL *tl; + unsigned char *write_buffer; + int write_len; + int bytes_reserved; + unsigned char reply[MAX_ISA_LENGTH]; + + if (asset_offset < 0) + return(-ELIBBAD); + tl = (TL *) &fru_buffer[asset_offset]; + bytes_reserved = tl->num_bytes; + if (len > bytes_reserved) + return(-EOVERFLOW); + write_len = bytes_reserved + + sizeof(unsigned short) + + sizeof(TL) + + sizeof(KCS_GENERIC_CMD); + if (write_len > PAGE_SIZE) + return(-EOVERFLOW); + + if (!(write_buffer= kmalloc(PAGE_SIZE, GFP_KERNEL))) + return(-ENOMEM); + + cmd = (KCS_GENERIC_CMD *) &write_buffer[0]; + fru_write_offset = (unsigned short *) &write_buffer[2]; + tl = (TL *) &write_buffer[4]; + + cmd->lun = 0x0; + cmd->netfn = STORAGE_REQUEST; + cmd->cmd = CMD_WRITE_FRU_INV_DATA; + + *fru_write_offset= asset_offset; + + tl->type_code= 0x03; + tl->num_bytes = bytes_reserved; + + memset(&write_buffer[5], 0, bytes_reserved); + memcpy(&write_buffer[5], tag, len); + + internal_cmd = 1; + if (ipmi_kcs_dispatch_internal((void *) &write_buffer[0], + write_len, + (void *) + &reply)<0) + { + return(-EIO); + } + internal_cmd = 0; + if (reply[2] != 0x00) + { + printk("[IPMI_KCS] Unable to set asset tag (0x%.2x)\n",reply[2]); + return(-EIO); + } + memset(board_area, 0, sizeof(board_area)); + memset(product_area, 0, sizeof(product_area)); + load_fru(); + return(0); +} + +static int get_deviceid() +{ + KCS_GENERIC_CMD cmd; + unsigned char reply[MAX_ISA_LENGTH]; + DEVICE_ID_RESPONSE *resp; + + memset(&cmd, 0, sizeof(cmd)); + memset(reply, 0, sizeof(reply)); + + cmd.lun = 0; + cmd.netfn = APP_REQUEST; + cmd.cmd = CMD_GET_DEVICE_ID; + + internal_cmd = 1; + if (ipmi_kcs_dispatch_internal((void *) &cmd, + sizeof(cmd), + (void *) + &reply[0])<0) + { + internal_cmd = 0; + return(-EIO); + } + internal_cmd = 0; + + if (reply[2] != 0x00) + { + printk("[IPMI_KCS] GET_DEVICE_ID command failed (0x%x)\n",reply[2]); + return(-EIO); + } + resp = (DEVICE_ID_RESPONSE *) &reply[2]; + memcpy(&dev_id, resp, sizeof(DEVICE_ID_RESPONSE)); + return(0); } +static int watchdog_get() +{ + KCS_GENERIC_CMD cmd; + unsigned char reply[MAX_ISA_LENGTH]; + GET_WATCHDOG_RESPONSE *resp; + + memset(&cmd, 0, sizeof(cmd)); + memset(reply, 0, sizeof(reply)); + + cmd.lun = 0; + cmd.netfn = APP_REQUEST; + cmd.cmd = CMD_WATCHDOG_GET; + + internal_cmd = 1; + if (ipmi_kcs_dispatch_internal((void *) &cmd, + sizeof(cmd), + (void *) + &reply)<0) + { + internal_cmd = 0; + return(-EIO); + } + internal_cmd = 0; + if (reply[2] != 0x00) + { + printk("[IPMI_KCS] GET_WATCHDOG command failed (0x%x)\n",reply[2]); + return(-EIO); + } + resp = (GET_WATCHDOG_RESPONSE *) &reply[2]; + memcpy(&wd_status, resp, sizeof(GET_WATCHDOG_RESPONSE)); + return(0); +} + +static int watchdog_set(unsigned char args, int disable) +{ + IPMI_KCS_SET_WATCHDOG pkt; + unsigned char reply[MAX_ISA_LENGTH]; + int ns_fixup = 0; + + memset(&pkt, 0, sizeof(pkt)); + pkt.netfn=APP_REQUEST; + pkt.lun=0x0; + pkt.cmd=CMD_WATCHDOG_SET; + pkt.timer_use = 0x04; + + if (args & WATCHDOG_ACTION_REBOOT) + pkt.timeout_action = 0x03; + if (args & WATCHDOG_ACTION_NMI) + pkt.pre_irq = 0x02; + + if (disable) + { + pkt.timeout_action = 0x00; + pkt.pre_irq = 0x00; + } + pkt.pretimeout_interval = 10; + pkt.tuefc_biosfrb2=0x00; + pkt.tuefc_biospost=0x0; + pkt.tuefc_osload=0x00; + pkt.tuefc_smsos=0x01; + pkt.initial_count = (30 * 10); + while(1) + { + if (disable) + internal_cmd = 1; + if (ipmi_kcs_dispatch_internal((void *) &pkt, + sizeof(pkt), + (void *) + &reply)<0) + { + internal_cmd = 0; + return(-EIO); + } + if (disable) + { + internal_cmd = 0; + if (reply[2] != (unsigned char) 0x00) + return(-EIO); + return(0); + } + if (reply[2] == (unsigned char) 0xcc) + { + ns_fixup++; + if (ns_fixup == 2) + { + printk("[IPMI KCS] Flakey NMI fixes failed\n"); + return(-EIO); + } + printk("[IPMI KCS] Flakey NMI fixups enabled\n"); + pkt.pretimeout_interval = 0; + pkt.pre_irq = 0; + } + else if (reply[2] == 0x00) + break; + else + { + printk("[IPMI_KCS] Command failed (rc = 0x%.2x)\n",reply[2]); + return(-EIO); + } + } + if (ns_fixup) + printk("[IPMI KCS] Flakey NMI fixups functional\n"); + watchdog_active = 1; + return(0); +} + +static int watchdog_ping(void) +{ + IPMI_KCS_RESET_WATCHDOG pkt; + unsigned char reply[MAX_ISA_LENGTH]; + time_t now = CURRENT_TIME; + + memset(&pkt, 0, sizeof(pkt)); + pkt.netfn = APP_REQUEST; + pkt.lun = 0x00; + pkt.cmd = CMD_WATCHDOG_RESET; + + if (ipmi_kcs_dispatch_internal((void *) &pkt, sizeof(pkt), (void *) &reply)<0) + { + return(-EIO); + } + if (reply[2] != 0x00) + { + printk("[IPMI_KCS] Command failed (rc = 0x%.2x)\n",reply[2]); + return(-EIO); + } + watchdog_last_pet = now; + return(0); +} + static int panel_set(unsigned char state) { - unsigned char reply[MAX_ISA_LENGTH]; - struct blinky_cmd - { - unsigned char lun :2; - unsigned char netfn :6; - - unsigned char cmd; - } pkt; - - memset(&pkt, 0, sizeof(pkt)); - pkt.netfn= 0x06; - pkt.lun= 0x00; - if (state == PANEL_LED_BLINK) - pkt.cmd= 0x55; - else - pkt.cmd= 0x56; - - if (ipmi_kcs_dispatch_internal((void *) &pkt, sizeof(pkt), (void *) &reply)<0) - { - printk("panel_set(): IPMI command timed out for reply\n"); - return(-EIO); - } - if (reply[2] != 0x00) - { - printk("panel_set(): IPMI command failed (rc = 0x%.2x)\n",reply[2]); - return(-EIO); - } - return(0); + unsigned char reply[MAX_ISA_LENGTH]; + struct blinky_cmd + { + unsigned char lun :2; + unsigned char netfn :6; + + unsigned char cmd; + } pkt; + + memset(&pkt, 0, sizeof(pkt)); + pkt.netfn= APP_REQUEST; + pkt.lun= 0x00; + if (state == PANEL_LED_BLINK) + pkt.cmd= 0x55; + else + pkt.cmd= 0x56; + + if (ipmi_kcs_dispatch_internal((void *) &pkt, sizeof(pkt), (void *) &reply)<0) + { + return(-EIO); + } + if (reply[2] != 0x00) + { + printk("[IPMI_KCS] Command failed (rc = 0x%.2x)\n",reply[2]); + return(-EIO); + } + return(0); } static int ipmi_kcs_dispatch_internal(void *data, int size, void *reply) { - volatile unsigned char status; - int rc; - int msglen; - unsigned int jiffystart; - int i; - - if ((rc =kcs_send_message((unsigned char *) data, size))<0) - { - printk("[IPMI_KCS] Message dispatch failed. (rc %d)\n",rc); - return(-EIO); - } - - interruptible_sleep_on(&wq); - if ((rc = remove_data_from_ringbuffer((unsigned char *) reply, - MAX_ISA_LENGTH))<0) - { - printk("[IPMI_KCS] Ring buffer remove failure\n"); - return -EIO; - } - return(rc); + int rc; + + if ((rc =kcs_send_message((unsigned char *) data, size))<0) + { + printk("[IPMI_KCS] Message dispatch failed. (rc %d)\n",rc); + return(-EIO); + } + interruptible_sleep_on(&wq); + if ((rc = remove_data_from_ringbuffer((unsigned char *) reply, + MAX_ISA_LENGTH))<0) + { + printk("[IPMI_KCS] Ring buffer remove failure\n"); + return -EIO; + } + return(rc); } static int kcs_open(struct inode *inode, struct file *file) { - switch(MINOR(inode->i_rdev)) - { - case IPMI_KCS_MINOR: - { - if(kcs_is_open) - return -EBUSY; - MOD_INC_USE_COUNT; - - kcs_is_open=1; - return 0; - } - default: - return -ENODEV; - } + switch(MINOR(inode->i_rdev)) + { + case IPMI_KCS_MINOR: + { + if(kcs_is_open) + return -EBUSY; + MOD_INC_USE_COUNT; + + kcs_is_open=1; + return 0; + } + default: + return -ENODEV; + } } static int kcs_release(struct inode *inode, struct file *file) { - if(MINOR(inode->i_rdev)==IPMI_KCS_MINOR) - kcs_is_open=0; - MOD_DEC_USE_COUNT; - return 0; + if(MINOR(inode->i_rdev)==IPMI_KCS_MINOR) + kcs_is_open=0; + MOD_DEC_USE_COUNT; + return 0; } #ifdef MODULE @@ -400,220 +930,411 @@ __initfunc(int kcs_init(void)) { - return(ipmi_kcs_init()); + return(ipmi_kcs_init()); } void cleanup_module(void) { - printk("[IPMI_KCS] Driver shutting down.\n"); - kfree(buffer); - del_timer(&poll_timer); - misc_deregister(&kcs_miscdev); - release_region(IO,16); + printk("[IPMI_KCS] Driver shutting down.\n"); +#ifdef CONFIG_PROC_FS + proc_unregister(&proc_root, ipmi_proc_entry.low_ino); +#endif + kfree(buffer); + kfree(fru_buffer); + del_timer(&poll_timer); + misc_deregister(&kcs_miscdev); + release_region(IO,16); } #endif static int add_data_to_ringbuffer(unsigned char *data, int length) { - int i; - int diff; + int i; + int diff; - /* Make sure we have room in the ringbuffer */ - diff = tail - head; - if (diff <0) - diff = PAGE_SIZE - head + tail; - diff = PAGE_SIZE - diff; - if (length > diff) - { - printk("[IPMI_KCS] Not enough room in ringbuffer\n"); - printk("[IPMI_KCS] len = %d, head = %d, tail = %d\n",length, head, tail); - return(-1); /* Not enough room */ - } - - for (i = 0; i < length; i++) - { - buffer[tail] = data[i]; - tail++; - tail &= (PAGE_SIZE -1); - } - return(0); + /* Make sure we have room in the ringbuffer */ + diff = tail - head; + if (diff <0) + diff = PAGE_SIZE - head + tail; + diff = PAGE_SIZE - diff; + if (length > diff) + { + printk("[IPMI_KCS] Not enough room in ringbuffer\n"); + printk("[IPMI_KCS] len = %d, head = %d, tail = %d\n",length, head, tail); + return(-1); /* Not enough room */ + } + + for (i = 0; i < length; i++) + { + buffer[tail] = data[i]; + tail++; + tail &= (PAGE_SIZE -1); + } + return(0); } static int remove_data_from_ringbuffer(unsigned char *data, int length) { - int i; + int i; - if (head == tail) - return(0); /* No data to be read */ + if (head == tail) + return(0); /* No data to be read */ - for (i = 0; i < length; i++) - { - *data++ = buffer[head++]; - head &= (PAGE_SIZE -1); - if (head == tail) - { - i++; - return(i); - } - } - i++; - return(i); + for (i = 0; i < length; i++) + { + *data++ = buffer[head++]; + head &= (PAGE_SIZE -1); + if (head == tail) + { + i++; + return(i); + } + } + i++; + return(i); } void ipmi_kcs_poll(unsigned long nothing) { - volatile unsigned char status; - unsigned char data[MAX_ISA_LENGTH]; - int rc; - int msglen; - - poll_timer.expires = jiffies + POLL_FREQ; - add_timer(&poll_timer); - - status = inb_p(ISA_BMC_STATUS); - if ((!(status & ISA_SMS_MSG_FLAG)) && ((status & ISA_STATE_MASK) !=ISA_READ_STATE)) - return; - /* Something in the queue */ - if ((rc = kcs_read_message(&msglen, &data[0]))<0) - { - printk("ipmi_kcs_poll(): Read Message failed\n"); - return; - } - if (!kcs_is_open) - return; /* Dont store it if nobody is listening.. */ - if (add_data_to_ringbuffer(&data[0],msglen)<0) - { - printk("ipmi_kcs_poll(): ring buffer overflow. Dropping newest frame\n"); - return; - } - wake_up_interruptible(&wq); + volatile unsigned char status; + unsigned char data[MAX_ISA_LENGTH]; + int rc; + int msglen; + + poll_timer.expires = jiffies + POLL_FREQ; + add_timer(&poll_timer); + + status = inb_p(ISA_BMC_STATUS); + if ((!(status & ISA_SMS_MSG_FLAG)) && ((status & ISA_STATE_MASK) !=ISA_READ_STATE)) + return; + /* Something in the queue */ + if ((rc = kcs_read_message(&msglen, &data[0]))<0) + { + printk("[IPMI_KCS] Read Message failed\n"); + return; + } + if ((!kcs_is_open) && (!internal_cmd)) + return; /* Dont store it if nobody is listening.. */ + if (add_data_to_ringbuffer(&data[0],msglen)<0) + { + printk("[IPMI_KCS] Ring buffer overflow. Dropping newest frame\n"); + return; + } + + wake_up_interruptible(&wq); } static int kcs_send_message(unsigned char *buf, int length) { - volatile unsigned char chipstatus; - int status; - int i; - - if ((status = wait_while_ibf(ISA_TIMEOUT)) <0) - return(-1); - - outb_p(ISA_WRITE_START, ISA_BMC_COMMAND); - - if ((status = wait_while_ibf(ISA_TIMEOUT)) <0) - return(-2); - - for (i=0; i = (unsigned char) 0x00) && (*s <= (unsigned char) 0x09)) + *d++ = (unsigned char) 0x30 + (unsigned char) *s++; + else + { + if (*s == (unsigned char) 0x0A) + *d++ = (unsigned char) ' '; + else if (*s == (unsigned char) 0x0B) + *d++ = (unsigned char) '-'; + else if (*s == (unsigned char) 0x0C) + *d++ = (unsigned char) '.'; + else if ((*s <= (unsigned char) 0x0D) && (*s <= (unsigned char) 0x0F)) + { + *d++ = (unsigned char) '*'; + } + s++; + } + size --; + } + } + else if (type == STRING_DATA_TYPE_SIX_BIT_ASCII) + { + printk("[IPMI_KCS] Six bit ASCII decode not supported\n"); + } + else if (type == STRING_DATA_TYPE_LANG_DEPENDANT) + { + if ((language_code == 0x00) || (language_code == 0x25)) + { + strncpy(target, source, size); + target[size] = 0x0; + } + else + { + printk("[IPMI_KCS] Language 0x%x dependant decode not supported\n", + language_code); + return; + } + } + else + { + printk("Unable to decode type 0x%.2x\n",type); + return; + } +} + +#ifdef CONFIG_PROC_FS +int ipmi_get_info(char *buf, char **start, off_t fpos, int length, int dummy) { - printk("IPMI KCS driver (San Mehat nettwerk@valinux.com) v0.10 at io 0x%x\n",IO); - if (!(buffer = kmalloc(PAGE_SIZE, GFP_KERNEL))) - { - printk("--Unable to allocate 1 page ring buffer\n"); - return(-ENOMEM); - } - printk("--Using %d byte ring buffer for incomming IPMI data\n",PAGE_SIZE); - printk("--Polling frequency set to %d ticks\n",POLL_FREQ); - request_region(IO, 16, "ipmi_kcs"); - if ((inb_p(ISA_BMC_STATUS) == 0xFF) && - (inb_p(ISA_BMC_DATA_IN) == 0xFF)) - { - printk("--IPMI ISA window not present. Driver exiting\n"); - release_region(IO,16); - kfree(buffer); - return(-ENXIO); - } - misc_register(&kcs_miscdev); - head = tail = 0; - - /* Set up a periodic timer to check if theres unsolicited data to be read */ - memset(&poll_timer, 0, sizeof(poll_timer)); - poll_timer.function = ipmi_kcs_poll; - poll_timer.expires = jiffies + POLL_FREQ; - add_timer(&poll_timer); - return(0); + char *p; + char nmi[64]; + time_t now = CURRENT_TIME; + + p = buf; + p+= sprintf(p, "Driver Version\t: %d.%d\n", + driver_major,driver_minor); + if (get_deviceid()!= 0) + { + printk("[IPMI_KCS] Unable to get device ID\n"); + memset(&dev_id, 0, sizeof(dev_id)); + } + p+=sprintf(p, "BMC Version\t: %x.%x\n", + dev_id.major_firmware_revision, + dev_id.minor_firmware_revision); + p+=sprintf(p, "IPMI Version\t: %d.%d\n", + dev_id.ipmi_version_major, + dev_id.ipmi_version_minor); + + p+=sprintf(p, "\n"); + + if (watchdog_get()!= 0) + { + printk("[IPMI_KCS] Unable to get watchdog status\n"); + memset(&wd_status, 0, sizeof(wd_status)); + } + + if (wd_status.timer_status == 0x01) + p+= sprintf(p, "WD Timer Status\t\t: STARTED\n"); + else if (watchdog_active) + p+= sprintf(p, "WD Timer Status\t\t: STARTED\n"); + else + p+= sprintf(p, "WD Timer Status\t\t: STOPPED\n"); + + if (wd_status.timeout_act == 0x00) + p+= sprintf(p, "WD Timeout Action\t: NONE\n"); + else if (wd_status.timeout_act == 0x01) + p+= sprintf(p, "WD Timeout Action\t: HARD RESET\n"); + else if (wd_status.timeout_act == 0x02) + p+= sprintf(p, "WD Timeout Action\t: POWER DOWN\n"); + else if (wd_status.timeout_act == 0x03) + p+= sprintf(p, "WD Timeout Action\t: POWER CYCLE\n"); + else + p+= sprintf(p, "WD Timeout Action\t: UNKNOWN\n"); + + if (wd_status.pre_irq_act == 0x00) + p+= sprintf(p, "WD Pre-Timeout IRQ\t: NONE\n"); + else if (wd_status.pre_irq_act == 0x01) + p+= sprintf(p, "WD Pre-Timeout IRQ\t: SMI\n"); + else if (wd_status.pre_irq_act == 0x02) + p+= sprintf(p, "WD Pre-Timeout IRQ\t: NMI\n"); + else + p+= sprintf(p, "WD Pre-Timeout IRQ\t: UNKNOWN\n"); + + p+= sprintf(p, "WD Last Pet\t\t: %d", (unsigned int) watchdog_last_pet); + if (watchdog_last_pet == 0) + p+= sprintf(p, " (Never)\n"); + else + p+= sprintf(p, " (%d seconds ago)\n",(unsigned int)(now-watchdog_last_pet)); + p+= sprintf(p, "WD countdown\t\t: %d\n", (unsigned int) wd_status.current_count); + p+= sprintf(p, "\n"); + + p+= sprintf(p, "Board Area Records:\n"); + p+= sprintf(p, "Board Manuf.\t: %s\n", + (board_area[BOARD_MANUFACTURER][0] ? board_area[0] : "Not Available")); + p+= sprintf(p, "Board Prod Name\t: %s\n", + (board_area[BOARD_PRODUCT_NAME][0] ? board_area[1] : "Not Available")); + p+= sprintf(p, "Board Serial\t: %s\n", + (board_area[BOARD_SERIAL][0] ? board_area[2] : "Not Available")); + p+= sprintf(p, "Board Part\t: %s\n", + (board_area[BOARD_PART][0] ? board_area[3] : "Not Available")); + p+= sprintf(p, "\n"); + + p+= sprintf(p, "Product Area Records:\n"); + p+= sprintf(p, "Product Manuf.\t: %s\n", + (product_area[PRODUCT_MANUFACTURER][0] ? product_area[0]:"Not Available")); + p+= sprintf(p, "Product Name\t: %s\n", + (product_area[PRODUCT_NAME][0] ? product_area[1] : "Not Available")); + p+= sprintf(p, "Product Part\t: %s\n", + (product_area[PRODUCT_PART][0] ? product_area[2] : "Not Available")); + p+= sprintf(p, "Product Version\t: %s\n", + (product_area[PRODUCT_VERSION][0] ? product_area[3] : "Not Available")); + p+= sprintf(p, "Product Serial\t: %s\n", + (product_area[PRODUCT_SERIAL][0] ? product_area[4] : "Not Available")); + + refresh_asset(); + p+= sprintf(p, "Product Asset\t: %s (%d byte maximum size)\n", + (product_area[PRODUCT_ASSET][0] ? product_area[5] : "Not Available"), + asset_length); + + return p - buf; } +#endif Index: oldkernel/linux/drivers/char/ipmi_kcs.h diff -u linux/drivers/char/ipmi_kcs.h:1.1 linux/drivers/char/ipmi_kcs.h:1.2 --- linux/drivers/char/ipmi_kcs.h:1.1 Thu Jun 1 17:01:59 2000 +++ linux/drivers/char/ipmi_kcs.h Mon Jul 10 16:23:53 2000 @@ -49,7 +49,7 @@ #define ISA_TIMEOUT 1000 typedef struct ipmi_ksc_set_watchdog - { + { unsigned char lun :2; unsigned char netfn :6; @@ -78,6 +78,28 @@ unsigned short initial_count; } IPMI_KCS_SET_WATCHDOG; +typedef struct get_watchdog_response + { + unsigned char cc __attribute__ ((packed)); + + unsigned char timer_use :3; + unsigned char res1 :3; + unsigned char timer_status :1; + unsigned char sel_log :1; + + unsigned char timeout_act :3; + unsigned char res2 :1; + unsigned char pre_irq_act :3; + unsigned char res3 :1; + + unsigned char pre_timeout __attribute__ ((packed)); + + unsigned char timer_use_xp __attribute__ ((packed)); + + unsigned short init_count __attribute__ ((packed)); + unsigned short current_count __attribute__ ((packed)); + } GET_WATCHDOG_RESPONSE; + typedef struct ipmi_ksc_reset_watchdog { unsigned char lun :2; @@ -94,3 +116,138 @@ unsigned char cmd; unsigned char sensor_number; } SENSOR_CMD; + +/* + * Structure for a generic cmd that requires no args + */ +typedef struct ipmi_kcs_generic_cmd + { + unsigned char lun :2; + unsigned char netfn :6; + + unsigned char cmd; + } KCS_GENERIC_CMD; + +/* + * FRU area info response + */ +typedef struct kcs_fru_area_info + { + unsigned char cc __attribute__ ((packed)); + unsigned short size __attribute__ ((packed)); + +#define ACCESSMODE_BYTE 0 +#define ACCESSMODE_WORD 1 + unsigned char accessmode:1; + unsigned char reserved:7; + } FRU_AREA_INFO; + +typedef struct kcs_fru_data_req + { + unsigned char lun :2; + unsigned char netfn :6; + + unsigned char cmd; + + unsigned short offset __attribute__ ((packed)); + unsigned char count __attribute__ ((packed)); + } FRU_DATA_REQ; + +typedef struct fru_common_header + { + unsigned char common_header_format_version; + unsigned char internal_use_offset; + unsigned char chassis_info_offset; + unsigned char board_area_offset; + unsigned char product_info_offset; + unsigned char multirecord_area_offset; + unsigned char pad; + unsigned char checksum; + } FRU_COMMON_HEADER; + +typedef struct type_length + { + unsigned char num_bytes :6; + unsigned char type_code :2; + } TL; + +typedef struct ipmi_kcs_add_sel_cmd + { + unsigned char lun :2; + unsigned char netfn :6; + + unsigned char cmd; + + unsigned short record_id __attribute__ ((packed)); + unsigned char record_type __attribute__ ((packed)); + unsigned int timestamp __attribute__ ((packed)); + unsigned short mfid __attribute__ ((packed)); + + unsigned char data[6] __attribute__ ((packed)); + } ADD_SEL_CMD; + +/* GET_DEVICE_ID RESPONSE */ +typedef struct device_id_response + { + unsigned char cc; + unsigned char device_id; + + unsigned char device_revision :4; + unsigned char reserved :3; + unsigned char provides_sdr :1; + + unsigned char major_firmware_revision :7; + #define NORMAL_OPERATION 0 + #define DEVICE_BUSY 1 + unsigned char device_available :1; + + unsigned char minor_firmware_revision; + + unsigned char ipmi_version_major :4; + unsigned char ipmi_version_minor :4; + + unsigned char supports_sensor_device :1; + unsigned char supports_sdr_device :1; + unsigned char supports_sel_device :1; + unsigned char supports_fru_device :1; + unsigned char supports_ipmb_receiver :1; + unsigned char supports_ipmb_generator :1; + unsigned char supports_bridge :1; + unsigned char supports_chassis_device :1; + + unsigned char manufacturer_id1; + unsigned char manufacturer_id2; + unsigned char manufacturer_id3; + + unsigned short product_id; + } DEVICE_ID_RESPONSE; + +/* + * The Netfn codes + */ +#define CHASSIS_REQUEST 0x00 +#define CHASSIS_RESPONSE 0x01 +#define BRIDGE_REQUEST 0x02 +#define BRIDGE_RESPONSE 0x03 +#define SENSOR_REQUEST 0x04 +#define SENSOR_RESPONSE 0x05 +#define APP_REQUEST 0x06 +#define APP_RESPONSE 0x07 +#define FIRMWARE_REQUEST 0x08 +#define FIRMWARE_RESPONSE 0x09 +#define STORAGE_REQUEST 0x0A +#define STORAGE_RESPONSE 0x0B + +/* + * The cmds + */ +#define CMD_GET_FRU_INV_AREA_INFO 0x10 +#define CMD_READ_FRU_INV_DATA 0x11 +#define CMD_WRITE_FRU_INV_DATA 0x12 +#define CMD_ADD_SEL_ENTRY 0x44 +#define CMD_WATCHDOG_SET 0x24 +#define CMD_WATCHDOG_GET 0x25 +#define CMD_WATCHDOG_RESET 0x22 +#define CMD_GET_DEVICE_ID 0x01 + +#define VALINUX_MFID 0x1B58 Index: oldkernel/linux/include/linux/ipmi_kcs_ioctls.h diff -u linux/include/linux/ipmi_kcs_ioctls.h:1.1 linux/include/linux/ipmi_kcs_ioctls.h:1.2 --- linux/include/linux/ipmi_kcs_ioctls.h:1.1 Thu Jun 1 17:01:59 2000 +++ linux/include/linux/ipmi_kcs_ioctls.h Mon Jul 10 16:23:53 2000 @@ -17,23 +17,37 @@ #ifndef _IPMI_KCS_IOCTLS_H #define _IPMI_KCS_IOCTLS_H + +#define IOCTL_WATCHDOG_SET 0x01 + #define WATCHDOG_ACTION_REBOOT 0x01 + #define WATCHDOG_ACTION_NMI 0x02 - -#define IOCTL_WATCHDOG_SET 0x01 - #define WATCHDOG_ACTION_REBOOT 0x01 - #define WATCHDOG_ACTION_NMI 0x02 - -#define IOCTL_WATCHDOG_PING 0x02 - -#define IOCTL_PANEL_LED_SET_BLINK 0x03 - #define PANEL_LED_NORMAL 0x00 - #define PANEL_LED_BLINK 0x01 +#define IOCTL_WATCHDOG_PING 0x02 -#define IOCTL_READ_SENSOR 0x04 +#define IOCTL_PANEL_LED_SET_BLINK 0x03 + #define PANEL_LED_NORMAL 0x00 + #define PANEL_LED_BLINK 0x01 + +#define IOCTL_READ_SENSOR 0x04 struct sensor_request - { - unsigned char sensor_number; - unsigned char result_buffer[64]; - int result_length; - }; + { + unsigned char sensor_number; + unsigned char result_buffer[64]; + int result_length; + }; + +#define IOCTL_SET_ASSET_TAG 0x05 +struct asset_tag_request + { + unsigned char buffer_len; + char *buffer; + }; + +#define IOCTL_REFRESH_FRU 0x06 + +#define IOCTL_ADD_SEL_ENTRY 0x07 +struct sel_entry_request + { + unsigned char data[6]; + }; #endif