Commit | Line | Data |
---|---|---|
2c89e159 GKH |
1 | /* |
2 | comedi/drivers/c6xdigio.c | |
3 | ||
4 | Hardware driver for Mechatronic Systems Inc. C6x_DIGIO DSP daughter card. | |
5 | (http://robot0.ge.uiuc.edu/~spong/mecha/) | |
6 | ||
7 | COMEDI - Linux Control and Measurement Device Interface | |
8 | Copyright (C) 1999 Dan Block | |
9 | ||
10 | This program is free software; you can redistribute it and/or modify | |
11 | it under the terms of the GNU General Public License as published by | |
12 | the Free Software Foundation; either version 2 of the License, or | |
13 | (at your option) any later version. | |
14 | ||
15 | This program is distributed in the hope that it will be useful, | |
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | GNU General Public License for more details. | |
19 | ||
20 | You should have received a copy of the GNU General Public License | |
21 | along with this program; if not, write to the Free Software | |
22 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
23 | ||
24 | */ | |
25 | /* | |
26 | Driver: c6xdigio | |
27 | Description: Mechatronic Systems Inc. C6x_DIGIO DSP daughter card | |
28 | Author: Dan Block | |
29 | Status: unknown | |
30 | Devices: [Mechatronic Systems Inc.] C6x_DIGIO DSP daughter card (c6xdigio) | |
31 | Updated: Sun Nov 20 20:18:34 EST 2005 | |
32 | ||
33 | This driver will not work with a 2.4 kernel. | |
34 | http://robot0.ge.uiuc.edu/~spong/mecha/ | |
35 | ||
36 | */ | |
37 | ||
38 | #include <linux/kernel.h> | |
39 | #include <linux/module.h> | |
40 | #include <linux/sched.h> | |
41 | #include <linux/mm.h> | |
42 | #include <linux/errno.h> | |
43 | #include <linux/ioport.h> | |
44 | #include <linux/delay.h> | |
45 | #include <linux/interrupt.h> | |
46 | #include <linux/timex.h> | |
47 | #include <linux/timer.h> | |
23d53b17 | 48 | #include <linux/io.h> |
2c89e159 GKH |
49 | #include <linux/pnp.h> |
50 | ||
51 | #include "../comedidev.h" | |
52 | ||
53 | static u8 ReadByteFromHwPort(unsigned long addr) | |
54 | { | |
55 | u8 result = inb(addr); | |
56 | return result; | |
57 | } | |
58 | ||
59 | static void WriteByteToHwPort(unsigned long addr, u8 val) | |
60 | { | |
61 | outb_p(val, addr); | |
62 | } | |
63 | ||
64 | #define C6XDIGIO_SIZE 3 | |
65 | ||
66 | /* | |
67 | * port offsets | |
68 | */ | |
69 | #define C6XDIGIO_PARALLEL_DATA 0 | |
70 | #define C6XDIGIO_PARALLEL_STATUS 1 | |
71 | #define C6XDIGIO_PARALLEL_CONTROL 2 | |
72 | struct pwmbitstype { | |
73 | unsigned sb0:2; | |
74 | unsigned sb1:2; | |
75 | unsigned sb2:2; | |
76 | unsigned sb3:2; | |
77 | unsigned sb4:2; | |
78 | }; | |
79 | union pwmcmdtype { | |
6a438139 | 80 | unsigned cmd; /* assuming here that int is 32bit */ |
2c89e159 GKH |
81 | struct pwmbitstype bits; |
82 | }; | |
83 | struct encbitstype { | |
84 | unsigned sb0:3; | |
85 | unsigned sb1:3; | |
86 | unsigned sb2:3; | |
87 | unsigned sb3:3; | |
88 | unsigned sb4:3; | |
89 | unsigned sb5:3; | |
90 | unsigned sb6:3; | |
91 | unsigned sb7:3; | |
92 | }; | |
93 | union encvaluetype { | |
94 | unsigned value; | |
95 | struct encbitstype bits; | |
96 | }; | |
97 | ||
98 | #define C6XDIGIO_TIME_OUT 20 | |
99 | ||
0a85b6f0 MT |
100 | static int c6xdigio_attach(struct comedi_device *dev, |
101 | struct comedi_devconfig *it); | |
da91b269 | 102 | static int c6xdigio_detach(struct comedi_device *dev); |
139dfbdf | 103 | struct comedi_driver driver_c6xdigio = { |
68c3dbff BP |
104 | .driver_name = "c6xdigio", |
105 | .module = THIS_MODULE, | |
106 | .attach = c6xdigio_attach, | |
107 | .detach = c6xdigio_detach, | |
2c89e159 GKH |
108 | }; |
109 | ||
110 | static void C6X_pwmInit(unsigned long baseAddr) | |
111 | { | |
112 | int timeout = 0; | |
113 | ||
6a438139 | 114 | /* printk("Inside C6X_pwmInit\n"); */ |
2c89e159 GKH |
115 | |
116 | WriteByteToHwPort(baseAddr, 0x70); | |
117 | while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0) | |
0a85b6f0 | 118 | && (timeout < C6XDIGIO_TIME_OUT)) { |
2c89e159 GKH |
119 | timeout++; |
120 | } | |
121 | ||
122 | WriteByteToHwPort(baseAddr, 0x74); | |
123 | timeout = 0; | |
124 | while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x80) | |
0a85b6f0 | 125 | && (timeout < C6XDIGIO_TIME_OUT)) { |
2c89e159 GKH |
126 | timeout++; |
127 | } | |
128 | ||
129 | WriteByteToHwPort(baseAddr, 0x70); | |
130 | timeout = 0; | |
131 | while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x0) | |
0a85b6f0 | 132 | && (timeout < C6XDIGIO_TIME_OUT)) { |
2c89e159 GKH |
133 | timeout++; |
134 | } | |
135 | ||
136 | WriteByteToHwPort(baseAddr, 0x0); | |
137 | timeout = 0; | |
138 | while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x80) | |
0a85b6f0 | 139 | && (timeout < C6XDIGIO_TIME_OUT)) { |
2c89e159 GKH |
140 | timeout++; |
141 | } | |
142 | ||
143 | } | |
144 | ||
145 | static void C6X_pwmOutput(unsigned long baseAddr, unsigned channel, int value) | |
146 | { | |
147 | unsigned ppcmd; | |
148 | union pwmcmdtype pwm; | |
149 | int timeout = 0; | |
150 | unsigned tmp; | |
151 | ||
6a438139 | 152 | /* printk("Inside C6X_pwmOutput\n"); */ |
2c89e159 GKH |
153 | |
154 | pwm.cmd = value; | |
155 | if (pwm.cmd > 498) | |
156 | pwm.cmd = 498; | |
157 | if (pwm.cmd < 2) | |
158 | pwm.cmd = 2; | |
159 | ||
160 | if (channel == 0) { | |
161 | ppcmd = 0x28; | |
6a438139 | 162 | } else { /* if channel == 1 */ |
2c89e159 GKH |
163 | ppcmd = 0x30; |
164 | } /* endif */ | |
165 | ||
166 | WriteByteToHwPort(baseAddr, ppcmd + pwm.bits.sb0); | |
167 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
168 | while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) { | |
169 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
170 | timeout++; | |
171 | } | |
172 | ||
173 | WriteByteToHwPort(baseAddr, ppcmd + pwm.bits.sb1 + 0x4); | |
174 | timeout = 0; | |
175 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
176 | while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) { | |
177 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
178 | timeout++; | |
179 | } | |
180 | ||
181 | WriteByteToHwPort(baseAddr, ppcmd + pwm.bits.sb2); | |
182 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
183 | while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) { | |
184 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
185 | timeout++; | |
186 | } | |
187 | ||
188 | WriteByteToHwPort(baseAddr, ppcmd + pwm.bits.sb3 + 0x4); | |
189 | timeout = 0; | |
190 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
191 | while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) { | |
192 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
193 | timeout++; | |
194 | } | |
195 | ||
196 | WriteByteToHwPort(baseAddr, ppcmd + pwm.bits.sb4); | |
197 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
198 | while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) { | |
199 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
200 | timeout++; | |
201 | } | |
202 | ||
203 | WriteByteToHwPort(baseAddr, 0x0); | |
204 | timeout = 0; | |
205 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
206 | while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) { | |
207 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
208 | timeout++; | |
209 | } | |
210 | ||
211 | } | |
212 | ||
213 | static int C6X_encInput(unsigned long baseAddr, unsigned channel) | |
214 | { | |
215 | unsigned ppcmd; | |
216 | union encvaluetype enc; | |
217 | int timeout = 0; | |
218 | int tmp; | |
219 | ||
6a438139 | 220 | /* printk("Inside C6X_encInput\n"); */ |
2c89e159 GKH |
221 | |
222 | enc.value = 0; | |
23d53b17 | 223 | if (channel == 0) |
2c89e159 | 224 | ppcmd = 0x48; |
23d53b17 | 225 | else |
2c89e159 | 226 | ppcmd = 0x50; |
23d53b17 | 227 | |
2c89e159 GKH |
228 | WriteByteToHwPort(baseAddr, ppcmd); |
229 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
230 | while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) { | |
231 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
232 | timeout++; | |
233 | } | |
234 | ||
235 | enc.bits.sb0 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7); | |
236 | WriteByteToHwPort(baseAddr, ppcmd + 0x4); | |
237 | timeout = 0; | |
238 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
239 | while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) { | |
240 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
241 | timeout++; | |
242 | } | |
243 | enc.bits.sb1 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7); | |
244 | WriteByteToHwPort(baseAddr, ppcmd); | |
245 | timeout = 0; | |
246 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
247 | while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) { | |
248 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
249 | timeout++; | |
250 | } | |
251 | enc.bits.sb2 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7); | |
252 | WriteByteToHwPort(baseAddr, ppcmd + 0x4); | |
253 | timeout = 0; | |
254 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
255 | while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) { | |
256 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
257 | timeout++; | |
258 | } | |
259 | enc.bits.sb3 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7); | |
260 | WriteByteToHwPort(baseAddr, ppcmd); | |
261 | timeout = 0; | |
262 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
263 | while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) { | |
264 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
265 | timeout++; | |
266 | } | |
267 | enc.bits.sb4 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7); | |
268 | WriteByteToHwPort(baseAddr, ppcmd + 0x4); | |
269 | timeout = 0; | |
270 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
271 | while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) { | |
272 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
273 | timeout++; | |
274 | } | |
275 | enc.bits.sb5 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7); | |
276 | WriteByteToHwPort(baseAddr, ppcmd); | |
277 | timeout = 0; | |
278 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
279 | while (((tmp & 0x80) == 0x0) && (timeout < C6XDIGIO_TIME_OUT)) { | |
280 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
281 | timeout++; | |
282 | } | |
283 | enc.bits.sb6 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7); | |
284 | WriteByteToHwPort(baseAddr, ppcmd + 0x4); | |
285 | timeout = 0; | |
286 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
287 | while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) { | |
288 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
289 | timeout++; | |
290 | } | |
291 | enc.bits.sb7 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7); | |
292 | WriteByteToHwPort(baseAddr, ppcmd); | |
293 | timeout = 0; | |
294 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
295 | while (((tmp & 0x80) == 0x0) && (timeout < C6XDIGIO_TIME_OUT)) { | |
296 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
297 | timeout++; | |
298 | } | |
299 | ||
300 | WriteByteToHwPort(baseAddr, 0x0); | |
301 | timeout = 0; | |
302 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
303 | while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) { | |
304 | tmp = ReadByteFromHwPort(baseAddr + 1); | |
305 | timeout++; | |
306 | } | |
307 | ||
dae0dc30 | 308 | return enc.value ^ 0x800000; |
2c89e159 GKH |
309 | } |
310 | ||
311 | static void C6X_encResetAll(unsigned long baseAddr) | |
312 | { | |
313 | unsigned timeout = 0; | |
314 | ||
6a438139 | 315 | /* printk("Inside C6X_encResetAll\n"); */ |
2c89e159 GKH |
316 | |
317 | WriteByteToHwPort(baseAddr, 0x68); | |
318 | while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0) | |
0a85b6f0 | 319 | && (timeout < C6XDIGIO_TIME_OUT)) { |
2c89e159 GKH |
320 | timeout++; |
321 | } | |
322 | WriteByteToHwPort(baseAddr, 0x6C); | |
323 | timeout = 0; | |
324 | while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x80) | |
0a85b6f0 | 325 | && (timeout < C6XDIGIO_TIME_OUT)) { |
2c89e159 GKH |
326 | timeout++; |
327 | } | |
328 | WriteByteToHwPort(baseAddr, 0x68); | |
329 | timeout = 0; | |
330 | while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x0) | |
0a85b6f0 | 331 | && (timeout < C6XDIGIO_TIME_OUT)) { |
2c89e159 GKH |
332 | timeout++; |
333 | } | |
334 | WriteByteToHwPort(baseAddr, 0x0); | |
335 | timeout = 0; | |
336 | while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x80) | |
0a85b6f0 | 337 | && (timeout < C6XDIGIO_TIME_OUT)) { |
2c89e159 GKH |
338 | timeout++; |
339 | } | |
340 | } | |
341 | ||
da91b269 | 342 | static int c6xdigio_pwmo_insn_read(struct comedi_device *dev, |
0a85b6f0 MT |
343 | struct comedi_subdevice *s, |
344 | struct comedi_insn *insn, unsigned int *data) | |
2c89e159 GKH |
345 | { |
346 | printk("c6xdigio_pwmo_insn_read %x\n", insn->n); | |
347 | return insn->n; | |
348 | } | |
349 | ||
da91b269 | 350 | static int c6xdigio_pwmo_insn_write(struct comedi_device *dev, |
0a85b6f0 MT |
351 | struct comedi_subdevice *s, |
352 | struct comedi_insn *insn, | |
353 | unsigned int *data) | |
2c89e159 GKH |
354 | { |
355 | int i; | |
356 | int chan = CR_CHAN(insn->chanspec); | |
357 | ||
6a438139 | 358 | /* printk("c6xdigio_pwmo_insn_write %x\n", insn->n); */ |
2c89e159 GKH |
359 | for (i = 0; i < insn->n; i++) { |
360 | C6X_pwmOutput(dev->iobase, chan, data[i]); | |
361 | /* devpriv->ao_readback[chan] = data[i]; */ | |
362 | } | |
363 | return i; | |
364 | } | |
365 | ||
6a438139 BP |
366 | /* static int c6xdigio_ei_init_insn_read(struct comedi_device *dev, */ |
367 | /* struct comedi_subdevice *s, */ | |
368 | /* struct comedi_insn *insn, */ | |
369 | /* unsigned int *data) */ | |
370 | /* { */ | |
371 | /* printk("c6xdigio_ei_init_insn_read %x\n", insn->n); */ | |
372 | /* return insn->n; */ | |
373 | /* } */ | |
374 | ||
375 | /* static int c6xdigio_ei_init_insn_write(struct comedi_device *dev, */ | |
376 | /* struct comedi_subdevice *s, */ | |
377 | /* struct comedi_insn *insn, */ | |
378 | /* unsigned int *data) */ | |
379 | /* { */ | |
380 | /* int i; */ | |
381 | /* int chan = CR_CHAN(insn->chanspec); */ | |
0a85b6f0 MT |
382 | /* *//* C6X_encResetAll( dev->iobase ); */ |
383 | /* *//* return insn->n; */ | |
6a438139 | 384 | /* } */ |
2c89e159 | 385 | |
da91b269 | 386 | static int c6xdigio_ei_insn_read(struct comedi_device *dev, |
0a85b6f0 MT |
387 | struct comedi_subdevice *s, |
388 | struct comedi_insn *insn, unsigned int *data) | |
2c89e159 | 389 | { |
6a438139 | 390 | /* printk("c6xdigio_ei__insn_read %x\n", insn->n); */ |
2c89e159 GKH |
391 | int n; |
392 | int chan = CR_CHAN(insn->chanspec); | |
393 | ||
23d53b17 | 394 | for (n = 0; n < insn->n; n++) |
2c89e159 | 395 | data[n] = (C6X_encInput(dev->iobase, chan) & 0xffffff); |
2c89e159 GKH |
396 | |
397 | return n; | |
398 | } | |
399 | ||
da91b269 | 400 | static void board_init(struct comedi_device *dev) |
2c89e159 GKH |
401 | { |
402 | ||
6a438139 | 403 | /* printk("Inside board_init\n"); */ |
2c89e159 GKH |
404 | |
405 | C6X_pwmInit(dev->iobase); | |
406 | C6X_encResetAll(dev->iobase); | |
407 | ||
408 | } | |
409 | ||
6a438139 BP |
410 | /* static void board_halt(struct comedi_device *dev) { */ |
411 | /* C6X_pwmInit(dev->iobase); */ | |
412 | /* } */ | |
2c89e159 GKH |
413 | |
414 | /* | |
415 | options[0] - I/O port | |
416 | options[1] - irq | |
417 | options[2] - number of encoder chips installed | |
418 | */ | |
419 | ||
420 | static const struct pnp_device_id c6xdigio_pnp_tbl[] = { | |
421 | /* Standard LPT Printer Port */ | |
23d53b17 | 422 | {.id = "PNP0400", .driver_data = 0}, |
2c89e159 | 423 | /* ECP Printer Port */ |
23d53b17 | 424 | {.id = "PNP0401", .driver_data = 0}, |
2c89e159 GKH |
425 | {} |
426 | }; | |
427 | ||
428 | static struct pnp_driver c6xdigio_pnp_driver = { | |
429 | .name = "c6xdigio", | |
430 | .id_table = c6xdigio_pnp_tbl, | |
431 | }; | |
432 | ||
0a85b6f0 MT |
433 | static int c6xdigio_attach(struct comedi_device *dev, |
434 | struct comedi_devconfig *it) | |
2c89e159 GKH |
435 | { |
436 | int result = 0; | |
437 | unsigned long iobase; | |
438 | unsigned int irq; | |
34c43922 | 439 | struct comedi_subdevice *s; |
2c89e159 GKH |
440 | |
441 | iobase = it->options[0]; | |
442 | printk("comedi%d: c6xdigio: 0x%04lx\n", dev->minor, iobase); | |
443 | if (!request_region(iobase, C6XDIGIO_SIZE, "c6xdigio")) { | |
444 | printk("comedi%d: I/O port conflict\n", dev->minor); | |
445 | return -EIO; | |
446 | } | |
447 | dev->iobase = iobase; | |
448 | dev->board_name = "c6xdigio"; | |
449 | ||
6a438139 | 450 | result = alloc_subdevices(dev, 2); /* 3 with encoder_init write */ |
2c89e159 GKH |
451 | if (result < 0) |
452 | return result; | |
453 | ||
23d53b17 | 454 | /* Make sure that PnP ports get activated */ |
2c89e159 GKH |
455 | pnp_register_driver(&c6xdigio_pnp_driver); |
456 | ||
457 | irq = it->options[1]; | |
23d53b17 | 458 | if (irq > 0) |
2c89e159 | 459 | printk("comedi%d: irq = %u ignored\n", dev->minor, irq); |
23d53b17 | 460 | else if (irq == 0) |
2c89e159 | 461 | printk("comedi%d: no irq\n", dev->minor); |
2c89e159 GKH |
462 | |
463 | s = dev->subdevices + 0; | |
464 | /* pwm output subdevice */ | |
6a438139 | 465 | s->type = COMEDI_SUBD_AO; /* Not sure what to put here */ |
2c89e159 GKH |
466 | s->subdev_flags = SDF_WRITEABLE; |
467 | s->n_chan = 2; | |
468 | /* s->trig[0] = c6xdigio_pwmo; */ | |
469 | s->insn_read = c6xdigio_pwmo_insn_read; | |
470 | s->insn_write = c6xdigio_pwmo_insn_write; | |
471 | s->maxdata = 500; | |
6a438139 | 472 | s->range_table = &range_bipolar10; /* A suitable lie */ |
2c89e159 GKH |
473 | |
474 | s = dev->subdevices + 1; | |
475 | /* encoder (counter) subdevice */ | |
476 | s->type = COMEDI_SUBD_COUNTER; | |
477 | s->subdev_flags = SDF_READABLE | SDF_LSAMPL; | |
478 | s->n_chan = 2; | |
479 | /* s->trig[0] = c6xdigio_ei; */ | |
480 | s->insn_read = c6xdigio_ei_insn_read; | |
481 | s->maxdata = 0xffffff; | |
482 | s->range_table = &range_unknown; | |
483 | ||
23d53b17 | 484 | /* s = dev->subdevices + 2; */ |
0a85b6f0 | 485 | /* pwm output subdevice */ |
23d53b17 BA |
486 | /* s->type = COMEDI_SUBD_COUNTER; // Not sure what to put here */ |
487 | /* s->subdev_flags = SDF_WRITEABLE; */ | |
488 | /* s->n_chan = 1; */ | |
489 | /* s->trig[0] = c6xdigio_ei_init; */ | |
490 | /* s->insn_read = c6xdigio_ei_init_insn_read; */ | |
491 | /* s->insn_write = c6xdigio_ei_init_insn_write; */ | |
492 | /* s->maxdata = 0xFFFF; // Really just a don't care */ | |
493 | /* s->range_table = &range_unknown; // Not sure what to put here */ | |
494 | ||
495 | /* I will call this init anyway but more than likely the DSP board */ | |
496 | /* will not be connected when device driver is loaded. */ | |
2c89e159 GKH |
497 | board_init(dev); |
498 | ||
499 | return 0; | |
500 | } | |
501 | ||
da91b269 | 502 | static int c6xdigio_detach(struct comedi_device *dev) |
2c89e159 | 503 | { |
23d53b17 | 504 | /* board_halt(dev); may not need this */ |
2c89e159 GKH |
505 | |
506 | printk("comedi%d: c6xdigio: remove\n", dev->minor); | |
507 | ||
23d53b17 | 508 | if (dev->iobase) |
2c89e159 | 509 | release_region(dev->iobase, C6XDIGIO_SIZE); |
23d53b17 BA |
510 | |
511 | /* Not using IRQ so I am not sure if I need this */ | |
512 | if (dev->irq) | |
2c89e159 | 513 | free_irq(dev->irq, dev); |
23d53b17 | 514 | |
2c89e159 GKH |
515 | pnp_unregister_driver(&c6xdigio_pnp_driver); |
516 | ||
517 | return 0; | |
518 | } | |
519 | ||
7114a280 AT |
520 | static int __init driver_c6xdigio_init_module(void) |
521 | { | |
522 | return comedi_driver_register(&driver_c6xdigio); | |
523 | } | |
524 | ||
525 | static void __exit driver_c6xdigio_cleanup_module(void) | |
526 | { | |
527 | comedi_driver_unregister(&driver_c6xdigio); | |
528 | } | |
529 | ||
530 | module_init(driver_c6xdigio_init_module); | |
531 | module_exit(driver_c6xdigio_cleanup_module); | |
90f703d3 AT |
532 | |
533 | MODULE_AUTHOR("Comedi http://www.comedi.org"); | |
534 | MODULE_DESCRIPTION("Comedi low-level driver"); | |
535 | MODULE_LICENSE("GPL"); |