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:
Mark D. Studebaker committed 2002-08-02 01:56:56 +00:00
1 parent cd943ec1c9
commit a51387a556
5 files changed
+284 -110

No files matched your search

+2
View File
@@ -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
+1 -1
View File
@@ -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
+251
View File
@@ -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
+15
View File
@@ -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
View File
@@ -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) {