Staging: comedi: Remove comedi_insn typedef
[deliverable/linux.git] / drivers / staging / comedi / drivers / cb_das16_cs.c
1 /*
2 comedi/drivers/das16cs.c
3 Driver for Computer Boards PC-CARD DAS16/16.
4
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 2000, 2001, 2002 David A. Schleef <ds@schleef.org>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 */
23 /*
24 Driver: cb_das16_cs
25 Description: Computer Boards PC-CARD DAS16/16
26 Devices: [ComputerBoards] PC-CARD DAS16/16 (cb_das16_cs), PC-CARD DAS16/16-AO
27 Author: ds
28 Updated: Mon, 04 Nov 2002 20:04:21 -0800
29 Status: experimental
30
31
32 */
33
34 #include "../comedidev.h"
35 #include <linux/delay.h>
36 #include <linux/pci.h>
37
38 #include <pcmcia/cs_types.h>
39 #include <pcmcia/cs.h>
40 #include <pcmcia/cistpl.h>
41 #include <pcmcia/ds.h>
42
43 #include "8253.h"
44
45 #define DAS16CS_SIZE 18
46
47 #define DAS16CS_ADC_DATA 0
48 #define DAS16CS_DIO_MUX 2
49 #define DAS16CS_MISC1 4
50 #define DAS16CS_MISC2 6
51 #define DAS16CS_CTR0 8
52 #define DAS16CS_CTR1 10
53 #define DAS16CS_CTR2 12
54 #define DAS16CS_CTR_CONTROL 14
55 #define DAS16CS_DIO 16
56
57 typedef struct das16cs_board_struct {
58 const char *name;
59 int device_id;
60 int n_ao_chans;
61 } das16cs_board;
62 static const das16cs_board das16cs_boards[] = {
63 {
64 device_id:0x0000,/* unknown */
65 name: "PC-CARD DAS16/16",
66 n_ao_chans:0,
67 },
68 {
69 device_id:0x0039,
70 name: "PC-CARD DAS16/16-AO",
71 n_ao_chans:2,
72 },
73 {
74 device_id:0x4009,
75 name: "PCM-DAS16s/16",
76 n_ao_chans:0,
77 },
78 };
79
80 #define n_boards (sizeof(das16cs_boards)/sizeof(das16cs_boards[0]))
81 #define thisboard ((const das16cs_board *)dev->board_ptr)
82
83 typedef struct {
84 struct pcmcia_device *link;
85
86 unsigned int ao_readback[2];
87 unsigned short status1;
88 unsigned short status2;
89 } das16cs_private;
90 #define devpriv ((das16cs_private *)dev->private)
91
92 static int das16cs_attach(struct comedi_device * dev, comedi_devconfig * it);
93 static int das16cs_detach(struct comedi_device * dev);
94 static struct comedi_driver driver_das16cs = {
95 driver_name:"cb_das16_cs",
96 module:THIS_MODULE,
97 attach:das16cs_attach,
98 detach:das16cs_detach,
99 };
100
101 static struct pcmcia_device *cur_dev = NULL;
102
103 static const struct comedi_lrange das16cs_ai_range = { 4, {
104 RANGE(-10, 10),
105 RANGE(-5, 5),
106 RANGE(-2.5, 2.5),
107 RANGE(-1.25, 1.25),
108 }
109 };
110
111 static irqreturn_t das16cs_interrupt(int irq, void *d PT_REGS_ARG);
112 static int das16cs_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
113 struct comedi_insn * insn, unsigned int * data);
114 static int das16cs_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
115 static int das16cs_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
116 struct comedi_cmd * cmd);
117 static int das16cs_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
118 struct comedi_insn * insn, unsigned int * data);
119 static int das16cs_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
120 struct comedi_insn * insn, unsigned int * data);
121 static int das16cs_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
122 struct comedi_insn * insn, unsigned int * data);
123 static int das16cs_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
124 struct comedi_insn * insn, unsigned int * data);
125 static int das16cs_timer_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
126 struct comedi_insn * insn, unsigned int * data);
127 static int das16cs_timer_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
128 struct comedi_insn * insn, unsigned int * data);
129
130 static int get_prodid(struct comedi_device * dev, struct pcmcia_device *link)
131 {
132 tuple_t tuple;
133 u_short buf[128];
134 int prodid = 0;
135
136 tuple.TupleData = (cisdata_t *) buf;
137 tuple.TupleOffset = 0;
138 tuple.TupleDataMax = 255;
139 tuple.DesiredTuple = CISTPL_MANFID;
140 tuple.Attributes = TUPLE_RETURN_COMMON;
141 if ((pcmcia_get_first_tuple(link, &tuple) == 0) &&
142 (pcmcia_get_tuple_data(link, &tuple) == 0)) {
143 prodid = le16_to_cpu(buf[1]);
144 }
145
146 return prodid;
147 }
148
149 static const das16cs_board *das16cs_probe(struct comedi_device * dev,
150 struct pcmcia_device *link)
151 {
152 int id;
153 int i;
154
155 id = get_prodid(dev, link);
156
157 for (i = 0; i < n_boards; i++) {
158 if (das16cs_boards[i].device_id == id) {
159 return das16cs_boards + i;
160 }
161 }
162
163 printk("unknown board!\n");
164
165 return NULL;
166 }
167
168 static int das16cs_attach(struct comedi_device * dev, comedi_devconfig * it)
169 {
170 struct pcmcia_device *link;
171 struct comedi_subdevice *s;
172 int ret;
173 int i;
174
175 printk("comedi%d: cb_das16_cs: ", dev->minor);
176
177 link = cur_dev; /* XXX hack */
178 if (!link)
179 return -EIO;
180
181 dev->iobase = link->io.BasePort1;
182 printk("I/O base=0x%04lx ", dev->iobase);
183
184 printk("fingerprint:\n");
185 for (i = 0; i < 48; i += 2) {
186 printk("%04x ", inw(dev->iobase + i));
187 }
188 printk("\n");
189
190 ret = comedi_request_irq(link->irq.AssignedIRQ, das16cs_interrupt,
191 IRQF_SHARED, "cb_das16_cs", dev);
192 if (ret < 0) {
193 return ret;
194 }
195 dev->irq = link->irq.AssignedIRQ;
196 printk("irq=%u ", dev->irq);
197
198 dev->board_ptr = das16cs_probe(dev, link);
199 if (!dev->board_ptr)
200 return -EIO;
201
202 dev->board_name = thisboard->name;
203
204 if (alloc_private(dev, sizeof(das16cs_private)) < 0)
205 return -ENOMEM;
206
207 if (alloc_subdevices(dev, 4) < 0)
208 return -ENOMEM;
209
210 s = dev->subdevices + 0;
211 dev->read_subdev = s;
212 /* analog input subdevice */
213 s->type = COMEDI_SUBD_AI;
214 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
215 s->n_chan = 16;
216 s->maxdata = 0xffff;
217 s->range_table = &das16cs_ai_range;
218 s->len_chanlist = 16;
219 s->insn_read = das16cs_ai_rinsn;
220 s->do_cmd = das16cs_ai_cmd;
221 s->do_cmdtest = das16cs_ai_cmdtest;
222
223 s = dev->subdevices + 1;
224 /* analog output subdevice */
225 if (thisboard->n_ao_chans) {
226 s->type = COMEDI_SUBD_AO;
227 s->subdev_flags = SDF_WRITABLE;
228 s->n_chan = thisboard->n_ao_chans;
229 s->maxdata = 0xffff;
230 s->range_table = &range_bipolar10;
231 s->insn_write = &das16cs_ao_winsn;
232 s->insn_read = &das16cs_ao_rinsn;
233 }
234
235 s = dev->subdevices + 2;
236 /* digital i/o subdevice */
237 if (1) {
238 s->type = COMEDI_SUBD_DIO;
239 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
240 s->n_chan = 8;
241 s->maxdata = 1;
242 s->range_table = &range_digital;
243 s->insn_bits = das16cs_dio_insn_bits;
244 s->insn_config = das16cs_dio_insn_config;
245 } else {
246 s->type = COMEDI_SUBD_UNUSED;
247 }
248
249 s = dev->subdevices + 3;
250 /* timer subdevice */
251 if (0) {
252 s->type = COMEDI_SUBD_TIMER;
253 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
254 s->n_chan = 1;
255 s->maxdata = 0xff;
256 s->range_table = &range_unknown;
257 s->insn_read = das16cs_timer_insn_read;
258 s->insn_config = das16cs_timer_insn_config;
259 } else {
260 s->type = COMEDI_SUBD_UNUSED;
261 }
262
263 printk("attached\n");
264
265 return 1;
266 }
267
268 static int das16cs_detach(struct comedi_device * dev)
269 {
270 printk("comedi%d: das16cs: remove\n", dev->minor);
271
272 if (dev->irq) {
273 comedi_free_irq(dev->irq, dev);
274 }
275
276 return 0;
277 }
278
279 static irqreturn_t das16cs_interrupt(int irq, void *d PT_REGS_ARG)
280 {
281 //struct comedi_device *dev = d;
282 return IRQ_HANDLED;
283 }
284
285 /*
286 * "instructions" read/write data in "one-shot" or "software-triggered"
287 * mode.
288 */
289 static int das16cs_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
290 struct comedi_insn * insn, unsigned int * data)
291 {
292 int i;
293 int to;
294 int aref;
295 int range;
296 int chan;
297 static int range_bits[] = { 0x800, 0x000, 0x100, 0x200 };
298
299 chan = CR_CHAN(insn->chanspec);
300 aref = CR_AREF(insn->chanspec);
301 range = CR_RANGE(insn->chanspec);
302
303 outw(chan, dev->iobase + 2);
304
305 devpriv->status1 &= ~0xf320;
306 devpriv->status1 |= (aref == AREF_DIFF) ? 0 : 0x0020;
307 outw(devpriv->status1, dev->iobase + 4);
308
309 devpriv->status2 &= ~0xff00;
310 devpriv->status2 |= range_bits[range];
311 outw(devpriv->status2, dev->iobase + 6);
312
313 for (i = 0; i < insn->n; i++) {
314 outw(0, dev->iobase);
315
316 #define TIMEOUT 1000
317 for (to = 0; to < TIMEOUT; to++) {
318 if (inw(dev->iobase + 4) & 0x0080)
319 break;
320 }
321 if (to == TIMEOUT) {
322 printk("cb_das16_cs: ai timeout\n");
323 return -ETIME;
324 }
325 data[i] = (unsigned short)inw(dev->iobase + 0);
326 }
327
328 return i;
329 }
330
331 static int das16cs_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
332 {
333 return -EINVAL;
334 }
335
336 static int das16cs_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
337 struct comedi_cmd * cmd)
338 {
339 int err = 0;
340 int tmp;
341
342 /* cmdtest tests a particular command to see if it is valid.
343 * Using the cmdtest ioctl, a user can create a valid cmd
344 * and then have it executes by the cmd ioctl.
345 *
346 * cmdtest returns 1,2,3,4 or 0, depending on which tests
347 * the command passes. */
348
349 /* step 1: make sure trigger sources are trivially valid */
350
351 tmp = cmd->start_src;
352 cmd->start_src &= TRIG_NOW;
353 if (!cmd->start_src || tmp != cmd->start_src)
354 err++;
355
356 tmp = cmd->scan_begin_src;
357 cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
358 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
359 err++;
360
361 tmp = cmd->convert_src;
362 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
363 if (!cmd->convert_src || tmp != cmd->convert_src)
364 err++;
365
366 tmp = cmd->scan_end_src;
367 cmd->scan_end_src &= TRIG_COUNT;
368 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
369 err++;
370
371 tmp = cmd->stop_src;
372 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
373 if (!cmd->stop_src || tmp != cmd->stop_src)
374 err++;
375
376 if (err)
377 return 1;
378
379 /* step 2: make sure trigger sources are unique and mutually compatible */
380
381 /* note that mutual compatiblity is not an issue here */
382 if (cmd->scan_begin_src != TRIG_TIMER &&
383 cmd->scan_begin_src != TRIG_EXT)
384 err++;
385 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
386 err++;
387 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
388 err++;
389
390 if (err)
391 return 2;
392
393 /* step 3: make sure arguments are trivially compatible */
394
395 if (cmd->start_arg != 0) {
396 cmd->start_arg = 0;
397 err++;
398 }
399 #define MAX_SPEED 10000 /* in nanoseconds */
400 #define MIN_SPEED 1000000000 /* in nanoseconds */
401
402 if (cmd->scan_begin_src == TRIG_TIMER) {
403 if (cmd->scan_begin_arg < MAX_SPEED) {
404 cmd->scan_begin_arg = MAX_SPEED;
405 err++;
406 }
407 if (cmd->scan_begin_arg > MIN_SPEED) {
408 cmd->scan_begin_arg = MIN_SPEED;
409 err++;
410 }
411 } else {
412 /* external trigger */
413 /* should be level/edge, hi/lo specification here */
414 /* should specify multiple external triggers */
415 if (cmd->scan_begin_arg > 9) {
416 cmd->scan_begin_arg = 9;
417 err++;
418 }
419 }
420 if (cmd->convert_src == TRIG_TIMER) {
421 if (cmd->convert_arg < MAX_SPEED) {
422 cmd->convert_arg = MAX_SPEED;
423 err++;
424 }
425 if (cmd->convert_arg > MIN_SPEED) {
426 cmd->convert_arg = MIN_SPEED;
427 err++;
428 }
429 } else {
430 /* external trigger */
431 /* see above */
432 if (cmd->convert_arg > 9) {
433 cmd->convert_arg = 9;
434 err++;
435 }
436 }
437
438 if (cmd->scan_end_arg != cmd->chanlist_len) {
439 cmd->scan_end_arg = cmd->chanlist_len;
440 err++;
441 }
442 if (cmd->stop_src == TRIG_COUNT) {
443 if (cmd->stop_arg > 0x00ffffff) {
444 cmd->stop_arg = 0x00ffffff;
445 err++;
446 }
447 } else {
448 /* TRIG_NONE */
449 if (cmd->stop_arg != 0) {
450 cmd->stop_arg = 0;
451 err++;
452 }
453 }
454
455 if (err)
456 return 3;
457
458 /* step 4: fix up any arguments */
459
460 if (cmd->scan_begin_src == TRIG_TIMER) {
461 unsigned int div1, div2;
462
463 tmp = cmd->scan_begin_arg;
464 i8253_cascade_ns_to_timer(100, &div1, &div2,
465 &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK);
466 if (tmp != cmd->scan_begin_arg)
467 err++;
468 }
469 if (cmd->convert_src == TRIG_TIMER) {
470 unsigned int div1, div2;
471
472 tmp = cmd->convert_arg;
473 i8253_cascade_ns_to_timer(100, &div1, &div2,
474 &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK);
475 if (tmp != cmd->convert_arg)
476 err++;
477 if (cmd->scan_begin_src == TRIG_TIMER &&
478 cmd->scan_begin_arg <
479 cmd->convert_arg * cmd->scan_end_arg) {
480 cmd->scan_begin_arg =
481 cmd->convert_arg * cmd->scan_end_arg;
482 err++;
483 }
484 }
485
486 if (err)
487 return 4;
488
489 return 0;
490 }
491
492 static int das16cs_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
493 struct comedi_insn * insn, unsigned int * data)
494 {
495 int i;
496 int chan = CR_CHAN(insn->chanspec);
497 unsigned short status1;
498 unsigned short d;
499 int bit;
500
501 for (i = 0; i < insn->n; i++) {
502 devpriv->ao_readback[chan] = data[i];
503 d = data[i];
504
505 outw(devpriv->status1, dev->iobase + 4);
506 comedi_udelay(1);
507
508 status1 = devpriv->status1 & ~0xf;
509 if (chan)
510 status1 |= 0x0001;
511 else
512 status1 |= 0x0008;
513
514 /* printk("0x%04x\n",status1);*/
515 outw(status1, dev->iobase + 4);
516 comedi_udelay(1);
517
518 for (bit = 15; bit >= 0; bit--) {
519 int b = (d >> bit) & 0x1;
520 b <<= 1;
521 /* printk("0x%04x\n",status1 | b | 0x0000);*/
522 outw(status1 | b | 0x0000, dev->iobase + 4);
523 comedi_udelay(1);
524 /* printk("0x%04x\n",status1 | b | 0x0004);*/
525 outw(status1 | b | 0x0004, dev->iobase + 4);
526 comedi_udelay(1);
527 }
528 /* make high both DAC0CS and DAC1CS to load
529 new data and update analog output*/
530 outw(status1 | 0x9, dev->iobase + 4);
531 }
532
533 return i;
534 }
535
536 /* AO subdevices should have a read insn as well as a write insn.
537 * Usually this means copying a value stored in devpriv. */
538 static int das16cs_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
539 struct comedi_insn * insn, unsigned int * data)
540 {
541 int i;
542 int chan = CR_CHAN(insn->chanspec);
543
544 for (i = 0; i < insn->n; i++)
545 data[i] = devpriv->ao_readback[chan];
546
547 return i;
548 }
549
550 /* DIO devices are slightly special. Although it is possible to
551 * implement the insn_read/insn_write interface, it is much more
552 * useful to applications if you implement the insn_bits interface.
553 * This allows packed reading/writing of the DIO channels. The
554 * comedi core can convert between insn_bits and insn_read/write */
555 static int das16cs_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
556 struct comedi_insn * insn, unsigned int * data)
557 {
558 if (insn->n != 2)
559 return -EINVAL;
560
561 if (data[0]) {
562 s->state &= ~data[0];
563 s->state |= data[0] & data[1];
564
565 outw(s->state, dev->iobase + 16);
566 }
567
568 /* on return, data[1] contains the value of the digital
569 * input and output lines. */
570 data[1] = inw(dev->iobase + 16);
571
572 return 2;
573 }
574
575 static int das16cs_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
576 struct comedi_insn * insn, unsigned int * data)
577 {
578 int chan = CR_CHAN(insn->chanspec);
579 int bits;
580
581 if (chan < 4)
582 bits = 0x0f;
583 else
584 bits = 0xf0;
585
586 switch (data[0]) {
587 case INSN_CONFIG_DIO_OUTPUT:
588 s->io_bits |= bits;
589 break;
590 case INSN_CONFIG_DIO_INPUT:
591 s->io_bits &= bits;
592 break;
593 case INSN_CONFIG_DIO_QUERY:
594 data[1] =
595 (s->
596 io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
597 return insn->n;
598 break;
599 default:
600 return -EINVAL;
601 break;
602 }
603
604 devpriv->status2 &= ~0x00c0;
605 devpriv->status2 |= (s->io_bits & 0xf0) ? 0x0080 : 0;
606 devpriv->status2 |= (s->io_bits & 0x0f) ? 0x0040 : 0;
607
608 outw(devpriv->status2, dev->iobase + 6);
609
610 return insn->n;
611 }
612
613 static int das16cs_timer_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
614 struct comedi_insn * insn, unsigned int * data)
615 {
616 return -EINVAL;
617 }
618
619 static int das16cs_timer_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
620 struct comedi_insn * insn, unsigned int * data)
621 {
622 return -EINVAL;
623 }
624
625 /* PCMCIA stuff */
626
627 /*======================================================================
628
629 The following pcmcia code for the pcm-das08 is adapted from the
630 dummy_cs.c driver of the Linux PCMCIA Card Services package.
631
632 The initial developer of the original code is David A. Hinds
633 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
634 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
635
636 ======================================================================*/
637
638 /*
639 All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
640 you do not define PCMCIA_DEBUG at all, all the debug code will be
641 left out. If you compile with PCMCIA_DEBUG=0, the debug code will
642 be present but disabled -- but it can then be enabled for specific
643 modules at load time with a 'pc_debug=#' option to insmod.
644 */
645 #if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
646
647 #ifdef PCMCIA_DEBUG
648 static int pc_debug = PCMCIA_DEBUG;
649 module_param(pc_debug, int, 0644);
650 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
651 static char *version =
652 "cb_das16_cs.c pcmcia code (David Schleef), modified from dummy_cs.c 1.31 2001/08/24 12:13:13 (David Hinds)";
653 #else
654 #define DEBUG(n, args...)
655 #endif
656
657 /*====================================================================*/
658
659 static void das16cs_pcmcia_config(struct pcmcia_device *link);
660 static void das16cs_pcmcia_release(struct pcmcia_device *link);
661 static int das16cs_pcmcia_suspend(struct pcmcia_device *p_dev);
662 static int das16cs_pcmcia_resume(struct pcmcia_device *p_dev);
663
664 /*
665 The attach() and detach() entry points are used to create and destroy
666 "instances" of the driver, where each instance represents everything
667 needed to manage one actual PCMCIA card.
668 */
669
670 static int das16cs_pcmcia_attach(struct pcmcia_device *);
671 static void das16cs_pcmcia_detach(struct pcmcia_device *);
672
673 /*
674 You'll also need to prototype all the functions that will actually
675 be used to talk to your device. See 'memory_cs' for a good example
676 of a fully self-sufficient driver; the other drivers rely more or
677 less on other parts of the kernel.
678 */
679
680 /*
681 The dev_info variable is the "key" that is used to match up this
682 device driver with appropriate cards, through the card configuration
683 database.
684 */
685
686 static dev_info_t dev_info = "cb_das16_cs";
687
688 typedef struct local_info_t {
689 struct pcmcia_device *link;
690 dev_node_t node;
691 int stop;
692 struct bus_operations *bus;
693 } local_info_t;
694
695 /*======================================================================
696
697 das16cs_pcmcia_attach() creates an "instance" of the driver, allocating
698 local data structures for one device. The device is registered
699 with Card Services.
700
701 The dev_link structure is initialized, but we don't actually
702 configure the card at this point -- we wait until we receive a
703 card insertion event.
704
705 ======================================================================*/
706
707 static int das16cs_pcmcia_attach(struct pcmcia_device *link)
708 {
709 local_info_t *local;
710
711 DEBUG(0, "das16cs_pcmcia_attach()\n");
712
713 /* Allocate space for private device-specific data */
714 local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
715 if (!local)
716 return -ENOMEM;
717 local->link = link;
718 link->priv = local;
719
720 /* Initialize the pcmcia_device structure */
721 /* Interrupt setup */
722 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
723 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
724 link->irq.Handler = NULL;
725
726 link->conf.Attributes = 0;
727 link->conf.IntType = INT_MEMORY_AND_IO;
728
729 cur_dev = link;
730
731 das16cs_pcmcia_config(link);
732
733 return 0;
734 } /* das16cs_pcmcia_attach */
735
736 static void das16cs_pcmcia_detach(struct pcmcia_device *link)
737 {
738 DEBUG(0, "das16cs_pcmcia_detach(0x%p)\n", link);
739
740 if (link->dev_node) {
741 ((local_info_t *) link->priv)->stop = 1;
742 das16cs_pcmcia_release(link);
743 }
744 /* This points to the parent local_info_t struct */
745 if (link->priv)
746 kfree(link->priv);
747 } /* das16cs_pcmcia_detach */
748
749 static void das16cs_pcmcia_config(struct pcmcia_device *link)
750 {
751 local_info_t *dev = link->priv;
752 tuple_t tuple;
753 cisparse_t parse;
754 int last_fn, last_ret;
755 u_char buf[64];
756 cistpl_cftable_entry_t dflt = { 0 };
757
758 DEBUG(0, "das16cs_pcmcia_config(0x%p)\n", link);
759
760 /*
761 This reads the card's CONFIG tuple to find its configuration
762 registers.
763 */
764 tuple.DesiredTuple = CISTPL_CONFIG;
765 tuple.Attributes = 0;
766 tuple.TupleData = buf;
767 tuple.TupleDataMax = sizeof(buf);
768 tuple.TupleOffset = 0;
769 last_fn = GetFirstTuple;
770 if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0)
771 goto cs_failed;
772 last_fn = GetTupleData;
773 if ((last_ret = pcmcia_get_tuple_data(link, &tuple)) != 0)
774 goto cs_failed;
775 last_fn = ParseTuple;
776 if ((last_ret = pcmcia_parse_tuple(link, &tuple, &parse)) != 0)
777 goto cs_failed;
778 link->conf.ConfigBase = parse.config.base;
779 link->conf.Present = parse.config.rmask[0];
780
781 /*
782 In this loop, we scan the CIS for configuration table entries,
783 each of which describes a valid card configuration, including
784 voltage, IO window, memory window, and interrupt settings.
785
786 We make no assumptions about the card to be configured: we use
787 just the information available in the CIS. In an ideal world,
788 this would work for any PCMCIA card, but it requires a complete
789 and accurate CIS. In practice, a driver usually "knows" most of
790 these things without consulting the CIS, and most client drivers
791 will only use the CIS to fill in implementation-defined details.
792 */
793 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
794 last_fn = GetFirstTuple;
795 if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0)
796 goto cs_failed;
797 while (1) {
798 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
799 if (pcmcia_get_tuple_data(link, &tuple))
800 goto next_entry;
801 if (pcmcia_parse_tuple(link, &tuple, &parse))
802 goto next_entry;
803
804 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
805 dflt = *cfg;
806 if (cfg->index == 0)
807 goto next_entry;
808 link->conf.ConfigIndex = cfg->index;
809
810 /* Does this card need audio output? */
811 /* if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
812 link->conf.Attributes |= CONF_ENABLE_SPKR;
813 link->conf.Status = CCSR_AUDIO_ENA;
814 }
815 */
816 /* Do we need to allocate an interrupt? */
817 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
818 link->conf.Attributes |= CONF_ENABLE_IRQ;
819
820 /* IO window settings */
821 link->io.NumPorts1 = link->io.NumPorts2 = 0;
822 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
823 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
824 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
825 if (!(io->flags & CISTPL_IO_8BIT))
826 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
827 if (!(io->flags & CISTPL_IO_16BIT))
828 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
829 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
830 link->io.BasePort1 = io->win[0].base;
831 link->io.NumPorts1 = io->win[0].len;
832 if (io->nwin > 1) {
833 link->io.Attributes2 = link->io.Attributes1;
834 link->io.BasePort2 = io->win[1].base;
835 link->io.NumPorts2 = io->win[1].len;
836 }
837 /* This reserves IO space but doesn't actually enable it */
838 if (pcmcia_request_io(link, &link->io))
839 goto next_entry;
840 }
841
842 /* If we got this far, we're cool! */
843 break;
844
845 next_entry:
846 last_fn = GetNextTuple;
847 if ((last_ret = pcmcia_get_next_tuple(link, &tuple)) != 0)
848 goto cs_failed;
849 }
850
851 /*
852 Allocate an interrupt line. Note that this does not assign a
853 handler to the interrupt, unless the 'Handler' member of the
854 irq structure is initialized.
855 */
856 if (link->conf.Attributes & CONF_ENABLE_IRQ) {
857 last_fn = RequestIRQ;
858 if ((last_ret = pcmcia_request_irq(link, &link->irq)) != 0)
859 goto cs_failed;
860 }
861 /*
862 This actually configures the PCMCIA socket -- setting up
863 the I/O windows and the interrupt mapping, and putting the
864 card and host interface into "Memory and IO" mode.
865 */
866 last_fn = RequestConfiguration;
867 if ((last_ret = pcmcia_request_configuration(link, &link->conf)) != 0)
868 goto cs_failed;
869
870 /*
871 At this point, the dev_node_t structure(s) need to be
872 initialized and arranged in a linked list at link->dev.
873 */
874 sprintf(dev->node.dev_name, "cb_das16_cs");
875 dev->node.major = dev->node.minor = 0;
876 link->dev_node = &dev->node;
877
878 /* Finally, report what we've done */
879 printk(KERN_INFO "%s: index 0x%02x",
880 dev->node.dev_name, link->conf.ConfigIndex);
881 if (link->conf.Attributes & CONF_ENABLE_IRQ)
882 printk(", irq %u", link->irq.AssignedIRQ);
883 if (link->io.NumPorts1)
884 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
885 link->io.BasePort1 + link->io.NumPorts1 - 1);
886 if (link->io.NumPorts2)
887 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
888 link->io.BasePort2 + link->io.NumPorts2 - 1);
889 printk("\n");
890
891 return;
892
893 cs_failed:
894 cs_error(link, last_fn, last_ret);
895 das16cs_pcmcia_release(link);
896 } /* das16cs_pcmcia_config */
897
898 static void das16cs_pcmcia_release(struct pcmcia_device *link)
899 {
900 DEBUG(0, "das16cs_pcmcia_release(0x%p)\n", link);
901 pcmcia_disable_device(link);
902 } /* das16cs_pcmcia_release */
903
904 static int das16cs_pcmcia_suspend(struct pcmcia_device *link)
905 {
906 local_info_t *local = link->priv;
907
908 /* Mark the device as stopped, to block IO until later */
909 local->stop = 1;
910
911 return 0;
912 } /* das16cs_pcmcia_suspend */
913
914 static int das16cs_pcmcia_resume(struct pcmcia_device *link)
915 {
916 local_info_t *local = link->priv;
917
918 local->stop = 0;
919 return 0;
920 } /* das16cs_pcmcia_resume */
921
922 /*====================================================================*/
923
924 static struct pcmcia_device_id das16cs_id_table[] = {
925 PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x0039),
926 PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4009),
927 PCMCIA_DEVICE_NULL
928 };
929
930 MODULE_DEVICE_TABLE(pcmcia, das16cs_id_table);
931
932 struct pcmcia_driver das16cs_driver = {
933 .probe = das16cs_pcmcia_attach,
934 .remove = das16cs_pcmcia_detach,
935 .suspend = das16cs_pcmcia_suspend,
936 .resume = das16cs_pcmcia_resume,
937 .id_table = das16cs_id_table,
938 .owner = THIS_MODULE,
939 .drv = {
940 .name = dev_info,
941 },
942 };
943
944 static int __init init_das16cs_pcmcia_cs(void)
945 {
946 DEBUG(0, "%s\n", version);
947 pcmcia_register_driver(&das16cs_driver);
948 return 0;
949 }
950
951 static void __exit exit_das16cs_pcmcia_cs(void)
952 {
953 DEBUG(0, "das16cs_pcmcia_cs: unloading\n");
954 pcmcia_unregister_driver(&das16cs_driver);
955 }
956
957 int __init init_module(void)
958 {
959 int ret;
960
961 ret = init_das16cs_pcmcia_cs();
962 if (ret < 0)
963 return ret;
964
965 return comedi_driver_register(&driver_das16cs);
966 }
967
968 void __exit cleanup_module(void)
969 {
970 exit_das16cs_pcmcia_cs();
971 comedi_driver_unregister(&driver_das16cs);
972 }
973
974 #else
975 COMEDI_INITCLEANUP(driver_das16cs);
976 #endif //CONFIG_PCMCIA
This page took 0.058846 seconds and 5 git commands to generate.