Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorey Minyard <minyard@acm.org>2005-02-10 16:02:47 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-02-10 16:02:47 -0800
commit3c503a0f7353b7223d9b973b72ad98a7ec73377e (patch)
tree322fd797e5abf2d9e1219a47a055334e9c69005b
parente920feb56b94c187602fb96f109f63c595e23c00 (diff)
[PATCH] Update to IPMI driver to support old DMI spec
The 1999 version of the DMI spec had a different configuration than the newer versions for the IPMI configuration information. This patch handles the differences between the two. Signed-off-by: Corey Minyard <minyard@acm.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c74
1 files changed, 40 insertions, 34 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 9a5894d0cf07..82f0ed43ea32 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -1564,48 +1564,54 @@ static int decode_dmi(dmi_header_t *dm, dmi_ipmi_data_t *ipmi_data)
u8 *data = (u8 *)dm;
unsigned long base_addr;
u8 reg_spacing;
+ u8 len = dm->length;
- ipmi_data->type = data[0x04];
+ ipmi_data->type = data[4];
- memcpy(&base_addr,&data[0x08],sizeof(unsigned long));
- if (base_addr & 1) {
- /* I/O */
- base_addr &= 0xFFFE;
+ memcpy(&base_addr, data+8, sizeof(unsigned long));
+ if (len >= 0x11) {
+ if (base_addr & 1) {
+ /* I/O */
+ base_addr &= 0xFFFE;
+ ipmi_data->addr_space = IPMI_IO_ADDR_SPACE;
+ }
+ else {
+ /* Memory */
+ ipmi_data->addr_space = IPMI_MEM_ADDR_SPACE;
+ }
+ /* If bit 4 of byte 0x10 is set, then the lsb for the address
+ is odd. */
+ ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
+
+ ipmi_data->irq = data[0x11];
+
+ /* The top two bits of byte 0x10 hold the register spacing. */
+ reg_spacing = (data[0x10] & 0xC0) >> 6;
+ switch(reg_spacing){
+ case 0x00: /* Byte boundaries */
+ ipmi_data->offset = 1;
+ break;
+ case 0x01: /* 32-bit boundaries */
+ ipmi_data->offset = 4;
+ break;
+ case 0x02: /* 16-byte boundaries */
+ ipmi_data->offset = 16;
+ break;
+ default:
+ /* Some other interface, just ignore it. */
+ return -EIO;
+ }
+ } else {
+ /* Old DMI spec. */
+ ipmi_data->base_addr = base_addr;
ipmi_data->addr_space = IPMI_IO_ADDR_SPACE;
- }
- else {
- /* Memory */
- ipmi_data->addr_space = IPMI_MEM_ADDR_SPACE;
- }
-
- /* The top two bits of byte 0x10 hold the register spacing. */
- reg_spacing = (data[0x10] & 0xC0) >> 6;
- switch(reg_spacing){
- case 0x00: /* Byte boundaries */
ipmi_data->offset = 1;
- break;
- case 0x01: /* 32-bit boundaries */
- ipmi_data->offset = 4;
- break;
- case 0x02: /* 16-byte boundaries */
- ipmi_data->offset = 16;
- break;
- default:
- printk("ipmi_si: Unknown SMBIOS IPMI Base Addr"
- " Modifier: 0x%x\n", reg_spacing);
- return -EIO;
}
- /* If bit 4 of byte 0x10 is set, then the lsb for the address
- is odd. */
- ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
-
- ipmi_data->irq = data[0x11];
-
if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr))
- return 0;
+ return 0;
- memset(ipmi_data,0,sizeof(dmi_ipmi_data_t));
+ memset(ipmi_data, 0, sizeof(dmi_ipmi_data_t));
return -1;
}