aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ipmi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/ipmi')
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c105
1 files changed, 17 insertions, 88 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index a44b97304e95..51ce508b2f51 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -75,6 +75,7 @@ static inline void add_usec_to_timer(struct timer_list *t, long v)
75#include <asm/io.h> 75#include <asm/io.h>
76#include "ipmi_si_sm.h" 76#include "ipmi_si_sm.h"
77#include <linux/init.h> 77#include <linux/init.h>
78#include <linux/dmi.h>
78 79
79#define IPMI_SI_VERSION "v33" 80#define IPMI_SI_VERSION "v33"
80 81
@@ -1610,22 +1611,15 @@ typedef struct dmi_ipmi_data
1610static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS]; 1611static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS];
1611static int dmi_data_entries; 1612static int dmi_data_entries;
1612 1613
1613typedef struct dmi_header 1614static int __init decode_dmi(struct dmi_header *dm, int intf_num)
1614{ 1615{
1615 u8 type; 1616 u8 *data = (u8 *)dm;
1616 u8 length;
1617 u16 handle;
1618} dmi_header_t;
1619
1620static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
1621{
1622 u8 __iomem *data = (u8 __iomem *)dm;
1623 unsigned long base_addr; 1617 unsigned long base_addr;
1624 u8 reg_spacing; 1618 u8 reg_spacing;
1625 u8 len = readb(&dm->length); 1619 u8 len = dm->length;
1626 dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; 1620 dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
1627 1621
1628 ipmi_data->type = readb(&data[4]); 1622 ipmi_data->type = data[4];
1629 1623
1630 memcpy(&base_addr, data+8, sizeof(unsigned long)); 1624 memcpy(&base_addr, data+8, sizeof(unsigned long));
1631 if (len >= 0x11) { 1625 if (len >= 0x11) {
@@ -1640,12 +1634,12 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
1640 } 1634 }
1641 /* If bit 4 of byte 0x10 is set, then the lsb for the address 1635 /* If bit 4 of byte 0x10 is set, then the lsb for the address
1642 is odd. */ 1636 is odd. */
1643 ipmi_data->base_addr = base_addr | ((readb(&data[0x10]) & 0x10) >> 4); 1637 ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
1644 1638
1645 ipmi_data->irq = readb(&data[0x11]); 1639 ipmi_data->irq = data[0x11];
1646 1640
1647 /* The top two bits of byte 0x10 hold the register spacing. */ 1641 /* The top two bits of byte 0x10 hold the register spacing. */
1648 reg_spacing = (readb(&data[0x10]) & 0xC0) >> 6; 1642 reg_spacing = (data[0x10] & 0xC0) >> 6;
1649 switch(reg_spacing){ 1643 switch(reg_spacing){
1650 case 0x00: /* Byte boundaries */ 1644 case 0x00: /* Byte boundaries */
1651 ipmi_data->offset = 1; 1645 ipmi_data->offset = 1;
@@ -1673,7 +1667,7 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
1673 ipmi_data->offset = 1; 1667 ipmi_data->offset = 1;
1674 } 1668 }
1675 1669
1676 ipmi_data->slave_addr = readb(&data[6]); 1670 ipmi_data->slave_addr = data[6];
1677 1671
1678 if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) { 1672 if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) {
1679 dmi_data_entries++; 1673 dmi_data_entries++;
@@ -1685,82 +1679,17 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
1685 return -1; 1679 return -1;
1686} 1680}
1687 1681
1688static int dmi_table(u32 base, int len, int num) 1682static void __init dmi_find_bmc(void)
1689{
1690 u8 __iomem *buf;
1691 struct dmi_header __iomem *dm;
1692 u8 __iomem *data;
1693 int i=1;
1694 int status=-1;
1695 int intf_num = 0;
1696
1697 buf = ioremap(base, len);
1698 if(buf==NULL)
1699 return -1;
1700
1701 data = buf;
1702
1703 while(i<num && (data - buf) < len)
1704 {
1705 dm=(dmi_header_t __iomem *)data;
1706
1707 if((data-buf+readb(&dm->length)) >= len)
1708 break;
1709
1710 if (readb(&dm->type) == 38) {
1711 if (decode_dmi(dm, intf_num) == 0) {
1712 intf_num++;
1713 if (intf_num >= SI_MAX_DRIVERS)
1714 break;
1715 }
1716 }
1717
1718 data+=readb(&dm->length);
1719 while((data-buf) < len && (readb(data)||readb(data+1)))
1720 data++;
1721 data+=2;
1722 i++;
1723 }
1724 iounmap(buf);
1725
1726 return status;
1727}
1728
1729static inline int dmi_checksum(u8 *buf)
1730{
1731 u8 sum=0;
1732 int a;
1733
1734 for(a=0; a<15; a++)
1735 sum+=buf[a];
1736 return (sum==0);
1737}
1738
1739static int dmi_decode(void)
1740{ 1683{
1741 u8 buf[15]; 1684 struct dmi_device *dev = NULL;
1742 u32 fp=0xF0000; 1685 int intf_num = 0;
1743
1744#ifdef CONFIG_SIMNOW
1745 return -1;
1746#endif
1747 1686
1748 while(fp < 0xFFFFF) 1687 while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) {
1749 { 1688 if (intf_num >= SI_MAX_DRIVERS)
1750 isa_memcpy_fromio(buf, fp, 15); 1689 break;
1751 if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
1752 {
1753 u16 num=buf[13]<<8|buf[12];
1754 u16 len=buf[7]<<8|buf[6];
1755 u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
1756 1690
1757 if(dmi_table(base, len, num) == 0) 1691 decode_dmi((struct dmi_header *) dev->device_data, intf_num++);
1758 return 0;
1759 }
1760 fp+=16;
1761 } 1692 }
1762
1763 return -1;
1764} 1693}
1765 1694
1766static int try_init_smbios(int intf_num, struct smi_info **new_info) 1695static int try_init_smbios(int intf_num, struct smi_info **new_info)
@@ -2293,7 +2222,7 @@ static __init int init_ipmi_si(void)
2293 printk("\n"); 2222 printk("\n");
2294 2223
2295#ifdef CONFIG_X86 2224#ifdef CONFIG_X86
2296 dmi_decode(); 2225 dmi_find_bmc();
2297#endif 2226#endif
2298 2227
2299 rv = init_one_smi(0, &(smi_infos[pos])); 2228 rv = init_one_smi(0, &(smi_infos[pos]));