diff options
author | Mark D. Studebaker <mdsxyz123@yahoo.com> | 2002-02-27 02:47:04 +0000 |
---|---|---|
committer | Mark D. Studebaker <mdsxyz123@yahoo.com> | 2002-02-27 02:47:04 +0000 |
commit | 55552ad444bba02f0e0cfb3939908cf65457fda1 (patch) | |
tree | 26df5d38f987a0c38b02e9f6a48d49f7065fcc95 /prog/hotplug | |
parent | 0c567ff863735c58a3e1c18d4717667220dbee4e (diff) | |
download | lm-sensors-git-55552ad444bba02f0e0cfb3939908cf65457fda1.tar.gz |
kernel module to enable i801 2443 device on Asus P4B boards.
from Ilja Rauhut <rauhut@alwa02.physik.uni-siegen.de>
git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@1329 7894878c-1315-0410-8ee3-d5d059ff63e0
Diffstat (limited to 'prog/hotplug')
-rw-r--r-- | prog/hotplug/Makefile.p4b | 35 | ||||
-rw-r--r-- | prog/hotplug/README.p4b | 69 | ||||
-rw-r--r-- | prog/hotplug/p4b_smbus.c | 268 |
3 files changed, 372 insertions, 0 deletions
diff --git a/prog/hotplug/Makefile.p4b b/prog/hotplug/Makefile.p4b new file mode 100644 index 00000000..e39057c1 --- /dev/null +++ b/prog/hotplug/Makefile.p4b @@ -0,0 +1,35 @@ +# pcwd Kernel Module Makefile +# + +VERSION=1.40 + +VER = $(shell uname -r) +INCLUDEDIR= /lib/modules/$(VER)/build/include + +CFLAGS= -D__KERNEL__ -DMODULE -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -I$(INCLUDEDIR) + +OBJS = p4b_smbus.o + +all: $(OBJS) + +install: + $(MAKE) + install -d /lib/modules/$(VER)/kernel/drivers/char + install -c p4bsmbus.o /lib/modules/$(VER)/kernel/drivers/char +# test ! -x /dev/watchdog || mknod -m 600 /dev/watchdog c 10 130 +# test ! -x /dev/temperature || mknod -m 600 /dev/temperature c 10 131 + +inst: + $(MAKE) + rmmod p4b_smbus + install -d /lib/modules/$(VER)/kernel/drivers/char + install -c p4b_smbus.o /lib/modules/$(VER)/kernel/drivers/char + depmod -a +# modprobe p4b_smbus + +clean: + rm -f *.o *~ core + +cleandist: + rm -f *.o *~ core + diff --git a/prog/hotplug/README.p4b b/prog/hotplug/README.p4b new file mode 100644 index 00000000..c04ffc30 --- /dev/null +++ b/prog/hotplug/README.p4b @@ -0,0 +1,69 @@ +What is it? +----------- + +This is just a quick and dirty hack to get the hardware monitoring working +on the ASUS P4B board under Linux. +ASUS switches of the SMBus PCI Device in the i801 ICH2 chip. I spoke two times +with the German support an learned that: "We do not want the users to be +irritated by just another PCI Device in the Win98 device manager." +Really funny :-). + +What does the module do? +------------------------ + +It turnes off (!) the bits number 8 and 3 in the LPC register of the ICH2. +This you can also try as root with setpci and pcitweak. +First do a: + +setpci -d 8086:2440 f2.w + +You will get an hex number VAL - in my case 148 (Hex)-, where you have to +erase the two bits - in my case you get 40 (Hex). +Then do a: + +setpci -d 8086:2440 f2.w=VAL + +Running "lspci -n" you will not see any new device, but with "pcitweak -l" you +should get a line similar to this in the output: + +PCI: 00:1f:3: chip 8086,2443 card 1043,8028 rev 12 class 0c,05,00 hdr 00 + +The important thing is the "8086,2443" here. +The device is activated, but not included in /proc/pci and +/proc/bus/pci/devices. This is the reason for running the module. + +What are the system requirements? +--------------------------------- + +- Obviously a board with Intel i801BA ICH2 with broken bios. +- A linux working with a 2.4 kernel AND hotplug support in it! +- A installed kernel tree and gcc. +- i2c and sensor modules installed. + +How to install? +--------------- + +Simply do a: + +make -f Makefile.p4b +insmod p4b_smbus.o +modprobe i2c-core +modprobe i2c-i801 +modprobe i2c-dev +modprobe i2c-proc + +Then run your sensor: + +modprobe w83781d + +What should i never do? +----------------------- + +Do not try to do a "rmmod p4b_smbus" before a "rmmod i2c-i801". +The other way around should be okay. Otherwise you remove the PCI device +without notifying the i2c driver. + + +------------------------------- +Ilja Rauhut <IljaRauhut@web.de> + diff --git a/prog/hotplug/p4b_smbus.c b/prog/hotplug/p4b_smbus.c new file mode 100644 index 00000000..711209ac --- /dev/null +++ b/prog/hotplug/p4b_smbus.c @@ -0,0 +1,268 @@ +/* + * p4b_smbus.c + * + * Initialize the I801SMBus device on ASUS P4B Bords + */ +/* + Copyright (c) 2002 Ilja Rauhut <IljaRauhut@web.de>, + + Based on the m7101.c hotplug example by: + + Copyright (c) 2000 Burkhard Kohl <buk@buks.ipn.de>, + Frank Bauer <frank.bauer@nikocity.de>, and + Mark D. Studebaker <mdsxyz123@yahoo.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* CHANGES: + * February 13,2002 IR First Version + * + * This code is absolutely experimental - use it at your own + * risk. + * + * Warning, this module will work only with 2.4.x kernels. + * If it works with earlier kernels then it is by luck. + * + * Warning, this module does not work with egcs < 2.95.2, use + * gcc > 2.7.2 or egcs >= 2.95.2. + * + */ + + +#ifdef P4Bsmbus_DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +#ifndef TRUE +#define TRUE 1 +#define FALSE !TRUE +#endif + +#include <linux/config.h> +#ifndef CONFIG_HOTPLUG +#error ERROR - You must have 'Support for hot-pluggable devices' enabled in your kernel (under 'general setup')!! +#endif + +/* Deal with CONFIG_MODVERSIONS */ +#ifdef CONFIG_MODVERSIONS +#define MODVERSIONS +#include <linux/modversions.h> +#endif + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/stddef.h> +#include <linux/ioport.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <asm/types.h> + +#include <linux/sched.h> +#include <linux/signal.h> +#include <asm/irq.h> + +/* +rmm from lm_sensors-2.3.3: + */ + +#define SMB_IO_SIZE 0xF +#define SMB_BASE 0x20 + +/* status, used to indicate that io space needs to be freed */ +static struct pci_dev *i801smbus = NULL; +static int i801smbus_inserted = FALSE; +extern void cleanup_module(); + +static rwlock_t i801smbus_lock = RW_LOCK_UNLOCKED; +static unsigned long i801smbus_lock_flags = 0; + +/* + * Checks whether SMBus is enabled and turns it on in case they are not. + * It's done by clearing Bit 8 and 4 in i801 config space F2h, PCI-Device 0x8086:0x2440 + */ +static int +i801smbus_enable(struct pci_dev *dev){ + u16 val = 0; + + pci_read_config_word(dev, 0xF2, &val); + DBG("i801smbus: i801smbus config byte reading 0x%X.\n", val); + if (val & 0x008) { + pci_write_config_word(dev, 0xF2, val & 0x77); + pci_read_config_word(dev, 0xF2, &val); + if(val & 0x008) + { + DBG("i801smbus: i801smbus config byte locked:-(\n"); + return -EIO; + } + else + printk("SMBus activated in LPC!\n"); + } + return 0; + +} + +/* + * Builds the basic pci_dev for the i801smbus + */ +static int i801smbus_build(struct pci_dev **i801smbus, struct pci_bus *bus) +{ + u32 devfn; + u16 id = 0; + u16 vid = 0; + int ret; + + DBG("i801smbus: requesting kernel space for the i801smbus entry.\n"); + *i801smbus = kmalloc(sizeof(**i801smbus), GFP_ATOMIC); + if(NULL == *i801smbus) { + printk("i801smbus: out of memory.\n"); + return -ENOMEM; + } + + /* minimally fill in structure for search */ + /* The device should be on the same bus as the i801. */ + memset(*i801smbus, 0, sizeof(**i801smbus)); + (*i801smbus)->bus = bus; + (*i801smbus)->sysdata = bus->sysdata; + (*i801smbus)->hdr_type = PCI_HEADER_TYPE_NORMAL; + + DBG("i801smbus: now looking for i801smbus.\n"); + for (id = 0, devfn = 0; devfn < 0xFF; devfn++) { + (*i801smbus)->devfn = devfn; + ret = pci_read_config_word(*i801smbus, PCI_DEVICE_ID, &id); + if (ret == 0 && 0x2443 == id) { + pci_read_config_word(*i801smbus, PCI_VENDOR_ID, &vid); + if(vid == 0x8086) + break; + } + } + if (0x2443 != id) { + DBG("i801smbus: i801smbus not found although i801 present - strange.\n"); + return -EACCES; + } else { + DBG("i801smbus: i801smbus found and enabled. Devfn: 0x%X.\n", devfn); + } + /* We now have the devfn and bus of the i801smbus device. + * let's put the rest of the device data together. + */ + + (*i801smbus)->vendor = 0x8086; + (*i801smbus)->hdr_type = PCI_HEADER_TYPE_NORMAL; + (*i801smbus)->device = 0x2443; + + return(pci_setup_device(*i801smbus)); +} + + + + +/* Initialize the module */ +int init_module(void) +{ + struct pci_bus *bus = NULL; + struct pci_dev *dev = NULL; + int ret = 0; + + DBG("i801smbus: init_module().\n"); + + /* Are we on a PCI-Board? */ + if (!pci_present()) { + printk("i801smbus: No PCI bus found - sorry.\n"); + return -ENODEV; + } + + /* We want to be sure that the i801smbus is not present yet. */ + dev = pci_find_device(0x8086,0x2443, NULL); + + if (dev) + { + printk("i801smbus: SMBus already actve\n"); + return -EPERM; + } + + /* Are we operating a i801 chipset */ + dev = pci_find_device(0x8086,0x2440, NULL); + if (NULL == dev) + { + printk("INTEL ICH2 type 82801BA not found.\n"); + return -ENODEV ; + } + /* we need the bus pointer later */ + bus = dev->bus; + + + if ( (ret = i801smbus_enable(dev)) ) + { + printk("i801smbus: Unable to turn on i801smbus device - sorry!\n"); + return ret; + } + + if ( (ret = i801smbus_build(&i801smbus, bus)) ) + return ret; + + + if ( (ret = pci_enable_device(i801smbus)) ) { + printk("i801smbus: Unable to pci_enable i801smbus device!\n"); + return ret; + } + + DBG("i801smbus: now inserting.\n"); + pci_insert_device(i801smbus, i801smbus->bus); + printk("i801smbus: Enabled\n"); + i801smbus_inserted = TRUE; + return 0; +} + + +void cleanup_module() +{ + write_lock_irqsave(i801smbus_lock, i801smbus_lock_flags); + if (i801smbus_inserted) { + pci_remove_device(i801smbus); + i801smbus_inserted = FALSE; + } + write_unlock_irqrestore(i801smbus_lock, i801smbus_lock_flags); + + if (NULL != i801smbus) + { + kfree(i801smbus); + } + printk("i801smbus: SMBus device removed\n"); +} + +EXPORT_NO_SYMBOLS; + +#ifdef MODULE +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ilja Rauhut <IljaRauhut@web.de>, " + "Burkhard Kohl <bku@buks.ipn.de>, " + "Frank Bauer <frank.bauer@nikocity.de>, " + "and Mark Studebaker <mdsxyz123@yahoo.com>"); +MODULE_DESCRIPTION("i801smbus PCI Inserter"); + +#endif /* MODULE */ + + + + + + + + + + |