root/i2c/trunk/kernel/i2c-velleman.c @ 3317

Revision 3317, 4.9 KB (checked in by frodo, 15 years ago)

Second part of Kyösti Mälkki's patches

MOD_{INC,DEC}_USE_COUNT should now really be fail-safe.

I wrote in email to Kyösti about this:

If I understand it correctly, the scheme you propose is as follows:

  • Each struct i2c_algorithm variable has inc_use and dec_use hooks in it.
  • The hooks should do a MOD_{INC,DEC}_USE_COUNT in the appropriate adapter modules (of course, these can only be done in the module which needs to be locked)
  • The struct i2c_driver had already similar hooks, for locking the client modules
  • The i2c_{inc,dec}_use_client function should *not* be called when a client is (de)registered; instead, it should only be called when a resource is used that makes it impossible to remove the client and its adapter. For example, the opening of a /proc file or the moving into a /proc directory owned by the client driver. I have applied the changes to i2c-core and i2c.h as in your patch, as well as to i2c-algo-bit. I saw you added MOD_INC_USE_COUNT to the algorithm drivers. That means we can't remove an algorithm module if an adapter module is still connected to it. Perhaps we should do the same as the in the case a driver module is deleted: scan for connected adapters and remove them one by one (including their clients, of course). What do you think? As i2c-algo-pcf is structured similar to i2c-algo-bit, I saw no reason not to apply the same patches to it, including the MOD_{INC,DEC}_USE_COUNT patch. If you know of a reason why I should not have done this, please tell me and/or revert the changes. I know this will break PCF adapter drivers; well, too bad :-) All included adapter drivers have been patched to do MOD_{INC,DEV}_USE_COUNT calls.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* ------------------------------------------------------------------------- */
2/* bit-velle.c i2c-hw access for Velleman K9000 adapters                     */
3/* ------------------------------------------------------------------------- */
4/*   Copyright (C) 1995-96 Simon G. Vogl
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
19/* -------------------------------------------------------------------------
20static char rcsid[] = "$Id$";
21  ------------------------------------------------------------------------- */
22
23#include <linux/kernel.h>
24#include <linux/ioport.h>
25#include <linux/module.h>
26#if LINUX_VERSION_CODE >= 0x020135
27#include <linux/init.h>
28#else
29#define __init
30#endif
31#include <linux/string.h>  /* for 2.0 kernels to get NULL   */
32#include <asm/errno.h>     /* for 2.0 kernels to get ENODEV */
33#include <asm/io.h>
34
35#include "i2c.h"
36#include "i2c-algo-bit.h"
37
38/* ----- global defines ----------------------------------------------- */
39#define DEB(x)          /* should be reasonable open, close &c.         */
40#define DEB2(x)         /* low level debugging - very slow              */
41#define DEBE(x) x       /* error messages                               */
42
43                                        /* Pin Port  Inverted   name    */
44#define I2C_SDA         0x02            /*  ctrl bit 1  (inv)   */
45#define I2C_SCL         0x08            /*  ctrl bit 3  (inv)   */
46
47#define I2C_SDAIN       0x10            /* stat bit 4           */
48#define I2C_SCLIN       0x08            /*  ctrl bit 3 (inv) (reads own output) */
49
50#define I2C_DMASK       0xfd
51#define I2C_CMASK       0xf7
52
53
54/* --- Convenience defines for the parallel port:                       */
55#define BASE    (unsigned int)(data)
56#define DATA    BASE                    /* Centronics data port         */
57#define STAT    (BASE+1)                /* Centronics status port       */
58#define CTRL    (BASE+2)                /* Centronics control port      */
59
60#define DEFAULT_BASE 0x378
61static int base=0;
62
63/* ----- local functions --------------------------------------------------- */
64
65static void bit_velle_setscl(void *data, int state)
66{
67        if (state) {
68                outb(inb(CTRL) & I2C_CMASK,   CTRL);
69        } else {
70                outb(inb(CTRL) | I2C_SCL, CTRL);
71        }
72       
73}
74
75static void bit_velle_setsda(void *data, int state)
76{
77        if (state) {
78                outb(inb(CTRL) & I2C_DMASK , CTRL);
79        } else {
80                outb(inb(CTRL) | I2C_SDA, CTRL);
81        }
82       
83} 
84
85static int bit_velle_getscl(void *data)
86{
87        return ( 0 == ( (inb(CTRL)) & I2C_SCLIN ) );
88}
89
90static int bit_velle_getsda(void *data)
91{
92        return ( 0 != ( (inb(STAT)) & I2C_SDAIN ) );
93}
94
95static int bit_velle_init(void)
96{
97        if (check_region(base,(base == 0x3bc)? 3 : 8) < 0 ) {
98                DEBE(printk("i2c_init: Port %#x already in use.\n", base));
99                return -ENODEV;
100        } else {
101                request_region(base, (base == 0x3bc)? 3 : 8, 
102                        "i2c (Vellemann adapter)");
103                bit_velle_setsda((void*)base,1);
104                bit_velle_setscl((void*)base,1);
105        }
106        return 0;
107}
108
109static void bit_velle_exit(void)
110{       
111        release_region( base , (base == 0x3bc)? 3 : 8 );
112}
113
114
115static int bit_velle_reg(struct i2c_client *client)
116{
117        return 0;
118}
119
120static int bit_velle_unreg(struct i2c_client *client)
121{
122        return 0;
123}
124
125static void bit_velle_inc_use(struct bit_adapter *adap)
126{
127#ifdef MODULE
128        MOD_INC_USE_COUNT;
129#endif
130}
131
132static void bit_velle_dec_use(struct bit_adapter *adap)
133{
134#ifdef MODULE
135        MOD_DEC_USE_COUNT;
136#endif
137}
138
139/* ------------------------------------------------------------------------
140 * Encapsulate the above functions in the correct operations structure.
141 * This is only done when more than one hardware adapter is supported.
142 */
143struct bit_adapter bit_velle_ops = {
144        "Philips Parallel port adapter",
145        HW_B_LP,
146        NULL,
147        bit_velle_setsda,
148        bit_velle_setscl,
149        bit_velle_getsda,
150        bit_velle_getscl,
151        bit_velle_reg,
152        bit_velle_unreg,
153        bit_velle_inc_use,
154        bit_velle_dec_use,
155        10, 10, 100,            /*      waits, timeout */
156};
157
158int __init  bitvelle_init(void)
159{
160        if (base==0) {
161                /* probe some values */
162                base=DEFAULT_BASE;
163                bit_velle_ops.data=(void*)DEFAULT_BASE;
164                if (bit_velle_init()==0) {
165                        i2c_bit_add_bus(&bit_velle_ops);
166                } else {
167                        return -ENODEV;
168                }
169        } else {
170                bit_velle_ops.data=(void*)base;
171                if (bit_velle_init()==0) {
172                        i2c_bit_add_bus(&bit_velle_ops);
173                } else {
174                        return -ENODEV;
175                }
176        }
177        printk("bit_velle: found device at %#x.\n",base);
178        return 0;
179}
180
181
182#ifdef MODULE
183MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
184MODULE_DESCRIPTION("I2C-Bus adapter routines for Velleman K9000 adapter");
185
186MODULE_PARM(base, "i");
187
188int init_module(void) 
189{
190        return bitvelle_init();
191}
192
193void cleanup_module(void) 
194{
195        i2c_bit_del_bus(&bit_velle_ops);
196        bit_velle_exit();
197}
198
199#endif
200
201
202
Note: See TracBrowser for help on using the browser.