diff options
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 105 |
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 | |||
1610 | static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS]; | 1611 | static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS]; |
1611 | static int dmi_data_entries; | 1612 | static int dmi_data_entries; |
1612 | 1613 | ||
1613 | typedef struct dmi_header | 1614 | static 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 | |||
1620 | static 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 | ||
1688 | static int dmi_table(u32 base, int len, int num) | 1682 | static 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 | |||
1729 | static 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 | |||
1739 | static 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 | ||
1766 | static int try_init_smbios(int intf_num, struct smi_info **new_info) | 1695 | static 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])); |