mirror of
https://github.com/lm-sensors/lm-sensors.git
synced 2026-10-29 12:50:43 +00:00
Move dmi detection code from i2c-piix4 to new dmi_scan.c.
This permits better kernel patching into kernels that
already have dmi_scan.c.
git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@1478 7894878c-1315-0410-8ee3-d5d059ff63e0
This commit is contained in:
1 parent
cd943ec1c9
commit
a51387a556
5 files changed
+284
-110
No files matched your search
@@ -18,7 +18,9 @@ ask CVS about it:
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
2.6.5 (2002????)
|
||||
Module dmi_scan: new
|
||||
Module i2c-piix4: Refuse to load on IBM systems
|
||||
Module lm92: Fix in-kernel initialization
|
||||
Program mkpatch: Add Config.in entries for, lm92,
|
||||
pcf8574, pcf8591, smsc47m1, vt1211
|
||||
Program sensors: Add /usr/local/etc to config file path
|
||||
|
||||
@@ -53,7 +53,7 @@ ifneq ($(shell if grep -q '^CONFIG_I2C_SIS5595=y' $(LINUX)/.config; then echo 1;
|
||||
KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-sis5595.o
|
||||
endif
|
||||
ifneq ($(shell if grep -q '^CONFIG_I2C_PIIX4=y' $(LINUX)/.config; then echo 1; fi),1)
|
||||
KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-piix4.o
|
||||
KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-piix4.o $(MODULE_DIR)/dmi_scan.o
|
||||
endif
|
||||
ifneq ($(shell if grep -q '^CONFIG_I2C_SAVAGE4=y' $(LINUX)/.config; then echo 1; fi),1)
|
||||
KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-savage4.o
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
Taken from arch/i386/kernel/dmi_scan.c.
|
||||
Changes dmi_ident to be non-static so we can access.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/config.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/apm_bios.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/pm.h>
|
||||
#include <asm/keyboard.h>
|
||||
#include <asm/system.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include "version.h"
|
||||
#include "dmi_scan.h"
|
||||
|
||||
struct dmi_header
|
||||
{
|
||||
u8 type;
|
||||
u8 length;
|
||||
u16 handle;
|
||||
};
|
||||
|
||||
#define dmi_printk(x)
|
||||
//#define dmi_printk(x) printk x
|
||||
|
||||
static char * __init dmi_string(struct dmi_header *dm, u8 s)
|
||||
{
|
||||
u8 *bp=(u8 *)dm;
|
||||
bp+=dm->length;
|
||||
if(!s)
|
||||
return "";
|
||||
s--;
|
||||
while(s>0)
|
||||
{
|
||||
bp+=strlen(bp);
|
||||
bp++;
|
||||
s--;
|
||||
}
|
||||
return bp;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have to be cautious here. We have seen BIOSes with DMI pointers
|
||||
* pointing to completely the wrong place for example
|
||||
*/
|
||||
|
||||
static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *))
|
||||
{
|
||||
u8 *buf;
|
||||
struct dmi_header *dm;
|
||||
u8 *data;
|
||||
int i=1;
|
||||
|
||||
buf = ioremap(base, len);
|
||||
if(buf==NULL)
|
||||
return -1;
|
||||
|
||||
data = buf;
|
||||
|
||||
/*
|
||||
* Stop when we see al the items the table claimed to have
|
||||
* OR we run off the end of the table (also happens)
|
||||
*/
|
||||
|
||||
while(i<num && (data - buf) < len)
|
||||
{
|
||||
dm=(struct dmi_header *)data;
|
||||
|
||||
/*
|
||||
* Avoid misparsing crud if the length of the last
|
||||
* record is crap
|
||||
*/
|
||||
if((data-buf+dm->length) >= len)
|
||||
break;
|
||||
decode(dm);
|
||||
data+=dm->length;
|
||||
/*
|
||||
* Don't go off the end of the data if there is
|
||||
* stuff looking like string fill past the end
|
||||
*/
|
||||
while((data-buf) < len && (*data || data[1]))
|
||||
data++;
|
||||
data+=2;
|
||||
i++;
|
||||
}
|
||||
iounmap(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int __init dmi_iterate(void (*decode)(struct dmi_header *))
|
||||
{
|
||||
unsigned char buf[20];
|
||||
long fp=0xE0000L;
|
||||
fp -= 16;
|
||||
|
||||
#ifdef CONFIG_SIMNOW
|
||||
/*
|
||||
* Skip on x86/64 with simnow. Will eventually go away
|
||||
* If you see this ifdef in 2.6pre mail me !
|
||||
*/
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
while( fp < 0xFFFFF)
|
||||
{
|
||||
fp+=16;
|
||||
isa_memcpy_fromio(buf, fp, 20);
|
||||
if(memcmp(buf, "_DMI_", 5)==0)
|
||||
{
|
||||
u16 num=buf[13]<<8|buf[12];
|
||||
u16 len=buf[7]<<8|buf[6];
|
||||
u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
|
||||
|
||||
dmi_printk((KERN_INFO "DMI %d.%d present.\n",
|
||||
buf[14]>>4, buf[14]&0x0F));
|
||||
dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n",
|
||||
buf[13]<<8|buf[12],
|
||||
buf[7]<<8|buf[6]));
|
||||
dmi_printk((KERN_INFO "DMI table at 0x%08X.\n",
|
||||
buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]));
|
||||
if(dmi_table(base,len, num, decode)==0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
char *dmi_ident[DMI_STRING_MAX];
|
||||
|
||||
/*
|
||||
* Save a DMI string
|
||||
*/
|
||||
|
||||
static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
|
||||
{
|
||||
char *d = (char*)dm;
|
||||
char *p = dmi_string(dm, d[string]);
|
||||
if(p==NULL || *p == 0)
|
||||
return;
|
||||
if (dmi_ident[slot])
|
||||
return;
|
||||
dmi_ident[slot] = kmalloc(strlen(p)+1, GFP_KERNEL);
|
||||
if(dmi_ident[slot])
|
||||
strcpy(dmi_ident[slot], p);
|
||||
else
|
||||
printk(KERN_ERR "dmi_save_ident: out of memory.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a DMI table entry. Right now all we care about are the BIOS
|
||||
* and machine entries. For 2.5 we should pull the smbus controller info
|
||||
* out of here.
|
||||
*/
|
||||
|
||||
static void __init dmi_decode(struct dmi_header *dm)
|
||||
{
|
||||
u8 *data = (u8 *)dm;
|
||||
char *p;
|
||||
|
||||
switch(dm->type)
|
||||
{
|
||||
case 0:
|
||||
p=dmi_string(dm,data[4]);
|
||||
if(*p)
|
||||
{
|
||||
dmi_printk(("BIOS Vendor: %s\n", p));
|
||||
dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
|
||||
dmi_printk(("BIOS Version: %s\n",
|
||||
dmi_string(dm, data[5])));
|
||||
dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
|
||||
dmi_printk(("BIOS Release: %s\n",
|
||||
dmi_string(dm, data[8])));
|
||||
dmi_save_ident(dm, DMI_BIOS_DATE, 8);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
p=dmi_string(dm,data[4]);
|
||||
if(*p)
|
||||
{
|
||||
dmi_printk(("System Vendor: %s.\n",p));
|
||||
dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
|
||||
dmi_printk(("Product Name: %s.\n",
|
||||
dmi_string(dm, data[5])));
|
||||
dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
|
||||
dmi_printk(("Version %s.\n",
|
||||
dmi_string(dm, data[6])));
|
||||
dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
|
||||
dmi_printk(("Serial Number %s.\n",
|
||||
dmi_string(dm, data[7])));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
p=dmi_string(dm,data[4]);
|
||||
if(*p)
|
||||
{
|
||||
dmi_printk(("Board Vendor: %s.\n",p));
|
||||
dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
|
||||
dmi_printk(("Board Name: %s.\n",
|
||||
dmi_string(dm, data[5])));
|
||||
dmi_save_ident(dm, DMI_BOARD_NAME, 5);
|
||||
dmi_printk(("Board Version: %s.\n",
|
||||
dmi_string(dm, data[6])));
|
||||
dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
p=dmi_string(dm,data[8]);
|
||||
if(*p && *p!=' ')
|
||||
dmi_printk(("Asset Tag: %s.\n", p));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void __init dmi_scan_machine(void)
|
||||
{
|
||||
int err;
|
||||
printk("dmi_scan.o version %s (%s)\n", LM_VERSION, LM_DATE);
|
||||
err = dmi_iterate(dmi_decode);
|
||||
if(err)
|
||||
printk("dmi_scan.o: SM BIOS not found\n");
|
||||
else
|
||||
printk("dmi_scan.o: SM BIOS found\n");
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
MODULE_DESCRIPTION("SM BIOS DMI Scanner");
|
||||
#ifdef MODULE_LICENSE
|
||||
MODULE_LICENSE("GPL");
|
||||
#endif
|
||||
EXPORT_SYMBOL(dmi_ident);
|
||||
EXPORT_SYMBOL(dmi_scan_machine);
|
||||
int init_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cleanup_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
enum
|
||||
{
|
||||
DMI_BIOS_VENDOR,
|
||||
DMI_BIOS_VERSION,
|
||||
DMI_BIOS_DATE,
|
||||
DMI_SYS_VENDOR,
|
||||
DMI_PRODUCT_NAME,
|
||||
DMI_PRODUCT_VERSION,
|
||||
DMI_BOARD_VENDOR,
|
||||
DMI_BOARD_NAME,
|
||||
DMI_BOARD_VERSION,
|
||||
DMI_STRING_MAX
|
||||
};
|
||||
|
||||
extern char *dmi_ident[DMI_STRING_MAX];
|
||||
+15
-109
@@ -30,6 +30,7 @@
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/config.h>
|
||||
#include <linux/pci.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/kernel.h>
|
||||
@@ -40,6 +41,7 @@
|
||||
#include "version.h"
|
||||
#include <linux/init.h>
|
||||
#include <linux/apm_bios.h>
|
||||
#include "dmi_scan.h"
|
||||
|
||||
/* Note: We assume all devices are identical
|
||||
to the Intel PIIX4; we only mention it during detection. */
|
||||
@@ -180,124 +182,26 @@ static struct i2c_adapter piix4_adapter = {
|
||||
static int __initdata piix4_initialized;
|
||||
static unsigned short piix4_smba = 0;
|
||||
|
||||
/* The following DMI section is used to detect IBM Thinkpad laptops,
|
||||
whose AT24RF08 serial eeproms on the PIIX4 SMBus get corrupted.
|
||||
We refuse to load on those systems.
|
||||
From drivers/char/i8k.c (retabbed), which was
|
||||
stolen from arch/i386/kernel/dmi_scan.c */
|
||||
|
||||
static char system_vendor[48] = "?";
|
||||
typedef struct {
|
||||
u8 type;
|
||||
u8 length;
|
||||
u16 handle;
|
||||
} DMIHeader;
|
||||
#define IBM_SIGNATURE "IBM"
|
||||
|
||||
static char* __init dmi_string(DMIHeader *dmi, u8 s)
|
||||
{
|
||||
u8 *p;
|
||||
|
||||
if (!s)
|
||||
return "";
|
||||
s--;
|
||||
|
||||
p = (u8 *)dmi + dmi->length;
|
||||
while (s > 0) {
|
||||
p += strlen(p);
|
||||
p++;
|
||||
s--;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static void __init dmi_decode(DMIHeader *dmi)
|
||||
{
|
||||
u8 *data = (u8 *) dmi;
|
||||
char *p;
|
||||
|
||||
switch (dmi->type) {
|
||||
case 1: /* System Information */
|
||||
p = dmi_string(dmi,data[4]);
|
||||
if (*p)
|
||||
strncpy(system_vendor, p, sizeof(system_vendor));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int __init dmi_table(u32 base, int len, int num, void (*fn)(DMIHeader*))
|
||||
{
|
||||
u8 *buf;
|
||||
u8 *data;
|
||||
DMIHeader *dmi;
|
||||
int i = 1;
|
||||
|
||||
buf = ioremap(base, len);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
data = buf;
|
||||
|
||||
/*
|
||||
* Stop when we see al the items the table claimed to have
|
||||
* or we run off the end of the table (also happens)
|
||||
*/
|
||||
while ((i<num) && ((data-buf) < len)) {
|
||||
dmi = (DMIHeader *)data;
|
||||
/*
|
||||
* Avoid misparsing crud if the length of the last
|
||||
* record is crap
|
||||
*/
|
||||
if ((data-buf+dmi->length) >= len)
|
||||
break;
|
||||
fn(dmi);
|
||||
data += dmi->length;
|
||||
/*
|
||||
* Don't go off the end of the data if there is
|
||||
* stuff looking like string fill past the end
|
||||
*/
|
||||
while (((data-buf) < len) && (*data || data[1]))
|
||||
data++;
|
||||
data += 2;
|
||||
i++;
|
||||
}
|
||||
iounmap(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init dmi_iterate(void (*decode)(DMIHeader *))
|
||||
{
|
||||
unsigned char buf[20];
|
||||
long fp = 0x000e0000L;
|
||||
fp -= 16;
|
||||
|
||||
while (fp < 0x000fffffL) {
|
||||
fp += 16;
|
||||
isa_memcpy_fromio(buf, fp, 20);
|
||||
if (memcmp(buf, "_DMI_", 5)==0) {
|
||||
u16 num = buf[13]<<8 | buf[12];
|
||||
u16 len = buf [7]<<8 | buf [6];
|
||||
u32 base = buf[11]<<24 | buf[10]<<16 |
|
||||
buf[9]<<8 | buf[8];
|
||||
if (dmi_table(base, len, num, decode)==0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/* end of DMI code */
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
/*
|
||||
* Get DMI information.
|
||||
*/
|
||||
void dmi_scan_machine(void);
|
||||
#define IBM_SIGNATURE "IBM"
|
||||
static int __init ibm_dmi_probe(void)
|
||||
{
|
||||
if (dmi_iterate(dmi_decode) != 0)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,99)
|
||||
|
||||
dmi_scan_machine();
|
||||
#endif
|
||||
if(dmi_ident[DMI_SYS_VENDOR] == NULL)
|
||||
return 0;
|
||||
if (strncmp(system_vendor,IBM_SIGNATURE,strlen(IBM_SIGNATURE)) == 0)
|
||||
if(strncmp(dmi_ident[DMI_SYS_VENDOR], IBM_SIGNATURE,
|
||||
strlen(IBM_SIGNATURE)) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Detect whether a PIIX4 can be found, and initialize it, where necessary.
|
||||
Note the differences between kernels with the old PCI BIOS interface and
|
||||
@@ -335,6 +239,7 @@ int piix4_setup(void)
|
||||
}
|
||||
printk(KERN_INFO "i2c-piix4.o: Found %s device\n", num->name);
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
if(ibm_dmi_probe()) {
|
||||
printk
|
||||
(KERN_ERR "i2c-piix4.o: IBM Laptop detected; this module may corrupt\n");
|
||||
@@ -343,6 +248,7 @@ int piix4_setup(void)
|
||||
error_return = -EPERM;
|
||||
goto END;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Determine the address of the SMBus areas */
|
||||
if (force_addr) {
|
||||
|
||||
Reference in new issue
Block a user