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