summaryrefslogtreecommitdiff
path: root/prog/hotplug
diff options
context:
space:
mode:
authorMark D. Studebaker <mdsxyz123@yahoo.com>2002-02-27 02:47:04 +0000
committerMark D. Studebaker <mdsxyz123@yahoo.com>2002-02-27 02:47:04 +0000
commit55552ad444bba02f0e0cfb3939908cf65457fda1 (patch)
tree26df5d38f987a0c38b02e9f6a48d49f7065fcc95 /prog/hotplug
parent0c567ff863735c58a3e1c18d4717667220dbee4e (diff)
downloadlm-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.p4b35
-rw-r--r--prog/hotplug/README.p4b69
-rw-r--r--prog/hotplug/p4b_smbus.c268
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 */
+
+
+
+
+
+
+
+
+
+