diff options
-rw-r--r-- | kernel/Module.mk | 49 | ||||
-rw-r--r-- | kernel/busses/i2c-isa.c | 198 | ||||
-rw-r--r-- | kernel/busses/i2c-piix4.c | 443 | ||||
-rw-r--r-- | kernel/chips/eeprom.c | 387 | ||||
-rw-r--r-- | kernel/chips/gl518sm.c | 674 | ||||
-rw-r--r-- | kernel/chips/lm75.c | 363 | ||||
-rw-r--r-- | kernel/chips/lm78.c | 926 | ||||
-rw-r--r-- | kernel/chips/lm80.c | 686 | ||||
-rw-r--r-- | kernel/chips/w83781d.c | 1120 | ||||
-rw-r--r-- | kernel/compat.h | 85 | ||||
-rw-r--r-- | kernel/i2c-proc.c | 478 | ||||
-rw-r--r-- | kernel/include/compat.h | 85 | ||||
-rw-r--r-- | kernel/include/i2c-isa.h | 158 | ||||
-rw-r--r-- | kernel/include/i2c.h | 30 | ||||
-rw-r--r-- | kernel/include/isa.h | 158 | ||||
-rw-r--r-- | kernel/include/sensors.h | 227 | ||||
-rw-r--r-- | kernel/include/smbus.h | 299 | ||||
-rw-r--r-- | kernel/sensors.c | 617 | ||||
-rw-r--r-- | kernel/smbus.c | 277 |
19 files changed, 0 insertions, 7260 deletions
diff --git a/kernel/Module.mk b/kernel/Module.mk deleted file mode 100644 index afb57a60..00000000 --- a/kernel/Module.mk +++ /dev/null @@ -1,49 +0,0 @@ -# Module.mk - Makefile for a Linux module for reading sensor data. -# Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> -# -# 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. - -# Note that MODULE_DIR (the directory in which this file resides) is a -# 'simply expanded variable'. That means that its value is substituted -# verbatim in the rules, until it is redefined. -MODULE_DIR := src - -# Regrettably, even 'simply expanded variables' will not put their currently -# defined value verbatim into the command-list of rules... -SRCTARGETS := $(MODULE_DIR)/smbus.o $(MODULE_DIR)/piix4.o $(MODULE_DIR)/isa.o \ - $(MODULE_DIR)/lm78.o $(MODULE_DIR)/sensors.o \ - $(MODULE_DIR)/i2c-proc.o $(MODULE_DIR)/lm75.o \ - $(MODULE_DIR)/i2c-proc.o $(MODULE_DIR)/gl518sm.o \ - $(MODULE_DIR)/eeprom.o $(MODULE_DIR)/w83781d.o \ - $(MODULE_DIR)/lm80.o - -SRCHEADERFILES := $(MODULE_DIR)/sensors.h $(MODULE_DIR)/isa.h \ - $(MODULE_DIR)/smbus.h - -# Include all dependency files -INCLUDEFILES += $(SRCTARGETS:.o=.d) - -all-src: $(SRCTARGETS) -all :: all-src - -install-src: - $(MKDIR) $(MODDIR) $(SYSINCLUDEDIR) - $(INSTALL) -o root -g root -m 644 $(SRCTARGETS) $(MODDIR) - $(INSTALL) -o root -g root -m 644 $(SRCHEADERFILES) $(SYSINCLUDEDIR) -install :: install-src - -clean-src: - $(RM) $(SRCTARGETS) $(SRCTARGETS:.o=.d) -clean :: clean-src diff --git a/kernel/busses/i2c-isa.c b/kernel/busses/i2c-isa.c deleted file mode 100644 index 8ec904ae..00000000 --- a/kernel/busses/i2c-isa.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - isa.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> - - 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. -*/ - -/* This implements an i2c algorithm/adapter for ISA bus. Not that this is - on first sight very useful; almost no functionality is preserved. - Except that it makes writing drivers for chips which can be on both - the SMBus and the ISA bus very much easier. See lm78.c for an example - of this. */ - -#include <linux/module.h> -#include <linux/kernel.h> - -#include "i2c.h" -#ifdef SPINLOCK -#include <asm/spinlock.h> -#else -#include <asm/semaphore.h> -#endif - -#include "version.h" -#include "isa.h" - -static int isa_master_xfer (struct isa_adapter *adap, - struct i2c_msg msgs[], int num); -static int isa_slave_send (struct isa_adapter *adap, char *data, int len); -static int isa_slave_recv (struct isa_adapter *adap, char *data, int len); -static int isa_algo_control (struct isa_adapter *adap, unsigned int cmd, - unsigned long arg); -static int isa_client_register (struct isa_client *client); -static int isa_client_unregister (struct isa_client *client); - -static int isa_init(void); -static int isa_cleanup(void); - -#ifdef MODULE -extern int init_module(void); -extern int cleanup_module(void); -#endif /* MODULE */ - -/* This is the actual algorithm we define */ -static struct isa_algorithm isa_algorithm = { - /* name */ "ISA bus adapter", - /* id */ ALGO_ISA, - /* master_xfer */ &isa_master_xfer, - /* slave_send */ &isa_slave_send, - /* slave_rcv */ &isa_slave_recv, - /* algo_control */ &isa_algo_control, - /* client_register */ &isa_client_register, - /* client_unregister*/&isa_client_unregister -}; - -/* There can only be one... */ -static struct isa_adapter isa_adapter; - -/* Used in isa_init/cleanup */ -static int isa_initialized; - -/* Algorithm master_xfer call-back implementation. Can't do that... */ -int isa_master_xfer (struct isa_adapter *adap, struct i2c_msg msgs[], - int num) -{ -#ifdef DEBUG - printk("isa.o: isa_master_xfer called for adapter `%s' " - "(no i2c level access possible!)\n", - adap->name); -#endif - return -1; -} - -/* Algorithm slave_send call-back implementation. Can't do that... */ -int isa_slave_send (struct isa_adapter *adap, char *data, int len) -{ -#ifdef DEBUG - printk("isa.o: isa_slave_send called for adapter `%s' " - "(no i2c level access possible!)\n", - adap->name); -#endif - return -1; -} - -/* Algorithm slave_recv call-back implementation. Can't do that... */ -int isa_slave_recv (struct isa_adapter *adap, char *data, int len) -{ -#ifdef DEBUG - printk("isa.o: isa_slave_recv called for adapter `%s' " - "(no i2c level access possible!)\n", - adap->name); -#endif - return -1; -} - -/* Here we can put additional calls to modify the workings of the algorithm. - But right now, there is no need for that. */ -int isa_algo_control (struct isa_adapter *adap, unsigned int cmd, - unsigned long arg) -{ - return 0; -} - -/* Ehm... This is called when a client is registered to an adapter. We could - do all kinds of neat stuff here like, ehm - returning success? */ -int isa_client_register (struct isa_client *client) -{ - return 0; -} - -int isa_client_unregister (struct isa_client *client) -{ - return 0; -} - -int isa_init(void) -{ - int res; - printk("isa.o version %s (%s)\n",LM_VERSION,LM_DATE); -#ifdef DEBUG - if (isa_initialized) { - printk("isa.o: Oops, isa_init called a second time!\n"); - return -EBUSY; - } -#endif - isa_initialized = 0; - if ((res = isa_add_algorithm(&isa_algorithm))) { - printk("isa.o: Algorithm registration failed, module not inserted.\n"); - isa_cleanup(); - return res; - } - isa_initialized++; - strcpy(isa_adapter.name,"ISA main adapter"); - isa_adapter.id = ALGO_ISA | ISA_MAIN; - isa_adapter.algo = &isa_algorithm; - if ((res = isa_add_adapter(&isa_adapter))) { - printk("isa.o: Adapter registration failed, " - "module isa.o is not inserted\n."); - isa_cleanup(); - return res; - } - isa_initialized++; - printk("isa.o: ISA bus access for i2c modules initialized.\n"); - return 0; -} - -int isa_cleanup(void) -{ - int res; - if (isa_initialized >= 2) - { - if ((res = isa_del_adapter(&isa_adapter))) { - printk("isa.o: Adapter deregistration failed, module not removed.\n"); - return res; - } else - isa_initialized--; - } - if (isa_initialized >= 1) - { - if ((res = isa_del_algorithm(&isa_algorithm))) { - printk("isa.o: Algorithm deregistration failed, module not removed.\n"); - return res; - } else - isa_initialized--; - } - return 0; -} - -#ifdef MODULE - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); -MODULE_DESCRIPTION("ISA bus access through i2c"); - -int init_module(void) -{ - return isa_init(); -} - -int cleanup_module(void) -{ - return isa_cleanup(); -} - -#endif /* MODULE */ - diff --git a/kernel/busses/i2c-piix4.c b/kernel/busses/i2c-piix4.c deleted file mode 100644 index 8488a6eb..00000000 --- a/kernel/busses/i2c-piix4.c +++ /dev/null @@ -1,443 +0,0 @@ -/* - smbus.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> and - Philip Edelbrock <phil@netroedge.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. -*/ - -/* Note: we assume there can only be one PIIX4, with one SMBus interface */ - -#include <linux/module.h> -#include <linux/pci.h> -#include <asm/io.h> -#include <linux/kernel.h> -#include <linux/stddef.h> -#include <linux/sched.h> -#include <linux/ioport.h> -#include "smbus.h" -#include "version.h" -#include "compat.h" - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,54)) -#include <linux/bios32.h> -#endif - - -/* PIIX4 SMBus address offsets */ -#define SMBHSTSTS (0 + piix4_smba) -#define SMBHSLVSTS (1 + piix4_smba) -#define SMBHSTCNT (2 + piix4_smba) -#define SMBHSTCMD (3 + piix4_smba) -#define SMBHSTADD (4 + piix4_smba) -#define SMBHSTDAT0 (5 + piix4_smba) -#define SMBHSTDAT1 (6 + piix4_smba) -#define SMBBLKDAT (7 + piix4_smba) -#define SMBSLVCNT (8 + piix4_smba) -#define SMBSHDWCMD (9 + piix4_smba) -#define SMBSLVEVT (0xA + piix4_smba) -#define SMBSLVDAT (0xC + piix4_smba) - -/* PCI Address Constants */ -#define SMBBA 0x090 -#define SMBHSTCFG 0x0D2 -#define SMBSLVC 0x0D3 -#define SMBSHDW1 0x0D4 -#define SMBSHDW2 0x0D5 -#define SMBREV 0x0D6 - -/* Other settings */ -#define MAX_TIMEOUT 500 -#define ENABLE_INT9 0 - -/* PIIX4 constants */ -#define PIIX4_QUICK 0x00 -#define PIIX4_BYTE 0x04 -#define PIIX4_BYTE_DATA 0x08 -#define PIIX4_WORD_DATA 0x0C -#define PIIX4_BLOCK_DATA 0x14 - - -static int piix4_init(void); -static int piix4_cleanup(void); -static int piix4_setup(void); -static s32 piix4_access(u8 addr, char read_write, - u8 command, int size, union smbus_data * data); -static void piix4_do_pause( unsigned int amount ); -static int piix4_transaction(void); - -#ifdef MODULE -extern int init_module(void); -extern int cleanup_module(void); -#endif /* MODULE */ - -static struct smbus_adapter piix4_adapter; -static int piix4_initialized; -static unsigned short piix4_smba = 0; - - -/* Detect whether a PIIX4 can be found, and initialize it, where necessary. - Note the differences between kernels with the old PCI BIOS interface and - newer kernels with the real PCI interface. In compat.h some things are - defined to make the transition easier. */ -int piix4_setup(void) -{ - int error_return=0; - unsigned char temp; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,54)) - struct pci_dev *PIIX4_dev; -#else - unsigned char PIIX4_bus, PIIX4_devfn; - int i,res; -#endif - - /* First check whether we can access PCI at all */ - if (pci_present() == 0) { - printk("piix4.o: Error: No PCI-bus found!\n"); - error_return=-ENODEV; - goto END; - } - - /* Look for the PIIX4, function 3 */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,54)) - /* Note: we keep on searching until we have found 'function 3' */ - PIIX4_dev = NULL; - do - PIIX4_dev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_3, PIIX4_dev); - while(PIIX4_dev && (PCI_FUNC(PIIX4_dev->devfn) != 3)); - if(PIIX4_dev == NULL) { -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,54) */ - for (i = 0; - ! (res = pcibios_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_3, - i,&PIIX4_bus, &PIIX4_devfn)) && - PCI_FUNC(PIIX4_devfn) != 3; - i++); - - if (res) { -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,54) */ - printk("piix4.o: Error: Can't detect PIIX4, function 3!\n"); - error_return=-ENODEV; - goto END; - } - -/* Determine the address of the SMBus areas */ - pci_read_config_word_united(PIIX4_dev, PIIX4_bus ,PIIX4_devfn, - SMBBA,&piix4_smba); - piix4_smba &= 0xfff0; - - if (check_region(piix4_smba, 8)) { - printk("piix4.o: PIIX4_smb region 0x%x already in use!\n", piix4_smba); - error_return=-ENODEV; - goto END; - } - - pci_read_config_byte_united(PIIX4_dev, PIIX4_bus, PIIX4_devfn, - SMBHSTCFG, &temp); - - -#ifdef FORCE_PIIX4_ENABLE -/* This should never need to be done, but has been noted that - many Dell machines have the SMBus interface on the PIIX4 - disabled!? NOTE: This assumes I/O space and other allocations WERE - done by the Bios! Don't complain if your hardware does weird - things after enabling this. :') Check for Bios updates before - resorting to this. */ - if ((temp & 1) == 0) { - pci_write_config_byte_united(PIIX4_dev, PIIX4_bus, PIIX4_devfn, - SMBHSTCFG, temp | 1); - printk("piix4.0: WARNING: PIIX4 SMBus interface has been FORCEFULLY " - "ENABLED!!\n"); - /* Update configuration value */ - pci_read_config_byte_united(PIIX4_dev, PIIX4_bus, PIIX4_devfn, - SMBHSTCFG, &temp); - /* Note: We test the bit again in the next 'if' just to be sure... */ - } -#endif /* FORCE_PIIX4_ENABLE */ - - if ((temp & 1) == 0) { - printk("SMBUS: Error: Host SMBus controller not enabled!\n"); - error_return=-ENODEV; - goto END; - } - - /* Everything is happy, let's grab the memory and set things up. */ - request_region(piix4_smba, 8, "piix4"); - -#ifdef DEBUG - if ((temp & 0x0E) == 8) - printk("piix4.o: PIIX4 using Interrupt 9 for SMBus.\n"); - else if ((temp & 0x0E) == 0) - printk("piix4.o: PIIX4 using Interrupt SMI# for SMBus.\n"); - else - printk("piix4.o: PIIX4: Illegal Interrupt configuration (or code out " - "of date)!\n"); - - pci_read_config_byte_united(PIIX4_dev, PIIX4_bus, PIIX4_devfn, SMBREV, - &temp); - printk("piix4.o: SMBREV = 0x%X\n",temp); - printk("piix4.o: PIIX4_smba = 0x%X\n",piix4_smba); -#endif /* DEBUG */ - -END: - return error_return; -} - - -/* Internally used pause function */ -void piix4_do_pause( unsigned int amount ) -{ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(amount); -} - -/* Another internally used function */ -int piix4_transaction(void) -{ - int temp; - int result=0; - int timeout=0; - -#ifdef DEBUG - printk("piix4.o: Transaction: CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, " - "DAT1=%02x\n", - inb_p(SMBHSTCNT),inb_p(SMBHSTCMD),inb_p(SMBHSTADD),inb_p(SMBHSTDAT0), - inb_p(SMBHSTDAT1)); -#endif - - /* Make sure the SMBus host is ready to start transmitting */ - if ((temp = inb_p(SMBHSTSTS)) != 0x00) { -#ifdef DEBUG - printk("piix4.o: SMBus busy (%02x). Resetting... \n",temp); -#endif - outb_p(temp, SMBHSTSTS); - if ((temp = inb_p(SMBHSTSTS)) != 0x00) { -#ifdef DEBUG - printk("piix4.o: Failed! (%02x)\n",temp); -#endif - return -1; - } else { -#ifdef DEBUG - printk("piix4.o: Successfull!\n"); -#endif - } - } - - /* start the transaction by setting bit 6 */ - outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT); - - /* We will always wait for a fraction of a second! (See PIIX4 docs errata) */ - do { - piix4_do_pause(1); - temp=inb_p(SMBHSTSTS); - } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); - - /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { -#ifdef DEBUG - printk("piix4.o: SMBus Timeout!\n"); - result = -1; -#endif - } - - if (temp & 0x10) { - result = -1; -#ifdef DEBUG - printk("piix4.o: Error: Failed bus transaction\n"); -#endif - } - - if (temp & 0x08) { - result = -1; - printk("piix4.o: Bus collision! SMBus may be locked until next hard - reset. (sorry!)\n"); - /* Clock stops and slave is stuck in mid-transmission */ - } - - if (temp & 0x04) { - result = -1; -#ifdef DEBUG - printk("piix4.o: Error: no response!\n"); -#endif - } - - if (inb_p(SMBHSTSTS) != 0x00) - outb_p( inb(SMBHSTSTS), SMBHSTSTS); - - if ((temp = inb_p(SMBHSTSTS)) != 0x00) { -#ifdef DEBUG - printk("piix4.o: Failed reset at end of transaction (%02x)\n",temp); -#endif - } - return result; -} - -/* Return -1 on error. See smbus.h for more information */ -s32 piix4_access(u8 addr, char read_write, - u8 command, int size, union smbus_data * data) -{ - int i,len; - - switch(size) { - case SMBUS_PROC_CALL: - printk("piix4.o: SMBUS_PROC_CALL not supported!\n"); - return -1; - case SMBUS_QUICK: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); - size = PIIX4_QUICK; - break; - case SMBUS_BYTE: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); - if (read_write == SMBUS_WRITE) - outb_p(command, SMBHSTCMD); - size = PIIX4_BYTE; - break; - case SMBUS_BYTE_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == SMBUS_WRITE) - outb_p(data->byte,SMBHSTDAT0); - size = PIIX4_BYTE_DATA; - break; - case SMBUS_WORD_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == SMBUS_WRITE) { - outb_p(data->word & 0xff,SMBHSTDAT0); - outb_p((data->word & 0xff00) >> 8,SMBHSTDAT1); - } - size = PIIX4_WORD_DATA; - break; - case SMBUS_BLOCK_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == SMBUS_WRITE) { - len = data->block[0]; - if (len < 0) - len = 0; - if (len > 32) - len = 32; - outb_p(len,SMBHSTDAT0); - i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ - for (i = 1; i <= len; i ++) - outb_p(data->block[i],SMBBLKDAT); - } - size = PIIX4_BLOCK_DATA; - break; - } - - outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT); - - if (piix4_transaction()) /* Error in transaction */ - return -1; - - if ((read_write == SMBUS_WRITE) || (size == PIIX4_QUICK)) - return 0; - - - switch(size) { - case PIIX4_BYTE: /* Where is the result put? I assume here it is in - SMBHSTDAT0 but it might just as well be in the - SMBHSTCMD. No clue in the docs */ - - data->byte = inb_p(SMBHSTDAT0); - break; - case PIIX4_BYTE_DATA: - data->byte = inb_p(SMBHSTDAT0); - break; - case PIIX4_WORD_DATA: - data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); - break; - case PIIX4_BLOCK_DATA: - data->block[0] = inb_p(SMBHSTDAT0); - i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ - for (i = 1; i <= data->block[0]; i++) - data->block[i] = inb_p(SMBBLKDAT); - break; - } - return 0; -} - - -int piix4_init(void) -{ - int res; - printk("piix4.o version %s (%s)\n",LM_VERSION,LM_DATE); -#ifdef DEBUG -/* PE- It might be good to make this a permanent part of the code! */ - if (piix4_initialized) { - printk("piix4.o: Oops, piix4_init called a second time!\n"); - return -EBUSY; - } -#endif - piix4_initialized = 0; - if ((res = piix4_setup())) { - printk("piix4.o: PIIX4 not detected, module not inserted.\n"); - piix4_cleanup(); - return res; - } - piix4_initialized ++; - sprintf(piix4_adapter.name,"SMBus PIIX4 adapter at %04x",piix4_smba); - piix4_adapter.id = ALGO_SMBUS | SMBUS_PIIX4; - piix4_adapter.algo = &smbus_algorithm; - piix4_adapter.smbus_access = &piix4_access; - if ((res = smbus_add_adapter(&piix4_adapter))) { - printk("piix4.o: Adapter registration failed, module not inserted.\n"); - piix4_cleanup(); - return res; - } - piix4_initialized++; - printk("piix4.o: PIIX4 bus detected and initialized\n"); - return 0; -} - -int piix4_cleanup(void) -{ - int res; - if (piix4_initialized >= 2) - { - if ((res = smbus_del_adapter(&piix4_adapter))) { - printk("piix4.o: smbus_del_adapter failed, module not removed\n"); - return res; - } else - piix4_initialized--; - } - if (piix4_initialized >= 1) { - release_region(piix4_smba, 8); - piix4_initialized--; - } - return 0; -} - -#ifdef MODULE - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>"); -MODULE_DESCRIPTION("PIIX4 SMBus driver"); - -int init_module(void) -{ - return piix4_init(); -} - -int cleanup_module(void) -{ - return piix4_cleanup(); -} - -#endif /* MODULE */ - diff --git a/kernel/chips/eeprom.c b/kernel/chips/eeprom.c deleted file mode 100644 index 20f1f876..00000000 --- a/kernel/chips/eeprom.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - eeprom.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> and - Philip Edelbrock <phil@netroedge.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. -*/ - -#include <linux/module.h> -#include <linux/malloc.h> -#include "smbus.h" -#include "sensors.h" -#include "i2c.h" -#include "version.h" - -/* Many constants specified below */ - -/* EEPROM memory types: */ -#define ONE_K 1 -#define TWO_K 2 -#define FOUR_K 3 -#define EIGHT_K 4 -#define SIXTEEN_K 5 - -/* Conversions */ -/* Size of EEPROM in bytes */ -#define EEPROM_SIZE 128 - -/* Each client has this additional data */ -struct eeprom_data { - int sysctl_id; - - struct semaphore update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - u8 data[EEPROM_SIZE]; /* Register values */ - int memtype; -}; - -#ifdef MODULE -extern int init_module(void); -extern int cleanup_module(void); -#endif /* MODULE */ - -static int eeprom_init(void); -static int eeprom_cleanup(void); - -static int eeprom_attach_adapter(struct i2c_adapter *adapter); -static int eeprom_detach_client(struct i2c_client *client); -static int eeprom_command(struct i2c_client *client, unsigned int cmd, - void *arg); - -static void eeprom_inc_use (struct i2c_client *client); -static void eeprom_dec_use (struct i2c_client *client); - -static u16 swap_bytes(u16 val); - -static int eeprom_read_value(struct i2c_client *client, u8 reg); -static int eeprom_write_value(struct i2c_client *client, u8 reg, u16 value); - -static void eeprom_contents(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); -static void eeprom_update_client(struct i2c_client *client); - - -/* This is the driver that will be inserted */ -static struct i2c_driver eeprom_driver = { - /* name */ "EEPROM READER", - /* id */ I2C_DRIVERID_EEPROM, - /* flags */ DF_NOTIFY, - /* attach_adapter */ &eeprom_attach_adapter, - /* detach_client */ &eeprom_detach_client, - /* command */ &eeprom_command, - /* inc_use */ &eeprom_inc_use, - /* dec_use */ &eeprom_dec_use -}; - -/* These files are created for each detected EEPROM. This is just a template; - though at first sight, you might think we could use a statically - allocated list, we need some way to get back to the parent - which - is done through one of the 'extra' fields which are initialized - when a new copy is allocated. */ -static ctl_table eeprom_dir_table_template[] = { - { EEPROM_SYSCTL1, "data0-15", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &eeprom_contents }, - { EEPROM_SYSCTL2, "data16-31", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &eeprom_contents }, - { EEPROM_SYSCTL3, "data32-47", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &eeprom_contents }, - { EEPROM_SYSCTL4, "data48-63", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &eeprom_contents }, - { EEPROM_SYSCTL5, "data64-79", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &eeprom_contents }, - { EEPROM_SYSCTL6, "data80-95", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &eeprom_contents }, - { EEPROM_SYSCTL7, "data96-111", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &eeprom_contents }, - { EEPROM_SYSCTL8, "data112-127", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &eeprom_contents }, - { 0 } -}; - -/* Used by init/cleanup */ -static int eeprom_initialized = 0; - -/* I choose here for semi-static LM78 allocation. Complete dynamic - allocation could also be used; the code needed for this would probably - take more memory than the datastructure takes now. */ -#define MAX_EEPROM_NR 8 -static struct i2c_client *eeprom_list[MAX_EEPROM_NR]; - - -int eeprom_attach_adapter(struct i2c_adapter *adapter) -{ - int address,err,i; - struct i2c_client *new_client; - struct eeprom_data *data; - - err = 0; - - /* OK, this is no detection. I know. It will do for now, though. */ - - /* Set err only if a global error would make registering other clients - impossible too (like out-of-memory). */ - - /* Serial EEPROMs for SMBus use addresses from 0x50 to 0x57 */ - for (address = 0x50; (! err) && (address <= 0x57); address ++) { - - /* Later on, we will keep a list of registered addresses for each - adapter, and check whether they are used here */ - - if (smbus_read_byte(adapter,address) < 0) { -#ifdef DEBUG - printk("eeprom.o: No eeprom found at: 0x%X\n",address); -#endif - continue; - } - - /* Real detection code goes here */ - - /* Allocate space for a new client structure */ - if (! (new_client = kmalloc(sizeof(struct i2c_client) + - sizeof(struct eeprom_data), - GFP_KERNEL))) { - err = -ENOMEM; - continue; - } - - /* Find a place in our global list */ - for (i = 0; i < MAX_EEPROM_NR; i++) - if (! eeprom_list[i]) - break; - if (i == MAX_EEPROM_NR) { - err = -ENOMEM; - printk("eeprom.o: No empty slots left, recompile and heighten " - "MAX_EEPROM_NR!\n"); - goto ERROR1; - } - eeprom_list[i] = new_client; - - /* Fill the new client structure with data */ - data = (struct eeprom_data *) (new_client + 1); - new_client->data = data; - new_client->id = i; - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &eeprom_driver; - strcpy(new_client->name,"EEPROM chip"); - data->valid = 0; - data->update_lock = MUTEX; - - /* Tell i2c-core a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto ERROR2; - - /* Register a new directory entry with module sensors */ - if ((err = sensors_register_entry(new_client,"eeprom", - eeprom_dir_table_template)) < 0) - goto ERROR3; - data->sysctl_id = err; - err = 0; - - continue; -/* OK, this is not exactly good programming practice, usually. But it is - very code-efficient in this case. */ - -ERROR3: - i2c_detach_client(new_client); -ERROR2: - eeprom_list[i] = NULL; -ERROR1: - kfree(new_client); - } - return err; -} - -int eeprom_detach_client(struct i2c_client *client) -{ - int err,i; - for (i = 0; i < MAX_EEPROM_NR; i++) - if (client == eeprom_list[i]) - break; - if ((i == MAX_EEPROM_NR)) { - printk("eeprom.o: Client to detach not found.\n"); - return -ENOENT; - } - - sensors_deregister_entry(((struct eeprom_data *)(client->data))->sysctl_id); - - if ((err = i2c_detach_client(client))) { - printk("eeprom.o: Client deregistration failed, client not detached.\n"); - return err; - } - - eeprom_list[i] = NULL; - kfree(client); - return 0; -} - - -/* No commands defined yet */ -int eeprom_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - return 0; -} - -void eeprom_inc_use (struct i2c_client *client) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -void eeprom_dec_use (struct i2c_client *client) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -u16 swap_bytes(u16 val) -{ - return (val >> 8) | (val << 8); -} - -/* No swapping needed here! */ -int eeprom_write_value(struct i2c_client *client, u8 reg, u16 value) -{/* - if (reg == EEPROM_REG_CONF) - return smbus_write_byte_data(client->adapter,client->addr,reg,value); - else - return smbus_write_word_data(client->adapter,client->addr,reg,value); */ - - /* No writes yet (PAE) */ - return 0; -} - -void eeprom_update_client(struct i2c_client *client) -{ - struct eeprom_data *data = client->data; - int i; - - down(&data->update_lock); - - if ((jiffies - data->last_updated > HZ+HZ/2 ) || - (jiffies < data->last_updated) || ! data->valid) { - -#ifdef DEBUG - printk("Starting eeprom update\n"); -#endif - - if (smbus_write_byte(client->adapter,client->addr,0)) { -#ifdef DEBUG - printk("eeprom read start has failed!\n"); -#endif - } - for (i=0;i<EEPROM_SIZE;i++) { - data->data[i] = (u8)smbus_read_byte(client->adapter,client->addr); - } - - data->last_updated = jiffies; - data->valid = 1; - } - - up(&data->update_lock); -} - - -void eeprom_contents(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - int i; - int base=0; - struct eeprom_data *data = client->data; - - if (ctl_name == EEPROM_SYSCTL2){ base=16; } - if (ctl_name == EEPROM_SYSCTL3){ base=32; } - if (ctl_name == EEPROM_SYSCTL4){ base=48; } - if (ctl_name == EEPROM_SYSCTL5){ base=64; } - if (ctl_name == EEPROM_SYSCTL6){ base=80; } - if (ctl_name == EEPROM_SYSCTL7){ base=96; } - if (ctl_name == EEPROM_SYSCTL8){ base=112; } - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - eeprom_update_client(client); - for (i=0; i<16; i++) { - results[i]=data->data[i + base]; - } -#ifdef DEBUG - printk("eeprom.o: 0x%X EEPROM Contents (base %d): ",client->addr,base); - for (i=0; i<16; i++) { - printk(" 0x%X",data->data[i + base]); - } - printk(" .\n"); -#endif - *nrels_mag = 16; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - -/* No writes to the EEPROM (yet, anyway) (PAE) */ - printk("eeprom.o: No writes to EEPROMs supported!\n"); - } -} - -int eeprom_init(void) -{ - int res; - - printk("eeprom.o version %s (%s)\n",LM_VERSION,LM_DATE); - eeprom_initialized = 0; - if ((res = i2c_add_driver(&eeprom_driver))) { - printk("eeprom.o: Driver registration failed, module not inserted.\n"); - eeprom_cleanup(); - return res; - } - eeprom_initialized ++; - return 0; -} - -int eeprom_cleanup(void) -{ - int res; - - if (eeprom_initialized >= 1) { - if ((res = i2c_del_driver(&eeprom_driver))) { - printk("eeprom.o: Driver deregistration failed, module not removed.\n"); - return res; - } - } else - eeprom_initialized --; - - return 0; -} - - -#ifdef MODULE - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>"); -MODULE_DESCRIPTION("EEPROM driver"); - -int init_module(void) -{ - return eeprom_init(); -} - -int cleanup_module(void) -{ - return eeprom_cleanup(); -} - -#endif /* MODULE */ - diff --git a/kernel/chips/gl518sm.c b/kernel/chips/gl518sm.c deleted file mode 100644 index b0aa613f..00000000 --- a/kernel/chips/gl518sm.c +++ /dev/null @@ -1,674 +0,0 @@ -/* - gl518sm.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> - - 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. -*/ - -#include <linux/module.h> -#include <linux/malloc.h> -#include "smbus.h" -#include "sensors.h" -#include "i2c.h" -#include "version.h" - - -/* Many GL518 constants specified below */ - -/* The GL518 registers */ -#define GL518_REG_CHIP_ID 0x00 -#define GL518_REG_REVISION 0x01 -#define GL518_REG_VENDOR_ID 0x02 -#define GL518_REG_CONF 0x03 -#define GL518_REG_TEMP 0x04 -#define GL518_REG_TEMP_OVER 0x05 -#define GL518_REG_TEMP_HYST 0x06 -#define GL518_REG_FAN_COUNT 0x07 -#define GL518_REG_FAN_LIMIT 0x08 -#define GL518_REG_VIN1_LIMIT 0x09 -#define GL518_REG_VIN2_LIMIT 0x0a -#define GL518_REG_VIN3_LIMIT 0x0b -#define GL518_REG_VDD_LIMIT 0x0c -#define GL518_REG_VIN3 0x0d -#define GL518_REG_MISC 0x0f -#define GL518_REG_ALARM 0x10 -#define GL518_REG_MASK 0x11 -#define GL518_REG_INT 0x12 -#define GL518_REG_VIN2 0x13 -#define GL518_REG_VIN1 0x14 -#define GL518_REG_VDD 0x15 - - -/* Conversions. Rounding is only done on the TO_REG variants. */ -#define TEMP_TO_REG(val) (((((val)<0?(val)-5:(val)+5) / 10) + 119) & 0xff) -#define TEMP_FROM_REG(val) (((val) - 119) * 10) - -#define FAN_TO_REG(val,div) (((val)==0?255:\ - (960000+((val)*(div)))/(2*(val)*(div))) & 0xff) -#define FAN_FROM_REG(val,div) ((val)==0?0:(val)==255?0:960000/(2*(val)*(div))) - -#define IN_TO_REG(val) ((((val)*10+8)/19) & 0xff) -#define IN_FROM_REG(val) (((val)*19)/10) - -#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1) -#define DIV_FROM_REG(val) (1 << (val)) - -#define ALARMS_FROM_REG(val) val - -#define BEEP_ENABLE_TO_REG(val) ((val)?0:1) -#define BEEP_ENABLE_FROM_REG(val) ((val)?0:1) - -#define BEEPS_TO_REG(val) ((val) & 0x7f) -#define BEEPS_FROM_REG(val) (val) - -/* Initial values */ -#define GL518_INIT_TEMP_OVER 600 -#define GL518_INIT_TEMP_HYST 500 -#define GL518_INIT_FAN_MIN_1 3000 -#define GL518_INIT_FAN_MIN_2 3000 - -/* What are sane values for these?!? */ -#define GL518_INIT_VIN_1 3000 -#define GL518_INIT_VIN_2 3000 -#define GL518_INIT_VIN_3 3000 -#define GL518_INIT_VDD 3000 - -#define GL518_INIT_PERCENTAGE 10 - -#define GL518_INIT_VIN_MIN_1 \ - (GL518_INIT_VIN_1 - GL518_INIT_VIN_1 * GL518_INIT_PERCENTAGE / 100) -#define GL518_INIT_VIN_MAX_1 \ - (GL518_INIT_VIN_1 + GL518_INIT_VIN_1 * GL518_INIT_PERCENTAGE / 100) -#define GL518_INIT_VIN_MIN_2 \ - (GL518_INIT_VIN_2 - GL518_INIT_VIN_2 * GL518_INIT_PERCENTAGE / 100) -#define GL518_INIT_VIN_MAX_2 \ - (GL518_INIT_VIN_2 + GL518_INIT_VIN_2 * GL518_INIT_PERCENTAGE / 100) -#define GL518_INIT_VIN_MIN_3 \ - (GL518_INIT_VIN_3 - GL518_INIT_VIN_3 * GL518_INIT_PERCENTAGE / 100) -#define GL518_INIT_VIN_MAX_3 \ - (GL518_INIT_VIN_3 + GL518_INIT_VIN_3 * GL518_INIT_PERCENTAGE / 100) -#define GL518_INIT_VDD_MIN \ - (GL518_INIT_VDD - GL518_INIT_VDD * GL518_INIT_PERCENTAGE / 100) -#define GL518_INIT_VDD_MAX \ - (GL518_INIT_VDD + GL518_INIT_VDD * GL518_INIT_PERCENTAGE / 100) - - -/* Each client has this additional data */ -struct gl518_data { - int sysctl_id; - - u8 revision; - - struct semaphore update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - u8 voltage[4]; /* Register values; [0] = VDD */ - u8 voltage_min[4]; /* Register values; [0] = VDD */ - u8 voltage_max[4]; /* Register values; [0] = VDD */ - u8 fan[2]; - u8 fan_min[2]; - u8 temp; /* Register values */ - u8 temp_over; /* Register values */ - u8 temp_hyst; /* Register values */ - u8 alarms,beeps; /* Register value */ - u8 fan_div[2]; /* Register encoding, shifted right */ - u8 beep_enable; /* Boolean */ -}; - -#ifdef MODULE -extern int init_module(void); -extern int cleanup_module(void); -#endif /* MODULE */ - -static int gl518_init(void); -static int gl518_cleanup(void); -static int gl518_attach_adapter(struct i2c_adapter *adapter); -static int gl518_detach_client(struct i2c_client *client); -static int gl518_command(struct i2c_client *client, unsigned int cmd, - void *arg); -static void gl518_inc_use (struct i2c_client *client); -static void gl518_dec_use (struct i2c_client *client); -static u16 swap_bytes(u16 val); -static int gl518_read_value(struct i2c_client *client, u8 reg); -static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value); -static void gl518_update_client(struct i2c_client *client); - -static void gl518_vin(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results); -static void gl518_fan(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results); -static void gl518_temp(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results); -static void gl518_fan_div(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results); -static void gl518_alarms(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results); -static void gl518_beep(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); - -/* This is the driver that will be inserted */ -static struct i2c_driver gl518_driver = { - /* name */ "GL518SM sensor chip driver", - /* id */ I2C_DRIVERID_GL518, - /* flags */ DF_NOTIFY, - /* attach_adapter */ &gl518_attach_adapter, - /* detach_client */ &gl518_detach_client, - /* command */ &gl518_command, - /* inc_use */ &gl518_inc_use, - /* dec_use */ &gl518_dec_use -}; - -/* These files are created for each detected GL518. This is just a template; - though at first sight, you might think we could use a statically - allocated list, we need some way to get back to the parent - which - is done through one of the 'extra' fields which are initialized - when a new copy is allocated. */ -static ctl_table gl518_dir_table_template[] = { - { GL518_SYSCTL_VIN1, "vin1", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &gl518_vin }, - { GL518_SYSCTL_VIN2, "vin2", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &gl518_vin }, - { GL518_SYSCTL_VIN3, "vin3", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &gl518_vin }, - { GL518_SYSCTL_VDD, "vdd", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &gl518_vin }, - { GL518_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &gl518_fan }, - { GL518_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &gl518_fan }, - { GL518_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &gl518_temp }, - { GL518_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &gl518_fan_div }, - { GL518_SYSCTL_ALARMS, "alarms", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &gl518_alarms }, - { GL518_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &gl518_beep }, - { 0 } -}; - -/* Used by init/cleanup */ -static int gl518_initialized = 0; - -/* I choose here for semi-static LM78 allocation. Complete dynamic - allocation could also be used; the code needed for this would probably - take more memory than the datastructure takes now. */ -#define MAX_GL518_NR 4 -static struct i2c_client *gl518_list[MAX_GL518_NR]; - - -int gl518_attach_adapter(struct i2c_adapter *adapter) -{ - int address,err,i; - struct i2c_client *new_client; - struct gl518_data *data; - u8 revision; - char name[11]; - - err = 0; - - /* OK, this is no detection. I know. It will do for now, though. */ - - /* Set err only if a global error would make registering other clients - impossible too (like out-of-memory). */ - for (address = 0x2c; (! err) && (address <= 0x2d); address ++) { - - /* Later on, we will keep a list of registered addresses for each - adapter, and check whether they are used here */ - - if ((i = smbus_read_byte_data(adapter,address,GL518_REG_CHIP_ID)) < 0) - continue; - - if (i != 0x80) - continue; - - revision = smbus_read_byte_data(adapter,address,GL518_REG_REVISION); - if ((revision != 0x00) && (revision != 0x80)) - continue; - - /* Real detection code goes here */ - - /* Allocate space for a new client structure */ - if (! (new_client = kmalloc(sizeof(struct i2c_client) + - sizeof(struct gl518_data), - GFP_KERNEL))) { - err = -ENOMEM; - continue; - } - - /* Find a place in our global list */ - for (i = 0; i < MAX_GL518_NR; i++) - if (! gl518_list[i]) - break; - if (i == MAX_GL518_NR) { - err = -ENOMEM; - printk("gl518sm.o: No empty slots left, recompile and heighten " - "MAX_GL518_NR!\n"); - goto ERROR1; - } - gl518_list[i] = new_client; - - /* Fill the new client structure with data */ - data = (struct gl518_data *) (new_client + 1); - new_client->data = data; - new_client->id = i; - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &gl518_driver; - sprintf(new_client->name,"GL518SM chip rev. %02x",revision); - data->valid = 0; - data->update_lock = MUTEX; - data->revision = revision; - - /* Tell i2c-core a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto ERROR2; - - sprintf(name,"gl518sm-r%02x",revision); - /* Register a new directory entry with module sensors */ - if ((err = sensors_register_entry(new_client,name, - gl518_dir_table_template)) < 0) - goto ERROR3; - data->sysctl_id = err; - err = 0; - - /* Initialize the GL518SM chip */ - /* Power-on defaults (bit 7=1) */ - gl518_write_value(new_client,GL518_REG_CONF,0x80); - /* No noisy output (bit 2=1), Comparator mode (bit 3=0), two fans (bit4=0), - standby mode (bit6=0) */ - gl518_write_value(new_client,GL518_REG_CONF,0x04); - /* Never interrupts */ - gl518_write_value(new_client,GL518_REG_MASK,0x00); - gl518_write_value(new_client,GL518_REG_TEMP_HYST, - TEMP_TO_REG(GL518_INIT_TEMP_HYST)); - gl518_write_value(new_client,GL518_REG_TEMP_OVER, - TEMP_TO_REG(GL518_INIT_TEMP_OVER)); - gl518_write_value(new_client,GL518_REG_MISC,(DIV_TO_REG(2) << 6) | - (DIV_TO_REG(2) << 4) | 0x08); - gl518_write_value(new_client,GL518_REG_FAN_LIMIT, - (FAN_TO_REG(GL518_INIT_FAN_MIN_1,2) << 8) | - FAN_TO_REG(GL518_INIT_FAN_MIN_2,2)); - gl518_write_value(new_client,GL518_REG_VIN1_LIMIT, - (IN_TO_REG(GL518_INIT_VIN_MIN_1) << 8) | - IN_TO_REG(GL518_INIT_VIN_MAX_1)); - gl518_write_value(new_client,GL518_REG_VIN2_LIMIT, - (IN_TO_REG(GL518_INIT_VIN_MIN_2) << 8) | - IN_TO_REG(GL518_INIT_VIN_MAX_2)); - gl518_write_value(new_client,GL518_REG_VIN3_LIMIT, - (IN_TO_REG(GL518_INIT_VIN_MIN_3) << 8) | - IN_TO_REG(GL518_INIT_VIN_MAX_3)); - gl518_write_value(new_client,GL518_REG_VDD_LIMIT, - (IN_TO_REG(GL518_INIT_VDD_MIN) << 8) | - IN_TO_REG(GL518_INIT_VDD_MAX)); - /* Clear status register (bit 5=1), start (bit6=1) */ - gl518_write_value(new_client,GL518_REG_CONF,0x24); - gl518_write_value(new_client,GL518_REG_CONF,0x44); - - continue; -/* OK, this is not exactly good programming practice, usually. But it is - very code-efficient in this case. */ - -ERROR3: - i2c_detach_client(new_client); -ERROR2: - gl518_list[i] = NULL; -ERROR1: - kfree(new_client); - } - return err; -} - -int gl518_detach_client(struct i2c_client *client) -{ - int err,i; - for (i = 0; i < MAX_GL518_NR; i++) - if (client == gl518_list[i]) - break; - if ((i == MAX_GL518_NR)) { - printk("gl518sm.o: Client to detach not found.\n"); - return -ENOENT; - } - - sensors_deregister_entry(((struct gl518_data *)(client->data))->sysctl_id); - - if ((err = i2c_detach_client(client))) { - printk("gl518sm.o: Client deregistration failed, client not detached.\n"); - return err; - } - - gl518_list[i] = NULL; - kfree(client); - return 0; -} - - -/* No commands defined yet */ -int gl518_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - return 0; -} - -/* Nothing here yet */ -void gl518_inc_use (struct i2c_client *client) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -/* Nothing here yet */ -void gl518_dec_use (struct i2c_client *client) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -u16 swap_bytes(u16 val) -{ - return (val >> 8) | (val << 8); -} - -/* Registers 0x07 to 0x0c are word-sized, others are byte-sized - GL518 uses a high-byte first convention, which is exactly opposite to - the usual practice. */ -int gl518_read_value(struct i2c_client *client, u8 reg) -{ - if ((reg >= 0x07) && (reg <= 0x0c)) - return swap_bytes(smbus_read_word_data(client->adapter,client->addr,reg)); - else - return smbus_read_byte_data(client->adapter,client->addr,reg); -} - -/* Registers 0x07 to 0x0c are word-sized, others are byte-sized - GL518 uses a high-byte first convention, which is exactly opposite to - the usual practice. */ -int gl518_write_value(struct i2c_client *client, u8 reg, u16 value) -{ - if ((reg >= 0x07) && (reg <= 0x0c)) - return smbus_write_word_data(client->adapter,client->addr,reg, - swap_bytes(value)); - else - return smbus_write_byte_data(client->adapter,client->addr,reg,value); -} - -void gl518_update_client(struct i2c_client *client) -{ - struct gl518_data *data = client->data; - int val; - - down(&data->update_lock); - - if ((jiffies - data->last_updated > HZ+HZ/2 ) || - (jiffies < data->last_updated) || ! data->valid) { - -#ifdef DEBUG - printk("Starting gl518 update\n"); -#endif - - if (data->revision != 0x00) { - data->voltage[0] = gl518_read_value(client,GL518_REG_VDD); - data->voltage[1] = gl518_read_value(client,GL518_REG_VIN1); - data->voltage[2] = gl518_read_value(client,GL518_REG_VIN2); - } - data->voltage[3] = gl518_read_value(client,GL518_REG_VIN3); - - val = gl518_read_value(client,GL518_REG_VDD_LIMIT); - data->voltage_min[0] = val & 0xff; - data->voltage_max[0] = (val >> 8) & 0xff; - val = gl518_read_value(client,GL518_REG_VIN1_LIMIT); - data->voltage_min[1] = val & 0xff; - data->voltage_max[1] = (val >> 8) & 0xff; - val = gl518_read_value(client,GL518_REG_VIN2_LIMIT); - data->voltage_min[2] = val & 0xff; - data->voltage_max[2] = (val >> 8) & 0xff; - val = gl518_read_value(client,GL518_REG_VIN3_LIMIT); - data->voltage_min[3] = val & 0xff; - data->voltage_max[3] = (val >> 8) & 0xff; - - val = gl518_read_value(client,GL518_REG_FAN_COUNT); - data->fan[0] = (val >> 8) & 0xff; - data->fan[1] = val & 0xff; - - val = gl518_read_value(client,GL518_REG_FAN_LIMIT); - data->fan_min[0] = (val >> 8) & 0xff; - data->fan_min[1] = val & 0xff; - - data->temp = gl518_read_value(client,GL518_REG_TEMP); - data->temp_over = gl518_read_value(client,GL518_REG_TEMP_OVER); - data->temp_hyst = gl518_read_value(client,GL518_REG_TEMP_HYST); - - data->alarms = gl518_read_value(client,GL518_REG_INT); - data->beeps = gl518_read_value(client,GL518_REG_ALARM); - - val = gl518_read_value(client,GL518_REG_MISC); - data->fan_div[0] = (val >> 4) & 0x03; - data->fan_div[1] = (val >> 6) & 0x03; - data->beep_enable = (gl518_read_value(client,GL518_REG_CONF) >> 2) & 1; - - data->last_updated = jiffies; - data->valid = 1; - } - - up(&data->update_lock); -} - - -void gl518_temp(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct gl518_data *data = client->data; - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 1; - else if (operation == SENSORS_PROC_REAL_READ) { - gl518_update_client(client); - results[0] = TEMP_FROM_REG(data->temp_over); - results[1] = TEMP_FROM_REG(data->temp_hyst); - results[2] = TEMP_FROM_REG(data->temp); - *nrels_mag = 3; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - if (*nrels_mag >= 1) { - data->temp_over = TEMP_TO_REG(results[0]); - gl518_write_value(client,GL518_REG_TEMP_OVER,data->temp_over); - } - if (*nrels_mag >= 2) { - data->temp_over = TEMP_TO_REG(results[1]); - gl518_write_value(client,GL518_REG_TEMP_HYST,data->temp_over); - } - } -} - -void gl518_vin(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct gl518_data *data = client->data; - int nr = ctl_name - GL518_SYSCTL_VDD; - int regnr,old=0; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 2; - else if (operation == SENSORS_PROC_REAL_READ) { - gl518_update_client(client); - results[0] = IN_FROM_REG(data->voltage_min[nr]); - results[1] = IN_FROM_REG(data->voltage_max[nr]); - if ((data->revision == 0x00) && (nr != 3)) - results[2] = 0; - else - results[2] = IN_FROM_REG(data->voltage[nr]); - *nrels_mag = 3; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - regnr=nr==0?GL518_REG_VDD_LIMIT:nr==1?GL518_REG_VIN1_LIMIT:nr==2? - GL518_REG_VIN2_LIMIT:GL518_REG_VIN3_LIMIT; - if (*nrels_mag == 1) - old = gl518_read_value(client,regnr) & 0xff00; - if (*nrels_mag >= 2) { - data->voltage_max[nr] = IN_TO_REG(results[1]); - old = data->voltage_max[nr] << 8; - } - if (*nrels_mag >= 1) { - data->voltage_min[nr] = IN_TO_REG(results[0]); - old |= data->voltage_min[nr]; - gl518_write_value(client,regnr,old); - } - } -} - - -void gl518_fan(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct gl518_data *data = client->data; - int nr = ctl_name - GL518_SYSCTL_FAN1; - int old; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - gl518_update_client(client); - results[0] = FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr])); - results[1] = FAN_FROM_REG(data->fan[nr],DIV_FROM_REG(data->fan_div[nr])); - *nrels_mag = 2; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - if (*nrels_mag >= 1) { - data->fan_min[nr] = FAN_TO_REG(results[0], - DIV_FROM_REG(data->fan_div[nr])); - old = gl518_read_value(client,GL518_REG_FAN_LIMIT); - if (nr == 0) - old = (old & 0x00ff) | (data->fan_min[nr] << 8); - else - old = (old & 0xff00) | data->fan_min[nr]; - gl518_write_value(client,GL518_REG_FAN_LIMIT,old); - } - } -} - - -void gl518_alarms(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct gl518_data *data = client->data; - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - gl518_update_client(client); - results[0] = ALARMS_FROM_REG(data->alarms); - *nrels_mag = 1; - } -} - -void gl518_beep(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct gl518_data *data = client->data; - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - gl518_update_client(client); - results[0] = BEEP_ENABLE_FROM_REG(data->beep_enable); - results[1] = BEEPS_FROM_REG(data->beeps); - *nrels_mag = 2; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - if (*nrels_mag >= 1) { - data->beep_enable = BEEP_ENABLE_TO_REG(results[0]); - gl518_write_value(client,GL518_REG_CONF, - (gl518_read_value(client,GL518_REG_CONF) & 0xfb) | - (data->beep_enable << 2)); - } - if (*nrels_mag >= 2) { - data->beeps = BEEPS_TO_REG(results[1]); - gl518_write_value(client,GL518_REG_ALARM,data->beeps); - } - } -} - -void gl518_fan_div(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct gl518_data *data = client->data; - int old; - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - gl518_update_client(client); - results[0] = DIV_FROM_REG(data->fan_div[0]); - results[1] = DIV_FROM_REG(data->fan_div[1]); - *nrels_mag = 2; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - old = gl518_read_value(client,GL518_REG_MISC); - if (*nrels_mag >= 2) { - data->fan_div[1] = DIV_TO_REG(results[1]); - old = (old & 0x3f) | (data->fan_div[1] << 6); - } - if (*nrels_mag >= 1) { - data->fan_div[0] = DIV_TO_REG(results[0]); - old = (old & 0xcf) | (data->fan_div[0] << 4); - gl518_write_value(client,GL518_REG_MISC,old); - } - } -} - - -int gl518_init(void) -{ - int res; - - printk("gl518sm.o version %s (%s)\n",LM_VERSION,LM_DATE); - gl518_initialized = 0; - if ((res = i2c_add_driver(&gl518_driver))) { - printk("gl518sm.o: Driver registration failed, module not inserted.\n"); - gl518_cleanup(); - return res; - } - gl518_initialized ++; - return 0; -} - -int gl518_cleanup(void) -{ - int res; - - if (gl518_initialized >= 1) { - if ((res = i2c_del_driver(&gl518_driver))) { - printk("gl518.o: Driver deregistration failed, module not removed.\n"); - return res; - } - gl518_initialized --; - } - - return 0; -} - - -#ifdef MODULE - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); -MODULE_DESCRIPTION("GL518SM driver"); - -int init_module(void) -{ - return gl518_init(); -} - -int cleanup_module(void) -{ - return gl518_cleanup(); -} - -#endif /* MODULE */ - diff --git a/kernel/chips/lm75.c b/kernel/chips/lm75.c deleted file mode 100644 index 4ab9f4de..00000000 --- a/kernel/chips/lm75.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - lm75.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> - - 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. -*/ - -#include <linux/module.h> -#include <linux/malloc.h> -#include "smbus.h" -#include "sensors.h" -#include "i2c.h" -#include "version.h" - -/* Many LM75 constants specified below */ - -/* The LM75 registers */ -#define LM75_REG_TEMP 0x00 -#define LM75_REG_CONF 0x01 -#define LM75_REG_TEMP_HYST 0x02 -#define LM75_REG_TEMP_OS 0x03 - -/* Conversions */ -#define TEMP_FROM_REG(val) (((val) >> 7) * 5) -#define TEMP_TO_REG(val) (((((val) + 2) / 5) << 7) & 0xff80) - -/* Initial values */ -#define LM75_INIT_TEMP_OS 600 -#define LM75_INIT_TEMP_HYST 500 - -/* Each client has this additional data */ -struct lm75_data { - int sysctl_id; - - struct semaphore update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - u16 temp,temp_os,temp_hyst; /* Register values */ -}; - -#ifdef MODULE -extern int init_module(void); -extern int cleanup_module(void); -#endif /* MODULE */ - -static int lm75_init(void); -static int lm75_cleanup(void); -static int lm75_attach_adapter(struct i2c_adapter *adapter); -static int lm75_detach_client(struct i2c_client *client); -static int lm75_command(struct i2c_client *client, unsigned int cmd, - void *arg); -static void lm75_inc_use (struct i2c_client *client); -static void lm75_dec_use (struct i2c_client *client); -static u16 swap_bytes(u16 val); -static int lm75_read_value(struct i2c_client *client, u8 reg); -static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value); -static void lm75_temp(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); -static void lm75_update_client(struct i2c_client *client); - - -/* This is the driver that will be inserted */ -static struct i2c_driver lm75_driver = { - /* name */ "LM75 sensor chip driver", - /* id */ I2C_DRIVERID_LM75, - /* flags */ DF_NOTIFY, - /* attach_adapter */ &lm75_attach_adapter, - /* detach_client */ &lm75_detach_client, - /* command */ &lm75_command, - /* inc_use */ &lm75_inc_use, - /* dec_use */ &lm75_dec_use -}; - -/* These files are created for each detected LM75. This is just a template; - though at first sight, you might think we could use a statically - allocated list, we need some way to get back to the parent - which - is done through one of the 'extra' fields which are initialized - when a new copy is allocated. */ -static ctl_table lm75_dir_table_template[] = { - { LM75_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm75_temp }, - { 0 } -}; - -/* Used by init/cleanup */ -static int lm75_initialized = 0; - -/* I choose here for semi-static LM78 allocation. Complete dynamic - allocation could also be used; the code needed for this would probably - take more memory than the datastructure takes now. */ -#define MAX_LM75_NR 8 -static struct i2c_client *lm75_list[MAX_LM75_NR]; - - -int lm75_attach_adapter(struct i2c_adapter *adapter) -{ - int address,err,i; - struct i2c_client *new_client; - struct lm75_data *data; - - err = 0; - - /* OK, this is no detection. I know. It will do for now, though. */ - - /* Set err only if a global error would make registering other clients - impossible too (like out-of-memory). */ - for (address = 0x48; (! err) && (address <= 0x4f); address ++) { - - /* Later on, we will keep a list of registered addresses for each - adapter, and check whether they are used here */ - - if (smbus_read_byte_data(adapter,address,LM75_REG_CONF) < 0) - continue; - - /* Real detection code goes here */ - - /* Allocate space for a new client structure */ - if (! (new_client = kmalloc(sizeof(struct i2c_client) + - sizeof(struct lm75_data), - GFP_KERNEL))) { - err = -ENOMEM; - continue; - } - - /* Find a place in our global list */ - for (i = 0; i < MAX_LM75_NR; i++) - if (! lm75_list[i]) - break; - if (i == MAX_LM75_NR) { - err = -ENOMEM; - printk("lm75.o: No empty slots left, recompile and heighten " - "MAX_LM75_NR!\n"); - goto ERROR1; - } - lm75_list[i] = new_client; - - /* Fill the new client structure with data */ - data = (struct lm75_data *) (new_client + 1); - new_client->data = data; - new_client->id = i; - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &lm75_driver; - strcpy(new_client->name,"LM75 chip"); - data->valid = 0; - data->update_lock = MUTEX; - - /* Tell i2c-core a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto ERROR2; - - /* Register a new directory entry with module sensors */ - if ((err = sensors_register_entry(new_client,"lm75", - lm75_dir_table_template)) < 0) - goto ERROR3; - data->sysctl_id = err; - err = 0; - - /* Initialize the LM75 chip */ - lm75_write_value(new_client,LM75_REG_TEMP_OS, - TEMP_TO_REG(LM75_INIT_TEMP_OS)); - lm75_write_value(new_client,LM75_REG_TEMP_HYST, - TEMP_TO_REG(LM75_INIT_TEMP_HYST)); - lm75_write_value(new_client,LM75_REG_CONF,0); - - continue; -/* OK, this is not exactly good programming practice, usually. But it is - very code-efficient in this case. */ - -ERROR3: - i2c_detach_client(new_client); -ERROR2: - lm75_list[i] = NULL; -ERROR1: - kfree(new_client); - } - return err; -} - -int lm75_detach_client(struct i2c_client *client) -{ - int err,i; - for (i = 0; i < MAX_LM75_NR; i++) - if (client == lm75_list[i]) - break; - if ((i == MAX_LM75_NR)) { - printk("lm75.o: Client to detach not found.\n"); - return -ENOENT; - } - - sensors_deregister_entry(((struct lm75_data *)(client->data))->sysctl_id); - - if ((err = i2c_detach_client(client))) { - printk("lm75.o: Client deregistration failed, client not detached.\n"); - return err; - } - - lm75_list[i] = NULL; - kfree(client); - return 0; -} - - -/* No commands defined yet */ -int lm75_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - return 0; -} - -/* Nothing here yet */ -void lm75_inc_use (struct i2c_client *client) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -/* Nothing here yet */ -void lm75_dec_use (struct i2c_client *client) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -u16 swap_bytes(u16 val) -{ - return (val >> 8) | (val << 8); -} - -/* All registers are word-sized, except for the configuration register. - LM75 uses a high-byte first convention, which is exactly opposite to - the usual practice. */ -int lm75_read_value(struct i2c_client *client, u8 reg) -{ - if (reg == LM75_REG_CONF) - return smbus_read_byte_data(client->adapter,client->addr,reg); - else - return swap_bytes(smbus_read_word_data(client->adapter,client->addr,reg)); -} - -/* All registers are word-sized, except for the configuration register. - LM75 uses a high-byte first convention, which is exactly opposite to - the usual practice. */ -int lm75_write_value(struct i2c_client *client, u8 reg, u16 value) -{ - if (reg == LM75_REG_CONF) - return smbus_write_byte_data(client->adapter,client->addr,reg,value); - else - return smbus_write_word_data(client->adapter,client->addr,reg, - swap_bytes(value)); -} - -void lm75_update_client(struct i2c_client *client) -{ - struct lm75_data *data = client->data; - - down(&data->update_lock); - - if ((jiffies - data->last_updated > HZ+HZ/2 ) || - (jiffies < data->last_updated) || ! data->valid) { - -#ifdef DEBUG - printk("Starting lm75 update\n"); -#endif - - data->temp = lm75_read_value(client,LM75_REG_TEMP); - data->temp_os = lm75_read_value(client,LM75_REG_TEMP_OS); - data->temp_hyst = lm75_read_value(client,LM75_REG_TEMP_HYST); - data->last_updated = jiffies; - data->valid = 1; - } - - up(&data->update_lock); -} - - -void lm75_temp(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct lm75_data *data = client->data; - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 1; - else if (operation == SENSORS_PROC_REAL_READ) { - lm75_update_client(client); - results[0] = TEMP_FROM_REG(data->temp_os); - results[1] = TEMP_FROM_REG(data->temp_hyst); - results[2] = TEMP_FROM_REG(data->temp); - *nrels_mag = 3; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - if (*nrels_mag >= 1) { - data->temp_os = TEMP_TO_REG(results[0]); - lm75_write_value(client,LM75_REG_TEMP_OS,data->temp_os); - } - if (*nrels_mag >= 2) { - data->temp_os = TEMP_TO_REG(results[1]); - lm75_write_value(client,LM75_REG_TEMP_HYST,data->temp_os); - } - } -} - -int lm75_init(void) -{ - int res; - - printk("lm75.o version %s (%s)\n",LM_VERSION,LM_DATE); - lm75_initialized = 0; - if ((res = i2c_add_driver(&lm75_driver))) { - printk("lm75.o: Driver registration failed, module not inserted.\n"); - lm75_cleanup(); - return res; - } - lm75_initialized ++; - return 0; -} - -int lm75_cleanup(void) -{ - int res; - - if (lm75_initialized >= 1) { - if ((res = i2c_del_driver(&lm75_driver))) { - printk("lm75.o: Driver deregistration failed, module not removed.\n"); - return res; - } - lm75_initialized --; - } - - return 0; -} - - -#ifdef MODULE - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); -MODULE_DESCRIPTION("LM75 driver"); - -int init_module(void) -{ - return lm75_init(); -} - -int cleanup_module(void) -{ - return lm75_cleanup(); -} - -#endif /* MODULE */ - diff --git a/kernel/chips/lm78.c b/kernel/chips/lm78.c deleted file mode 100644 index f8a56de4..00000000 --- a/kernel/chips/lm78.c +++ /dev/null @@ -1,926 +0,0 @@ -/* - lm78.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> - - 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. -*/ - -#include <linux/module.h> -#include <linux/malloc.h> -#include <linux/proc_fs.h> -#include <linux/ioport.h> -#include <linux/sysctl.h> -#include <asm/errno.h> -#include <asm/io.h> -#include <linux/types.h> -#include "smbus.h" -#include "version.h" -#include "isa.h" -#include "sensors.h" -#include "i2c.h" -#include "compat.h" - -/* Many LM78 constants specified below */ - -/* Length of ISA address segment */ -#define LM78_EXTENT 8 - -/* Where are the ISA address/data registers relative to the base address */ -#define LM78_ADDR_REG_OFFSET 5 -#define LM78_DATA_REG_OFFSET 6 - -/* The LM78 registers */ -#define LM78_REG_IN_MAX(nr) (0x2b + (nr) * 2) -#define LM78_REG_IN_MIN(nr) (0x2c + (nr) * 2) -#define LM78_REG_IN(nr) (0x20 + (nr)) - -#define LM78_REG_FAN_MIN(nr) (0x3a + (nr)) -#define LM78_REG_FAN(nr) (0x27 + (nr)) - -#define LM78_REG_TEMP 0x27 -#define LM78_REG_TEMP_OVER 0x39 -#define LM78_REG_TEMP_HYST 0x3a - -#define LM78_REG_ALARM1 0x41 -#define LM78_REG_ALARM2 0x42 - -#define LM78_REG_VID_FANDIV 0x47 - -#define LM78_REG_CONFIG 0x40 -#define LM78_REG_CHIPID 0x49 - - -/* Conversions. Rounding is only done on the TO_REG variants. */ -#define IN_TO_REG(val) (((val) * 10 + 8)/16) -#define IN_FROM_REG(val) (((val) * 16) / 10) - -#define FAN_TO_REG(val,div) ((val)==0?255:((1350000+(val)*(div)/2)/\ - ((val)*(div))) & 0xff) -#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div))) - -#define TEMP_TO_REG(val) (((val)<0?(((val)-5)/10)&0xff:((val)+5)/10) & 0xff) -#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10) - -#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\ - (val)>=0x06?0:205-(val)*5) -#define ALARMS_FROM_REG(val) (val) - -#define DIV_FROM_REG(val) (1 << (val)) -#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1) - -/* Initial limits. To keep them sane, we use the 'standard' translation as - specified in the LM78 sheet. Use the config file to set better limits. */ -#define LM78_INIT_IN_0 (vid==350?280:vid) -#define LM78_INIT_IN_1 (vid==350?280:vid) -#define LM78_INIT_IN_2 330 -#define LM78_INIT_IN_3 (((500) * 100)/168) -#define LM78_INIT_IN_4 (((1200) * 10)/38) -#define LM78_INIT_IN_5 (((-1200) * -604)/2100) -#define LM78_INIT_IN_6 (((-500) * -604)/909) - -#define LM78_INIT_IN_PERCENTAGE 10 - -#define LM78_INIT_IN_MIN_0 \ - (LM78_INIT_IN_0 - LM78_INIT_IN_0 * LM78_INIT_IN_PERCENTAGE / 100) -#define LM78_INIT_IN_MAX_0 \ - (LM78_INIT_IN_0 + LM78_INIT_IN_0 * LM78_INIT_IN_PERCENTAGE / 100) -#define LM78_INIT_IN_MIN_1 \ - (LM78_INIT_IN_1 - LM78_INIT_IN_1 * LM78_INIT_IN_PERCENTAGE / 100) -#define LM78_INIT_IN_MAX_1 \ - (LM78_INIT_IN_1 + LM78_INIT_IN_1 * LM78_INIT_IN_PERCENTAGE / 100) -#define LM78_INIT_IN_MIN_2 \ - (LM78_INIT_IN_2 - LM78_INIT_IN_2 * LM78_INIT_IN_PERCENTAGE / 100) -#define LM78_INIT_IN_MAX_2 \ - (LM78_INIT_IN_2 + LM78_INIT_IN_2 * LM78_INIT_IN_PERCENTAGE / 100) -#define LM78_INIT_IN_MIN_3 \ - (LM78_INIT_IN_3 - LM78_INIT_IN_3 * LM78_INIT_IN_PERCENTAGE / 100) -#define LM78_INIT_IN_MAX_3 \ - (LM78_INIT_IN_3 + LM78_INIT_IN_3 * LM78_INIT_IN_PERCENTAGE / 100) -#define LM78_INIT_IN_MIN_4 \ - (LM78_INIT_IN_4 - LM78_INIT_IN_4 * LM78_INIT_IN_PERCENTAGE / 100) -#define LM78_INIT_IN_MAX_4 \ - (LM78_INIT_IN_4 + LM78_INIT_IN_4 * LM78_INIT_IN_PERCENTAGE / 100) -#define LM78_INIT_IN_MIN_5 \ - (LM78_INIT_IN_5 - LM78_INIT_IN_5 * LM78_INIT_IN_PERCENTAGE / 100) -#define LM78_INIT_IN_MAX_5 \ - (LM78_INIT_IN_5 + LM78_INIT_IN_5 * LM78_INIT_IN_PERCENTAGE / 100) -#define LM78_INIT_IN_MIN_6 \ - (LM78_INIT_IN_6 - LM78_INIT_IN_6 * LM78_INIT_IN_PERCENTAGE / 100) -#define LM78_INIT_IN_MAX_6 \ - (LM78_INIT_IN_6 + LM78_INIT_IN_6 * LM78_INIT_IN_PERCENTAGE / 100) - -#define LM78_INIT_FAN_MIN_1 3000 -#define LM78_INIT_FAN_MIN_2 3000 -#define LM78_INIT_FAN_MIN_3 3000 - -#define LM78_INIT_TEMP_OVER 600 -#define LM78_INIT_TEMP_HYST 500 - -#ifdef MODULE -extern int init_module(void); -extern int cleanup_module(void); -#endif /* MODULE */ - -/* There are some complications in a module like this. First off, LM78 chips - may be both present on the SMBus and the ISA bus, and we have to handle - those cases separately at some places. Second, there might be several - LM78 chips available (well, actually, that is probably never done; but - it is a clean illustration of how to handle a case like that). Finally, - a specific chip may be attached to *both* ISA and SMBus, and we would - not like to detect it double. Fortunately, in the case of the LM78 at - least, a register tells us what SMBus address we are on, so that helps - a bit - except if there could be more than one SMBus. Groan. No solution - for this yet. */ - -/* This module may seem overly long and complicated. In fact, it is not so - bad. Quite a lot of bookkeeping is done. A real driver can often cut - some corners. */ - -/* Types of chips supported */ -enum lm78_type { lm78, lm78j, lm79 }; - -/* For each registered LM78, we need to keep some data in memory. That - data is pointed to by lm78_list[NR]->data. The structure itself is - dynamically allocated, at the same time when a new lm78 client is - allocated. */ -struct lm78_data { - struct semaphore lock; - int sysctl_id; - enum lm78_type type; - - struct semaphore update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - u8 in[7]; /* Register value */ - u8 in_max[7]; /* Register value */ - u8 in_min[7]; /* Register value */ - u8 fan[3]; /* Register value */ - u8 fan_min[3]; /* Register value */ - u8 temp; /* Register value */ - u8 temp_over; /* Register value */ - u8 temp_hyst; /* Register value */ - u8 fan_div[3]; /* Register encoding, shifted right */ - u8 vid; /* Register encoding, combined */ - u16 alarms; /* Register encoding, combined */ -}; - - -static int lm78_init(void); -static int lm78_cleanup(void); - -static int lm78_attach_adapter(struct i2c_adapter *adapter); -static int lm78_detect_isa(struct isa_adapter *adapter); -static int lm78_detect_smbus(struct i2c_adapter *adapter); -static int lm78_detach_client(struct i2c_client *client); -static int lm78_detach_isa(struct isa_client *client); -static int lm78_detach_smbus(struct i2c_client *client); -static int lm78_new_client(struct i2c_adapter *adapter, - struct i2c_client *new_client); -static void lm78_remove_client(struct i2c_client *client); -static int lm78_command(struct i2c_client *client, unsigned int cmd, - void *arg); -static void lm78_inc_use (struct i2c_client *client); -static void lm78_dec_use (struct i2c_client *client); - -static int lm78_read_value(struct i2c_client *client, u8 register); -static int lm78_write_value(struct i2c_client *client, u8 register, u8 value); -static void lm78_update_client(struct i2c_client *client); -static void lm78_init_client(struct i2c_client *client); - - -static void lm78_in(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); -static void lm78_fan(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); -static void lm78_temp(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); -static void lm78_vid(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); -static void lm78_alarms(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); -static void lm78_fan_div(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); - -/* I choose here for semi-static LM78 allocation. Complete dynamic - allocation could also be used; the code needed for this would probably - take more memory than the datastructure takes now. */ -#define MAX_LM78_NR 4 -static struct i2c_client *lm78_list[MAX_LM78_NR]; - -/* The driver. I choose to use type i2c_driver, as at is identical to both - smbus_driver and isa_driver, and clients could be of either kind */ -static struct i2c_driver lm78_driver = { - /* name */ "LM78(-J) and LM79 sensor driver", - /* id */ I2C_DRIVERID_LM78, - /* flags */ DF_NOTIFY, - /* attach_adapter */ &lm78_attach_adapter, - /* detach_client */ &lm78_detach_client, - /* command */ &lm78_command, - /* inc_use */ &lm78_inc_use, - /* dec_use */ &lm78_dec_use -}; - -/* Used by lm78_init/cleanup */ -static int lm78_initialized = 0; - -/* The /proc/sys entries */ -/* These files are created for each detected LM78. This is just a template; - though at first sight, you might think we could use a statically - allocated list, we need some way to get back to the parent - which - is done through one of the 'extra' fields which are initialized - when a new copy is allocated. */ -static ctl_table lm78_dir_table_template[] = { - { LM78_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm78_in }, - { LM78_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm78_in }, - { LM78_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm78_in }, - { LM78_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm78_in }, - { LM78_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm78_in }, - { LM78_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm78_in }, - { LM78_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm78_in }, - { LM78_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm78_fan }, - { LM78_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm78_fan }, - { LM78_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm78_fan }, - { LM78_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm78_temp }, - { LM78_SYSCTL_VID, "vid", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm78_vid }, - { LM78_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm78_fan_div }, - { LM78_SYSCTL_ALARMS, "alarms", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm78_alarms }, - { 0 } -}; - - -/* This function is called when: - * lm78_driver is inserted (when this module is loaded), for each - available adapter - * when a new adapter is inserted (and lm78_driver is still present) */ -int lm78_attach_adapter(struct i2c_adapter *adapter) -{ - if (i2c_is_isa_adapter(adapter)) - return lm78_detect_isa((struct isa_adapter *) adapter); - else - return lm78_detect_smbus(adapter); -} - -/* This function is called whenever a client should be removed: - * lm78_driver is removed (when this module is unloaded) - * when an adapter is removed which has a lm78 client (and lm78_driver - is still present). */ -int lm78_detach_client(struct i2c_client *client) -{ - if (i2c_is_isa_client(client)) - return lm78_detach_isa((struct isa_client *) client); - else - return lm78_detach_smbus(client); -} - -/* Detect whether there is a LM78 on the ISA bus, register and initialize - it. */ -int lm78_detect_isa(struct isa_adapter *adapter) -{ - int address,err; - struct isa_client *new_client; - enum lm78_type type; - const char *type_name; - const char *client_name; - - /* OK, this is no detection. I know. It will do for now, though. */ - - err = 0; - for (address = 0x290; (! err) && (address <= 0x290); address += 0x08) { - if (check_region(address, LM78_EXTENT)) - continue; - - /* Awful, but true: unused port addresses should return 0xff */ - if ((inb_p(address + 1) != 0xff) || (inb_p(address + 2) != 0xff) || - (inb_p(address + 3) != 0xff) || (inb_p(address + 7) != 0xff)) - continue; - - if (inb_p(address + LM78_ADDR_REG_OFFSET) == 0xff) { - outb_p(0x00,address + LM78_ADDR_REG_OFFSET); - if (inb_p(address + LM78_ADDR_REG_OFFSET) == 0xff) - continue; - } - - /* Real detection code goes here */ - - /* Determine exact type */ - outb_p(LM78_REG_CHIPID,address + LM78_ADDR_REG_OFFSET); - err = inb_p(address + LM78_DATA_REG_OFFSET) & 0xfe; - if (err == 0x00) { - type = lm78; - type_name = "lm78"; - client_name = "LM78 chip"; - } else if (err == 0x40) { - type = lm78j; - type_name = "lm78-j"; - client_name = "LM78-J chip"; - } else if (err == 0xc0) { - type = lm79; - type_name = "lm79"; - client_name = "LM79 chip"; - } else if (err == 0x02) { - printk("lm78.o: Warning: Winbond W83781D detected (treated as a LM79)\n"); - type = lm79; - type_name = "lm79"; - client_name = "LM79 chip"; - } else { -#ifdef DEBUG - printk("lm78.o: warning: probed non-lm78 chip?!? (%x)\n",err); -#endif - continue; - } - - request_region(address, LM78_EXTENT, type_name); - - /* Allocate space for a new client structure */ - if (! (new_client = kmalloc(sizeof(struct isa_client) + - sizeof(struct lm78_data), - GFP_KERNEL))) - { - err=-ENOMEM; - goto ERROR1; - } - - /* Fill the new client structure with data */ - new_client->data = (struct lm78_data *) (new_client + 1); - new_client->addr = 0; - strcpy(new_client->name,client_name); - ((struct lm78_data *) (new_client->data))->type = type; - new_client->isa_addr = address; - if ((err = lm78_new_client((struct i2c_adapter *) adapter, - (struct i2c_client *) new_client))) - goto ERROR2; - - /* Tell i2c-core a new client has arrived */ - if ((err = isa_attach_client(new_client))) - goto ERROR3; - - /* Register a new directory entry with module sensors */ - if ((err = sensors_register_entry((struct i2c_client *) new_client, - type_name, - lm78_dir_table_template)) < 0) - goto ERROR4; - ((struct lm78_data *) (new_client->data)) -> sysctl_id = err; - err = 0; - - /* Initialize the LM78 chip */ - lm78_init_client((struct i2c_client *) new_client); - continue; - -/* OK, this is not exactly good programming practice, usually. But it is - very code-efficient in this case. */ - -ERROR4: - isa_detach_client(new_client); -ERROR3: - lm78_remove_client((struct i2c_client *) new_client); -ERROR2: - kfree(new_client); -ERROR1: - release_region(address, LM78_EXTENT); - } - return err; - -} - -/* Deregister and remove a LM78 client */ -int lm78_detach_isa(struct isa_client *client) -{ - int err,i; - for (i = 0; i < MAX_LM78_NR; i++) - if ((client == (struct isa_client *) (lm78_list[i]))) - break; - if (i == MAX_LM78_NR) { - printk("lm78.o: Client to detach not found.\n"); - return -ENOENT; - } - - sensors_deregister_entry(((struct lm78_data *)(client->data))->sysctl_id); - - if ((err = isa_detach_client(client))) { - printk("lm78.o: Client deregistration failed, client not detached.\n"); - return err; - } - lm78_remove_client((struct i2c_client *) client); - release_region(client->isa_addr,LM78_EXTENT); - kfree(client); - return 0; -} - -int lm78_detect_smbus(struct i2c_adapter *adapter) -{ - int address,err; - struct i2c_client *new_client; - enum lm78_type type; - const char *type_name,*client_name; - - /* OK, this is no detection. I know. It will do for now, though. */ - err = 0; - for (address = 0x20; (! err) && (address <= 0x2f); address ++) { - - /* Later on, we will keep a list of registered addresses for each - adapter, and check whether they are used here */ - - if (smbus_read_byte_data(adapter,address,LM78_REG_CONFIG) < 0) - continue; - - /* Real detection code goes here */ - - /* Determine exact type */ - err = smbus_read_byte_data(adapter,address,LM78_REG_CHIPID) & 0xfe; - if (err == 0x00) { - type = lm78; - type_name = "lm78"; - client_name = "LM78 chip"; - } else if (err == 0x40) { - type = lm78j; - type_name = "lm78-j"; - client_name = "LM78-J chip"; - } else if (err == 0xc0) { - type = lm79; - type_name = "lm79"; - client_name = "LM79 chip"; - } else if (err == 0x02) { - printk("lm78.o: Warning: Winbond W83781D detected (treated as a LM79)\n"); - type = lm79; - type_name = "lm79"; - client_name = "LM79 chip"; - } else { -#ifdef DEBUG - printk("lm78.o: warning: probed non-lm78 chip?!? (%x)\n",err); -#endif - continue; - } - - - /* Allocate space for a new client structure. To counter memory - ragmentation somewhat, we only do one kmalloc. */ - if (! (new_client = kmalloc(sizeof(struct i2c_client) + - sizeof(struct lm78_data), - GFP_KERNEL))) { - err = -ENOMEM; - continue; - } - - /* Fill the new client structure with data */ - new_client->data = (struct lm78_data *) (new_client + 1); - new_client->addr = address; - strcpy(new_client->name,client_name); - ((struct lm78_data *) (new_client->data))->type = type; - if ((err = lm78_new_client(adapter,new_client))) - goto ERROR2; - - /* Tell i2c-core a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto ERROR3; - - /* Register a new directory entry with module sensors */ - if ((err = sensors_register_entry(new_client,type_name, - lm78_dir_table_template)) < 0) - goto ERROR4; - ((struct lm78_data *) (new_client->data))->sysctl_id = err; - err = 0; - - /* Initialize the LM78 chip */ - lm78_init_client(new_client); - continue; - -/* OK, this is not exactly good programming practice, usually. But it is - very code-efficient in this case. */ -ERROR4: - i2c_detach_client(new_client); -ERROR3: - lm78_remove_client((struct i2c_client *) new_client); -ERROR2: - kfree(new_client); - } - return err; -} - -int lm78_detach_smbus(struct i2c_client *client) -{ - int err,i; - for (i = 0; i < MAX_LM78_NR; i++) - if (client == lm78_list[i]) - break; - if ((i == MAX_LM78_NR)) { - printk("lm78.o: Client to detach not found.\n"); - return -ENOENT; - } - - sensors_deregister_entry(((struct lm78_data *)(client->data))->sysctl_id); - - if ((err = i2c_detach_client(client))) { - printk("lm78.o: Client deregistration failed, client not detached.\n"); - return err; - } - lm78_remove_client(client); - kfree(client); - return 0; -} - - -/* Find a free slot, and initialize most of the fields */ -int lm78_new_client(struct i2c_adapter *adapter, - struct i2c_client *new_client) -{ - int i; - struct lm78_data *data; - - /* First, seek out an empty slot */ - for(i = 0; i < MAX_LM78_NR; i++) - if (! lm78_list[i]) - break; - if (i == MAX_LM78_NR) { - printk("lm78.o: No empty slots left, recompile and heighten " - "MAX_LM78_NR!\n"); - return -ENOMEM; - } - - lm78_list[i] = new_client; - new_client->id = i; - new_client->adapter = adapter; - new_client->driver = &lm78_driver; - data = new_client->data; - data->valid = 0; - data->lock = MUTEX; - data->update_lock = MUTEX; - return 0; -} - -/* Inverse of lm78_new_client */ -void lm78_remove_client(struct i2c_client *client) -{ - int i; - for (i = 0; i < MAX_LM78_NR; i++) - if (client == lm78_list[i]) - lm78_list[i] = NULL; -} - -/* No commands defined yet */ -int lm78_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - return 0; -} - -/* Nothing here yet */ -void lm78_inc_use (struct i2c_client *client) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -/* Nothing here yet */ -void lm78_dec_use (struct i2c_client *client) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - - -/* The SMBus locks itself, but ISA access must be locked explicitely! - We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks, - would slow down the LM78 access and should not be necessary. - There are some ugly typecasts here, but the good new is - they should - nowhere else be necessary! */ -int lm78_read_value(struct i2c_client *client, u8 reg) -{ - int res; - if (i2c_is_isa_client(client)) { - down((struct semaphore *) (client->data)); - outb_p(reg,(((struct isa_client *) client)->isa_addr) + - LM78_ADDR_REG_OFFSET); - res = inb_p((((struct isa_client *) client)->isa_addr) + - LM78_DATA_REG_OFFSET); - up((struct semaphore *) (client->data)); - return res; - } else - return smbus_read_byte_data(client->adapter,client->addr, reg); -} - -/* The SMBus locks itself, but ISA access muse be locked explicitely! - We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks, - would slow down the LM78 access and should not be necessary. - There are some ugly typecasts here, but the good new is - they should - nowhere else be necessary! */ -int lm78_write_value(struct i2c_client *client, u8 reg, u8 value) -{ - if (i2c_is_isa_client(client)) { - down((struct semaphore *) (client->data)); - outb_p(reg,((struct isa_client *) client)->isa_addr + LM78_ADDR_REG_OFFSET); - outb_p(value,((struct isa_client *) client)->isa_addr + LM78_DATA_REG_OFFSET); - up((struct semaphore *) (client->data)); - return 0; - } else - return smbus_write_byte_data(client->adapter, client->addr, reg,value); -} - -/* Called when we have found a new LM78. It should set limits, etc. */ -void lm78_init_client(struct i2c_client *client) -{ - int vid; - - /* Reset all except Watchdog values and last conversion values - This sets fan-divs to 2, among others */ - lm78_write_value(client,LM78_REG_CONFIG,0x80); - - vid = lm78_read_value(client,LM78_REG_VID_FANDIV) & 0x0f; - if (((struct lm78_data *) (client->data))->type == lm79) - vid |= (lm78_read_value(client,LM78_REG_CHIPID) & 0x01) >> 4; - else - vid |= 0x10; - vid = VID_FROM_REG(vid); - - lm78_write_value(client,LM78_REG_IN_MIN(0),IN_TO_REG(LM78_INIT_IN_MIN_0)); - lm78_write_value(client,LM78_REG_IN_MAX(0),IN_TO_REG(LM78_INIT_IN_MAX_0)); - lm78_write_value(client,LM78_REG_IN_MIN(1),IN_TO_REG(LM78_INIT_IN_MIN_1)); - lm78_write_value(client,LM78_REG_IN_MAX(1),IN_TO_REG(LM78_INIT_IN_MAX_1)); - lm78_write_value(client,LM78_REG_IN_MIN(2),IN_TO_REG(LM78_INIT_IN_MIN_2)); - lm78_write_value(client,LM78_REG_IN_MAX(2),IN_TO_REG(LM78_INIT_IN_MAX_2)); - lm78_write_value(client,LM78_REG_IN_MIN(3),IN_TO_REG(LM78_INIT_IN_MIN_3)); - lm78_write_value(client,LM78_REG_IN_MAX(3),IN_TO_REG(LM78_INIT_IN_MAX_3)); - lm78_write_value(client,LM78_REG_IN_MIN(4),IN_TO_REG(LM78_INIT_IN_MIN_4)); - lm78_write_value(client,LM78_REG_IN_MAX(4),IN_TO_REG(LM78_INIT_IN_MAX_4)); - lm78_write_value(client,LM78_REG_IN_MIN(5),IN_TO_REG(LM78_INIT_IN_MIN_5)); - lm78_write_value(client,LM78_REG_IN_MAX(5),IN_TO_REG(LM78_INIT_IN_MAX_5)); - lm78_write_value(client,LM78_REG_IN_MIN(6),IN_TO_REG(LM78_INIT_IN_MIN_6)); - lm78_write_value(client,LM78_REG_IN_MAX(6),IN_TO_REG(LM78_INIT_IN_MAX_6)); - lm78_write_value(client,LM78_REG_FAN_MIN(1), - FAN_TO_REG(LM78_INIT_FAN_MIN_1,2)); - lm78_write_value(client,LM78_REG_FAN_MIN(2), - FAN_TO_REG(LM78_INIT_FAN_MIN_2,2)); - lm78_write_value(client,LM78_REG_FAN_MIN(3), - FAN_TO_REG(LM78_INIT_FAN_MIN_3,2)); - lm78_write_value(client,LM78_REG_TEMP_OVER,TEMP_TO_REG(LM78_INIT_TEMP_OVER)); - lm78_write_value(client,LM78_REG_TEMP_HYST,TEMP_TO_REG(LM78_INIT_TEMP_HYST)); - - /* Start monitoring */ - lm78_write_value(client,LM78_REG_CONFIG, - (lm78_read_value(client,LM78_REG_CONFIG) & 0xf7) | 0x01); - -} - -void lm78_update_client(struct i2c_client *client) -{ - struct lm78_data *data = client->data; - int i; - - down(&data->update_lock); - - if ((jiffies - data->last_updated > HZ+HZ/2 ) || - (jiffies < data->last_updated) || ! data->valid) { - -#ifdef DEBUG - printk("Starting lm78 update\n"); -#endif - for (i = 0; i <= 6; i++) { - data->in[i] = lm78_read_value(client,LM78_REG_IN(i)); - data->in_min[i] = lm78_read_value(client,LM78_REG_IN_MIN(i)); - data->in_max[i] = lm78_read_value(client,LM78_REG_IN_MAX(i)); - } - for (i = 1; i <= 3; i++) { - data->fan[i-1] = lm78_read_value(client,LM78_REG_FAN(i)); - data->fan_min[i-1] = lm78_read_value(client,LM78_REG_FAN_MIN(i)); - } - data->temp = lm78_read_value(client,LM78_REG_TEMP); - data->temp_over = lm78_read_value(client,LM78_REG_TEMP_OVER); - data->temp_hyst = lm78_read_value(client,LM78_REG_TEMP_HYST); - i = lm78_read_value(client,LM78_REG_VID_FANDIV); - data->vid = i & 0x0f; - if (data->type == lm79) - data->vid |= (lm78_read_value(client,LM78_REG_CHIPID) & 0x01) >> 4; - else - data->vid |= 0x10; - data->fan_div[0] = (i >> 4) & 0x03; - data->fan_div[1] = i >> 6; - data->alarms = lm78_read_value(client,LM78_REG_ALARM1) + - (lm78_read_value(client,LM78_REG_ALARM2) << 8); - data->last_updated = jiffies; - data->valid = 1; - - data->fan_div[2] = 1; - } - - up(&data->update_lock); -} - - -/* The next few functions are the call-back functions of the /proc/sys and - sysctl files. Which function is used is defined in the ctl_table in - the extra1 field. - Each function must return the magnitude (power of 10 to divide the date - with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must - put a maximum of *nrels elements in results reflecting the data of this - file, and set *nrels to the number it actually put in it, if operation== - SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from - results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE. - Note that on SENSORS_PROC_REAL_READ, I do not check whether results is - large enough (by checking the incoming value of *nrels). This is not very - good practice, but as long as you put less than about 5 values in results, - you can assume it is large enough. */ -void lm78_in(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct lm78_data *data = client->data; - int nr = ctl_name - LM78_SYSCTL_IN0; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 2; - else if (operation == SENSORS_PROC_REAL_READ) { - lm78_update_client(client); - results[0] = IN_FROM_REG(data->in_min[nr]); - results[1] = IN_FROM_REG(data->in_max[nr]); - results[2] = IN_FROM_REG(data->in[nr]); - *nrels_mag = 3; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - if (*nrels_mag >= 1) { - data->in_min[nr] = IN_TO_REG(results[0]); - lm78_write_value(client,LM78_REG_IN_MIN(nr),data->in_min[nr]); - } - if (*nrels_mag >= 2) { - data->in_max[nr] = IN_TO_REG(results[1]); - lm78_write_value(client,LM78_REG_IN_MAX(nr),data->in_max[nr]); - } - } -} - -void lm78_fan(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct lm78_data *data = client->data; - int nr = ctl_name - LM78_SYSCTL_FAN1 + 1; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - lm78_update_client(client); - results[0] = FAN_FROM_REG(data->fan_min[nr-1], - DIV_FROM_REG(data->fan_div[nr-1])); - results[1] = FAN_FROM_REG(data->fan[nr-1], - DIV_FROM_REG(data->fan_div[nr-1])); - *nrels_mag = 2; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - if (*nrels_mag >= 1) { - data->fan_min[nr-1] = FAN_TO_REG(results[0], - DIV_FROM_REG(data->fan_div[nr-1])); - lm78_write_value(client,LM78_REG_FAN_MIN(nr),data->fan_min[nr-1]); - } - } -} - - -void lm78_temp(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct lm78_data *data = client->data; - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 1; - else if (operation == SENSORS_PROC_REAL_READ) { - lm78_update_client(client); - results[0] = TEMP_FROM_REG(data->temp_over); - results[1] = TEMP_FROM_REG(data->temp_hyst); - results[2] = TEMP_FROM_REG(data->temp); - *nrels_mag = 3; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - if (*nrels_mag >= 1) { - data->temp_over = TEMP_TO_REG(results[0]); - lm78_write_value(client,LM78_REG_TEMP_OVER,data->temp_over); - } - if (*nrels_mag >= 2) { - data->temp_hyst = TEMP_TO_REG(results[1]); - lm78_write_value(client,LM78_REG_TEMP_HYST,data->temp_hyst); - } - } -} - -void lm78_vid(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct lm78_data *data = client->data; - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 2; - else if (operation == SENSORS_PROC_REAL_READ) { - lm78_update_client(client); - results[0] = VID_FROM_REG(data->vid); - *nrels_mag = 1; - } -} - -void lm78_alarms(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct lm78_data *data = client->data; - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - lm78_update_client(client); - results[0] = ALARMS_FROM_REG(data->alarms); - *nrels_mag = 1; - } -} - -void lm78_fan_div(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct lm78_data *data = client->data; - int old; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - lm78_update_client(client); - results[0] = DIV_FROM_REG(data->fan_div[0]); - results[1] = DIV_FROM_REG(data->fan_div[1]); - results[2] = 2; - *nrels_mag = 3; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - old = lm78_read_value(client,LM78_REG_VID_FANDIV); - if (*nrels_mag >= 2) { - data->fan_div[1] = DIV_TO_REG(results[1]); - old = (old & 0x3f) | (data->fan_div[1] << 6); - } - if (*nrels_mag >= 1) { - data->fan_div[0] = DIV_TO_REG(results[0]); - old = (old & 0xcf) | (data->fan_div[0] << 4); - lm78_write_value(client,LM78_REG_VID_FANDIV,old); - } - } -} - -int lm78_init(void) -{ - int res; - - printk("lm78.o version %s (%s)\n",LM_VERSION,LM_DATE); - lm78_initialized = 0; - - if ((res =i2c_add_driver(&lm78_driver))) { - printk("lm78.o: Driver registration failed, module not inserted.\n"); - lm78_cleanup(); - return res; - } - lm78_initialized ++; - return 0; -} - -int lm78_cleanup(void) -{ - int res; - - if (lm78_initialized >= 1) { - if ((res = i2c_del_driver(&lm78_driver))) { - printk("lm78.o: Driver deregistration failed, module not removed.\n"); - return res; - } - lm78_initialized --; - } - return 0; -} - - -#ifdef MODULE - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); -MODULE_DESCRIPTION("LM78, LM78-J and LM79 driver"); - -int init_module(void) -{ - return lm78_init(); -} - -int cleanup_module(void) -{ - return lm78_cleanup(); -} - -#endif /* MODULE */ - diff --git a/kernel/chips/lm80.c b/kernel/chips/lm80.c deleted file mode 100644 index 72ba020e..00000000 --- a/kernel/chips/lm80.c +++ /dev/null @@ -1,686 +0,0 @@ -/* - lm80.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> - and Philip Edelbrock <phil@netroedge.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. -*/ - -#include <linux/module.h> -#include <linux/malloc.h> -#include <linux/proc_fs.h> -#include <linux/ioport.h> -#include <linux/sysctl.h> -#include <asm/errno.h> -#include <asm/io.h> -#include <linux/types.h> -#include "smbus.h" -#include "version.h" -#include "isa.h" -#include "sensors.h" -#include "i2c.h" -#include "compat.h" - -/* Many LM80 constants specified below */ - -/* The LM80 registers */ -#define LM80_REG_IN_MAX(nr) (0x2a + (nr) * 2) -#define LM80_REG_IN_MIN(nr) (0x2b + (nr) * 2) -#define LM80_REG_IN(nr) (0x20 + (nr)) - -#define LM80_REG_FAN1_MIN 0x3c -#define LM80_REG_FAN2_MIN 0x3d -#define LM80_REG_FAN1 0x28 -#define LM80_REG_FAN2 0x29 - -#define LM80_REG_TEMP 0x27 -#define LM80_REG_TEMP_HOT_MAX 0x38 -#define LM80_REG_TEMP_HOT_HYST 0x39 -#define LM80_REG_TEMP_OS_MAX 0x3a -#define LM80_REG_TEMP_OS_HYST 0x3b - -#define LM80_REG_CONFIG 0x00 -#define LM80_REG_ALARM1 0x01 -#define LM80_REG_ALARM2 0x02 -#define LM80_REG_MASK1 0x03 -#define LM80_REG_MASK2 0x04 -#define LM80_REG_FANDIV 0x05 -#define LM80_REG_RES 0x06 - - -/* Conversions. Rounding is only done on the TO_REG variants. */ -#define IN_TO_REG(val,nr) ((val) & 0xff) -#define IN_FROM_REG(val,nr) (val) - -#define FAN_TO_REG(val,div) ((val)==0?255:\ - ((1350000+(val)*(div)/2)/((val)*(div))) & 0xff) -#define FAN_FROM_REG(val,div) ((val)==0?-1:\ - (val)==255?0:1350000/((div)*(val))) - -#define TEMP_FROM_REG(val) lm80_temp_from_reg(val) - -#define TEMP_LIMIT_TO_REG(val) (((val)<0?(((val)-50)/100)&0xff:\ - ((val)+50)/100) & 0xff) -#define TEMP_LIMIT_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*100) - -#define ALARMS_FROM_REG(val) (val) - -#define DIV_FROM_REG(val) (1 << (val)) -#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1) - -/* Initial limits */ -#define LM80_INIT_IN_0 190 -#define LM80_INIT_IN_1 190 -#define LM80_INIT_IN_2 190 -#define LM80_INIT_IN_3 190 -#define LM80_INIT_IN_4 190 -#define LM80_INIT_IN_5 190 -#define LM80_INIT_IN_6 190 - -#define LM80_INIT_IN_PERCENTAGE 10 - -#define LM80_INIT_IN_MIN_0 \ - (LM80_INIT_IN_0 - LM80_INIT_IN_0 * LM80_INIT_IN_PERCENTAGE / 100) -#define LM80_INIT_IN_MAX_0 \ - (LM80_INIT_IN_0 + LM80_INIT_IN_0 * LM80_INIT_IN_PERCENTAGE / 100) -#define LM80_INIT_IN_MIN_1 \ - (LM80_INIT_IN_1 - LM80_INIT_IN_1 * LM80_INIT_IN_PERCENTAGE / 100) -#define LM80_INIT_IN_MAX_1 \ - (LM80_INIT_IN_1 + LM80_INIT_IN_1 * LM80_INIT_IN_PERCENTAGE / 100) -#define LM80_INIT_IN_MIN_2 \ - (LM80_INIT_IN_2 - LM80_INIT_IN_2 * LM80_INIT_IN_PERCENTAGE / 100) -#define LM80_INIT_IN_MAX_2 \ - (LM80_INIT_IN_2 + LM80_INIT_IN_2 * LM80_INIT_IN_PERCENTAGE / 100) -#define LM80_INIT_IN_MIN_3 \ - (LM80_INIT_IN_3 - LM80_INIT_IN_3 * LM80_INIT_IN_PERCENTAGE / 100) -#define LM80_INIT_IN_MAX_3 \ - (LM80_INIT_IN_3 + LM80_INIT_IN_3 * LM80_INIT_IN_PERCENTAGE / 100) -#define LM80_INIT_IN_MIN_4 \ - (LM80_INIT_IN_4 - LM80_INIT_IN_4 * LM80_INIT_IN_PERCENTAGE / 100) -#define LM80_INIT_IN_MAX_4 \ - (LM80_INIT_IN_4 + LM80_INIT_IN_4 * LM80_INIT_IN_PERCENTAGE / 100) -#define LM80_INIT_IN_MIN_5 \ - (LM80_INIT_IN_5 - LM80_INIT_IN_5 * LM80_INIT_IN_PERCENTAGE / 100) -#define LM80_INIT_IN_MAX_5 \ - (LM80_INIT_IN_5 + LM80_INIT_IN_5 * LM80_INIT_IN_PERCENTAGE / 100) -#define LM80_INIT_IN_MIN_6 \ - (LM80_INIT_IN_6 - LM80_INIT_IN_6 * LM80_INIT_IN_PERCENTAGE / 100) -#define LM80_INIT_IN_MAX_6 \ - (LM80_INIT_IN_6 + LM80_INIT_IN_6 * LM80_INIT_IN_PERCENTAGE / 100) - -#define LM80_INIT_FAN_MIN_1 3000 -#define LM80_INIT_FAN_MIN_2 3000 - -#define LM80_INIT_TEMP_OS_MAX 600 -#define LM80_INIT_TEMP_OS_HYST 500 -#define LM80_INIT_TEMP_HOT_MAX 700 -#define LM80_INIT_TEMP_HOT_HYST 600 - -#ifdef MODULE -extern int init_module(void); -extern int cleanup_module(void); -#endif /* MODULE */ - -/* For each registered LM80, we need to keep some data in memory. That - data is pointed to by lm80_list[NR]->data. The structure itself is - dynamically allocated, at the same time when a new lm80 client is - allocated. */ -struct lm80_data { - int sysctl_id; - - struct semaphore update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - u8 in[7]; /* Register value */ - u8 in_max[7]; /* Register value */ - u8 in_min[7]; /* Register value */ - u8 fan[2]; /* Register value */ - u8 fan_min[2]; /* Register value */ - u8 fan_div[2]; /* Register encoding, shifted right */ - u16 temp; /* Register values, shifted right */ - u8 temp_hot_max; /* Register value */ - u8 temp_hot_hyst; /* Register value */ - u8 temp_os_max; /* Register value */ - u8 temp_os_hyst; /* Register value */ - u16 alarms; /* Register encoding, combined */ -}; - - -static int lm80_init(void); -static int lm80_cleanup(void); - -static int lm80_attach_adapter(struct i2c_adapter *adapter); -static int lm80_detach_client(struct i2c_client *client); -static int lm80_new_client(struct i2c_adapter *adapter, - struct i2c_client *new_client); -static void lm80_remove_client(struct i2c_client *client); -static int lm80_command(struct i2c_client *client, unsigned int cmd, - void *arg); -static void lm80_inc_use (struct i2c_client *client); -static void lm80_dec_use (struct i2c_client *client); - -static long lm80_temp_from_reg(u16 regs); - -static int lm80_read_value(struct i2c_client *client, u8 register); -static int lm80_write_value(struct i2c_client *client, u8 register, u8 value); -static void lm80_update_client(struct i2c_client *client); -static void lm80_init_client(struct i2c_client *client); - - -static void lm80_in(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); -static void lm80_fan(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); -static void lm80_temp(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); -static void lm80_alarms(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); -static void lm80_fan_div(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); - -/* I choose here for semi-static LM80 allocation. Complete dynamic - allocation could also be used; the code needed for this would probably - take more memory than the datastructure takes now. */ -#define MAX_LM80_NR 4 -static struct i2c_client *lm80_list[MAX_LM80_NR]; - -/* The driver. I choose to use type i2c_driver, as at is identical to both - smbus_driver and isa_driver, and clients could be of either kind */ -static struct i2c_driver lm80_driver = { - /* name */ "LM80 sensor driver", - /* id */ I2C_DRIVERID_LM80, - /* flags */ DF_NOTIFY, - /* attach_adapter */ &lm80_attach_adapter, - /* detach_client */ &lm80_detach_client, - /* command */ &lm80_command, - /* inc_use */ &lm80_inc_use, - /* dec_use */ &lm80_dec_use -}; - -/* Used by lm80_init/cleanup */ -static int lm80_initialized = 0; - -/* The /proc/sys entries */ -/* These files are created for each detected LM80. This is just a template; - though at first sight, you might think we could use a statically - allocated list, we need some way to get back to the parent - which - is done through one of the 'extra' fields which are initialized - when a new copy is allocated. */ -static ctl_table lm80_dir_table_template[] = { - { LM80_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm80_in }, - { LM80_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm80_in }, - { LM80_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm80_in }, - { LM80_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm80_in }, - { LM80_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm80_in }, - { LM80_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm80_in }, - { LM80_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm80_in }, - { LM80_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm80_fan }, - { LM80_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm80_fan }, - { LM80_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm80_temp }, - { LM80_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm80_fan_div }, - { LM80_SYSCTL_ALARMS, "alarms", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &lm80_alarms }, - { 0 } -}; - - -int lm80_attach_adapter(struct i2c_adapter *adapter) -{ - int address,err; - struct i2c_client *new_client; - const char *type_name,*client_name; - - /* OK, this is no detection. I know. It will do for now, though. */ - err = 0; - for (address = 0x20; (! err) && (address <= 0x2f); address ++) { - - /* Later on, we will keep a list of registered addresses for each - adapter, and check whether they are used here */ - - if (smbus_read_byte_data(adapter,address,LM80_REG_CONFIG) < 0) - continue; - - /* Real detection code goes here */ - - printk("lm80.o: LM80 detected\n"); - type_name = "lm80"; - client_name = "LM80 chip"; - - - /* Allocate space for a new client structure. To counter memory - fragmentation somewhat, we only do one kmalloc. */ - if (! (new_client = kmalloc(sizeof(struct i2c_client) + - sizeof(struct lm80_data), - GFP_KERNEL))) { - err = -ENOMEM; - continue; - } - - /* Fill the new client structure with data */ - new_client->data = (struct lm80_data *) (new_client + 1); - new_client->addr = address; - strcpy(new_client->name,client_name); - if ((err = lm80_new_client(adapter,new_client))) - goto ERROR2; - - /* Tell i2c-core a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto ERROR3; - - /* Register a new directory entry with module sensors */ - if ((err = sensors_register_entry(new_client,type_name, - lm80_dir_table_template)) < 0) - goto ERROR4; - ((struct lm80_data *) (new_client->data))->sysctl_id = err; - err = 0; - - /* Initialize the LM80 chip */ - lm80_init_client(new_client); - continue; - -/* OK, this is not exactly good programming practice, usually. But it is - very code-efficient in this case. */ -ERROR4: - i2c_detach_client(new_client); -ERROR3: - lm80_remove_client((struct i2c_client *) new_client); -ERROR2: - kfree(new_client); - } - return err; -} - -int lm80_detach_client(struct i2c_client *client) -{ - int err,i; - for (i = 0; i < MAX_LM80_NR; i++) - if (client == lm80_list[i]) - break; - if ((i == MAX_LM80_NR)) { - printk("lm80.o: Client to detach not found.\n"); - return -ENOENT; - } - - sensors_deregister_entry(((struct lm80_data *)(client->data))->sysctl_id); - - if ((err = i2c_detach_client(client))) { - printk("lm80.o: Client deregistration failed, client not detached.\n"); - return err; - } - lm80_remove_client(client); - kfree(client); - return 0; -} - - -/* Find a free slot, and initialize most of the fields */ -int lm80_new_client(struct i2c_adapter *adapter, - struct i2c_client *new_client) -{ - int i; - struct lm80_data *data; - - /* First, seek out an empty slot */ - for(i = 0; i < MAX_LM80_NR; i++) - if (! lm80_list[i]) - break; - if (i == MAX_LM80_NR) { - printk("lm80.o: No empty slots left, recompile and heighten " - "MAX_LM80_NR!\n"); - return -ENOMEM; - } - - lm80_list[i] = new_client; - new_client->id = i; - new_client->adapter = adapter; - new_client->driver = &lm80_driver; - data = new_client->data; - data->valid = 0; - data->update_lock = MUTEX; - return 0; -} - -/* Inverse of lm80_new_client */ -void lm80_remove_client(struct i2c_client *client) -{ - int i; - for (i = 0; i < MAX_LM80_NR; i++) - if (client == lm80_list[i]) - lm80_list[i] = NULL; -} - -/* No commands defined yet */ -int lm80_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - return 0; -} - -void lm80_inc_use (struct i2c_client *client) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -void lm80_dec_use (struct i2c_client *client) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - - -long lm80_temp_from_reg(u16 temp) -{ - long res; - res = ((temp & 0xff00) >> 8) * 10000 + ((temp & 0x10) >> 4) * 5000 + - ((temp & 0x20) >> 5) * 2500 + ((temp & 0x40) >> 6) * 1250 + - ((temp & 0x80) >> 7) * 625; - temp /= 100; - if (temp >= 0x80 * 100) - temp = - (0x100 * 100 - temp); - return temp; -} - -int lm80_read_value(struct i2c_client *client, u8 reg) -{ - return smbus_read_byte_data(client->adapter,client->addr, reg); -} - -int lm80_write_value(struct i2c_client *client, u8 reg, u8 value) -{ - return smbus_write_byte_data(client->adapter, client->addr, reg,value); -} - -/* Called when we have found a new LM80. It should set limits, etc. */ -void lm80_init_client(struct i2c_client *client) -{ - /* Reset all except Watchdog values and last conversion values - This sets fan-divs to 2, among others. This makes most other - initializations unnecessary */ - lm80_write_value(client,LM80_REG_CONFIG,0x80); - /* Set 11-bit temperature resolution */ - lm80_write_value(client,LM80_REG_RES,0x08); - - lm80_write_value(client,LM80_REG_IN_MIN(0),IN_TO_REG(LM80_INIT_IN_MIN_0,0)); - lm80_write_value(client,LM80_REG_IN_MAX(0),IN_TO_REG(LM80_INIT_IN_MAX_0,0)); - lm80_write_value(client,LM80_REG_IN_MIN(1),IN_TO_REG(LM80_INIT_IN_MIN_1,1)); - lm80_write_value(client,LM80_REG_IN_MAX(1),IN_TO_REG(LM80_INIT_IN_MAX_1,1)); - lm80_write_value(client,LM80_REG_IN_MIN(2),IN_TO_REG(LM80_INIT_IN_MIN_2,2)); - lm80_write_value(client,LM80_REG_IN_MAX(2),IN_TO_REG(LM80_INIT_IN_MAX_2,2)); - lm80_write_value(client,LM80_REG_IN_MIN(3),IN_TO_REG(LM80_INIT_IN_MIN_3,3)); - lm80_write_value(client,LM80_REG_IN_MAX(3),IN_TO_REG(LM80_INIT_IN_MAX_3,3)); - lm80_write_value(client,LM80_REG_IN_MIN(4),IN_TO_REG(LM80_INIT_IN_MIN_4,4)); - lm80_write_value(client,LM80_REG_IN_MAX(4),IN_TO_REG(LM80_INIT_IN_MAX_4,4)); - lm80_write_value(client,LM80_REG_IN_MIN(5),IN_TO_REG(LM80_INIT_IN_MIN_5,5)); - lm80_write_value(client,LM80_REG_IN_MAX(5),IN_TO_REG(LM80_INIT_IN_MAX_5,5)); - lm80_write_value(client,LM80_REG_IN_MIN(6),IN_TO_REG(LM80_INIT_IN_MIN_6,6)); - lm80_write_value(client,LM80_REG_IN_MAX(6),IN_TO_REG(LM80_INIT_IN_MAX_6,6)); - lm80_write_value(client,LM80_REG_FAN1_MIN,FAN_TO_REG(LM80_INIT_FAN_MIN_1,2)); - lm80_write_value(client,LM80_REG_FAN2_MIN,FAN_TO_REG(LM80_INIT_FAN_MIN_2,2)); - lm80_write_value(client,LM80_REG_TEMP_HOT_MAX, - TEMP_LIMIT_TO_REG(LM80_INIT_TEMP_OS_MAX)); - lm80_write_value(client,LM80_REG_TEMP_HOT_HYST, - TEMP_LIMIT_TO_REG(LM80_INIT_TEMP_OS_HYST)); - lm80_write_value(client,LM80_REG_TEMP_OS_MAX, - TEMP_LIMIT_TO_REG(LM80_INIT_TEMP_OS_MAX)); - lm80_write_value(client,LM80_REG_TEMP_OS_HYST, - TEMP_LIMIT_TO_REG(LM80_INIT_TEMP_OS_HYST)); - - /* Start monitoring */ - lm80_write_value(client,LM80_REG_CONFIG,0x01); -} - -void lm80_update_client(struct i2c_client *client) -{ - struct lm80_data *data = client->data; - int i; - - down(&data->update_lock); - - if ((jiffies - data->last_updated > 2*HZ ) || - (jiffies < data->last_updated) || ! data->valid) { - -#ifdef DEBUG - printk("Starting lm80 update\n"); -#endif - for (i = 0; i <= 6; i++) { - data->in[i] = lm80_read_value(client,LM80_REG_IN(i)); - data->in_min[i] = lm80_read_value(client,LM80_REG_IN_MIN(i)); - data->in_max[i] = lm80_read_value(client,LM80_REG_IN_MAX(i)); - } - data->fan[0] = lm80_read_value(client,LM80_REG_FAN1); - data->fan_min[0] = lm80_read_value(client,LM80_REG_FAN1_MIN); - data->fan[1] = lm80_read_value(client,LM80_REG_FAN2); - data->fan_min[1] = lm80_read_value(client,LM80_REG_FAN2_MIN); - - data->temp = (lm80_read_value(client,LM80_REG_TEMP) << 8) | - (lm80_read_value(client,LM80_REG_RES) & 0xf0); - data->temp_os_max = lm80_read_value(client,LM80_REG_TEMP_OS_MAX); - data->temp_os_hyst = lm80_read_value(client,LM80_REG_TEMP_OS_HYST); - data->temp_hot_max = lm80_read_value(client,LM80_REG_TEMP_HOT_MAX); - data->temp_hot_hyst = lm80_read_value(client,LM80_REG_TEMP_HOT_HYST); - - i = lm80_read_value(client,LM80_REG_FANDIV); - data->fan_div[0] = (i >> 2) & 0x03; - data->fan_div[1] = (i >> 4) & 0x03; - data->alarms = lm80_read_value(client,LM80_REG_ALARM1) + - (lm80_read_value(client,LM80_REG_ALARM2) << 8); - data->last_updated = jiffies; - data->valid = 1; - } - - up(&data->update_lock); -} - - -/* The next few functions are the call-back functions of the /proc/sys and - sysctl files. Which function is used is defined in the ctl_table in - the extra1 field. - Each function must return the magnitude (power of 10 to divide the date - with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must - put a maximum of *nrels elements in results reflecting the data of this - file, and set *nrels to the number it actually put in it, if operation== - SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from - results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE. - Note that on SENSORS_PROC_REAL_READ, I do not check whether results is - large enough (by checking the incoming value of *nrels). This is not very - good practice, but as long as you put less than about 5 values in results, - you can assume it is large enough. */ -void lm80_in(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct lm80_data *data = client->data; - int nr = ctl_name - LM80_SYSCTL_IN0; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 2; - else if (operation == SENSORS_PROC_REAL_READ) { - lm80_update_client(client); - results[0] = IN_FROM_REG(data->in_min[nr],nr); - results[1] = IN_FROM_REG(data->in_max[nr],nr); - results[2] = IN_FROM_REG(data->in[nr],nr); - *nrels_mag = 3; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - if (*nrels_mag >= 1) { - data->in_min[nr] = IN_TO_REG(results[0],nr); - lm80_write_value(client,LM80_REG_IN_MIN(nr),data->in_min[nr]); - } - if (*nrels_mag >= 2) { - data->in_max[nr] = IN_TO_REG(results[1],nr); - lm80_write_value(client,LM80_REG_IN_MAX(nr),data->in_max[nr]); - } - } -} - -void lm80_fan(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct lm80_data *data = client->data; - int nr = ctl_name - LM80_SYSCTL_FAN1 + 1; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - lm80_update_client(client); - results[0] = FAN_FROM_REG(data->fan_min[nr-1],data->fan_div[nr-1]); - results[1] = FAN_FROM_REG(data->fan[nr-1],data->fan_div[nr-1]); - *nrels_mag = 2; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - if (*nrels_mag >= 1) { - data->fan_min[nr-1] = FAN_TO_REG(results[0],data->fan_div[nr-1]); - lm80_write_value(client,nr==1?LM80_REG_FAN1_MIN:LM80_REG_FAN2_MIN, - data->fan_min[nr-1]); - } - } -} - - -void lm80_temp(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct lm80_data *data = client->data; - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 1; - else if (operation == SENSORS_PROC_REAL_READ) { - lm80_update_client(client); - results[0] = TEMP_LIMIT_FROM_REG(data->temp_hot_max); - results[1] = TEMP_LIMIT_FROM_REG(data->temp_hot_hyst); - results[2] = TEMP_LIMIT_FROM_REG(data->temp_os_max); - results[3] = TEMP_LIMIT_FROM_REG(data->temp_os_hyst); - results[4] = TEMP_FROM_REG(data->temp); - *nrels_mag = 5; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - if (*nrels_mag >= 1) { - data->temp_hot_max = TEMP_LIMIT_TO_REG(results[0]); - lm80_write_value(client,LM80_REG_TEMP_HOT_MAX,data->temp_hot_max); - } - if (*nrels_mag >= 2) { - data->temp_hot_hyst = TEMP_LIMIT_TO_REG(results[1]); - lm80_write_value(client,LM80_REG_TEMP_HOT_HYST,data->temp_hot_hyst); - } - if (*nrels_mag >= 3) { - data->temp_os_max = TEMP_LIMIT_TO_REG(results[2]); - lm80_write_value(client,LM80_REG_TEMP_OS_MAX,data->temp_os_max); - } - if (*nrels_mag >= 4) { - data->temp_os_hyst = TEMP_LIMIT_TO_REG(results[3]); - lm80_write_value(client,LM80_REG_TEMP_OS_HYST,data->temp_os_hyst); - } - } -} - -void lm80_alarms(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct lm80_data *data = client->data; - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - lm80_update_client(client); - results[0] = ALARMS_FROM_REG(data->alarms); - *nrels_mag = 1; - } -} - -void lm80_fan_div(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct lm80_data *data = client->data; - int old; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - lm80_update_client(client); - results[0] = DIV_FROM_REG(data->fan_div[0]); - results[1] = DIV_FROM_REG(data->fan_div[1]); - results[2] = 2; - *nrels_mag = 3; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - old = lm80_read_value(client,LM80_REG_FANDIV); - if (*nrels_mag >= 2) { - data->fan_div[1] = DIV_TO_REG(results[1]); - old = (old & 0xcf) | (data->fan_div[1] << 4); - } - if (*nrels_mag >= 1) { - data->fan_div[0] = DIV_TO_REG(results[0]); - old = (old & 0xf3) | (data->fan_div[0] << 2); - lm80_write_value(client,LM80_REG_FANDIV,old); - } - } -} - -int lm80_init(void) -{ - int res; - - printk("lm80.o version %s (%s)\n",LM_VERSION,LM_DATE); - lm80_initialized = 0; - - if ((res =i2c_add_driver(&lm80_driver))) { - printk("lm80.o: Driver registration failed, module not inserted.\n"); - lm80_cleanup(); - return res; - } - lm80_initialized ++; - return 0; -} - -int lm80_cleanup(void) -{ - int res; - - if (lm80_initialized >= 1) { - if ((res = i2c_del_driver(&lm80_driver))) { - printk("lm80.o: Driver deregistration failed, module not removed.\n"); - return res; - } - lm80_initialized --; - } - return 0; -} - - -#ifdef MODULE - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>"); -MODULE_DESCRIPTION("LM80 driver"); - -int init_module(void) -{ - return lm80_init(); -} - -int cleanup_module(void) -{ - return lm80_cleanup(); -} - -#endif /* MODULE */ - diff --git a/kernel/chips/w83781d.c b/kernel/chips/w83781d.c deleted file mode 100644 index f2c8fd27..00000000 --- a/kernel/chips/w83781d.c +++ /dev/null @@ -1,1120 +0,0 @@ -/* - w83781d.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> - and Philip Edelbrock <phil@netroedge.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. -*/ - -#include <linux/module.h> -#include <linux/malloc.h> -#include <linux/proc_fs.h> -#include <linux/ioport.h> -#include <linux/sysctl.h> -#include <asm/errno.h> -#include <asm/io.h> -#include <linux/types.h> -#include "smbus.h" -#include "version.h" -#include "isa.h" -#include "sensors.h" -#include "i2c.h" -#include "compat.h" - -/* Many W83781D constants specified below */ - -/* Length of ISA address segment */ -#define W83781D_EXTENT 8 - -/* Where are the ISA address/data registers relative to the base address */ -#define W83781D_ADDR_REG_OFFSET 5 -#define W83781D_DATA_REG_OFFSET 6 - -/* The W83781D registers */ -#define W83781D_REG_IN_MAX(nr) (0x2b + (nr) * 2) -#define W83781D_REG_IN_MIN(nr) (0x2c + (nr) * 2) -#define W83781D_REG_IN(nr) (0x20 + (nr)) - -#define W83781D_REG_FAN_MIN(nr) (0x3a + (nr)) -#define W83781D_REG_FAN(nr) (0x27 + (nr)) - -#define W83781D_REG_TEMP2 0x0150 -#define W83781D_REG_TEMP3 0x0250 -#define W83781D_REG_TEMP2_HYST 0x153 -#define W83781D_REG_TEMP3_HYST 0x253 -#define W83781D_REG_TEMP2_CONFIG 0x152 -#define W83781D_REG_TEMP3_CONFIG 0x252 -#define W83781D_REG_TEMP2_OVER 0x155 -#define W83781D_REG_TEMP3_OVER 0x255 - -#define W83781D_REG_TEMP 0x27 -#define W83781D_REG_TEMP_OVER 0x39 -#define W83781D_REG_TEMP_HYST 0x3A -#define W83781D_REG_TEMP_CONFIG 0x52 -#define W83781D_REG_BANK 0x4E - -#define W83781D_REG_CONFIG 0x40 -#define W83781D_REG_ALARM1 0x41 -#define W83781D_REG_ALARM2 0x42 - -#define W83781D_REG_BEEP_CONFIG 0x4D -#define W83781D_REG_BEEP_INTS1 0x56 -#define W83781D_REG_BEEP_INTS2 0x57 - -#define W83781D_REG_VID_FANDIV 0x47 - -#define W83781D_REG_CHIPID 0x49 -#define W83781D_REG_WCHIPID 0x58 -#define W83781D_REG_CHIPMAN 0x4F -#define W83781D_REG_PIN 0x4B - - -/* Conversions. Rounding is only done on the TO_REG variants. */ -#define IN_TO_REG(val,nr) (((val) * 10 + 8)/16) -#define IN_FROM_REG(val,nr) (((val) * 16) / 10) - -#define FAN_TO_REG(val,div) ((val)==0?255:((1350000+(val)*(div)/2)/\ - ((val)*(div))) & 0xff) -#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*2*(div))) - -#define TEMP_TO_REG(val) (((val)<0?(((val)-5)/10)&0xff:((val)+5)/10) & 0xff) -#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10) - -#define TEMP_ADD_TO_REG(val) (((((val) + 2) / 5) << 7) & 0xff80) -#define TEMP_ADD_FROM_REG(val) (((val) >> 7) * 5) - -#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\ - (val)>=0x06?0:205-(val)*5) -#define ALARMS_FROM_REG(val) (val) -#define BEEPS_FROM_REG(val) (val) -#define BEEPS_TO_REG(val) ((val) & 0xffff) - -#define BEEP_ENABLE_TO_REG(val) (val) -#define BEEP_ENABLE_FROM_REG(val) ((val)?1:0) - -#define DIV_FROM_REG(val) (1 << (val)) -#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1) - -/* Initial limits */ -#define W83781D_INIT_IN_0 (vid==350?280:vid) -#define W83781D_INIT_IN_1 (vid==350?280:vid) -#define W83781D_INIT_IN_2 330 -#define W83781D_INIT_IN_3 (((500) * 100)/168) -#define W83781D_INIT_IN_4 (((1200) * 10)/38) -#define W83781D_INIT_IN_5 (((-1200) * -604)/2100) -#define W83781D_INIT_IN_6 (((-500) * -604)/909) - -#define W83781D_INIT_IN_PERCENTAGE 10 - -#define W83781D_INIT_IN_MIN_0 \ - (W83781D_INIT_IN_0 - W83781D_INIT_IN_0 * W83781D_INIT_IN_PERCENTAGE \ - / 100) -#define W83781D_INIT_IN_MAX_0 \ - (W83781D_INIT_IN_0 + W83781D_INIT_IN_0 * W83781D_INIT_IN_PERCENTAGE \ - / 100) -#define W83781D_INIT_IN_MIN_1 \ - (W83781D_INIT_IN_1 - W83781D_INIT_IN_1 * W83781D_INIT_IN_PERCENTAGE \ - / 100) -#define W83781D_INIT_IN_MAX_1 \ - (W83781D_INIT_IN_1 + W83781D_INIT_IN_1 * W83781D_INIT_IN_PERCENTAGE \ - / 100) -#define W83781D_INIT_IN_MIN_2 \ - (W83781D_INIT_IN_2 - W83781D_INIT_IN_2 * W83781D_INIT_IN_PERCENTAGE \ - / 100) -#define W83781D_INIT_IN_MAX_2 \ - (W83781D_INIT_IN_2 + W83781D_INIT_IN_2 * W83781D_INIT_IN_PERCENTAGE \ - / 100) -#define W83781D_INIT_IN_MIN_3 \ - (W83781D_INIT_IN_3 - W83781D_INIT_IN_3 * W83781D_INIT_IN_PERCENTAGE \ - / 100) -#define W83781D_INIT_IN_MAX_3 \ - (W83781D_INIT_IN_3 + W83781D_INIT_IN_3 * W83781D_INIT_IN_PERCENTAGE \ - / 100) -#define W83781D_INIT_IN_MIN_4 \ - (W83781D_INIT_IN_4 - W83781D_INIT_IN_4 * W83781D_INIT_IN_PERCENTAGE \ - / 100) -#define W83781D_INIT_IN_MAX_4 \ - (W83781D_INIT_IN_4 + W83781D_INIT_IN_4 * W83781D_INIT_IN_PERCENTAGE \ - / 100) -#define W83781D_INIT_IN_MIN_5 \ - (W83781D_INIT_IN_5 - W83781D_INIT_IN_5 * W83781D_INIT_IN_PERCENTAGE \ - / 100) -#define W83781D_INIT_IN_MAX_5 \ - (W83781D_INIT_IN_5 + W83781D_INIT_IN_5 * W83781D_INIT_IN_PERCENTAGE \ - / 100) -#define W83781D_INIT_IN_MIN_6 \ - (W83781D_INIT_IN_6 - W83781D_INIT_IN_6 * W83781D_INIT_IN_PERCENTAGE \ - / 100) -#define W83781D_INIT_IN_MAX_6 \ - (W83781D_INIT_IN_6 + W83781D_INIT_IN_6 * W83781D_INIT_IN_PERCENTAGE \ - / 100) - -#define W83781D_INIT_FAN_MIN_1 3000 -#define W83781D_INIT_FAN_MIN_2 3000 -#define W83781D_INIT_FAN_MIN_3 3000 - -#define W83781D_INIT_TEMP_OVER 600 -#define W83781D_INIT_TEMP_HYST 500 -#define W83781D_INIT_TEMP2_OVER 600 -#define W83781D_INIT_TEMP2_HYST 500 -#define W83781D_INIT_TEMP3_OVER 600 -#define W83781D_INIT_TEMP3_HYST 500 - -#ifdef MODULE -extern int init_module(void); -extern int cleanup_module(void); -#endif /* MODULE */ - -/* There are some complications in a module like this. First off, W83781D chips - may be both present on the SMBus and the ISA bus, and we have to handle - those cases separately at some places. Second, there might be several - W83781D chips available (well, actually, that is probably never done; but - it is a clean illustration of how to handle a case like that). Finally, - a specific chip may be attached to *both* ISA and SMBus, and we would - not like to detect it double. Fortunately, in the case of the W83781D at - least, a register tells us what SMBus address we are on, so that helps - a bit - except if there could be more than one SMBus. Groan. No solution - for this yet. */ - -/* This module may seem overly long and complicated. In fact, it is not so - bad. Quite a lot of bookkeeping is done. A real driver can often cut - some corners. */ - -/* For each registered W83781D, we need to keep some data in memory. That - data is pointed to by w83781d_list[NR]->data. The structure itself is - dynamically allocated, at the same time when a new w83781d client is - allocated. */ -struct w83781d_data { - struct semaphore lock; - int sysctl_id; - - struct semaphore update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - u8 in[7]; /* Register value */ - u8 in_max[7]; /* Register value */ - u8 in_min[7]; /* Register value */ - u8 fan[3]; /* Register value */ - u8 fan_min[3]; /* Register value */ - u8 temp; - u8 temp_over; /* Register value */ - u8 temp_hyst; /* Register value */ - u16 temp_add[2]; /* Register value */ - u16 temp_add_over[2]; /* Register value */ - u16 temp_add_hyst[2]; /* Register value */ - u8 fan_div[3]; /* Register encoding, shifted right */ - u8 vid; /* Register encoding, combined */ - u16 alarms; /* Register encoding, combined */ - u16 beeps; /* Register encoding, combined */ - u8 beep_enable; /* Boolean */ -}; - - -static int w83781d_init(void); -static int w83781d_cleanup(void); - -static int w83781d_attach_adapter(struct i2c_adapter *adapter); -static int w83781d_detect_isa(struct isa_adapter *adapter); -static int w83781d_detect_smbus(struct i2c_adapter *adapter); -static int w83781d_detach_client(struct i2c_client *client); -static int w83781d_detach_isa(struct isa_client *client); -static int w83781d_detach_smbus(struct i2c_client *client); -static int w83781d_new_client(struct i2c_adapter *adapter, - struct i2c_client *new_client); -static void w83781d_remove_client(struct i2c_client *client); -static int w83781d_command(struct i2c_client *client, unsigned int cmd, - void *arg); -static void w83781d_inc_use (struct i2c_client *client); -static void w83781d_dec_use (struct i2c_client *client); - -static int w83781d_read_value(struct i2c_client *client, u16 register); -static int w83781d_write_value(struct i2c_client *client, u16 register, - u16 value); -static void w83781d_update_client(struct i2c_client *client); -static void w83781d_init_client(struct i2c_client *client); - - -static void w83781d_in(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); -static void w83781d_fan(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); -static void w83781d_temp(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results); -static void w83781d_temp_add(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results); -static void w83781d_vid(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); -static void w83781d_alarms(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results); -static void w83781d_beep(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results); -static void w83781d_fan_div(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results); - -/* I choose here for semi-static W83781D allocation. Complete dynamic - allocation could also be used; the code needed for this would probably - take more memory than the datastructure takes now. */ -#define MAX_W83781D_NR 4 -static struct i2c_client *w83781d_list[MAX_W83781D_NR]; - -/* The driver. I choose to use type i2c_driver, as at is identical to both - smbus_driver and isa_driver, and clients could be of either kind */ -static struct i2c_driver w83781d_driver = { - /* name */ "W83781D sensor driver", - /* id */ I2C_DRIVERID_W83781D, - /* flags */ DF_NOTIFY, - /* attach_adapter */ &w83781d_attach_adapter, - /* detach_client */ &w83781d_detach_client, - /* command */ &w83781d_command, - /* inc_use */ &w83781d_inc_use, - /* dec_use */ &w83781d_dec_use -}; - -/* Used by w83781d_init/cleanup */ -static int w83781d_initialized = 0; - -/* The /proc/sys entries */ -/* These files are created for each detected W83781D. This is just a template; - though at first sight, you might think we could use a statically - allocated list, we need some way to get back to the parent - which - is done through one of the 'extra' fields which are initialized - when a new copy is allocated. */ -static ctl_table w83781d_dir_table_template[] = { - { W83781D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &w83781d_in }, - { W83781D_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &w83781d_in }, - { W83781D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &w83781d_in }, - { W83781D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &w83781d_in }, - { W83781D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &w83781d_in }, - { W83781D_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &w83781d_in }, - { W83781D_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &w83781d_in }, - { W83781D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &w83781d_fan }, - { W83781D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &w83781d_fan }, - { W83781D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &w83781d_fan }, - { W83781D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &w83781d_temp }, - { W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &w83781d_temp_add }, - { W83781D_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &w83781d_temp_add }, - { W83781D_SYSCTL_VID, "vid", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &w83781d_vid }, - { W83781D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &w83781d_fan_div }, - { W83781D_SYSCTL_ALARMS, "alarms", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &w83781d_alarms }, - { W83781D_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &sensors_proc_real, - &sensors_sysctl_real, NULL, &w83781d_beep }, - { 0 } -}; - - -/* This function is called when: - * w83781d_driver is inserted (when this module is loaded), for each - available adapter - * when a new adapter is inserted (and w83781d_driver is still present) */ -int w83781d_attach_adapter(struct i2c_adapter *adapter) -{ - if (i2c_is_isa_adapter(adapter)) - return w83781d_detect_isa((struct isa_adapter *) adapter); - else - return w83781d_detect_smbus(adapter); -} - -/* This function is called whenever a client should be removed: - * w83781d_driver is removed (when this module is unloaded) - * when an adapter is removed which has a w83781d client (and w83781d_driver - is still present). */ -int w83781d_detach_client(struct i2c_client *client) -{ - if (i2c_is_isa_client(client)) - return w83781d_detach_isa((struct isa_client *) client); - else - return w83781d_detach_smbus(client); -} - -/* Detect whether there is a W83781D on the ISA bus, register and initialize - it. */ -int w83781d_detect_isa(struct isa_adapter *adapter) -{ - int address,err; - struct isa_client *new_client; - const char *type_name; - const char *client_name; - - /* OK, this is no detection. I know. It will do for now, though. */ - - err = 0; - for (address = 0x290; (! err) && (address <= 0x290); address += 0x08) { - if (check_region(address, W83781D_EXTENT)) - continue; - - /* Awful, but true: unused port addresses should return 0xff */ - if ((inb_p(address + 1) != 0xff) || (inb_p(address + 2) != 0xff) || - (inb_p(address + 3) != 0xff) || (inb_p(address + 7) != 0xff)) - continue; - - if (inb_p(address + W83781D_ADDR_REG_OFFSET) == 0xff) { - outb_p(0x00,address + W83781D_ADDR_REG_OFFSET); - if (inb_p(address + W83781D_ADDR_REG_OFFSET) == 0xff) - continue; - } - - /* Real detection code goes here */ - - /* The Winbond may be stuck in bank 1 or 2. This should reset it. - We really need some nifty detection code, because this can lead - to a lot of problems if there is no Winbond present! */ - outb_p(W83781D_REG_BANK,address + W83781D_ADDR_REG_OFFSET); - outb_p(0x00,address + W83781D_DATA_REG_OFFSET); - - outb_p(W83781D_REG_WCHIPID,address + W83781D_ADDR_REG_OFFSET); - err = inb_p(address + W83781D_DATA_REG_OFFSET) & 0xfe; - - if (err != 0x20) { - printk("w83781d.o: Winbond W83781D detected (ISA addr=0x%X)\n",address); - type_name = "w83781d"; - client_name = "Winbond W83781D chip"; - } else { - #ifdef DEBUG - printk("83781d.o: Winbond W83781D not detected (ISA)\n"); - #endif - continue; - } - - request_region(address, W83781D_EXTENT, type_name); - - /* Allocate space for a new client structure */ - if (! (new_client = kmalloc(sizeof(struct isa_client) + - sizeof(struct w83781d_data), - GFP_KERNEL))) - { - err=-ENOMEM; - goto ERROR1; - } - - /* Fill the new client structure with data */ - new_client->data = (struct w83781d_data *) (new_client + 1); - new_client->addr = 0; - strcpy(new_client->name,client_name); - new_client->isa_addr = address; - if ((err = w83781d_new_client((struct i2c_adapter *) adapter, - (struct i2c_client *) new_client))) - goto ERROR2; - - /* Tell i2c-core a new client has arrived */ - if ((err = isa_attach_client(new_client))) - goto ERROR3; - - /* Register a new directory entry with module sensors */ - if ((err = sensors_register_entry((struct i2c_client *) new_client, - type_name, - w83781d_dir_table_template)) < 0) - goto ERROR4; - ((struct w83781d_data *) (new_client->data)) -> sysctl_id = err; - err = 0; - - /* Initialize the W83781D chip */ - w83781d_init_client((struct i2c_client *) new_client); - continue; - -/* OK, this is not exactly good programming practice, usually. But it is - very code-efficient in this case. */ - -ERROR4: - isa_detach_client(new_client); -ERROR3: - w83781d_remove_client((struct i2c_client *) new_client); -ERROR2: - kfree(new_client); -ERROR1: - release_region(address, W83781D_EXTENT); - } - return err; - -} - -/* Deregister and remove a W83781D client */ -int w83781d_detach_isa(struct isa_client *client) -{ - int err,i; - for (i = 0; i < MAX_W83781D_NR; i++) - if ((client == (struct isa_client *) (w83781d_list[i]))) - break; - if (i == MAX_W83781D_NR) { - printk("w83781d.o: Client to detach not found.\n"); - return -ENOENT; - } - - sensors_deregister_entry(((struct w83781d_data *)(client->data))->sysctl_id); - - if ((err = isa_detach_client(client))) { - printk("w83781d.o: Client deregistration failed, client not detached.\n"); - return err; - } - w83781d_remove_client((struct i2c_client *) client); - release_region(client->isa_addr,W83781D_EXTENT); - kfree(client); - return 0; -} - -int w83781d_detect_smbus(struct i2c_adapter *adapter) -{ - int address,err; - struct i2c_client *new_client; - const char *type_name,*client_name; - - /* OK, this is no detection. I know. It will do for now, though. */ - err = 0; - for (address = 0x20; (! err) && (address <= 0x2f); address ++) { - - /* Later on, we will keep a list of registered addresses for each - adapter, and check whether they are used here */ - - if (smbus_read_byte_data(adapter,address,W83781D_REG_CONFIG) < 0) - continue; - - smbus_write_byte_data(adapter,address,W83781D_REG_BANK,0x00); - - err = smbus_read_byte_data(adapter,address,W83781D_REG_WCHIPID); - - if (err == 0x20) { - printk("w83781d.o: Winbond W83781D detected (SMBus addr 0x%X)\n",address); - type_name = "w83781d"; - client_name = "Winbond W83781D chip"; - } else { - #ifdef DEBUG - printk("83781d.o: Winbond W83781D not detected (SMBus/I2C)\n"); - #endif - continue; - } - - /* Allocate space for a new client structure. To counter memory - ragmentation somewhat, we only do one kmalloc. */ - if (! (new_client = kmalloc(sizeof(struct i2c_client) + - sizeof(struct w83781d_data), - GFP_KERNEL))) { - err = -ENOMEM; - continue; - } - - /* Fill the new client structure with data */ - new_client->data = (struct w83781d_data *) (new_client + 1); - new_client->addr = address; - strcpy(new_client->name,client_name); - if ((err = w83781d_new_client(adapter,new_client))) - goto ERROR2; - - /* Tell i2c-core a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto ERROR3; - - /* Register a new directory entry with module sensors */ - if ((err = sensors_register_entry(new_client,type_name, - w83781d_dir_table_template)) < 0) - goto ERROR4; - ((struct w83781d_data *) (new_client->data))->sysctl_id = err; - err = 0; - - /* Initialize the W83781D chip */ - w83781d_init_client(new_client); - continue; - -/* OK, this is not exactly good programming practice, usually. But it is - very code-efficient in this case. */ -ERROR4: - i2c_detach_client(new_client); -ERROR3: - w83781d_remove_client((struct i2c_client *) new_client); -ERROR2: - kfree(new_client); - } - return err; -} - -int w83781d_detach_smbus(struct i2c_client *client) -{ - int err,i; - for (i = 0; i < MAX_W83781D_NR; i++) - if (client == w83781d_list[i]) - break; - if ((i == MAX_W83781D_NR)) { - printk("w83781d.o: Client to detach not found.\n"); - return -ENOENT; - } - - sensors_deregister_entry(((struct w83781d_data *)(client->data))->sysctl_id); - - if ((err = i2c_detach_client(client))) { - printk("w83781d.o: Client deregistration failed, client not detached.\n"); - return err; - } - w83781d_remove_client(client); - kfree(client); - return 0; -} - - -/* Find a free slot, and initialize most of the fields */ -int w83781d_new_client(struct i2c_adapter *adapter, - struct i2c_client *new_client) -{ - int i; - struct w83781d_data *data; - - /* First, seek out an empty slot */ - for(i = 0; i < MAX_W83781D_NR; i++) - if (! w83781d_list[i]) - break; - if (i == MAX_W83781D_NR) { - printk("w83781d.o: No empty slots left, recompile and heighten " - "MAX_W83781D_NR!\n"); - return -ENOMEM; - } - - w83781d_list[i] = new_client; - new_client->id = i; - new_client->adapter = adapter; - new_client->driver = &w83781d_driver; - data = new_client->data; - data->valid = 0; - data->lock = MUTEX; - data->update_lock = MUTEX; - return 0; -} - -/* Inverse of w83781d_new_client */ -void w83781d_remove_client(struct i2c_client *client) -{ - int i; - for (i = 0; i < MAX_W83781D_NR; i++) - if (client == w83781d_list[i]) - w83781d_list[i] = NULL; -} - -/* No commands defined yet */ -int w83781d_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - return 0; -} - -/* Nothing here yet */ -void w83781d_inc_use (struct i2c_client *client) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -/* Nothing here yet */ -void w83781d_dec_use (struct i2c_client *client) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - - -/* The SMBus locks itself, usually, but nothing may access the Winbond between - bank switches. ISA access must always be locked explicitely! - We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, - would slow down the W83781D access and should not be necessary. - There are some ugly typecasts here, but the good new is - they should - nowhere else be necessary! */ -int w83781d_read_value(struct i2c_client *client, u16 reg) -{ - int res,word_sized; - - word_sized = (reg & 0xff00) && (((reg & 0x00ff) == 0x50) || - ((reg & 0x00ff) == 0x53) || - ((reg & 0x00ff) == 0x55)); - down((struct semaphore *) (client->data)); - if (i2c_is_isa_client(client)) { - if (reg & 0xff00) { - outb_p(W83781D_REG_BANK,(((struct isa_client *) client)->isa_addr) + - W83781D_ADDR_REG_OFFSET); - outb_p(reg >> 8,(((struct isa_client *) client)->isa_addr) + - W83781D_DATA_REG_OFFSET); - } - outb_p(reg & 0xff,(((struct isa_client *) client)->isa_addr) + - W83781D_ADDR_REG_OFFSET); - res = inb_p((((struct isa_client *) client)->isa_addr) + - W83781D_DATA_REG_OFFSET); - if (word_sized) { - outb_p((reg & 0xff)+1,(((struct isa_client *) client)->isa_addr) + - W83781D_ADDR_REG_OFFSET); - res = (res << 8) + inb_p((((struct isa_client *) client)->isa_addr) + - W83781D_DATA_REG_OFFSET); - } - if (reg & 0xff00) { - outb_p(W83781D_REG_BANK,(((struct isa_client *) client)->isa_addr) + - W83781D_ADDR_REG_OFFSET); - outb_p(0,(((struct isa_client *) client)->isa_addr) + - W83781D_DATA_REG_OFFSET); - } - } else { - if (reg & 0xff00) - smbus_write_byte_data(client->adapter,client->addr,W83781D_REG_BANK, - reg >> 8); - res = smbus_read_byte_data(client->adapter,client->addr, reg); - if (word_sized) - res = (res << 8) + smbus_read_byte_data(client->adapter,client->addr, - reg); - if (reg & 0xff00) - smbus_write_byte_data(client->adapter,client->addr,W83781D_REG_BANK,0); - } - up((struct semaphore *) (client->data)); - return res; -} - -/* The SMBus locks itself, usually, but nothing may access the Winbond between - bank switches. ISA access must always be locked explicitely! - We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, - would slow down the W83781D access and should not be necessary. - There are some ugly typecasts here, but the good new is - they should - nowhere else be necessary! */ -int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value) -{ - int word_sized; - - word_sized = (reg & 0xff00) && (((reg & 0x00ff) == 0x50) || - ((reg & 0x00ff) == 0x53) || - ((reg & 0x00ff) == 0x55)); - down((struct semaphore *) (client->data)); - if (i2c_is_isa_client(client)) { - if (reg & 0xff00) { - outb_p(W83781D_REG_BANK,(((struct isa_client *) client)->isa_addr) + - W83781D_ADDR_REG_OFFSET); - outb_p(reg >> 8,(((struct isa_client *) client)->isa_addr) + - W83781D_DATA_REG_OFFSET); - } - outb_p(reg & 0xff,(((struct isa_client *) client)->isa_addr) + - W83781D_ADDR_REG_OFFSET); - if (word_sized) { - outb_p(value >> 8,(((struct isa_client *) client)->isa_addr) + - W83781D_DATA_REG_OFFSET); - outb_p((reg & 0xff)+1,(((struct isa_client *) client)->isa_addr) + - W83781D_ADDR_REG_OFFSET); - } - outb_p(value &0xff,(((struct isa_client *) client)->isa_addr) + - W83781D_DATA_REG_OFFSET); - if (reg & 0xff00) { - outb_p(W83781D_REG_BANK,(((struct isa_client *) client)->isa_addr) + - W83781D_ADDR_REG_OFFSET); - outb_p(0,(((struct isa_client *) client)->isa_addr) + - W83781D_DATA_REG_OFFSET); - } - } else { - if (reg & 0xff00) - smbus_write_byte_data(client->adapter,client->addr,W83781D_REG_BANK, - reg >> 8); - if (word_sized) { - smbus_write_byte_data(client->adapter,client->addr, reg, value >> 8); - smbus_write_byte_data(client->adapter,client->addr, reg+1, value &0xff); - } else - smbus_write_byte_data(client->adapter,client->addr, reg, value &0xff); - if (reg & 0xff00) - smbus_write_byte_data(client->adapter,client->addr,W83781D_REG_BANK,0); - } - up((struct semaphore *) (client->data)); - return 0; -} - -/* Called when we have found a new W83781D. It should set limits, etc. */ -void w83781d_init_client(struct i2c_client *client) -{ - int vid; - - /* Reset all except Watchdog values and last conversion values - This sets fan-divs to 2, among others */ - w83781d_write_value(client,W83781D_REG_CONFIG,0x80); - - vid = w83781d_read_value(client,W83781D_REG_VID_FANDIV) & 0x0f; - vid |= (w83781d_read_value(client,W83781D_REG_CHIPID) & 0x01) >> 4; - vid = VID_FROM_REG(vid); - - w83781d_write_value(client,W83781D_REG_IN_MIN(0), - IN_TO_REG(W83781D_INIT_IN_MIN_0,0)); - w83781d_write_value(client,W83781D_REG_IN_MAX(0), - IN_TO_REG(W83781D_INIT_IN_MAX_0,0)); - w83781d_write_value(client,W83781D_REG_IN_MIN(1), - IN_TO_REG(W83781D_INIT_IN_MIN_1,1)); - w83781d_write_value(client,W83781D_REG_IN_MAX(1), - IN_TO_REG(W83781D_INIT_IN_MAX_1,1)); - w83781d_write_value(client,W83781D_REG_IN_MIN(2), - IN_TO_REG(W83781D_INIT_IN_MIN_2,2)); - w83781d_write_value(client,W83781D_REG_IN_MAX(2), - IN_TO_REG(W83781D_INIT_IN_MAX_2,2)); - w83781d_write_value(client,W83781D_REG_IN_MIN(3), - IN_TO_REG(W83781D_INIT_IN_MIN_3,3)); - w83781d_write_value(client,W83781D_REG_IN_MAX(3), - IN_TO_REG(W83781D_INIT_IN_MAX_3,3)); - w83781d_write_value(client,W83781D_REG_IN_MIN(4), - IN_TO_REG(W83781D_INIT_IN_MIN_4,4)); - w83781d_write_value(client,W83781D_REG_IN_MAX(4), - IN_TO_REG(W83781D_INIT_IN_MAX_4,4)); - w83781d_write_value(client,W83781D_REG_IN_MIN(5), - IN_TO_REG(W83781D_INIT_IN_MIN_5,5)); - w83781d_write_value(client,W83781D_REG_IN_MAX(5), - IN_TO_REG(W83781D_INIT_IN_MAX_5,5)); - w83781d_write_value(client,W83781D_REG_IN_MIN(6), - IN_TO_REG(W83781D_INIT_IN_MIN_6,6)); - w83781d_write_value(client,W83781D_REG_IN_MAX(6), - IN_TO_REG(W83781D_INIT_IN_MAX_6,6)); - w83781d_write_value(client,W83781D_REG_FAN_MIN(1), - FAN_TO_REG(W83781D_INIT_FAN_MIN_1,2)); - w83781d_write_value(client,W83781D_REG_FAN_MIN(2), - FAN_TO_REG(W83781D_INIT_FAN_MIN_2,2)); - w83781d_write_value(client,W83781D_REG_FAN_MIN(3), - FAN_TO_REG(W83781D_INIT_FAN_MIN_3,2)); - - w83781d_write_value(client,W83781D_REG_TEMP_OVER, - TEMP_TO_REG(W83781D_INIT_TEMP_OVER)); - w83781d_write_value(client,W83781D_REG_TEMP_HYST, - TEMP_TO_REG(W83781D_INIT_TEMP_HYST)); - w83781d_write_value(client,W83781D_REG_TEMP_CONFIG,0x00); - - w83781d_write_value(client,W83781D_REG_TEMP2_OVER, - TEMP_ADD_TO_REG(W83781D_INIT_TEMP2_OVER)); - w83781d_write_value(client,W83781D_REG_TEMP2_HYST, - TEMP_ADD_TO_REG(W83781D_INIT_TEMP2_HYST)); - w83781d_write_value(client,W83781D_REG_TEMP2_CONFIG,0x00); - - w83781d_write_value(client,W83781D_REG_TEMP3_OVER, - TEMP_ADD_TO_REG(W83781D_INIT_TEMP3_OVER)); - w83781d_write_value(client,W83781D_REG_TEMP3_HYST, - TEMP_ADD_TO_REG(W83781D_INIT_TEMP3_HYST)); - w83781d_write_value(client,W83781D_REG_TEMP3_CONFIG,0x00); - - /* Start monitoring */ - w83781d_write_value(client,W83781D_REG_CONFIG, - (w83781d_read_value(client, - W83781D_REG_CONFIG) & 0xf7) | 0x01); -} - -void w83781d_update_client(struct i2c_client *client) -{ - struct w83781d_data *data = client->data; - int i; - - down(&data->update_lock); - - if ((jiffies - data->last_updated > HZ+HZ/2 ) || - (jiffies < data->last_updated) || ! data->valid) { - -#ifdef DEBUG - printk("Starting w83781d update\n"); -#endif - for (i = 0; i <= 6; i++) { - data->in[i] = w83781d_read_value(client,W83781D_REG_IN(i)); - data->in_min[i] = w83781d_read_value(client,W83781D_REG_IN_MIN(i)); - data->in_max[i] = w83781d_read_value(client,W83781D_REG_IN_MAX(i)); - } - for (i = 1; i <= 3; i++) { - data->fan[i-1] = w83781d_read_value(client,W83781D_REG_FAN(i)); - data->fan_min[i-1] = w83781d_read_value(client,W83781D_REG_FAN_MIN(i)); - } - data->temp = w83781d_read_value(client,W83781D_REG_TEMP); - data->temp_over = w83781d_read_value(client,W83781D_REG_TEMP_OVER); - data->temp_hyst = w83781d_read_value(client,W83781D_REG_TEMP_HYST); - data->temp_add[0] = w83781d_read_value(client,W83781D_REG_TEMP2); - data->temp_add_over[0] = w83781d_read_value(client,W83781D_REG_TEMP2_OVER); - data->temp_add_hyst[0] = w83781d_read_value(client,W83781D_REG_TEMP2_HYST); - data->temp_add[1] = w83781d_read_value(client,W83781D_REG_TEMP3); - data->temp_add_over[1] = w83781d_read_value(client,W83781D_REG_TEMP3_OVER); - data->temp_add_hyst[1] = w83781d_read_value(client,W83781D_REG_TEMP3_HYST); - i = w83781d_read_value(client,W83781D_REG_VID_FANDIV); - data->vid = i & 0x0f; - data->vid |= (w83781d_read_value(client,W83781D_REG_CHIPID) & 0x01) >> 4; - data->fan_div[0] = (i >> 4) & 0x03; - data->fan_div[1] = i >> 6; - data->fan_div[2] = (w83781d_read_value(client,W83781D_REG_PIN) >> 6) & 0x03; - data->alarms = w83781d_read_value(client,W83781D_REG_ALARM1) + - (w83781d_read_value(client,W83781D_REG_ALARM2) << 8); - i = w83781d_read_value(client,W83781D_REG_BEEP_INTS2); - data->beep_enable = i >> 7; - data->beeps = ((i & 0x7f) << 8) + - w83781d_read_value(client,W83781D_REG_BEEP_INTS1); - data->last_updated = jiffies; - data->valid = 1; - } - - up(&data->update_lock); -} - - -/* The next few functions are the call-back functions of the /proc/sys and - sysctl files. Which function is used is defined in the ctl_table in - the extra1 field. - Each function must return the magnitude (power of 10 to divide the date - with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must - put a maximum of *nrels elements in results reflecting the data of this - file, and set *nrels to the number it actually put in it, if operation== - SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from - results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE. - Note that on SENSORS_PROC_REAL_READ, I do not check whether results is - large enough (by checking the incoming value of *nrels). This is not very - good practice, but as long as you put less than about 5 values in results, - you can assume it is large enough. */ -void w83781d_in(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct w83781d_data *data = client->data; - int nr = ctl_name - W83781D_SYSCTL_IN0; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 2; - else if (operation == SENSORS_PROC_REAL_READ) { - w83781d_update_client(client); - results[0] = IN_FROM_REG(data->in_min[nr],nr); - results[1] = IN_FROM_REG(data->in_max[nr],nr); - results[2] = IN_FROM_REG(data->in[nr],nr); - *nrels_mag = 3; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - if (*nrels_mag >= 1) { - data->in_min[nr] = IN_TO_REG(results[0],nr); - w83781d_write_value(client,W83781D_REG_IN_MIN(nr),data->in_min[nr]); - } - if (*nrels_mag >= 2) { - data->in_max[nr] = IN_TO_REG(results[1],nr); - w83781d_write_value(client,W83781D_REG_IN_MAX(nr),data->in_max[nr]); - } - } -} - -void w83781d_fan(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct w83781d_data *data = client->data; - int nr = ctl_name - W83781D_SYSCTL_FAN1 + 1; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - w83781d_update_client(client); - results[0] = FAN_FROM_REG(data->fan_min[nr-1],data->fan_div[nr-1]); - results[1] = FAN_FROM_REG(data->fan[nr-1],data->fan_div[nr-1]); - *nrels_mag = 2; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - if (*nrels_mag >= 1) { - data->fan_min[nr-1] = FAN_TO_REG(results[0],data->fan_div[nr-1]); - w83781d_write_value(client,W83781D_REG_FAN_MIN(nr),data->fan_min[nr-1]); - } - } -} - - -void w83781d_temp(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct w83781d_data *data = client->data; - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 1; - else if (operation == SENSORS_PROC_REAL_READ) { - w83781d_update_client(client); - results[0] = TEMP_FROM_REG(data->temp_over); - results[1] = TEMP_FROM_REG(data->temp_hyst); - results[2] = TEMP_FROM_REG(data->temp); - *nrels_mag = 3; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - if (*nrels_mag >= 1) { - data->temp_over = TEMP_TO_REG(results[0]); - w83781d_write_value(client,W83781D_REG_TEMP_OVER,data->temp_over); - } - if (*nrels_mag >= 2) { - data->temp_hyst = TEMP_TO_REG(results[1]); - w83781d_write_value(client,W83781D_REG_TEMP_HYST,data->temp_hyst); - } - } -} - - -void w83781d_temp_add(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct w83781d_data *data = client->data; - int nr = ctl_name - W83781D_SYSCTL_TEMP2; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 1; - else if (operation == SENSORS_PROC_REAL_READ) { - w83781d_update_client(client); - results[0] = TEMP_ADD_FROM_REG(data->temp_add_over[nr]); - results[1] = TEMP_ADD_FROM_REG(data->temp_add_hyst[nr]); - results[2] = TEMP_ADD_FROM_REG(data->temp_add[nr]); - *nrels_mag = 3; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - if (*nrels_mag >= 1) { - data->temp_add_over[nr] = TEMP_ADD_TO_REG(results[0]); - w83781d_write_value(client, - nr?W83781D_REG_TEMP3_OVER:W83781D_REG_TEMP2_OVER, - data->temp_add_over[nr]); - } - if (*nrels_mag >= 2) { - data->temp_add_hyst[nr] = TEMP_ADD_TO_REG(results[1]); - w83781d_write_value(client, - nr?W83781D_REG_TEMP3_HYST:W83781D_REG_TEMP2_HYST, - data->temp_add_hyst[nr]); - } - } -} - - -void w83781d_vid(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct w83781d_data *data = client->data; - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 2; - else if (operation == SENSORS_PROC_REAL_READ) { - w83781d_update_client(client); - results[0] = VID_FROM_REG(data->vid); - *nrels_mag = 1; - } -} - -void w83781d_alarms(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct w83781d_data *data = client->data; - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - w83781d_update_client(client); - results[0] = ALARMS_FROM_REG(data->alarms); - *nrels_mag = 1; - } -} - -void w83781d_beep(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct w83781d_data *data = client->data; - int val; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - w83781d_update_client(client); - results[0] = BEEP_ENABLE_FROM_REG(data->beep_enable); - results[1] = BEEPS_FROM_REG(data->beeps); - *nrels_mag = 2; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - if (*nrels_mag >= 2) { - data->beeps = BEEPS_TO_REG(results[1]); - w83781d_write_value(client,W83781D_REG_BEEP_INTS1,data->beeps & 0xff); - val = data->beeps >> 8; - } else if (*nrels_mag >= 1) - val = w83781d_read_value(client,W83781D_REG_BEEP_INTS1) & 0x7f; - if (*nrels_mag >= 1) { - data->beep_enable = BEEP_ENABLE_TO_REG(results[0]); - w83781d_write_value(client,W83781D_REG_BEEP_INTS2, - val | data->beep_enable << 7); - } - } -} - -void w83781d_fan_div(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) -{ - struct w83781d_data *data = client->data; - int old; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - w83781d_update_client(client); - results[0] = DIV_FROM_REG(data->fan_div[0]); - results[1] = DIV_FROM_REG(data->fan_div[1]); - results[2] = DIV_FROM_REG(data->fan_div[2]); - *nrels_mag = 3; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - old = w83781d_read_value(client,W83781D_REG_VID_FANDIV); - if (*nrels_mag >= 2) { - data->fan_div[1] = DIV_TO_REG(results[1]); - old = (old & 0x3f) | (data->fan_div[1] << 6); - } - if (*nrels_mag >= 1) { - data->fan_div[0] = DIV_TO_REG(results[0]); - old = (old & 0xcf) | (data->fan_div[0] << 4); - w83781d_write_value(client,W83781D_REG_VID_FANDIV,old); - } - if (*nrels_mag >= 3) { - data->fan_div[2] = DIV_TO_REG(results[2]); - w83781d_write_value(client,W83781D_REG_PIN, - w83781d_read_value(client,W83781D_REG_PIN)); - } - } -} - -int w83781d_init(void) -{ - int res; - - printk("w83781d.o version %s (%s)\n",LM_VERSION,LM_DATE); - w83781d_initialized = 0; - - if ((res =i2c_add_driver(&w83781d_driver))) { - printk("w83781d.o: Driver registration failed, module not inserted.\n"); - w83781d_cleanup(); - return res; - } - w83781d_initialized ++; - return 0; -} - -int w83781d_cleanup(void) -{ - int res; - - if (w83781d_initialized >= 1) { - if ((res = i2c_del_driver(&w83781d_driver))) { - printk("w83781d.o: Driver deregistration failed, module not removed.\n"); - return res; - } - w83781d_initialized --; - } - return 0; -} - - -#ifdef MODULE - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>"); -MODULE_DESCRIPTION("W83781D driver"); - -int init_module(void) -{ - return w83781d_init(); -} - -int cleanup_module(void) -{ - return w83781d_cleanup(); -} - -#endif /* MODULE */ - diff --git a/kernel/compat.h b/kernel/compat.h deleted file mode 100644 index 04b0c455..00000000 --- a/kernel/compat.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - compat.h - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> - - 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. -*/ - -#ifndef SENSORS_COMPAT_H -#define SENSORS_COMPAT_H - -/* This useful macro is not defined in the 2.0 kernels */ - -#include <linux/version.h> -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(a,b,c) (((a) << 16) | ((b) << 8) | (c)) -#endif - -#ifdef MODULE -#include <linux/module.h> -#ifndef MODULE_AUTHOR -#define MODULE_AUTHOR(whatever) -#endif -#ifndef MODULE_DESCRIPTION -#define MODULE_DESCRIPTION(whatever) -#endif -#endif /* def MODULE */ - -/* copy_from/to_usr is called memcpy_from/to_fs in 2.0 kernels - get_user was redefined in 2.1 kernels to use two arguments, and returns - an error code */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,4)) -#define copy_from_user memcpy_fromfs -#define copy_to_user memcpy_tofs -#define get_user_data(to,from) ((to) = get_user(from),0) -#else -#include <asm/uaccess.h> -#define get_user_data(to,from) get_user(to,from) -#endif - -/* Add a scheduling fix for the new code in kernel 2.1.127 */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,127)) -#define schedule_timeout(x) ( current->timeout = jiffies + (x), schedule() ) -#endif - -/* If the new PCI interface is not present, fall back on the old PCI BIOS - interface. We also define some things to unite both interfaces. Not - very nice, but it works like a charm. - device is the 2.1 struct pci_dev, bus is the 2.0 bus number, dev is the - 2.0 device/function code, com is the PCI command, and res is the result. */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,54)) -#define pci_present pcibios_present -#define pci_read_config_byte_united(device,bus,dev,com,res) \ - pcibios_read_config_byte(bus,dev,com,res); -#define pci_read_config_word_united(device,bus,dev,com,res) \ - pcibios_read_config_word(bus,dev,com,res); -#define pci_write_config_byte_united(device,bus,dev,com,res) \ - pcibios_write_config_byte(bus,dev,com,res); -#define pci_write_config_word_united(device,bus,dev,com,res) \ - pcibios_write_config_word(bus,dev,com,res); -#else -#define pci_read_config_byte_united(device,bus,dev,com,res) \ - pci_read_config_byte(device,com,res); -#define pci_read_config_word_united(device,bus,dev,com,res) \ - pci_read_config_word(device,com,res); -#define pci_write_config_byte_united(device,bus,dev,com,res) \ - pci_write_config_byte(device,com,res); -#define pci_write_config_word_united(device,bus,dev,com,res) \ - pci_write_config_byte(device,com,res); -#endif - - -#endif /* SENSORS_COMPAT_H */ diff --git a/kernel/i2c-proc.c b/kernel/i2c-proc.c deleted file mode 100644 index 4b2c49d2..00000000 --- a/kernel/i2c-proc.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - i2c-proc.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> - - 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. -*/ - -#include <linux/module.h> -#include <linux/proc_fs.h> - -#include "i2c.h" -#include "smbus.h" -#include "isa.h" -#include "version.h" -#include "compat.h" -#include "sensors.h" - -#ifdef MODULE -extern int init_module(void); -extern int cleanup_module(void); -#endif /* def MODULE */ - -static int i2cproc_init(void); -static int i2cproc_cleanup(void); -static int i2cproc_attach_adapter(struct i2c_adapter *adapter); -static int i2cproc_detach_client(struct i2c_client *client); -static int i2cproc_command(struct i2c_client *client, unsigned int cmd, - void *arg); -static void i2cproc_inc_use(struct i2c_client *client); -static void i2cproc_dec_use(struct i2c_client *client); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) -static void monitor_bus_i2c(struct inode *inode, int fill); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) */ - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) - -static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count, - loff_t *ppos); -static int read_bus_i2c(char *buf, char **start, off_t offset, int len, - int *eof , void *private); - -#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */ - -static int i2cproc_bus_read(struct inode * inode, struct file * file, - char * buf, int count); -static int read_bus_i2c(char *buf, char **start, off_t offset, int len, - int unused); - -static struct proc_dir_entry proc_bus_dir = - { - /* low_ino */ 0, /* Set by proc_register_dynamic */ - /* namelen */ 3, - /* name */ "bus", - /* mode */ S_IRUGO | S_IXUGO | S_IFDIR, - /* nlink */ 2, /* Corrected by proc_register[_dynamic] */ - /* uid */ 0, - /* gid */ 0, - /* size */ 0, - /* ops */ &proc_dir_inode_operations, - }; - -static struct proc_dir_entry proc_bus_i2c_dir = - { - /* low_ino */ 0, /* Set by proc_register_dynamic */ - /* namelen */ 3, - /* name */ "i2c", - /* mode */ S_IRUGO | S_IFREG, - /* nlink */ 1, - /* uid */ 0, - /* gid */ 0, - /* size */ 0, - /* ops */ NULL, - /* get_info */ &read_bus_i2c - }; - -/* List of registered entries in /proc/bus */ -static struct proc_dir_entry *i2cproc_proc_entries[I2C_ADAP_MAX]; - -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ - -/* To implement the dynamic /proc/bus/i2c-? files, we need our own - implementation of the read hook */ -static struct file_operations i2cproc_operations = { - NULL, - i2cproc_bus_read, -}; - -static struct inode_operations i2cproc_inode_operations = { - &i2cproc_operations -}; - - -/* Used by init/cleanup */ -static int i2cproc_initialized; - -/* This is a sorted list of all adapters that will have entries in /proc/bus */ -static struct i2c_adapter *i2cproc_adapters[I2C_ADAP_MAX]; - -/* Inodes of /dev/bus/i2c-? files */ -static int i2cproc_inodes[I2C_ADAP_MAX]; - -/* We will use a nasty trick: we register a driver, that will be notified - for each adapter. Then, we register a dummy client on the adapter, that - will get notified if the adapter is removed. This is the same trick as - used in i2c/i2c-dev.c */ -static struct i2c_driver i2cproc_driver = { - /* name */ "i2c-proc dummy driver", - /* id */ I2C_DRIVERID_I2CPROC, - /* flags */ DF_NOTIFY, - /* attach_adapter */ &i2cproc_attach_adapter, - /* detach_client */ &i2cproc_detach_client, - /* command */ &i2cproc_command, - /* inc_use */ &i2cproc_inc_use, - /* dec_use */ &i2cproc_dec_use -}; - -static struct i2c_client i2cproc_client_template = { - /* name */ "i2c-proc dummy client", - /* id */ 1, - /* flags */ 0, - /* addr */ -1, - /* adapter */ NULL, - /* driver */ &i2cproc_driver, - /* data */ NULL -}; - - -int i2cproc_init(void) -{ - int res; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) - struct proc_dir_entry *proc_bus_i2c; -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ - - printk("i2c-proc.o version %s (%s)\n",LM_VERSION,LM_DATE); - i2cproc_initialized = 0; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) - if (! proc_bus) { - printk("i2c-proc.o: /proc/bus/ does not exist, module not inserted.\n"); - i2cproc_cleanup(); - return -ENOENT; - } - proc_bus_i2c = create_proc_entry("i2c",0,proc_bus); - if (!proc_bus_i2c) { - printk("i2c-proc.o: Could not create /proc/bus/i2c, " - "module not inserted.\n"); - i2cproc_cleanup(); - return -ENOENT; - } - proc_bus_i2c->read_proc = &read_bus_i2c; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) - proc_bus_i2c->fill_inode = &monitor_bus_i2c; -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ - i2cproc_initialized += 2; -#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */ - /* In Linux 2.0.x, there is no /proc/bus! But I hope no other module - introduced it, or we are fucked. */ - if ((res = proc_register_dynamic(&proc_root, &proc_bus_dir))) { - printk("i2c-proc.o: Could not create /proc/bus/, module not inserted.\n"); - i2cproc_cleanup(); - return res; - } - i2cproc_initialized ++; - if ((res = proc_register_dynamic(&proc_bus_dir, &proc_bus_i2c_dir))) { - printk("i2c-proc.o: Could not create /proc/bus/i2c, " - "module not inserted.\n"); - i2cproc_cleanup(); - return res; - } - i2cproc_initialized ++; -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ - if ((res = i2c_add_driver(&i2cproc_driver))) { - printk("i2c-proc.o: Driver registration failed, module not inserted.\n"); - i2cproc_cleanup(); - return res; - } - i2cproc_initialized ++; - return 0; -} - -int i2cproc_cleanup(void) -{ - int res; - - if (i2cproc_initialized >= 3) { - if ((res = i2c_del_driver(&i2cproc_driver))) { - printk("i2c-proc.o: Driver deregistration failed, " - "module not removed.\n"); - return res; - } - i2cproc_initialized--; - } - if (i2cproc_initialized >= 1) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) - remove_proc_entry("i2c",proc_bus); - i2cproc_initialized -= 2; -#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */ - if (i2cproc_initialized >= 2) { - if ((res = proc_unregister(&proc_bus_dir,proc_bus_i2c_dir.low_ino))) { - printk("i2c-proc.o: could not delete /proc/bus/i2c, " - "module not removed."); - return res; - } - i2cproc_initialized --; - } - if ((res = proc_unregister(&proc_root,proc_bus_dir.low_ino))) { - printk("i2c-proc.o: could not delete /proc/bus/, " - "module not removed."); - return res; - } - i2cproc_initialized --; -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ - } - return 0; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) -/* Monitor access to /proc/bus/i2c*; make unloading i2c-proc.o impossible - if some process still uses it or some file in it */ -void monitor_bus_i2c(struct inode *inode, int fill) -{ - if (fill) - MOD_INC_USE_COUNT; - else - MOD_DEC_USE_COUNT; -} -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) */ - - -/* This function generates the output for /proc/bus/i2c */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) -int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof, - void *private) -#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */ -int read_bus_i2c(char *buf, char **start, off_t offset, int len, int unused) -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ -{ - int i; - len = 0; - for (i = 0; i < I2C_ADAP_MAX; i++) - if (i2cproc_adapters[i]) - len += sprintf(buf+len, "i2c-%d\t%s\t%-32s\t%-32s\n", - i2c_adapter_id(i2cproc_adapters[i]), - i2c_is_smbus_adapter(i2cproc_adapters[i])?"smbus": -#ifdef DEBUG - i2c_is_isa_adapter(i2cproc_adapters[i])?"isa": -#endif /* def DEBUG */ - "i2c", - i2cproc_adapters[i]->name, - i2cproc_adapters[i]->algo->name); - return len; -} - -/* This function generates the output for /proc/bus/i2c-? */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) -ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count, - loff_t *ppos) -{ - struct inode * inode = file->f_dentry->d_inode; -#else (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) -int i2cproc_bus_read(struct inode * inode, struct file * file,char * buf, - int count) -{ -#endif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) - char *kbuf; - struct i2c_client *client; - int i,j,len=0; - - if (count < 0) - return -EINVAL; - if (count > 4000) - count = 4000; - for (i = 0; i < I2C_ADAP_MAX; i++) - if (i2cproc_inodes[i] == inode->i_ino) { - if (! (kbuf = kmalloc(count,GFP_KERNEL))) - return -ENOMEM; - for (j = 0; j < I2C_CLIENT_MAX; j++) - if ((client = i2cproc_adapters[i]->clients[j])) - /* Filter out dummy clients */ -#ifndef DEBUG - if (client->driver->id != I2C_DRIVERID_I2CPROC) -#endif /* ndef DEBUG */ - len += sprintf(kbuf+len,"%x\t%-32s\t%-32s\n", -#ifdef DEBUG - i2c_is_isa_client(client)? - ((struct isa_client *) client)->isa_addr&0xffffff: -#endif /* def DEBUG */ - client->addr, - client->name,client->driver->name); - if (file->f_pos+len > count) - len = count - file->f_pos; - len = len - file->f_pos; - if (len < 0) - len = 0; - copy_to_user (buf,kbuf+file->f_pos,len); - file->f_pos += len; - kfree(kbuf); - return len; - } - return -ENOENT; -} - - -/* We need to add the adapter to i2cproc_adapters, if it is interesting - enough */ -int i2cproc_attach_adapter(struct i2c_adapter *adapter) -{ - struct i2c_client *client; - int i,res; - char name[8]; - - struct proc_dir_entry *proc_entry; - -#ifndef DEBUG - if (i2c_is_isa_adapter(adapter)) - return 0; -#endif /* ndef DEBUG */ - - for (i = 0; i < I2C_ADAP_MAX; i++) - if(!i2cproc_adapters[i]) - break; - if (i == I2C_ADAP_MAX) { - printk("i2c-proc.o: Too many adapters!\n"); - return -ENOMEM; - } - -#ifndef DEBUG - if (! (client = kmalloc(sizeof(struct i2c_client),GFP_KERNEL))) { -#else /* def DEBUG */ - if (! (client = kmalloc(sizeof(struct isa_client),GFP_KERNEL))) { -#endif - printk("i2c-proc.o: Out of memory!\n"); - return -ENOMEM; - } - memcpy(client,&i2cproc_client_template,sizeof(struct i2c_client)); -#ifdef DEBUG - ((struct isa_client *) client) -> isa_addr = -1; -#endif /* def DEBUG */ - client->adapter = adapter; - if ((res = i2c_attach_client(client))) { - printk("i2c-proc.o: Attaching client failed.\n"); - kfree(client); - return res; - } - i2cproc_adapters[i] = adapter; - - sprintf(name,"i2c-%d",i2c_adapter_id(adapter)); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) - proc_entry = create_proc_entry(name,0,proc_bus); - if (! proc_entry) { - printk("i2c-proc.o: Could not create /proc/bus/%s\n",name); - kfree(client); - return -ENOENT; - } - proc_entry->ops = &i2cproc_inode_operations; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) - proc_entry->fill_inode = &monitor_bus_i2c; -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) */ -#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */ - if (!(proc_entry = kmalloc(sizeof(struct proc_dir_entry)+strlen(name)+1, - GFP_KERNEL))) { - printk("i2c-proc.o: Out of memory!\n"); - return -ENOMEM; - } - - memset(proc_entry,0,sizeof(struct proc_dir_entry)); - proc_entry->namelen = strlen(name); - proc_entry->name = (char *) (proc_entry + 1); - proc_entry->mode = S_IRUGO | S_IFREG; - proc_entry->nlink = 1; - proc_entry->ops = &i2cproc_inode_operations; - strcpy((char *) proc_entry->name,name); - - if ((res = proc_register_dynamic(&proc_bus_dir, proc_entry))) { - printk("i2c-proc.o: Could not create %s.\n",name); - kfree(proc_entry); - kfree(client); - return res; - } - - i2cproc_proc_entries[i] = proc_entry; -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ - - i2cproc_inodes[i] = proc_entry->low_ino; - return 0; -} - -int i2cproc_detach_client(struct i2c_client *client) -{ - int i,res; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) - char name[8]; -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ - -#ifndef DEBUG - if (i2c_is_isa_client(client)) - return 0; -#endif /* ndef DEBUG */ - - for (i = 0; i < I2C_ADAP_MAX; i++) - if (client->adapter == i2cproc_adapters[i]) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) - sprintf(name,"i2c-%d",i2c_adapter_id(i2cproc_adapters[i])); - remove_proc_entry(name,proc_bus); -#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */ - if ((res = proc_unregister(&proc_bus_dir, - i2cproc_proc_entries[i]->low_ino))) { - printk("i2c-proc.o: Deregistration of /proc entry failed, " - "client not detached.\n"); - return res; - } - kfree(i2cproc_proc_entries[i]); - i2cproc_proc_entries[i] = NULL; -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ - if ((res = i2c_detach_client(client))) { - printk("i2c-proc.o: Client deregistration failed, " - "client not detached.\n"); - return res; - } - i2cproc_adapters[i] = NULL; - i2cproc_inodes[i] = 0; - kfree(client); - return 0; - } - return -ENOENT; -} - -/* Nothing here yet */ -int i2cproc_command(struct i2c_client *client, unsigned int cmd, - void *arg) -{ - return -1; -} - -/* Nothing here yet */ -void i2cproc_inc_use(struct i2c_client *client) -{ -} - -/* Nothing here yet */ -void i2cproc_dec_use(struct i2c_client *client) -{ -} - -#ifdef MODULE - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); -MODULE_DESCRIPTION("I2C /proc/bus entries driver"); - -int init_module(void) -{ - return i2cproc_init(); -} - -int cleanup_module(void) -{ - return i2cproc_cleanup(); -} - -#endif /* def MODULE */ - diff --git a/kernel/include/compat.h b/kernel/include/compat.h deleted file mode 100644 index 04b0c455..00000000 --- a/kernel/include/compat.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - compat.h - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> - - 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. -*/ - -#ifndef SENSORS_COMPAT_H -#define SENSORS_COMPAT_H - -/* This useful macro is not defined in the 2.0 kernels */ - -#include <linux/version.h> -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(a,b,c) (((a) << 16) | ((b) << 8) | (c)) -#endif - -#ifdef MODULE -#include <linux/module.h> -#ifndef MODULE_AUTHOR -#define MODULE_AUTHOR(whatever) -#endif -#ifndef MODULE_DESCRIPTION -#define MODULE_DESCRIPTION(whatever) -#endif -#endif /* def MODULE */ - -/* copy_from/to_usr is called memcpy_from/to_fs in 2.0 kernels - get_user was redefined in 2.1 kernels to use two arguments, and returns - an error code */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,4)) -#define copy_from_user memcpy_fromfs -#define copy_to_user memcpy_tofs -#define get_user_data(to,from) ((to) = get_user(from),0) -#else -#include <asm/uaccess.h> -#define get_user_data(to,from) get_user(to,from) -#endif - -/* Add a scheduling fix for the new code in kernel 2.1.127 */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,127)) -#define schedule_timeout(x) ( current->timeout = jiffies + (x), schedule() ) -#endif - -/* If the new PCI interface is not present, fall back on the old PCI BIOS - interface. We also define some things to unite both interfaces. Not - very nice, but it works like a charm. - device is the 2.1 struct pci_dev, bus is the 2.0 bus number, dev is the - 2.0 device/function code, com is the PCI command, and res is the result. */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,54)) -#define pci_present pcibios_present -#define pci_read_config_byte_united(device,bus,dev,com,res) \ - pcibios_read_config_byte(bus,dev,com,res); -#define pci_read_config_word_united(device,bus,dev,com,res) \ - pcibios_read_config_word(bus,dev,com,res); -#define pci_write_config_byte_united(device,bus,dev,com,res) \ - pcibios_write_config_byte(bus,dev,com,res); -#define pci_write_config_word_united(device,bus,dev,com,res) \ - pcibios_write_config_word(bus,dev,com,res); -#else -#define pci_read_config_byte_united(device,bus,dev,com,res) \ - pci_read_config_byte(device,com,res); -#define pci_read_config_word_united(device,bus,dev,com,res) \ - pci_read_config_word(device,com,res); -#define pci_write_config_byte_united(device,bus,dev,com,res) \ - pci_write_config_byte(device,com,res); -#define pci_write_config_word_united(device,bus,dev,com,res) \ - pci_write_config_byte(device,com,res); -#endif - - -#endif /* SENSORS_COMPAT_H */ diff --git a/kernel/include/i2c-isa.h b/kernel/include/i2c-isa.h deleted file mode 100644 index df8bb5ff..00000000 --- a/kernel/include/i2c-isa.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - isa.h - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> - - 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. -*/ - -#ifndef SENSORS_SENSOR_H -#define SENSORS_SENSOR_H - -#ifdef __KERNEL__ - -/* This file must interface with Simon Vogl's i2c driver. Version 19981006 is - OK, earlier versions are not; later versions will probably give problems - too. -*/ -#include <asm/types.h> - -/* SPINLOCK is defined in i2c.h. */ -#ifdef SPINLOCK -#include <asm/spinlock.h> -#else -#include <asm/semaphore.h> -#endif - -#ifdef LM_SENSORS -#include "i2c.h" -#else /* ndef LM_SENSORS */ -#include <linux/i2c.h> -#endif /* def LM_SENSORS */ - -/* Note that this driver is *not* built upon smbus.c, but is parallel to it. - We do not need SMBus facilities if we are on the ISA bus, after all */ - -/* Declarations, to keep the compiler happy */ -struct isa_driver; -struct isa_client; -struct isa_algorithm; -struct isa_adapter; - -/* A driver tells us how we should handle a specific kind of chip. - A specific instance of such a chip is called a client. - This structure is essentially the same as i2c_driver. */ -struct isa_driver { - char name[32]; - int id; - unsigned int flags; - int (* attach_adapter) (struct isa_adapter *); - int (* detach_client) (struct isa_client *); - int (* command) (struct isa_client *, unsigned int cmd, void *arg); - void (* inc_use) (struct isa_client *); - void (* dec_use) (struct isa_client *); -}; - -/* A client is a specifc instance of a chip: for each detected chip, there will - be a client. Its operation is controlled by a driver. - This structure is an extension of i2c_client. */ -struct isa_client { - char name[32]; - int id; - unsigned int flags; - unsigned char addr; - struct isa_adapter *adapter; - struct isa_driver *driver; - void *data; - - /* Here ended i2c_client */ - unsigned int isa_addr; -}; - -/* An algorithm describes how a certain class of busses can be accessed. - A specific instance of sucj a bus is called an adapter. - This structure is essentially the same as i2c_adapter. */ -struct isa_algorithm { - char name[32]; - unsigned int id; - int (* master_xfer) (struct isa_adapter *adap, struct i2c_msg msgs[], - int num); - int (* slave_send) (struct isa_adapter *,char *, int); - int (* slave_recv) (struct isa_adapter *,char *, int); - int (* algo_control) (struct isa_adapter *, unsigned int, unsigned long); - int (* client_register) (struct isa_client *); - int (* client_unregister) (struct isa_client *); -}; - -/* An adapter is a specifc instance of a bus: for each detected bus, there will - be an adapter. Its operation is controlled by an algorithm. - SPINLOCK must be the same as declared in i2c.h. - This structure is essentially the same as i2c_algorithm. */ -struct isa_adapter { - char name[32]; - unsigned int id; - struct isa_algorithm *algo; - void *data; -#ifdef SPINLOCK - spinlock_t lock; - unsigned long lockflags; -#else - struct semaphore lock; -#endif - unsigned int flags; - struct isa_client *clients[I2C_CLIENT_MAX]; - int client_count; - int timeout; - int retries; -}; - - -/* Detect whether we are on the isa bus. If this returns true, all i2c - access will fail! */ -#define i2c_is_isa_client(clientptr) \ - ((clientptr)->adapter->algo->id == ALGO_ISA) -#define i2c_is_isa_adapter(adapptr) \ - ((adapptr)->algo->id == ALGO_ISA) - -/* Next: define ISA variants of registering. */ -#define isa_add_algorithm(algoptr) \ - i2c_add_algorithm((struct i2c_algorithm *) (algoptr)) -#define isa_del_algorithm(algoptr) \ - i2c_del_algorithm((struct i2c_algorithm *) (algoptr)) - -#define isa_add_adapter(adapptr) \ - i2c_add_adapter((struct i2c_adapter *) (adapptr)) -#define isa_del_adapter(adapptr) \ - i2c_del_adapter((struct i2c_adapter *) (adapptr)) - -#define isa_add_driver(driverptr) \ - i2c_add_driver((struct i2c_driver *) (driverptr)) -#define isa_del_driver(driverptr) \ - i2c_add_driver((struct i2c_driver *) (driverptr)) - -#define isa_attach_client(clientptr) \ - i2c_attach_client((struct i2c_client *) (clientptr)) -#define isa_detach_client(clientptr) \ - i2c_detach_client((struct i2c_client *) (clientptr)) - -#endif /* def __KERNEL__ */ - -/* We need to mark ISA algorithms in the algorithm structure. */ -#define ALGO_ISA 0x50000 - -/* ISA Adapter ids */ -#define ISA_MAIN 1 - -#endif /* ndef SENSORS_ISA_H */ diff --git a/kernel/include/i2c.h b/kernel/include/i2c.h deleted file mode 100644 index 644565c5..00000000 --- a/kernel/include/i2c.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - i2c.h - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> - - 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. -*/ - - -/* This is a stub files, that either includes <linux/i2c.h> (the kernel - header) or "i2c/i2c.h" (the header in the i2c directory). */ - -#ifdef I2C -#include "i2c/i2c.h" -#else /* def I2C */ -#include <linux/i2c.h> -#endif /* def I2C */ - diff --git a/kernel/include/isa.h b/kernel/include/isa.h deleted file mode 100644 index df8bb5ff..00000000 --- a/kernel/include/isa.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - isa.h - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> - - 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. -*/ - -#ifndef SENSORS_SENSOR_H -#define SENSORS_SENSOR_H - -#ifdef __KERNEL__ - -/* This file must interface with Simon Vogl's i2c driver. Version 19981006 is - OK, earlier versions are not; later versions will probably give problems - too. -*/ -#include <asm/types.h> - -/* SPINLOCK is defined in i2c.h. */ -#ifdef SPINLOCK -#include <asm/spinlock.h> -#else -#include <asm/semaphore.h> -#endif - -#ifdef LM_SENSORS -#include "i2c.h" -#else /* ndef LM_SENSORS */ -#include <linux/i2c.h> -#endif /* def LM_SENSORS */ - -/* Note that this driver is *not* built upon smbus.c, but is parallel to it. - We do not need SMBus facilities if we are on the ISA bus, after all */ - -/* Declarations, to keep the compiler happy */ -struct isa_driver; -struct isa_client; -struct isa_algorithm; -struct isa_adapter; - -/* A driver tells us how we should handle a specific kind of chip. - A specific instance of such a chip is called a client. - This structure is essentially the same as i2c_driver. */ -struct isa_driver { - char name[32]; - int id; - unsigned int flags; - int (* attach_adapter) (struct isa_adapter *); - int (* detach_client) (struct isa_client *); - int (* command) (struct isa_client *, unsigned int cmd, void *arg); - void (* inc_use) (struct isa_client *); - void (* dec_use) (struct isa_client *); -}; - -/* A client is a specifc instance of a chip: for each detected chip, there will - be a client. Its operation is controlled by a driver. - This structure is an extension of i2c_client. */ -struct isa_client { - char name[32]; - int id; - unsigned int flags; - unsigned char addr; - struct isa_adapter *adapter; - struct isa_driver *driver; - void *data; - - /* Here ended i2c_client */ - unsigned int isa_addr; -}; - -/* An algorithm describes how a certain class of busses can be accessed. - A specific instance of sucj a bus is called an adapter. - This structure is essentially the same as i2c_adapter. */ -struct isa_algorithm { - char name[32]; - unsigned int id; - int (* master_xfer) (struct isa_adapter *adap, struct i2c_msg msgs[], - int num); - int (* slave_send) (struct isa_adapter *,char *, int); - int (* slave_recv) (struct isa_adapter *,char *, int); - int (* algo_control) (struct isa_adapter *, unsigned int, unsigned long); - int (* client_register) (struct isa_client *); - int (* client_unregister) (struct isa_client *); -}; - -/* An adapter is a specifc instance of a bus: for each detected bus, there will - be an adapter. Its operation is controlled by an algorithm. - SPINLOCK must be the same as declared in i2c.h. - This structure is essentially the same as i2c_algorithm. */ -struct isa_adapter { - char name[32]; - unsigned int id; - struct isa_algorithm *algo; - void *data; -#ifdef SPINLOCK - spinlock_t lock; - unsigned long lockflags; -#else - struct semaphore lock; -#endif - unsigned int flags; - struct isa_client *clients[I2C_CLIENT_MAX]; - int client_count; - int timeout; - int retries; -}; - - -/* Detect whether we are on the isa bus. If this returns true, all i2c - access will fail! */ -#define i2c_is_isa_client(clientptr) \ - ((clientptr)->adapter->algo->id == ALGO_ISA) -#define i2c_is_isa_adapter(adapptr) \ - ((adapptr)->algo->id == ALGO_ISA) - -/* Next: define ISA variants of registering. */ -#define isa_add_algorithm(algoptr) \ - i2c_add_algorithm((struct i2c_algorithm *) (algoptr)) -#define isa_del_algorithm(algoptr) \ - i2c_del_algorithm((struct i2c_algorithm *) (algoptr)) - -#define isa_add_adapter(adapptr) \ - i2c_add_adapter((struct i2c_adapter *) (adapptr)) -#define isa_del_adapter(adapptr) \ - i2c_del_adapter((struct i2c_adapter *) (adapptr)) - -#define isa_add_driver(driverptr) \ - i2c_add_driver((struct i2c_driver *) (driverptr)) -#define isa_del_driver(driverptr) \ - i2c_add_driver((struct i2c_driver *) (driverptr)) - -#define isa_attach_client(clientptr) \ - i2c_attach_client((struct i2c_client *) (clientptr)) -#define isa_detach_client(clientptr) \ - i2c_detach_client((struct i2c_client *) (clientptr)) - -#endif /* def __KERNEL__ */ - -/* We need to mark ISA algorithms in the algorithm structure. */ -#define ALGO_ISA 0x50000 - -/* ISA Adapter ids */ -#define ISA_MAIN 1 - -#endif /* ndef SENSORS_ISA_H */ diff --git a/kernel/include/sensors.h b/kernel/include/sensors.h deleted file mode 100644 index 575a29db..00000000 --- a/kernel/include/sensors.h +++ /dev/null @@ -1,227 +0,0 @@ -/* - sensors.h - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> - - 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. -*/ - -#ifndef SENSORS_SENSORS_H -#define SENSORS_SENSORS_H - -#ifdef __KERNEL__ - -/* Next two must be included before sysctl.h can be included, in 2.0 kernels */ -#include <linux/types.h> -#include <linux/fs.h> -#include <linux/sysctl.h> - -/* The type of callback functions used in sensors_{proc,sysctl}_real */ -typedef void (*sensors_real_callback) (struct i2c_client *client, - int operation, int ctl_name, - int *nrels_mag, long *results); - -/* Values for the operation field in the above function type */ -#define SENSORS_PROC_REAL_INFO 1 -#define SENSORS_PROC_REAL_READ 2 -#define SENSORS_PROC_REAL_WRITE 3 - -/* These funcion reads or writes a 'real' value (encoded by the combination - of an integer and a magnitude, the last is the power of ten the value - should be divided with) to a /proc/sys directory. To use these functions, - you must (before registering the ctl_table) set the extra2 field to the - client, and the extra1 field to a function of the form: - void func(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) - This last function can be called for three values of operation. If - operation equals SENSORS_PROC_REAL_INFO, the magnitude should be returned - in nrels_mag. If operation equals SENSORS_PROC_REAL_READ, values should - be read into results. nrels_mag should return the number of elements - read; the maximum number is put in it on entry. Finally, if operation - equals SENSORS_PROC_REAL_WRITE, the values in results should be - written to the chip. nrels_mag contains on entry the number of elements - found. - In all cases, client points to the client we wish to interact with, - and ctl_name is the SYSCTL id of the file we are accessing. */ -extern int sensors_sysctl_real (ctl_table *table, int *name, int nlen, - void *oldval, size_t *oldlenp, void *newval, - size_t newlen, void **context); -extern int sensors_proc_real(ctl_table *ctl, int write, struct file * filp, - void *buffer, size_t *lenp); - - - -/* These rather complex functions must be called when you want to add or - delete an entry in /proc/sys/dev/sensors/chips (not yet implemented). It - also creates a new directory within /proc/sys/dev/sensors/. - ctl_template should be a template of the newly created directory. It is - copied in memory. The extra2 field of each file is set to point to client. - If any driver wants subdirectories within the newly created directory, - these functions must be updated! */ -extern int sensors_register_entry(struct i2c_client *client, - const char *prefix, ctl_table *ctl_template); -extern void sensors_deregister_entry(int id); - -#endif /* def __KERNEL__ */ - - -/* The maximum length of the prefix */ -#define SENSORS_PREFIX_MAX 20 - -/* Driver IDs */ -#define I2C_DRIVERID_I2CPROC 1001 -#define I2C_DRIVERID_LM78 1002 -#define I2C_DRIVERID_LM75 1003 -#define I2C_DRIVERID_GL518 1004 -#define I2C_DRIVERID_EEPROM 1005 -#define I2C_DRIVERID_W83781D 1006 -#define I2C_DRIVERID_LM80 1007 - -/* Sysctl IDs */ -#ifdef DEV_HWMON -#define DEV_SENSORS DEV_HWMON -#else /* ndef DEV_HWMOM */ -#define DEV_SENSORS 2 /* The id of the lm_sensors directory within the - dev table */ -#endif /* def DEV_HWMON */ - -#define SENSORS_CHIPS 1 -struct sensors_chips_data { - int sysctl_id; - char name[SENSORS_PREFIX_MAX + 13]; -}; - -#define LM78_SYSCTL_IN0 1000 /* Volts * 100 */ -#define LM78_SYSCTL_IN1 1001 -#define LM78_SYSCTL_IN2 1002 -#define LM78_SYSCTL_IN3 1003 -#define LM78_SYSCTL_IN4 1004 -#define LM78_SYSCTL_IN5 1005 -#define LM78_SYSCTL_IN6 1006 -#define LM78_SYSCTL_FAN1 1101 /* Rotations/min */ -#define LM78_SYSCTL_FAN2 1102 -#define LM78_SYSCTL_FAN3 1103 -#define LM78_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */ -#define LM78_SYSCTL_VID 1300 /* Volts * 100 */ -#define LM78_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */ -#define LM78_SYSCTL_ALARMS 2001 /* bitvector */ - -#define LM78_ALARM_IN0 0x0001 -#define LM78_ALARM_IN1 0x0002 -#define LM78_ALARM_IN2 0x0004 -#define LM78_ALARM_IN3 0x0008 -#define LM78_ALARM_IN4 0x0100 -#define LM78_ALARM_IN5 0x0200 -#define LM78_ALARM_IN6 0x0400 -#define LM78_ALARM_FAN1 0x0040 -#define LM78_ALARM_FAN2 0x0080 -#define LM78_ALARM_FAN3 0x0800 -#define LM78_ALARM_TEMP 0x0010 -#define LM78_ALARM_BTI 0x0020 -#define LM78_ALARM_CHAS 0x1000 -#define LM78_ALARM_FIFO 0x2000 -#define LM78_ALARM_SMI_IN 0x4000 - -#define W83781D_SYSCTL_IN0 1000 /* Volts * 100 */ -#define W83781D_SYSCTL_IN1 1001 -#define W83781D_SYSCTL_IN2 1002 -#define W83781D_SYSCTL_IN3 1003 -#define W83781D_SYSCTL_IN4 1004 -#define W83781D_SYSCTL_IN5 1005 -#define W83781D_SYSCTL_IN6 1006 -#define W83781D_SYSCTL_FAN1 1101 /* Rotations/min */ -#define W83781D_SYSCTL_FAN2 1102 -#define W83781D_SYSCTL_FAN3 1103 -#define W83781D_SYSCTL_TEMP1 1200 /* Degrees Celcius * 10 */ -#define W83781D_SYSCTL_TEMP2 1201 /* Degrees Celcius * 10 */ -#define W83781D_SYSCTL_TEMP3 1202 /* Degrees Celcius * 10 */ -#define W83781D_SYSCTL_VID 1300 /* Volts * 100 */ -#define W83781D_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */ -#define W83781D_SYSCTL_ALARMS 2001 /* bitvector */ -#define W83781D_SYSCTL_BEEP 2002 /* bitvector */ - -#define W83781D_ALARM_IN0 0x0001 -#define W83781D_ALARM_IN1 0x0002 -#define W83781D_ALARM_IN2 0x0004 -#define W83781D_ALARM_IN3 0x0008 -#define W83781D_ALARM_IN4 0x0100 -#define W83781D_ALARM_IN5 0x0200 -#define W83781D_ALARM_IN6 0x0400 -#define W83781D_ALARM_FAN1 0x0040 -#define W83781D_ALARM_FAN2 0x0080 -#define W83781D_ALARM_FAN3 0x0800 -#define W83781D_ALARM_TEMP1 0x0010 -#define W83781D_ALARM_TEMP23 0x0020 -#define W83781D_ALARM_CHAS 0x1000 - -#define LM75_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */ - -#define GL518_SYSCTL_VDD 1000 /* Volts * 100 */ -#define GL518_SYSCTL_VIN1 1001 -#define GL518_SYSCTL_VIN2 1002 -#define GL518_SYSCTL_VIN3 1003 -#define GL518_SYSCTL_FAN1 1101 /* RPM */ -#define GL518_SYSCTL_FAN2 1102 -#define GL518_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */ -#define GL518_SYSCTL_VID 1300 -#define GL518_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */ -#define GL518_SYSCTL_ALARMS 2001 /* bitvector */ -#define GL518_SYSCTL_BEEP 2002 /* bitvector */ - -#define GL518_ALARM_VDD 0x01 -#define GL518_ALARM_VIN1 0x02 -#define GL518_ALARM_VIN2 0x04 -#define GL518_ALARM_VIN3 0x08 -#define GL518_ALARM_TEMP 0x10 -#define GL518_ALARM_FAN1 0x20 -#define GL518_ALARM_FAN2 0x40 - -#define EEPROM_SYSCTL1 1000 -#define EEPROM_SYSCTL2 1001 -#define EEPROM_SYSCTL3 1002 -#define EEPROM_SYSCTL4 1003 -#define EEPROM_SYSCTL5 1004 -#define EEPROM_SYSCTL6 1005 -#define EEPROM_SYSCTL7 1006 -#define EEPROM_SYSCTL8 1007 - -#define LM80_SYSCTL_IN0 1000 /* Volts * 100 */ -#define LM80_SYSCTL_IN1 1001 -#define LM80_SYSCTL_IN2 1002 -#define LM80_SYSCTL_IN3 1003 -#define LM80_SYSCTL_IN4 1004 -#define LM80_SYSCTL_IN5 1005 -#define LM80_SYSCTL_IN6 1006 -#define LM80_SYSCTL_FAN1 1101 /* Rotations/min */ -#define LM80_SYSCTL_FAN2 1102 -#define LM80_SYSCTL_TEMP 1250 /* Degrees Celcius * 100 */ -#define LM80_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */ -#define LM80_SYSCTL_ALARMS 2001 /* bitvector */ - -#define LM80_ALARM_IN0 0x0001 -#define LM80_ALARM_IN1 0x0002 -#define LM80_ALARM_IN2 0x0004 -#define LM80_ALARM_IN3 0x0008 -#define LM80_ALARM_IN4 0x0010 -#define LM80_ALARM_IN5 0x0020 -#define LM80_ALARM_IN6 0x0040 -#define LM80_ALARM_FAN1 0x0400 -#define LM80_ALARM_FAN2 0x0800 -#define LM80_ALARM_TEMP_HOT 0x0100 -#define LM80_ALARM_TEMP_OS 0x2000 -#define LM80_ALARM_CHAS 0x1000 -#define LM80_ALARM_BTI 0x0200 -#define LM80_ALARM_INT_IN 0x0080 -#endif /* def SENSORS_SENSORS_H */ diff --git a/kernel/include/smbus.h b/kernel/include/smbus.h deleted file mode 100644 index c50ce233..00000000 --- a/kernel/include/smbus.h +++ /dev/null @@ -1,299 +0,0 @@ -/* - smbus.h - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> - - 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. -*/ - -#ifndef SENSORS_SMBUS_H -#define SENSORS_SMBUS_H - -#ifdef __KERNEL__ - -/* This file must interface with Simon Vogl's i2c driver. Version 19981006 is - OK, earlier versions are not; later versions will probably give problems - too. -*/ -#include <asm/types.h> - -/* SPINLOCK is defined in i2c.h. */ -#ifdef SPINLOCK -#include <asm/spinlock.h> -#else -#include <asm/semaphore.h> -#endif - -#ifdef LM_SENSORS -#include "i2c.h" -#else -#include <linux/i2c.h> -#endif - -/* Declarations, to keep the compiler happy */ -struct smbus_driver; -struct smbus_client; -struct smbus_algorithm; -struct smbus_adapter; -union smbus_data; - -/* A driver tells us how we should handle a specific kind of chip. - A specific instance of such a chip is called a client. - This structure is essentially the same as i2c_driver. */ -struct smbus_driver { - char name[32]; - int id; - unsigned int flags; - int (* attach_adapter) (struct smbus_adapter *); - int (* detach_client) (struct smbus_client *); - int (* command) (struct smbus_client *, unsigned int cmd, void *arg); - void (* inc_use) (struct smbus_client *); - void (* dec_use) (struct smbus_client *); -}; - -/* A client is a specifc instance of a chip: for each detected chip, there will - be a client. Its operation is controlled by a driver. - This structure is essentially the same as i2c_client. */ -struct smbus_client { - char name[32]; - int id; - unsigned int flags; - unsigned char addr; - struct smbus_adapter *adapter; - struct smbus_driver *driver; - void *data; -}; - -/* An algorithm describes how a certain class of busses can be accessed. - A specific instance of sucj a bus is called an adapter. - This structure is essentially the same as i2c_adapter. */ -struct smbus_algorithm { - char name[32]; - unsigned int id; - int (* master_xfer) (struct smbus_adapter *adap, struct i2c_msg msgs[], - int num); - int (* slave_send) (struct smbus_adapter *,char *, int); - int (* slave_recv) (struct smbus_adapter *,char *, int); - int (* algo_control) (struct smbus_adapter *, unsigned int, unsigned long); - int (* client_register) (struct smbus_client *); - int (* client_unregister) (struct smbus_client *); -}; - -/* An adapter is a specifc instance of a bus: for each detected bus, there will - be an adapter. Its operation is controlled by an algorithm. - SPINLOCK must be the same as declared in i2c.h. - This structure is an extension of i2c_algorithm. */ -struct smbus_adapter { - char name[32]; - unsigned int id; - struct smbus_algorithm *algo; - void *data; -#ifdef SPINLOCK - spinlock_t lock; - unsigned long lockflags; -#else - struct semaphore lock; -#endif - unsigned int flags; - struct smbus_client *clients[I2C_CLIENT_MAX]; - int client_count; - int timeout; - int retries; - - /* Here ended i2c_adapter */ - s32 (* smbus_access) (u8 addr, char read_write, - u8 command, int size, union smbus_data * data); -}; - -/* We need to mark SMBus algorithms in the algorithm structure. - Note that any and all adapters using a non-i2c driver use in this - setup ALGO_SMBUS. Adapters define their own smbus access routine. - This also means that adapter->smbus_access is only available if - this flag is set! */ -#define ALGO_SMBUS 0x40000 - -/* SMBus Adapter ids */ -#define SMBUS_PIIX4 1 - -/* Detect whether we are on an SMBus-only bus. Note that if this returns - false, you can still use the smbus access routines, as these emulate - the SMBus on I2C. Unless they are undefined on your algorithm, of - course. */ -#define i2c_is_smbus_client(clientptr) \ - ((clientptr)->adapter->algo->id == ALGO_SMBUS) -#define i2c_is_smbus_adapter(adapptr) \ - ((adapptr)->algo->id == ALGO_SMBUS) - -/* This union is used within smbus_access routines */ -union smbus_data { - u8 byte; - u16 word; - u8 block[32]; -}; - -/* smbus_access read or write markers */ -#define SMBUS_READ 1 -#define SMBUS_WRITE 0 - -/* SMBus transaction types (size parameter in the above functions) - Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */ -#define SMBUS_QUICK 0 -#define SMBUS_BYTE 1 -#define SMBUS_BYTE_DATA 2 -#define SMBUS_WORD_DATA 3 -#define SMBUS_PROC_CALL 4 -#define SMBUS_BLOCK_DATA 5 - -/* Declare an algorithm structure. All SMBus derived adapters should use this - algorithm! */ -extern struct smbus_algorithm smbus_algorithm; - -/* This is the very generalized SMBus access routine. You probably do not - want to use this, though; one of the functions below may be much easier, - and probably just as fast. - Note that we use i2c_adapter here, because you do not need a specific - smbus adapter to call this function. */ -extern s32 smbus_access (struct i2c_adapter * adapter, u8 addr, - char read_write, u8 command, int size, - union smbus_data * data); - -/* Now follow the 'nice' access routines. These also document the calling - conventions of smbus_access. */ - -extern inline s32 smbus_write_quick(struct i2c_adapter * adapter, u8 addr, - u8 value) -{ - return smbus_access(adapter,addr,value,0,SMBUS_QUICK,NULL); -} - -extern inline s32 smbus_read_byte(struct i2c_adapter * adapter,u8 addr) -{ - union smbus_data data; - if (smbus_access(adapter,addr,SMBUS_READ,0,SMBUS_BYTE,&data)) - return -1; - else - return data.byte; -} - -extern inline s32 smbus_write_byte(struct i2c_adapter * adapter, u8 addr, - u8 value) -{ - return smbus_access(adapter,addr,SMBUS_WRITE,value, SMBUS_BYTE,NULL); -} - -extern inline s32 smbus_read_byte_data(struct i2c_adapter * adapter, - u8 addr, u8 command) -{ - union smbus_data data; - if (smbus_access(adapter,addr,SMBUS_READ,command,SMBUS_BYTE_DATA,&data)) - return -1; - else - return data.byte; -} - -extern inline s32 smbus_write_byte_data(struct i2c_adapter * adapter, - u8 addr, u8 command, u8 value) -{ - union smbus_data data; - data.byte = value; - return smbus_access(adapter,addr,SMBUS_WRITE,command,SMBUS_BYTE_DATA,&data); -} - -extern inline s32 smbus_read_word_data(struct i2c_adapter * adapter, - u8 addr, u8 command) -{ - union smbus_data data; - if (smbus_access(adapter,addr,SMBUS_READ,command,SMBUS_WORD_DATA,&data)) - return -1; - else - return data.word; -} - -extern inline s32 smbus_write_word_data(struct i2c_adapter * adapter, - u8 addr, u8 command, u16 value) -{ - union smbus_data data; - data.word = value; - return smbus_access(adapter,addr,SMBUS_WRITE,command,SMBUS_WORD_DATA,&data); -} - -extern inline s32 smbus_process_call(struct i2c_adapter * adapter, - u8 addr, u8 command, u16 value) -{ - union smbus_data data; - data.word = value; - if (smbus_access(adapter,addr,SMBUS_WRITE,command,SMBUS_PROC_CALL,&data)) - return -1; - else - return data.word; -} - -/* Returns the number of read bytes */ -extern inline s32 smbus_read_block_data(struct i2c_adapter * adapter, - u8 addr, u8 command, u8 *values) -{ - union smbus_data data; - int i; - if (smbus_access(adapter,addr,SMBUS_READ,command,SMBUS_BLOCK_DATA,&data)) - return -1; - else { - for (i = 1; i <= data.block[0]; i++) - values[i-1] = data.block[i]; - return data.block[0]; - } -} - -extern inline int smbus_write_block_data(struct i2c_adapter * adapter, - u8 addr, u8 command, u8 length, - u8 *values) -{ - union smbus_data data; - int i; - if (length > 32) - length = 32; - for (i = 1; i <= length; i++) - data.block[i] = values[i-1]; - data.block[0] = length; - return smbus_access(adapter,addr,SMBUS_WRITE,command,SMBUS_BLOCK_DATA,&data); -} - - -/* Next: define SMBus variants of registering. */ - -#define smbus_add_algorithm(algoptr) \ - i2c_add_algorithm((struct i2c_algorithm *) (algoptr)) -#define smbus_del_algorithm(algoptr) \ - i2c_del_algorithm((struct i2c_algorithm *) (algoptr)) - -#define smbus_add_adapter(adapptr) \ - i2c_add_adapter((struct i2c_adapter *) (adapptr)) -#define smbus_del_adapter(adapptr) \ - i2c_del_adapter((struct i2c_adapter *) (adapptr)) - -#define smbus_add_driver(driverptr) \ - i2c_add_driver((struct i2c_driver *) (driverptr)) -#define smbus_del_driver(driverptr) \ - i2c_add_driver((struct i2c_driver *) (driverptr)) - -#define smbus_attach_client(clientptr) \ - i2c_attach_client((struct i2c_client *) (clientptr)) -#define smbus_detach_client(clientptr) \ - i2c_detach_client((struct i2c_client *) (clientptr)) - - -#endif /* def __KERNEL__ */ - -#endif /* ndef SENSORS_SMBUS_H */ - diff --git a/kernel/sensors.c b/kernel/sensors.c deleted file mode 100644 index 20aad3c4..00000000 --- a/kernel/sensors.c +++ /dev/null @@ -1,617 +0,0 @@ -/* - sensors.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> - - 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. -*/ - -#include <linux/module.h> -#include <linux/malloc.h> -#include <linux/ctype.h> -#include <linux/sysctl.h> -#include <linux/proc_fs.h> - -#include "version.h" -#include "compat.h" -#include "i2c.h" -#include "isa.h" -#include "sensors.h" - - -#ifdef MODULE -extern int init_module(void); -extern int cleanup_module(void); -#endif /* MODULE */ - -static int sensors_create_name(char **name, const char *prefix, - struct i2c_adapter * adapter, int addr); -static void sensors_parse_reals(int *nrels, void *buffer, int bufsize, - long *results, int magnitude); -static void sensors_write_reals(int nrels,void *buffer,int *bufsize, - long *results, int magnitude); -static int sensors_proc_chips(ctl_table *ctl, int write, struct file * filp, - void *buffer, size_t *lenp); -static int sensors_sysctl_chips (ctl_table *table, int *name, int nlen, - void *oldval, size_t *oldlenp, void *newval, - size_t newlen, void **context); - -static int sensors_init(void); -static int sensors_cleanup(void); - -#define SENSORS_ENTRY_MAX 20 -static struct ctl_table_header *sensors_entries[SENSORS_ENTRY_MAX]; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) -static struct i2c_client *sensors_clients[SENSORS_ENTRY_MAX]; -static unsigned short sensors_inodes[SENSORS_ENTRY_MAX]; -static void sensors_fill_inode(struct inode *inode, int fill); -static void sensors_dir_fill_inode(struct inode *inode, int fill); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) */ - -static ctl_table sysctl_table[] = { - { CTL_DEV, "dev", NULL, 0, 0555 }, - { 0 }, - { DEV_SENSORS, "sensors", NULL, 0, 0555 }, - { 0 }, - { 0, NULL, NULL, 0, 0555 }, - { 0 } -}; - -static ctl_table sensors_proc_dev_sensors[] = { - { SENSORS_CHIPS, "chips", NULL, 0, 0644, NULL, &sensors_proc_chips, - &sensors_sysctl_chips }, - { 0 } -}; - -static ctl_table sensors_proc_dev[] = { - { DEV_SENSORS, "sensors", NULL, 0, 0555, sensors_proc_dev_sensors }, - { 0 }, -}; - - -static ctl_table sensors_proc[] = { - { CTL_DEV, "dev", NULL, 0, 0555, sensors_proc_dev }, - { 0 } -}; - - -static struct ctl_table_header *sensors_proc_header; -static int sensors_initialized; - -/* This returns a nice name for a new directory; for example lm78-isa-0310 - (for a LM78 chip on the ISA bus at port 0x310), or lm75-i2c-3-4e (for - a LM75 chip on the third i2c bus at address 0x4e). - name is allocated first. */ -int sensors_create_name(char **name, const char *prefix, - struct i2c_adapter * adapter, int addr) -{ - char name_buffer[50]; - int id; - if (i2c_is_isa_adapter(adapter)) - sprintf(name_buffer,"%s-isa-%04x",prefix,addr); - else { - if ((id = i2c_adapter_id(adapter)) < 0) - return -ENOENT; - sprintf(name_buffer,"%s-i2c-%d-%02x",prefix,id,addr); - } - *name = kmalloc(strlen(name_buffer)+1,GFP_KERNEL); - strcpy(*name,name_buffer); - return 0; -} - -/* This rather complex function must be called when you want to add an entry - to /proc/sys/dev/sensors/chips (not yet implemented). It also creates - a new directory within /proc/sys/dev/sensors/. - ctl_template should be a template of the newly created directory. It is - copied in memory. The extra2 field of each file is set to point to client. - If any driver wants subdirectories within the newly created directory, - this function must be updated! */ -int sensors_register_entry(struct i2c_client *client ,const char *prefix, - ctl_table *ctl_template) -{ - int i,res,len,id; - ctl_table *new_table; - char *name; - struct ctl_table_header *new_header; - - if ((res = sensors_create_name(&name,prefix,client->adapter, - i2c_is_isa_client(client)? - ((struct isa_client *) client)->isa_addr: - client->addr))) - return res; - - for (id = 0; id < SENSORS_ENTRY_MAX; id++) - if (! sensors_entries[id]) { - break; - } - if (id == SENSORS_ENTRY_MAX) { - kfree(name); - return -ENOMEM; - } - id += 256; - - len = 0; - while (ctl_template[len].procname) - len++; - len += 7; - if (! (new_table = kmalloc(sizeof(ctl_table) * len,GFP_KERNEL))) { - kfree(name); - return -ENOMEM; - } - - memcpy(new_table,sysctl_table,6 * sizeof(ctl_table)); - new_table[0].child = &new_table[2]; - new_table[2].child = &new_table[4]; - new_table[4].child = &new_table[6]; - new_table[4].procname = name; - new_table[4].ctl_name = id; - memcpy(new_table+6,ctl_template,(len-6) * sizeof(ctl_table)); - for (i = 6; i < len; i++) - new_table[i].extra2 = client; - - if (! (new_header = register_sysctl_table(new_table,0))) { - kfree(new_table); - kfree(name); - return -ENOMEM; - } - - sensors_entries[id-256] = new_header; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) - sensors_clients[id-256] = client; -#ifdef DEBUG - if (!new_header || !new_header->ctl_table || - !new_header->ctl_table->child || - !new_header->ctl_table->child->child || - !new_header->ctl_table->child->child->de) { - printk("sensors.o: NULL pointer when trying to install fill_inode fix!\n"); - return id; - } -#endif /* DEBUG */ - sensors_inodes[id-256] = new_header->ctl_table->child->child->de->low_ino; - new_header->ctl_table->child->child->de->fill_inode = &sensors_dir_fill_inode; -#endif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) - - return id; -} - -void sensors_deregister_entry(int id) -{ - ctl_table *table; - id -= 256; - if (sensors_entries[id]) { - table = sensors_entries[id]->ctl_table; - unregister_sysctl_table(sensors_entries[id]); - kfree((void *) (table[4].procname)); - kfree(table); - sensors_entries[id] = NULL; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) - sensors_clients[id] = NULL; -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) */ - } -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) -/* Monitor access for /proc/sys/dev/sensors; make unloading sensors.o - impossible if some process still uses it or some file in it */ -void sensors_fill_inode(struct inode *inode, int fill) -{ - if (fill) - MOD_INC_USE_COUNT; - else - MOD_DEC_USE_COUNT; -} - -/* Monitor access for /proc/sys/dev/sensors/* directories; make unloading - the corresponding module impossible if some process still uses it or - some file in it */ -void sensors_dir_fill_inode(struct inode *inode, int fill) -{ - int i; - struct i2c_client *client; - -#ifdef DEBUG - if (! inode) { - printk("sensors.o: Warning: inode NULL in fill_inode()\n"); - return; - } -#endif /* def DEBUG */ - - for (i = 0; i < SENSORS_ENTRY_MAX; i++) - if (sensors_clients[i] && (sensors_inodes[i] == inode->i_ino)) - break; -#ifdef DEBUG - if (i == SENSORS_ENTRY_MAX) { - printk("sensors.o: Warning: inode (%ld) not found in fill_inode()\n", - inode->i_ino); - return; - } -#endif /* def DEBUG */ - client = sensors_clients[i]; - if (fill) - client->driver->inc_use(client); - else - client->driver->dec_use(client); -} -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) */ - -int sensors_proc_chips(ctl_table *ctl, int write, struct file * filp, - void *buffer, size_t *lenp) -{ - char BUF[SENSORS_PREFIX_MAX + 30]; - int buflen,curbufsize,i; - struct ctl_table *client_tbl; - - if (write) - return 0; - - /* If buffer is size 0, or we try to read when not at the start, we - return nothing. Note that I think writing when not at the start - does not work either, but anyway, this is straight from the kernel - sources. */ - if (!*lenp || (filp->f_pos && !write)) { - *lenp = 0; - return 0; - } - curbufsize = 0; - for (i = 0; i < SENSORS_ENTRY_MAX; i ++) - if (sensors_entries[i]) { - client_tbl = sensors_entries[i]->ctl_table->child->child; - buflen = sprintf(BUF,"%d\t%s\n",client_tbl->ctl_name, - client_tbl->procname); - if (buflen + curbufsize > *lenp) - buflen=*lenp-curbufsize; - copy_to_user(buffer,BUF,buflen); - curbufsize += buflen; - (char *) buffer += buflen; - } - *lenp = curbufsize; - filp->f_pos += curbufsize; - return 0; -} - -int sensors_sysctl_chips (ctl_table *table, int *name, int nlen, void *oldval, - size_t *oldlenp, void *newval, size_t newlen, - void **context) -{ - struct sensors_chips_data data; - int i,oldlen,nrels,maxels; - struct ctl_table *client_tbl; - - if (oldval && oldlenp && ! get_user_data(oldlen,oldlenp) && oldlen) { - maxels = oldlen / sizeof(struct sensors_chips_data); - nrels = 0; - for (i = 0; (i < SENSORS_ENTRY_MAX) && (nrels < maxels); i++) - if (sensors_entries[i]) { - client_tbl = sensors_entries[i]->ctl_table->child->child; - data.sysctl_id = client_tbl->ctl_name; - strcpy(data.name,client_tbl->procname); - copy_to_user(oldval,&data,sizeof(struct sensors_chips_data)); - (char *) oldval += sizeof(struct sensors_chips_data); - nrels++; - } - oldlen = nrels * sizeof(struct sensors_chips_data); - put_user(oldlen,oldlenp); - } - return 0; -} - - -/* This funcion reads or writes a 'real' value (encoded by the combination - of an integer and a magnitude, the last is the power of ten the value - should be divided with) to a /proc/sys directory. To use this function, - you must (before registering the ctl_table) set the extra2 field to the - client, and the extra1 field to a function of the form: - void func(struct i2c_client *client, int operation, int ctl_name, - int *nrels_mag, long *results) - This function can be called for three values of operation. If operation - equals SENSORS_PROC_REAL_INFO, the magnitude should be returned in - nrels_mag. If operation equals SENSORS_PROC_REAL_READ, values should - be read into results. nrels_mag should return the number of elements - read; the maximum number is put in it on entry. Finally, if operation - equals SENSORS_PROC_REAL_WRITE, the values in results should be - written to the chip. nrels_mag contains on entry the number of elements - found. - In all cases, client points to the client we wish to interact with, - and ctl_name is the SYSCTL id of the file we are accessing. */ -int sensors_proc_real(ctl_table *ctl, int write, struct file * filp, - void *buffer, size_t *lenp) -{ -#define MAX_RESULTS 20 - int mag,nrels=MAX_RESULTS; - long results[MAX_RESULTS]; - sensors_real_callback callback = ctl -> extra1; - struct i2c_client *client = ctl -> extra2; - - /* If buffer is size 0, or we try to read when not at the start, we - return nothing. Note that I think writing when not at the start - does not work either, but anyway, this is straight from the kernel - sources. */ - if (!*lenp || (filp->f_pos && !write)) { - *lenp = 0; - return 0; - } - - /* Get the magnitude */ - callback(client,SENSORS_PROC_REAL_INFO,ctl->ctl_name,&mag,NULL); - - if (write) { - /* Read the complete input into results, converting to longs */ - sensors_parse_reals(&nrels,buffer,*lenp,results,mag); - - if (! nrels) - return 0; - - /* Now feed this information back to the client */ - callback(client,SENSORS_PROC_REAL_WRITE,ctl->ctl_name,&nrels,results); - - filp->f_pos += *lenp; - return 0; - } else { /* read */ - /* Get the information from the client into results */ - callback(client,SENSORS_PROC_REAL_READ,ctl->ctl_name,&nrels,results); - - /* And write them to buffer, converting to reals */ - sensors_write_reals(nrels,buffer,lenp,results,mag); - filp->f_pos += *lenp; - return 0; - } -} - -/* This function is equivalent to sensors_proc_real, only it interacts with - the sysctl(2) syscall, and returns no reals, but integers */ -int sensors_sysctl_real (ctl_table *table, int *name, int nlen, void *oldval, - size_t *oldlenp, void *newval, size_t newlen, - void **context) -{ - long results[MAX_RESULTS]; - int oldlen,nrels=MAX_RESULTS; - sensors_real_callback callback = table -> extra1; - struct i2c_client *client = table -> extra2; - - /* Check if we need to output the old values */ - if (oldval && oldlenp && ! get_user_data(oldlen,oldlenp) && oldlen) { - callback(client,SENSORS_PROC_REAL_READ,table->ctl_name,&nrels,results); - - /* Note the rounding factor! */ - if (nrels * sizeof(long) < oldlen) - oldlen = nrels * sizeof(long); - oldlen = (oldlen / sizeof(long)) * sizeof(long); - copy_to_user(oldval,results,oldlen); - put_user(oldlen,oldlenp); - } - - if (newval && newlen) { - /* Note the rounding factor! */ - newlen -= newlen % sizeof(long); - nrels = newlen / sizeof(long); - copy_from_user(results,newval,newlen); - - /* Get the new values back to the client */ - callback(client,SENSORS_PROC_REAL_WRITE,table->ctl_name,&nrels,results); - } - return 0; -} - - -/* nrels contains initially the maximum number of elements which can be - put in results, and finally the number of elements actually put there. - A magnitude of 1 will multiply everything with 10; etc. - buffer, bufsize is the character buffer we read from and its length. - results will finally contain the parsed integers. - - Buffer should contain several reals, separated by whitespace. A real - has the following syntax: - [ Minus ] Digit* [ Dot Digit* ] - (everything between [] is optional; * means zero or more). - When the next character is unparsable, everything is skipped until the - next whitespace. - - WARNING! This is tricky code. I have tested it, but there may still be - hidden bugs in it, even leading to crashes and things! -*/ -void sensors_parse_reals(int *nrels, void *buffer, int bufsize, - long *results, int magnitude) -{ - int maxels,min,mag; - long res; - char nextchar=0; - - maxels = *nrels; - *nrels = 0; - - while (bufsize && (*nrels < maxels)) { - - /* Skip spaces at the start */ - while (bufsize && ! get_user_data(nextchar,(char *) buffer) && - isspace((int) nextchar)) { - bufsize --; - ((char *) buffer)++; - } - - /* Well, we may be done now */ - if (! bufsize) - return; - - /* New defaults for our result */ - min = 0; - res = 0; - mag = magnitude; - - /* Check for a minus */ - if (! get_user_data(nextchar,(char *) buffer) && (nextchar == '-')) { - min=1; - bufsize--; - ((char *) buffer)++; - } - - /* Digits before a decimal dot */ - while (bufsize && !get_user_data(nextchar,(char *) buffer) && - isdigit((int) nextchar)) { - res = res * 10 + nextchar - '0'; - bufsize--; - ((char *) buffer)++; - } - - /* If mag < 0, we must actually divide here! */ - while (mag < 0) { - res = res / 10; - mag++; - } - - if (bufsize && (nextchar == '.')) { - /* Skip the dot */ - bufsize--; - ((char *) buffer)++; - - /* Read digits while they are significant */ - while(bufsize && (mag > 0) && - !get_user_data(nextchar,(char *) buffer) && - isdigit((int) nextchar)) { - res = res * 10 + nextchar - '0'; - mag--; - bufsize--; - ((char *) buffer)++; - } - } - /* If we are out of data, but mag > 0, we need to scale here */ - while (mag > 0) { - res = res * 10; - mag --; - } - - /* Skip everything until we hit whitespace */ - while(bufsize && !get_user_data(nextchar,(char *) buffer) && - isspace ((int) nextchar)) { - bufsize --; - ((char *) buffer) ++; - } - - /* Put res in results */ - results[*nrels] = (min?-1:1)*res; - (*nrels)++; - } - - /* Well, there may be more in the buffer, but we need no more data. - Ignore anything that is left. */ - return; -} - -void sensors_write_reals(int nrels,void *buffer,int *bufsize,long *results, - int magnitude) -{ - #define BUFLEN 20 - char BUF[BUFLEN+1]; /* An individual representation should fit in here! */ - char printfstr[10]; - int nr=0; - int buflen,mag,times; - int curbufsize=0; - - while ((nr < nrels) && (curbufsize < *bufsize)) { - mag=magnitude; - - if (nr != 0) { - put_user(' ', (char *) buffer); - curbufsize ++; - ((char *) buffer) ++; - } - - /* Fill BUF with the representation of the next string */ - if (mag <= 0) { - - buflen=sprintf(BUF,"%ld",results[nr]); - if (buflen < 0) { /* Oops, a sprintf error! */ - *bufsize=0; - return; - } - while ((mag < 0) && (buflen < BUFLEN)) { - BUF[buflen++]='0'; - mag++; - } - BUF[buflen]=0; - } else { - times=1; - for (times=1; mag-- > 0; times *= 10); - if (results[nr] < 0) { - BUF[0] = '-'; - buflen = 1; - } else - buflen=0; - strcpy(printfstr,"%ld.%0Xld"); - printfstr[6]=magnitude+'0'; - buflen+=sprintf(BUF+buflen,printfstr,abs(results[nr])/times, - abs(results[nr])%times); - if (buflen < 0) { /* Oops, a sprintf error! */ - *bufsize=0; - return; - } - } - - /* Now copy it to the user-space buffer */ - if (buflen + curbufsize > *bufsize) - buflen=*bufsize-curbufsize; - copy_to_user(buffer,BUF,buflen); - curbufsize += buflen; - (char *) buffer += buflen; - - nr ++; - } - if (curbufsize < *bufsize) { - put_user('\n', (char *) buffer); - curbufsize ++; - } - *bufsize=curbufsize; -} - -int sensors_init(void) -{ - printk("sensors.o version %s (%s)\n",LM_VERSION,LM_DATE); - sensors_initialized = 0; - if (! (sensors_proc_header = register_sysctl_table(sensors_proc,0))) - return -ENOMEM; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) - sensors_proc_header->ctl_table->child->de->fill_inode = &sensors_fill_inode; -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) */ - sensors_initialized ++; - return 0; -} - -int sensors_cleanup(void) -{ - if (sensors_initialized >= 1) { - unregister_sysctl_table(sensors_proc_header); - sensors_initialized --; - } - return 0; -} - -#ifdef MODULE - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); -MODULE_DESCRIPTION("LM78 driver"); - -int init_module(void) -{ - return sensors_init(); -} - -int cleanup_module(void) -{ - return sensors_cleanup(); -} - -#endif /* MODULE */ - diff --git a/kernel/smbus.c b/kernel/smbus.c deleted file mode 100644 index d61c2e94..00000000 --- a/kernel/smbus.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - smbus.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 Frodo Looijaard <frodol@dds.nl> - - 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. -*/ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/stddef.h> - -#include "i2c.h" -#ifdef SPINLOCK -#include <asm/spinlock.h> -#else -#include <asm/semaphore.h> -#endif - -#include "version.h" -#include "smbus.h" - -static s32 smbus_access_i2c (struct i2c_adapter * adapter, u8 addr, - char read_write, u8 command, int size, - union smbus_data * data); - -static int smbus_master_xfer (struct smbus_adapter *adap, - struct i2c_msg msgs[], int num); -static int smbus_slave_send (struct smbus_adapter *adap, char *data, int len); -static int smbus_slave_recv (struct smbus_adapter *adap, char *data, int len); -static int smbus_algo_control (struct smbus_adapter *adap, unsigned int cmd, - unsigned long arg); -static int smbus_client_register (struct smbus_client *client); -static int smbus_client_unregister (struct smbus_client *client); - -static int smbus_init(void); -static int smbus_cleanup(void); - -#ifdef MODULE -extern int init_module(void); -extern int cleanup_module(void); -#endif /* MODULE */ - -/* This is the actual algorithm we define */ -struct smbus_algorithm smbus_algorithm = { - /* name */ "Non-I2C SMBus adapter", - /* id */ ALGO_SMBUS, - /* master_xfer */ &smbus_master_xfer, - /* slave_send */ &smbus_slave_send, - /* slave_rcv */ &smbus_slave_recv, - /* algo_control */ &smbus_algo_control, - /* client_register */ &smbus_client_register, - /* client_unregister*/&smbus_client_unregister -}; - - -/* OK, so you want to access a bus using the SMBus protocols. Well, it either - is registered as a SMBus-only adapter (like the PIIX4), or we need to - simulate the SMBus commands using the i2c access routines. - We do all locking here, so you can ignore that in the adapter-specific - smbus_accesss routine. */ -s32 smbus_access (struct i2c_adapter * adapter, u8 addr, char read_write, - u8 command, int size, union smbus_data * data) -{ - int res; - if ((adapter->id & ALGO_MASK) == ALGO_SMBUS) { -#ifdef SPINLOCK - spin_lock_irqsave(&adapter->lock,adapter->lockflags); -#else - down(&adapter->lock); -#endif - res = ((struct smbus_adapter *) adapter) -> - smbus_access(addr,read_write,command,size,data); -#ifdef SPINLOCK - spin_unlock_irqrestore(&adapter->lock,adapter->lockflags); -#else - up(&adapter->lock); -#endif - } else - res = smbus_access_i2c(adapter,addr,read_write,command,size,data); - return res; -} - -/* Simulate a SMBus command using the i2c protocol - No checking of paramters is done! */ -s32 smbus_access_i2c(struct i2c_adapter * adapter, u8 addr, char read_write, - u8 command, int size, union smbus_data * data) -{ - /* So we need to generate a series of msgs. In the case of writing, we - need to use only one message; when reading, we need two. We initialize - most things with sane defaults, to keep the code below somewhat - simpler. */ - char msgbuf0[33]; - char msgbuf1[33]; - int num = read_write == SMBUS_READ?2:1; - struct i2c_msg msg[2] = { { addr, 0, 1, msgbuf0 }, - { addr, I2C_M_RD, 0, msgbuf1 } - }; - int i; - - msgbuf0[0] = command; - switch(size) { - case SMBUS_QUICK: - msg[0].len = 0; - num = 1; /* Special case: The read/write field is used as data */ - break; - case SMBUS_BYTE: - if (read_write == SMBUS_READ) - /* Special case: only a read! */ - msg[0].flags = I2C_M_RD; - break; - case SMBUS_BYTE_DATA: - if (read_write == SMBUS_READ) - msg[1].len = 1; - else { - msg[0].len = 2; - msgbuf0[1] = data->byte; - } - break; - case SMBUS_WORD_DATA: - if (read_write == SMBUS_READ) - msg[1].len = 2; - else { - msg[0].len=3; - msgbuf0[1] = data->word & 0xff; - msgbuf0[2] = (data->word >> 8) & 0xff; - } - break; - case SMBUS_PROC_CALL: - num = 2; /* Special case */ - msg[0].len = 3; - msg[1].len = 2; - msgbuf0[1] = data->word & 0xff; - msgbuf0[2] = (data->word >> 8) & 0xff; - break; - case SMBUS_BLOCK_DATA: - if (read_write == SMBUS_READ) { - printk("smbus.o: Block read not supported under I2C emulation!\n"); - return -1; - } else { - msg[1].len = data->block[0] + 1; - if (msg[1].len > 32) { - printk("smbus.o: smbus_access called with invalid block write " - "size (%d)\n",msg[1].len); - return -1; - } - for (i = 1; i <= msg[1].len; i++) - msgbuf0[i] = data->block[1]; - } - break; - default: - printk("smbus.o: smbus_access called with invalid size (%d)\n",size); - return -1; - } - - if (i2c_transfer(adapter, msg, num) < 0) - return -1; - - if(read_write == SMBUS_READ) - switch(size) { - case SMBUS_BYTE: - data->byte = msgbuf0[0]; - break; - case SMBUS_BYTE_DATA: - data->byte = msgbuf1[0]; - break; - case SMBUS_WORD_DATA: - case SMBUS_PROC_CALL: - data->word = msgbuf1[0] + (msgbuf1[1] << 8); - break; - } - return 0; -} - -/* Algorithm master_xfer call-back implementation. Can't do that... */ -int smbus_master_xfer (struct smbus_adapter *adap, struct i2c_msg msgs[], - int num) -{ -#ifdef DEBUG - printk("smbus.o: smbus_master_xfer called for adapter `%s' " - "(no i2c level access possible!)\n", - adap->name); -#endif - return -1; -} - -/* Algorithm slave_send call-back implementation. Can't do that... */ -int smbus_slave_send (struct smbus_adapter *adap, char *data, int len) -{ -#ifdef DEBUG - printk("smbus.o: smbus_slave_send called for adapter `%s' " - "(no i2c level access possible!)\n", - adap->name); -#endif - return -1; -} - -/* Algorithm slave_recv call-back implementation. Can't do that... */ -int smbus_slave_recv (struct smbus_adapter *adap, char *data, int len) -{ -#ifdef DEBUG - printk("smbus.o: smbus_slave_recv called for adapter `%s' " - "(no i2c level access possible!)\n", - adap->name); -#endif - return -1; -} - -/* Here we can put additional calls to modify the workings of the algorithm. - But right now, there is no need for that. */ -int smbus_algo_control (struct smbus_adapter *adap, unsigned int cmd, - unsigned long arg) -{ - return 0; -} - -/* Ehm... This is called when a client is registered to an adapter. We could - do all kinds of neat stuff here like, ehm - returning success? */ -int smbus_client_register (struct smbus_client *client) -{ - return 0; -} - -int smbus_client_unregister (struct smbus_client *client) -{ - return 0; -} - -int smbus_init(void) -{ - int res; - printk("smbus.o version %s (%s)\n",LM_VERSION,LM_DATE); - if ((res = smbus_add_algorithm(&smbus_algorithm))) - printk("smbus.o: Algorithm registration failed, module not inserted.\n"); - else - printk("smbus.o initialized\n"); - return res; -} - -int smbus_cleanup(void) -{ - int res; - if ((res = smbus_del_algorithm(&smbus_algorithm))) - printk("smbus.o: Algorithm deregistration failed, module not removed\n"); - return res; -} - -/* OK, this will for now _only_ compile as a module, but this is neat for - later, if we want to compile it straight into the kernel */ -#ifdef MODULE - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); -MODULE_DESCRIPTION("System Management Bus (SMBus) access"); - -int init_module(void) -{ - return smbus_init(); -} - -int cleanup_module(void) -{ - return smbus_cleanup(); -} - -#endif /* MODULE */ |