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