Staging: comedi: Remove comedi_subdevice typedef
[pandora-kernel.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 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 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         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         comedi_cmd * cmd);
117 static int das16cs_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
118         comedi_insn * insn, unsigned int * data);
119 static int das16cs_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
120         comedi_insn * insn, unsigned int * data);
121 static int das16cs_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
122         comedi_insn * insn, unsigned int * data);
123 static int das16cs_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
124         comedi_insn * insn, unsigned int * data);
125 static int das16cs_timer_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
126         comedi_insn * insn, unsigned int * data);
127 static int das16cs_timer_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
128         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         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         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         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         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         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         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         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         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