diff options
author | Mark D. Studebaker <mdsxyz123@yahoo.com> | 2000-10-09 03:10:03 +0000 |
---|---|---|
committer | Mark D. Studebaker <mdsxyz123@yahoo.com> | 2000-10-09 03:10:03 +0000 |
commit | d51bdd40d24ee96aae0d58919471fb0964f23010 (patch) | |
tree | b895c17411715fc2fc3b30023069ecea40536c03 /prog/hotplug | |
parent | ec8a8ef06cd9e4ee57b0e1e7f5b9ad9abcb90dae (diff) | |
download | lm-sensors-git-d51bdd40d24ee96aae0d58919471fb0964f23010.tar.gz |
(mds) Big update for 2.4.0-testx kernels. Now uses kernel
"hotplug" facility. Somewhat tested on my PC.
git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@894 7894878c-1315-0410-8ee3-d5d059ff63e0
Diffstat (limited to 'prog/hotplug')
-rw-r--r-- | prog/hotplug/Makefile | 16 | ||||
-rw-r--r-- | prog/hotplug/README | 19 | ||||
-rw-r--r-- | prog/hotplug/m7101.c | 380 |
3 files changed, 167 insertions, 248 deletions
diff --git a/prog/hotplug/Makefile b/prog/hotplug/Makefile index 869003f6..0e457898 100644 --- a/prog/hotplug/Makefile +++ b/prog/hotplug/Makefile @@ -1,9 +1,10 @@ INCLUDEDIR = /usr/include -CFLAGS = -D__KERNEL__ -DMODULE -DLINUX -DMODVERSION -O2 -Wall -I$(INCLUDEDIR) +#CFLAGS := -D__KERNEL__ -DMODULE -DLINUX -O2 -Wall -I$(INCLUDEDIR) +CC := gcc # Compile with Debugging turned on - watch out, lots of pci device infos. -#CFLAGS = -D__KERNEL__ -DMODULE -DLINUX -DMODVERSION -DM7101_DEBUG -O2 -Wall -I$(INCLUDEDIR) -LD = ld +CFLAGS = -D__KERNEL__ -DMODULE -DLINUX -DM7101_DEBUG -O2 -Wall -I$(INCLUDEDIR) +LD := ld # extract versionnumber from version.h VER = $(shell awk -F\" '/REL/ {print $$2}' $(INCLUDEDIR)/linux/version.h) @@ -11,3 +12,12 @@ VER = $(shell awk -F\" '/REL/ {print $$2}' $(INCLUDEDIR)/linux/version.h) OBJS = m7101.o all: $(OBJS) + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +install: all + install -o root -g root -m 644 $(OBJS) /lib/modules/$(VER)/misc + +clean: + rm -f $(OBJS) diff --git a/prog/hotplug/README b/prog/hotplug/README index 52a6b7d8..6df9806a 100644 --- a/prog/hotplug/README +++ b/prog/hotplug/README @@ -1,5 +1,23 @@ M7101 - SMBus Support for ALi M15x3 based motherboards. +-------------------------------------------------------- +Quick Start: + "lspci" to verify that 7101 device is not present + "make" + (as root) "make install" + (as root) "insmod m7101" + "lspci" to verify that 7101 device is present +-------------------------------------------------------- + +Version 0.2 for 2.4.0-testx kernels. +Mark D. Studebaker <mdsxyz123@yahoo.com> + +*** You must have 'Support for hot-pluggable devices' enabled +*** in your kernel (under 'general setup') for this module to work!! + +Notes below from the 0.1 version, B. Kohl. +-------------------------------------------------------- + This module was written to enable SMBus support on ALi M15x3 chipset based motherboards. Although it was written for and tested on Gigabytes GA-5AX it should work on any M15x3 chipset based board. @@ -42,6 +60,7 @@ motherboard's SMBus through the M7101. Values for the ACPI-IO port (normally 0x4000) and the SMBus-IO port (normally 0x5000) can be specified using the parameters acpi_io and smbus_io respectively on the insmod command line. +The module defaults to ports 0xec00 and 0xe800. In case the module does not load you might want to switch on debugging by uncommenting the second CFLAGS-line (with the -DM7101_DEBUG switch) diff --git a/prog/hotplug/m7101.c b/prog/hotplug/m7101.c index 6b33843d..9bbf5e70 100644 --- a/prog/hotplug/m7101.c +++ b/prog/hotplug/m7101.c @@ -4,8 +4,9 @@ * Initialize the M7101 device on ALi M15x3 Chipsets */ /* - Copyright (c) 2000 Burkhard Kohl <buk@buks.ipn.de> - and Frank Bauer <frank.bauer@nikocity.de> + 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 @@ -33,9 +34,17 @@ * June 21, 2000 MDS: Add Copyright and GPL comments, * distribute as release 0.1. * + * Sept 21, 2000 MDS: Rewrite to use kernel hotplug facility, + * (similar to drivers/pcmcia/cardbus.c), + * fix makefile so it will compile, + * distribute as release 0.2. + * * 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. * @@ -53,8 +62,13 @@ #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 */ -#if CONFIG_MODVERSIONS==1 +#ifdef CONFIG_MODVERSIONS #define MODVERSIONS #include <linux/modversions.h> #endif @@ -66,41 +80,16 @@ #include <linux/ioport.h> #include <linux/errno.h> #include <linux/malloc.h> -#include <asm/spinlock.h> +#include <asm/types.h> /* from lm_sensors-2.3.3: */ #define SMBHSTCFG 0x0E0 /* PCI Address Constants */ -#define SMBCOM 0x004 -#define ACPIBA 0x010 -#define SMBBA 0x014 #define SMBATPC 0x05B /* used to unlock xxxBA registers */ -#define SMBHSTCFG 0x0E0 -#define SMBSLVC 0x0E1 -#define SMBCLK 0x0E2 -#define SMBREV 0x008 /* ALI15X3 address lock bits */ #define ALI15X3_LOCK 0x06 -/* ALI15X3 command constants */ -#define ALI15X3_ABORT 0x02 -#define ALI15X3_T_OUT 0x04 -#define ALI15X3_QUICK 0x00 -#define ALI15X3_BYTE 0x10 -#define ALI15X3_BYTE_DATA 0x20 -#define ALI15X3_WORD_DATA 0x30 -#define ALI15X3_BLOCK_DATA 0x40 -#define ALI15X3_BLOCK_CLR 0x80 -/* ALI15X3 status register bits */ -#define ALI15X3_STS_IDLE 0x04 -#define ALI15X3_STS_BUSY 0x08 -#define ALI15X3_STS_DONE 0x10 -#define ALI15X3_STS_DEV 0x20 /* device error */ -#define ALI15X3_STS_COLL 0x40 /* collision or no response */ -#define ALI15X3_STS_TERM 0x80 /* terminated by abort */ -#define ALI15X3_STS_ERR 0xE0 /* all the bad error bits */ - /* addresses the i/o space gets mapped to, @@ -110,52 +99,25 @@ #define SMB_IO_SIZE 0x20 #define ACPI_BASE 0x0 #define SMB_BASE 0x1 -static u32 acpi_io_parm = 0; -static u32 smb_io_parm = 0; -MODULE_PARM(acpi_io_parm, "l"); -MODULE_PARM(smb_io_parm, "l"); +static u32 acpi_io = 0xEC00; /* Set I/O Base defaults here */ +static u32 smb_io = 0xE800; +static int debug = 0; +MODULE_PARM(acpi_io, "l"); +MODULE_PARM(smb_io, "l"); +#ifdef M7101_DEBUG +MODULE_PARM(debug, "i"); +#endif /* status, used to indicate that io space needs to be freed */ static struct pci_dev *m7101 = NULL; -static int m7101_attached = FALSE; static int m7101_inserted = FALSE; extern void cleanup_module(); -static rwlock_t m7101_lock = RW_LOCK_UNLOCKED; -static unsigned long m7101_lock_flags = 0; +static rwlock_t m7101_lock = RW_LOCK_UNLOCKED; +static unsigned long m7101_lock_flags = 0; -/* - * This function was shamelessly stolen from the kernel pci - * driver code. - */ -static void -pci_read_bases(struct pci_dev *dev, unsigned int howmany) -{ - unsigned int reg; - u32 l; - - for(reg=0; reg<howmany; reg++) { - pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), &l); - if (l == 0xffffffff) - continue; - dev->base_address[reg] = l; - if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) - == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) { reg++; - pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), &l); - if (l) { -#if BITS_PER_LONG == 64 - dev->base_address[reg-1] |= ((unsigned long) l) << 32; -#else - DBG("PCI: Unable to handle 64-bit address for device %02x:%02x\n", - dev->bus->number, dev->devfn); - dev->base_address[reg-1] = 0; -#endif - } - } - } -} - +#ifdef M7101_DEBUG static void dump_dev_data(struct pci_dev *dev, int address_data) { @@ -166,17 +128,18 @@ dump_dev_data(struct pci_dev *dev, int address_data) dev->vendor, dev->device); if (address_data) { - printk("m7101: base_address[0]: 0x%08lx base_address[1]: 0x%08lx\n", - dev->base_address[0], dev->base_address[1]); - printk("m7101: base_address[2]: 0x%08lx base_address[3]: 0x%08lx\n", - dev->base_address[2], dev->base_address[3]); - printk("m7101: base_address[4]: 0x%08lx base_address[5]: 0x%08lx\n", - dev->base_address[4], dev->base_address[5]); + printk("m7101: resource[0]: 0x%08lx resource[1]: 0x%08lx\n", + dev->resource[0].start, dev->resource[1].start); + printk("m7101: resource[2]: 0x%08lx resource[3]: 0x%08lx\n", + dev->resource[2].start, dev->resource[3].start); + printk("m7101: resource[4]: 0x%08lx resource[5]: 0x%08lx\n", + dev->resource[4].start, dev->resource[5].start); printk("m7101: rom_address: 0x%08lx \n", - dev->rom_address); + dev->resource[PCI_ROM_RESOURCE].start); } } } +#endif /* * Checks whether PMU and SMB are enabled and turns them on in case they are not. @@ -184,13 +147,12 @@ dump_dev_data(struct pci_dev *dev, int address_data) * I/O */ static int -m7101_enable(struct pci_dev *dev, u32 *devfn){ +m7101_enable(struct pci_dev *dev){ u8 val = 0; - u16 id = 0; pci_read_config_byte(dev, 0x5F, &val); DBG("m7101: M7101 config byte reading 0x%X.\n", val); - if (val & 0x4) { + if (val & 0x4) { pci_write_config_byte(dev, 0x5F, val & 0xFB); pci_read_config_byte(dev, 0x5F, &val); if(val & 0x4) { @@ -198,58 +160,59 @@ m7101_enable(struct pci_dev *dev, u32 *devfn){ return -EIO; } } - - /* The device should be on the same bus as the M1533. */ - DBG("m7101: now looking for M7101.\n"); - for (id = 0, *devfn = 0; *devfn < 0xFF; (*devfn)++) { - pcibios_read_config_word(dev->bus->number, *devfn, PCI_DEVICE_ID, &id); - if (PCI_DEVICE_ID_AL_M7101 == id) { - break; - } - } - if (PCI_DEVICE_ID_AL_M7101 != id) { - DBG("m7101: M7101 not found although M1533 present - strange.\n"); - return -EACCES; - } else { - DBG("m7101: M7101 found and enabled. Devfn: 0x%X.\n", *devfn); - } return 0; + } /* * Builds the basic pci_dev for the M7101 - * */ static int -m7101_build(struct pci_dev **m7101, u32 devfn, struct pci_bus *bus) +m7101_build(struct pci_dev **m7101, struct pci_bus *bus) { - u32 val = 0; + u32 devfn; + u16 id = 0; + u16 vid = 0; + int ret; - /* We now have the devfn and bus of the M7101 device. - * let's put the device data together. - */ - if ((pcibios_read_config_dword(bus->number, devfn, PCI_VENDOR_ID, &val) || - /* some broken boards return 0 if a slot is empty: */ - val == 0xffffffff || val == 0x00000000 || - val == 0x0000ffff || val == 0xffff0000)) { - - m7101 = NULL; - return -ENODEV; - } else { - DBG("m7101: requesting kernel space for the m7101 entry.\n"); + DBG("m7101: requesting kernel space for the m7101 entry.\n"); *m7101 = kmalloc(sizeof(**m7101), GFP_ATOMIC); - if(NULL == *m7101) - { - printk("m7101: out of memory.\n"); - return -ENOMEM; + if(NULL == *m7101) { + printk("m7101: out of memory.\n"); + return -ENOMEM; } + + /* minimally fill in structure for search */ + /* The device should be on the same bus as the M1533. */ memset(*m7101, 0, sizeof(**m7101)); (*m7101)->bus = bus; - (*m7101)->devfn = devfn; - (*m7101)->vendor = val & 0xffff; - (*m7101)->device = (val >> 16) & 0xffff; + (*m7101)->sysdata = bus->sysdata; + (*m7101)->hdr_type = PCI_HEADER_TYPE_NORMAL; + + DBG("m7101: now looking for M7101.\n"); + for (id = 0, devfn = 0; devfn < 0xFF; devfn++) { + (*m7101)->devfn = devfn; + ret = pci_read_config_word(*m7101, PCI_DEVICE_ID, &id); + if (ret == 0 && PCI_DEVICE_ID_AL_M7101 == id) { + pci_read_config_word(*m7101, PCI_VENDOR_ID, &vid); + if(vid == PCI_VENDOR_ID_AL) + break; + } } - return 0; + if (PCI_DEVICE_ID_AL_M7101 != id) { + DBG("m7101: M7101 not found although M1533 present - strange.\n"); + return -EACCES; + } else { + DBG("m7101: M7101 found and enabled. Devfn: 0x%X.\n", devfn); + } + /* We now have the devfn and bus of the M7101 device. + * let's put the rest of the device data together. + */ + + (*m7101)->vendor = PCI_VENDOR_ID_AL; + (*m7101)->hdr_type = PCI_HEADER_TYPE_NORMAL; + (*m7101)->device = PCI_DEVICE_ID_AL_M7101; + return(pci_setup_device(*m7101)); } /* @@ -267,7 +230,7 @@ m7101_unlock_registers(struct pci_dev *m7101) if(val & ALI15X3_LOCK) { DBG("m7101: need to unlock the address registers\n"); val &= ~ALI15X3_LOCK; - if (pci_write_config_byte(m7101, SMBATPC, val)) { + if (pci_write_config_byte(m7101, SMBATPC, val)) { DBG("m7101: failed to write SMBATPC\n"); return -EIO; } @@ -283,149 +246,100 @@ m7101_set_io_address(struct pci_dev *m7101, u32 addr, int base_idx, int size) { if (!addr) { printk("m7101: Sorry - cannot assign address 0 to region.\n"); - return -EINVAL; + return -EINVAL; } if (check_region(addr, size)) { printk("m7101: Requested IO-region 0x%x already in use.\n", addr); - return -EBUSY; + return -EBUSY; } else { - m7101->base_address[base_idx] = - addr | PCI_BASE_ADDRESS_SPACE_IO; + m7101->resource[base_idx].start = addr; } return 0; } -/* - * Maintain the ordering of the other devices. - * We know that first_on_bus and dev are on the same bus. - */ -static void -m7101_insert(struct pci_dev *m7101) -{ - struct pci_dev *first_on_bus = NULL, *dev = NULL; - u32 devfn = 0; - unsigned char bus_number = m7101->bus->number; - - /* Insert device into global chain of devices. */ - /* We have at least one other sibling on this bus */ - DBG("m7101: find first device in chain.\n"); - first_on_bus = NULL; devfn = 0; - while (NULL == (first_on_bus = pci_find_slot(bus_number, devfn)) ) { - devfn++; - } - write_lock_irqsave(m7101_lock, m7101_lock_flags); - if (first_on_bus->devfn < m7101->devfn) { - DBG("m7101: inserting M7101 after other devices on bus 0x%X.\n", - bus_number); - dev = first_on_bus; - while (dev->sibling) { - if (dev->sibling->devfn > m7101->devfn) { - break; - } - dev = dev->sibling; - } - m7101->next = dev->next; - m7101->sibling = dev->sibling; - dev->next = m7101; - dev->sibling = m7101; - } else { - /* - * If we insert dev before first_on_bus, we have to find the - * device pointing to first_on_bus. - */ - DBG("m7101: inserting M7101 as first device on bus 0x%X.\n", - bus_number); - - m7101->next = first_on_bus; - m7101->sibling = first_on_bus; - dev = pci_devices; - if (dev == first_on_bus) { - dev = m7101; - } else { - while (dev->next != first_on_bus) { - dev = dev->next; - } - /* We can't miss first_on_bus, can we ? */ - dev->next = m7101; - } - } - write_unlock_irqrestore(m7101_lock, m7101_lock_flags); -} /* Initialize the module */ int init_module(void) { struct pci_bus *bus = NULL; struct pci_dev *dev = NULL; - u32 devfn = 0; - u32 acpi_addr = 0, smb_addr = 0; + u32 acpi_addr = 0, smb_addr = 0; int ret = 0; DBG("m7101: init_module().\n"); /* Are we on a PCI-Board? */ if (!pci_present()) { - printk("m7101: No pci board found - sorry.\n"); + printk("m7101: No PCI bus found - sorry.\n"); return -ENODEV; } /* We want to be sure that the M7101 is not present yet. */ - dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL); - if (dev) { + dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL); + if (dev) { printk("m7101: M7101 already present, no need to run this module.\n"); - dev = NULL; - return -EPERM; - } +#ifdef M7101_DEBUG + if(debug) + { + pci_remove_device(dev); + printk("m7101: removing device for testing\n"); + m7101_inserted = 0; + return 0; + } + else +#endif + return -EPERM; + } /* Are we operating a M15x3 chipset */ - dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); - if (NULL == dev) { - printk("m7101: This is not an ALi M15x3 chipset.\n"); + dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); + if (NULL == dev) { + printk("m7101: ALi M15xx chipset not found.\n"); return -ENODEV ; - } else { - /* we need the bus pointer later */ - bus = dev->bus; } + /* we need the bus pointer later */ + bus = dev->bus; - if ( (ret = m7101_enable(dev, &devfn)) ) { + if ( (ret = m7101_enable(dev)) ) { printk("m7101: Unable to turn on M7101 device - sorry!\n"); return ret; } - if ( (ret = m7101_build(&m7101, devfn, bus)) ){ + if ( (ret = m7101_build(&m7101, bus)) ){ return ret; } - /* thus, now we have a rudimentary dev for M7101 ... */ - /* check wether register need to be unlocked. */ + /* thus, now we have a rudimentary dev for M7101 ... */ + /* check wether register need to be unlocked. */ if ( (ret = m7101_unlock_registers(m7101)) ){ return ret; } - /* Just for debugging purposes */ - pci_read_bases(m7101, 6); - /* * Handle address assignment for ACPI_IO * If address is already assigned do nothing. */ - acpi_addr = m7101->base_address[ACPI_BASE]; + acpi_addr = m7101->resource[ACPI_BASE].start; if (!acpi_addr) { - ret = m7101_set_io_address(m7101, acpi_io_parm,ACPI_BASE, ACPI_IO_SIZE); + acpi_io |= PCI_BASE_ADDRESS_SPACE_IO; + ret = m7101_set_io_address(m7101, acpi_io,ACPI_BASE, ACPI_IO_SIZE); if (ret) return ret; + acpi_addr = acpi_io; } /* * Handle address assignment for SMB_IO * If address is already assigned then do nothing. */ - smb_addr = m7101->base_address[SMB_BASE]; + smb_addr = m7101->resource[SMB_BASE].start; if (!smb_addr) { - ret = m7101_set_io_address(m7101, smb_io_parm, SMB_BASE, SMB_IO_SIZE); + smb_io |= PCI_BASE_ADDRESS_SPACE_IO; + ret = m7101_set_io_address(m7101, smb_io, SMB_BASE, SMB_IO_SIZE); if (ret) return ret; + smb_addr = smb_io; } #ifdef M7101_DEBUG @@ -433,31 +347,16 @@ int init_module(void) #endif - DBG("m7101: now inserting.\n"); - m7101_insert(m7101); - m7101_inserted = TRUE; - - DBG("m7101: now dumping global list.\n"); - for (dev = pci_devices; NULL != dev->next ; dev = dev->next) { -#ifdef M7101_DEBUG - dump_dev_data(dev, 0); - dump_dev_data(dev->next, 0); - dump_dev_data(dev->sibling, 0); - printk("\n"); -#endif + if ( (ret = pci_enable_device(m7101)) ) { + printk("m7101: Unable to pci_enable M7101 device!\n"); + return ret; } - /* Attach the device to the proc listing. */ - DBG("m7101: Attaching device to proc file system.\n"); - if ( (ret = pci_proc_attach_device(m7101)) ){ - printk("m7101: could not attach device to proc fs.\n"); - /* Get it out of the way or /proc/bus/pci will be garbled. */ - cleanup_module(); - return ret; - } else { - m7101_attached = TRUE; - printk("m7101: device inserted.\n"); - } + DBG("m7101: now inserting.\n"); + pci_insert_device(m7101, m7101->bus); + printk("m7101: Enabled with ACPI I/O address 0x%04X and SMB I/O address 0x%04X\n", + acpi_addr, smb_addr); + m7101_inserted = TRUE; return 0; } @@ -465,28 +364,9 @@ int init_module(void) void cleanup_module() { - - struct pci_dev *dev; - - if (m7101_attached) { - pci_proc_detach_device(m7101); - m7101_attached = FALSE; - } - write_lock_irqsave(m7101_lock, m7101_lock_flags); if (m7101_inserted) { - if (pci_devices == m7101) - pci_devices = m7101->next; - else { - dev = pci_devices; - while (dev->next != m7101) { - dev = dev->next; - } - dev->next = m7101->next; - if (dev->sibling) { - dev->sibling = m7101->sibling; - } - } + pci_remove_device(m7101); m7101_inserted = FALSE; } write_unlock_irqrestore(m7101_lock, m7101_lock_flags); @@ -495,5 +375,15 @@ void cleanup_module() kfree(m7101); printk("m7101: bye bye\n"); - } + +EXPORT_NO_SYMBOLS; + +#ifdef MODULE + +MODULE_AUTHOR("Burkhard Kohl <bku@buks.ipn.de>, " + "Frank Bauer <frank.bauer@nikocity.de>, " + "and Mark Studebaker <mdsxyz123@yahoo.com>"); +MODULE_DESCRIPTION("M7101 PCI Inserter"); + +#endif /* MODULE */ |