1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/delay.h>
29#include <linux/slab.h>
30#include <linux/init.h>
31
32#include <asm/uaccess.h>
33
34#include <linux/ioport.h>
35#include <asm/io.h>
36#include <linux/errno.h>
37#include <linux/i2c.h>
38#include <linux/i2c-algo-bit.h>
39
40#define DEFAULT_BASE 0x378
41static int base=0;
42static unsigned char PortData = 0;
43
44
45#define DEB(x)
46#define DEB2(x)
47#define DEBE(x) x
48#define DEBINIT(x) x
49
50
51#define BASE (unsigned int)(data)
52#define DATA BASE
53#define STAT (BASE+1)
54#define CTRL (BASE+2)
55
56
57
58
59
60static void bit_elv_setscl(void *data, int state)
61{
62 if (state) {
63 PortData &= 0xfe;
64 } else {
65 PortData |=1;
66 }
67 outb(PortData, DATA);
68}
69
70static void bit_elv_setsda(void *data, int state)
71{
72 if (state) {
73 PortData &=0xfd;
74 } else {
75 PortData |=2;
76 }
77 outb(PortData, DATA);
78}
79
80static int bit_elv_getscl(void *data)
81{
82 return ( 0 == ( (inb_p(STAT)) & 0x08 ) );
83}
84
85static int bit_elv_getsda(void *data)
86{
87 return ( 0 == ( (inb_p(STAT)) & 0x40 ) );
88}
89
90static int bit_elv_init(void)
91{
92 if (check_region(base,(base == 0x3bc)? 3 : 8) < 0 ) {
93 return -ENODEV;
94 } else {
95
96 if (inb(base+1) & 0x80) {
97 DEBINIT(printk(KERN_DEBUG "i2c-elv.o: Busy was low.\n"));
98 return -ENODEV;
99 } else {
100 outb(0x0c,base+2);
101 udelay(400);
102 if ( !(inb(base+1) && 0x10) ) {
103 outb(0x04,base+2);
104 DEBINIT(printk(KERN_DEBUG "i2c-elv.o: Select was high.\n"));
105 return -ENODEV;
106 }
107 }
108 request_region(base,(base == 0x3bc)? 3 : 8,
109 "i2c (ELV adapter)");
110 PortData = 0;
111 bit_elv_setsda((void*)base,1);
112 bit_elv_setscl((void*)base,1);
113 }
114 return 0;
115}
116
117static void __exit bit_elv_exit(void)
118{
119 release_region( base , (base == 0x3bc)? 3 : 8 );
120}
121
122static int bit_elv_reg(struct i2c_client *client)
123{
124 return 0;
125}
126
127static int bit_elv_unreg(struct i2c_client *client)
128{
129 return 0;
130}
131
132static void bit_elv_inc_use(struct i2c_adapter *adap)
133{
134#ifdef MODULE
135 MOD_INC_USE_COUNT;
136#endif
137}
138
139static void bit_elv_dec_use(struct i2c_adapter *adap)
140{
141#ifdef MODULE
142 MOD_DEC_USE_COUNT;
143#endif
144}
145
146
147
148
149
150static struct i2c_algo_bit_data bit_elv_data = {
151 NULL,
152 bit_elv_setsda,
153 bit_elv_setscl,
154 bit_elv_getsda,
155 bit_elv_getscl,
156 80, 80, 100,
157};
158
159static struct i2c_adapter bit_elv_ops = {
160 "ELV Parallel port adaptor",
161 I2C_HW_B_ELV,
162 NULL,
163 &bit_elv_data,
164 bit_elv_inc_use,
165 bit_elv_dec_use,
166 bit_elv_reg,
167 bit_elv_unreg,
168};
169
170int __init i2c_bitelv_init(void)
171{
172 printk(KERN_INFO "i2c-elv.o: i2c ELV parallel port adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
173 if (base==0) {
174
175 base=DEFAULT_BASE;
176 bit_elv_data.data=(void*)DEFAULT_BASE;
177 if (bit_elv_init()==0) {
178 if(i2c_bit_add_bus(&bit_elv_ops) < 0)
179 return -ENODEV;
180 } else {
181 return -ENODEV;
182 }
183 } else {
184 bit_elv_ops.data=(void*)base;
185 if (bit_elv_init()==0) {
186 if(i2c_bit_add_bus(&bit_elv_ops) < 0)
187 return -ENODEV;
188 } else {
189 return -ENODEV;
190 }
191 }
192 printk(KERN_DEBUG "i2c-elv.o: found device at %#x.\n",base);
193 return 0;
194}
195
196
197EXPORT_NO_SYMBOLS;
198
199#ifdef MODULE
200MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
201MODULE_DESCRIPTION("I2C-Bus adapter routines for ELV parallel port adapter");
202MODULE_LICENSE("GPL");
203
204MODULE_PARM(base, "i");
205
206int init_module(void)
207{
208 return i2c_bitelv_init();
209}
210
211void cleanup_module(void)
212{
213 i2c_bit_del_bus(&bit_elv_ops);
214 bit_elv_exit();
215}
216
217#endif
218