blob: ec31a39706648a212083d1215e9e51bf2ea75519 [file] [log] [blame]
Fred Brooks1f9bbbe2009-02-19 10:05:01 -08001/*
2 * comedi/drivers/ni_daq_700.c
3 * Driver for DAQCard-700 DIO only
4 * copied from 8255
5 *
6 * COMEDI - Linux Control and Measurement Device Interface
7 * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25/*
26Driver: ni_daq_700
27Description: National Instruments PCMCIA DAQCard-700 DIO only
28Author: Fred Brooks <nsaspook@nsaspook.com>,
29 based on ni_daq_dio24 by Daniel Vecino Castel <dvecino@able.es>
30Devices: [National Instruments] PCMCIA DAQ-Card-700 (ni_daq_700)
31Status: works
32Updated: Thu, 21 Feb 2008 12:07:20 +0000
33
34The daqcard-700 appears in Comedi as a single digital I/O subdevice with
3516 channels. The channel 0 corresponds to the daqcard-700's output
36port, bit 0; channel 8 corresponds to the input port, bit 0.
37
38Direction configuration: channels 0-7 output, 8-15 input (8225 device
39emu as port A output, port B input, port C N/A).
40
41IRQ is assigned but not used.
42*/
43
Greg Kroah-Hartman25436dc2009-04-27 15:14:34 -070044#include <linux/interrupt.h>
Fred Brooks1f9bbbe2009-02-19 10:05:01 -080045#include "../comedidev.h"
46
47#include <linux/ioport.h>
Fred Brooks1f9bbbe2009-02-19 10:05:01 -080048
49#include <pcmcia/cs_types.h>
50#include <pcmcia/cs.h>
51#include <pcmcia/cistpl.h>
52#include <pcmcia/cisreg.h>
53#include <pcmcia/ds.h>
54
55static struct pcmcia_device *pcmcia_cur_dev = NULL;
56
Bill Pemberton2696fb52009-03-27 11:29:34 -040057#define DIO700_SIZE 8 /* size of io region used by board */
Fred Brooks1f9bbbe2009-02-19 10:05:01 -080058
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +053059static int dio700_attach(struct comedi_device *dev,
60 struct comedi_devconfig *it);
Bill Pembertonda91b262009-04-09 16:07:03 -040061static int dio700_detach(struct comedi_device *dev);
Fred Brooks1f9bbbe2009-02-19 10:05:01 -080062
63enum dio700_bustype { pcmcia_bustype };
64
Bill Pemberton4cab3742009-03-19 17:59:34 -040065struct dio700_board {
Fred Brooks1f9bbbe2009-02-19 10:05:01 -080066 const char *name;
Bill Pemberton2696fb52009-03-27 11:29:34 -040067 int device_id; /* device id for pcmcia board */
68 enum dio700_bustype bustype; /* PCMCIA */
69 int have_dio; /* have daqcard-700 dio */
70 /* function pointers so we can use inb/outb or readb/writeb */
71 /* as appropriate */
Fred Brooks1f9bbbe2009-02-19 10:05:01 -080072 unsigned int (*read_byte) (unsigned int address);
73 void (*write_byte) (unsigned int byte, unsigned int address);
Bill Pemberton4cab3742009-03-19 17:59:34 -040074};
Fred Brooks1f9bbbe2009-02-19 10:05:01 -080075
Bill Pemberton4cab3742009-03-19 17:59:34 -040076static const struct dio700_board dio700_boards[] = {
Fred Brooks1f9bbbe2009-02-19 10:05:01 -080077 {
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +053078 .name = "daqcard-700",
79 .device_id = 0x4743, /* 0x10b is manufacturer id, 0x4743 is device id */
80 .bustype = pcmcia_bustype,
81 .have_dio = 1,
82 },
Fred Brooks1f9bbbe2009-02-19 10:05:01 -080083 {
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +053084 .name = "ni_daq_700",
85 .device_id = 0x4743, /* 0x10b is manufacturer id, 0x4743 is device id */
86 .bustype = pcmcia_bustype,
87 .have_dio = 1,
88 },
Fred Brooks1f9bbbe2009-02-19 10:05:01 -080089};
90
91/*
92 * Useful for shorthand access to the particular board structure
93 */
Bill Pemberton4cab3742009-03-19 17:59:34 -040094#define thisboard ((const struct dio700_board *)dev->board_ptr)
Fred Brooks1f9bbbe2009-02-19 10:05:01 -080095
Bill Pembertonadf32842009-03-16 22:16:23 -040096struct dio700_private {
Fred Brooks1f9bbbe2009-02-19 10:05:01 -080097
Bill Pembertonadf32842009-03-16 22:16:23 -040098 int data; /* number of data points left to be taken */
99};
100
Bill Pembertonadf32842009-03-16 22:16:23 -0400101#define devpriv ((struct dio700_private *)dev->private)
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800102
Bill Pemberton139dfbd2009-03-16 22:05:25 -0400103static struct comedi_driver driver_dio700 = {
Bill Pemberton68c3dbf2009-04-22 21:11:49 -0400104 .driver_name = "ni_daq_700",
105 .module = THIS_MODULE,
106 .attach = dio700_attach,
107 .detach = dio700_detach,
Bill Pemberton8629efa2009-04-23 15:54:56 -0400108 .num_names = ARRAY_SIZE(dio700_boards),
Bill Pemberton68c3dbf2009-04-22 21:11:49 -0400109 .board_name = &dio700_boards[0].name,
110 .offset = sizeof(struct dio700_board),
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800111};
112
113/* the real driver routines */
114
115#define _700_SIZE 8
116
117#define _700_DATA 0
118
119#define DIO_W 0x04
120#define DIO_R 0x05
121
122struct subdev_700_struct {
123 unsigned long cb_arg;
124 int (*cb_func) (int, int, int, unsigned long);
125 int have_irq;
126};
127
128#define CALLBACK_ARG (((struct subdev_700_struct *)s->private)->cb_arg)
129#define CALLBACK_FUNC (((struct subdev_700_struct *)s->private)->cb_func)
130#define subdevpriv ((struct subdev_700_struct *)s->private)
131
Bill Pembertonda91b262009-04-09 16:07:03 -0400132static void do_config(struct comedi_device *dev, struct comedi_subdevice *s);
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800133
Bill Pembertonda91b262009-04-09 16:07:03 -0400134void subdev_700_interrupt(struct comedi_device *dev, struct comedi_subdevice *s)
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800135{
Bill Pemberton790c5542009-03-16 22:05:02 -0400136 short d;
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800137
138 d = CALLBACK_FUNC(0, _700_DATA, 0, CALLBACK_ARG);
139
140 comedi_buf_put(s->async, d);
141 s->async->events |= COMEDI_CB_EOS;
142
143 comedi_event(dev, s);
144}
145
146static int subdev_700_cb(int dir, int port, int data, unsigned long arg)
147{
148 /* port is always A for output and B for input (8255 emu) */
149 unsigned long iobase = arg;
150
151 if (dir) {
152 outb(data, iobase + DIO_W);
153 return 0;
154 } else {
155 return inb(iobase + DIO_R);
156 }
157}
158
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530159static int subdev_700_insn(struct comedi_device *dev,
160 struct comedi_subdevice *s, struct comedi_insn *insn,
161 unsigned int *data)
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800162{
163 if (data[0]) {
164 s->state &= ~data[0];
165 s->state |= (data[0] & data[1]);
166
167 if (data[0] & 0xff)
168 CALLBACK_FUNC(1, _700_DATA, s->state & 0xff,
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530169 CALLBACK_ARG);
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800170 }
171
172 data[1] = s->state & 0xff;
173 data[1] |= CALLBACK_FUNC(0, _700_DATA, 0, CALLBACK_ARG) << 8;
174
175 return 2;
176}
177
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530178static int subdev_700_insn_config(struct comedi_device *dev,
179 struct comedi_subdevice *s,
180 struct comedi_insn *insn, unsigned int *data)
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800181{
182
183 switch (data[0]) {
184 case INSN_CONFIG_DIO_INPUT:
185 break;
186 case INSN_CONFIG_DIO_OUTPUT:
187 break;
188 case INSN_CONFIG_DIO_QUERY:
189 data[1] =
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530190 (s->
191 io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
192 COMEDI_INPUT;
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800193 return insn->n;
194 break;
195 default:
196 return -EINVAL;
197 }
198
199 return 1;
200}
201
Bill Pembertonda91b262009-04-09 16:07:03 -0400202static void do_config(struct comedi_device *dev, struct comedi_subdevice *s)
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800203{ /* use powerup defaults */
204 return;
205}
206
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530207static int subdev_700_cmdtest(struct comedi_device *dev,
208 struct comedi_subdevice *s,
209 struct comedi_cmd *cmd)
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800210{
211 int err = 0;
212 unsigned int tmp;
213
214 /* step 1 */
215
216 tmp = cmd->start_src;
217 cmd->start_src &= TRIG_NOW;
218 if (!cmd->start_src || tmp != cmd->start_src)
219 err++;
220
221 tmp = cmd->scan_begin_src;
222 cmd->scan_begin_src &= TRIG_EXT;
223 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
224 err++;
225
226 tmp = cmd->convert_src;
227 cmd->convert_src &= TRIG_FOLLOW;
228 if (!cmd->convert_src || tmp != cmd->convert_src)
229 err++;
230
231 tmp = cmd->scan_end_src;
232 cmd->scan_end_src &= TRIG_COUNT;
233 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
234 err++;
235
236 tmp = cmd->stop_src;
237 cmd->stop_src &= TRIG_NONE;
238 if (!cmd->stop_src || tmp != cmd->stop_src)
239 err++;
240
241 if (err)
242 return 1;
243
244 /* step 2 */
245
246 if (err)
247 return 2;
248
249 /* step 3 */
250
251 if (cmd->start_arg != 0) {
252 cmd->start_arg = 0;
253 err++;
254 }
255 if (cmd->scan_begin_arg != 0) {
256 cmd->scan_begin_arg = 0;
257 err++;
258 }
259 if (cmd->convert_arg != 0) {
260 cmd->convert_arg = 0;
261 err++;
262 }
263 if (cmd->scan_end_arg != 1) {
264 cmd->scan_end_arg = 1;
265 err++;
266 }
267 if (cmd->stop_arg != 0) {
268 cmd->stop_arg = 0;
269 err++;
270 }
271
272 if (err)
273 return 3;
274
275 /* step 4 */
276
277 if (err)
278 return 4;
279
280 return 0;
281}
282
Bill Pembertonda91b262009-04-09 16:07:03 -0400283static int subdev_700_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800284{
285 /* FIXME */
286
287 return 0;
288}
289
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530290static int subdev_700_cancel(struct comedi_device *dev,
291 struct comedi_subdevice *s)
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800292{
293 /* FIXME */
294
295 return 0;
296}
297
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530298int subdev_700_init(struct comedi_device *dev, struct comedi_subdevice *s,
299 int (*cb) (int, int, int, unsigned long), unsigned long arg)
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800300{
301 s->type = COMEDI_SUBD_DIO;
302 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
303 s->n_chan = 16;
304 s->range_table = &range_digital;
305 s->maxdata = 1;
306
307 s->private = kmalloc(sizeof(struct subdev_700_struct), GFP_KERNEL);
308 if (!s->private)
309 return -ENOMEM;
310
311 CALLBACK_ARG = arg;
312 if (cb == NULL) {
313 CALLBACK_FUNC = subdev_700_cb;
314 } else {
315 CALLBACK_FUNC = cb;
316 }
317 s->insn_bits = subdev_700_insn;
318 s->insn_config = subdev_700_insn_config;
319
320 s->state = 0;
321 s->io_bits = 0x00ff;
322 do_config(dev, s);
323
324 return 0;
325}
326
Bill Pembertonda91b262009-04-09 16:07:03 -0400327int subdev_700_init_irq(struct comedi_device *dev, struct comedi_subdevice *s,
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530328 int (*cb) (int, int, int, unsigned long),
329 unsigned long arg)
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800330{
331 int ret;
332
333 ret = subdev_700_init(dev, s, cb, arg);
334 if (ret < 0)
335 return ret;
336
337 s->do_cmdtest = subdev_700_cmdtest;
338 s->do_cmd = subdev_700_cmd;
339 s->cancel = subdev_700_cancel;
340
341 subdevpriv->have_irq = 1;
342
343 return 0;
344}
345
Bill Pembertonda91b262009-04-09 16:07:03 -0400346void subdev_700_cleanup(struct comedi_device *dev, struct comedi_subdevice *s)
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800347{
348 if (s->private) {
349 if (subdevpriv->have_irq) {
350 }
351
352 kfree(s->private);
353 }
354}
355
356EXPORT_SYMBOL(subdev_700_init);
357EXPORT_SYMBOL(subdev_700_init_irq);
358EXPORT_SYMBOL(subdev_700_cleanup);
359EXPORT_SYMBOL(subdev_700_interrupt);
360
Bill Pembertonda91b262009-04-09 16:07:03 -0400361static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800362{
Bill Pemberton34c43922009-03-16 22:05:14 -0400363 struct comedi_subdevice *s;
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800364 unsigned long iobase = 0;
365#ifdef incomplete
366 unsigned int irq = 0;
367#endif
368 struct pcmcia_device *link;
369
370 /* allocate and initialize dev->private */
Bill Pembertonadf32842009-03-16 22:16:23 -0400371 if (alloc_private(dev, sizeof(struct dio700_private)) < 0)
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800372 return -ENOMEM;
373
Bill Pemberton2696fb52009-03-27 11:29:34 -0400374 /* get base address, irq etc. based on bustype */
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800375 switch (thisboard->bustype) {
376 case pcmcia_bustype:
377 link = pcmcia_cur_dev; /* XXX hack */
378 if (!link)
379 return -EIO;
380 iobase = link->io.BasePort1;
381#ifdef incomplete
382 irq = link->irq.AssignedIRQ;
383#endif
384 break;
385 default:
386 printk("bug! couldn't determine board type\n");
387 return -EINVAL;
388 break;
389 }
390 printk("comedi%d: ni_daq_700: %s, io 0x%lx", dev->minor,
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530391 thisboard->name, iobase);
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800392#ifdef incomplete
393 if (irq) {
394 printk(", irq %u", irq);
395 }
396#endif
397
398 printk("\n");
399
400 if (iobase == 0) {
401 printk("io base address is zero!\n");
402 return -EINVAL;
403 }
404
405 dev->iobase = iobase;
406
407#ifdef incomplete
408 /* grab our IRQ */
409 dev->irq = irq;
410#endif
411
412 dev->board_name = thisboard->name;
413
414 if (alloc_subdevices(dev, 1) < 0)
415 return -ENOMEM;
416
417 /* DAQCard-700 dio */
418 s = dev->subdevices + 0;
419 subdev_700_init(dev, s, NULL, dev->iobase);
420
421 return 0;
422};
423
Bill Pembertonda91b262009-04-09 16:07:03 -0400424static int dio700_detach(struct comedi_device *dev)
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800425{
426 printk("comedi%d: ni_daq_700: cs-remove\n", dev->minor);
427
428 if (dev->subdevices)
429 subdev_700_cleanup(dev, dev->subdevices + 0);
430
431 if (thisboard->bustype != pcmcia_bustype && dev->iobase)
432 release_region(dev->iobase, DIO700_SIZE);
433 if (dev->irq)
Greg Kroah-Hartman5f74ea12009-04-27 14:44:31 -0700434 free_irq(dev->irq, dev);
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800435
436 return 0;
437};
438
Bill Pemberton2696fb52009-03-27 11:29:34 -0400439/* PCMCIA crap */
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800440
441/*
442 All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
443 you do not define PCMCIA_DEBUG at all, all the debug code will be
444 left out. If you compile with PCMCIA_DEBUG=0, the debug code will
445 be present but disabled -- but it can then be enabled for specific
446 modules at load time with a 'pc_debug=#' option to insmod.
447*/
448#ifdef PCMCIA_DEBUG
449static int pc_debug = PCMCIA_DEBUG;
450module_param(pc_debug, int, 0644);
451#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
452static char *version = "ni_daq_700.c, based on dummy_cs.c";
453#else
454#define DEBUG(n, args...)
455#endif
456
457/*====================================================================*/
458
459static void dio700_config(struct pcmcia_device *link);
460static void dio700_release(struct pcmcia_device *link);
461static int dio700_cs_suspend(struct pcmcia_device *p_dev);
462static int dio700_cs_resume(struct pcmcia_device *p_dev);
463
464/*
465 The attach() and detach() entry points are used to create and destroy
466 "instances" of the driver, where each instance represents everything
467 needed to manage one actual PCMCIA card.
468*/
469
470static int dio700_cs_attach(struct pcmcia_device *);
471static void dio700_cs_detach(struct pcmcia_device *);
472
473/*
474 You'll also need to prototype all the functions that will actually
475 be used to talk to your device. See 'memory_cs' for a good example
476 of a fully self-sufficient driver; the other drivers rely more or
477 less on other parts of the kernel.
478*/
479
480/*
481 The dev_info variable is the "key" that is used to match up this
482 device driver with appropriate cards, through the card configuration
483 database.
484*/
485
486static const dev_info_t dev_info = "ni_daq_700";
487
Bill Pemberton30570f02009-03-19 17:59:39 -0400488struct local_info_t {
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800489 struct pcmcia_device *link;
490 dev_node_t node;
491 int stop;
492 struct bus_operations *bus;
Bill Pemberton30570f02009-03-19 17:59:39 -0400493};
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800494
495/*======================================================================
496
497 dio700_cs_attach() creates an "instance" of the driver, allocating
498 local data structures for one device. The device is registered
499 with Card Services.
500
501 The dev_link structure is initialized, but we don't actually
502 configure the card at this point -- we wait until we receive a
503 card insertion event.
504
505======================================================================*/
506
507static int dio700_cs_attach(struct pcmcia_device *link)
508{
Bill Pemberton30570f02009-03-19 17:59:39 -0400509 struct local_info_t *local;
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800510
511 printk(KERN_INFO "ni_daq_700: cs-attach\n");
512
513 DEBUG(0, "dio700_cs_attach()\n");
514
515 /* Allocate space for private device-specific data */
Bill Pemberton30570f02009-03-19 17:59:39 -0400516 local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800517 if (!local)
518 return -ENOMEM;
519 local->link = link;
520 link->priv = local;
521
522 /* Interrupt setup */
Frank Mori Hess3d1c2882009-09-22 16:32:55 -0400523 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800524 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
525 link->irq.Handler = NULL;
526
527 /*
528 General socket configuration defaults can go here. In this
529 client, we assume very little, and rely on the CIS for almost
530 everything. In most clients, many details (i.e., number, sizes,
531 and attributes of IO windows) are fixed by the nature of the
532 device, and can be hard-wired here.
533 */
534 link->conf.Attributes = 0;
535 link->conf.IntType = INT_MEMORY_AND_IO;
536
537 pcmcia_cur_dev = link;
538
539 dio700_config(link);
540
541 return 0;
542} /* dio700_cs_attach */
543
544/*======================================================================
545
546 This deletes a driver "instance". The device is de-registered
547 with Card Services. If it has been released, all local data
548 structures are freed. Otherwise, the structures will be freed
549 when the device is released.
550
551======================================================================*/
552
553static void dio700_cs_detach(struct pcmcia_device *link)
554{
555
556 printk(KERN_INFO "ni_daq_700: cs-detach!\n");
557
558 DEBUG(0, "dio700_cs_detach(0x%p)\n", link);
559
560 if (link->dev_node) {
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530561 ((struct local_info_t *)link->priv)->stop = 1;
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800562 dio700_release(link);
563 }
564
Bill Pemberton30570f02009-03-19 17:59:39 -0400565 /* This points to the parent struct local_info_t struct */
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800566 if (link->priv)
567 kfree(link->priv);
568
569} /* dio700_cs_detach */
570
571/*======================================================================
572
573 dio700_config() is scheduled to run after a CARD_INSERTION event
574 is received, to configure the PCMCIA socket, and to make the
575 device available to the system.
576
577======================================================================*/
578
579static void dio700_config(struct pcmcia_device *link)
580{
Bill Pemberton30570f02009-03-19 17:59:39 -0400581 struct local_info_t *dev = link->priv;
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800582 tuple_t tuple;
583 cisparse_t parse;
584 int last_ret;
585 u_char buf[64];
586 win_req_t req;
587 memreq_t map;
588 cistpl_cftable_entry_t dflt = { 0 };
589
590 printk(KERN_INFO "ni_daq_700: cs-config\n");
591
592 DEBUG(0, "dio700_config(0x%p)\n", link);
593
594 /*
595 This reads the card's CONFIG tuple to find its configuration
596 registers.
597 */
598 tuple.DesiredTuple = CISTPL_CONFIG;
599 tuple.Attributes = 0;
600 tuple.TupleData = buf;
601 tuple.TupleDataMax = sizeof(buf);
602 tuple.TupleOffset = 0;
Bill Pembertonc3744132009-04-22 21:11:47 -0400603
604 last_ret = pcmcia_get_first_tuple(link, &tuple);
605 if (last_ret) {
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800606 cs_error(link, GetFirstTuple, last_ret);
607 goto cs_failed;
608 }
Bill Pembertonc3744132009-04-22 21:11:47 -0400609
610 last_ret = pcmcia_get_tuple_data(link, &tuple);
611 if (last_ret) {
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800612 cs_error(link, GetTupleData, last_ret);
613 goto cs_failed;
614 }
Bill Pembertonc3744132009-04-22 21:11:47 -0400615
616 last_ret = pcmcia_parse_tuple(&tuple, &parse);
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530617 if (last_ret) {
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800618 cs_error(link, ParseTuple, last_ret);
619 goto cs_failed;
620 }
621 link->conf.ConfigBase = parse.config.base;
622 link->conf.Present = parse.config.rmask[0];
623
624 /*
625 In this loop, we scan the CIS for configuration table entries,
626 each of which describes a valid card configuration, including
627 voltage, IO window, memory window, and interrupt settings.
628
629 We make no assumptions about the card to be configured: we use
630 just the information available in the CIS. In an ideal world,
631 this would work for any PCMCIA card, but it requires a complete
632 and accurate CIS. In practice, a driver usually "knows" most of
633 these things without consulting the CIS, and most client drivers
634 will only use the CIS to fill in implementation-defined details.
635 */
636 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
Bill Pembertonc3744132009-04-22 21:11:47 -0400637 last_ret = pcmcia_get_first_tuple(link, &tuple);
638 if (last_ret != 0) {
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800639 cs_error(link, GetFirstTuple, last_ret);
640 goto cs_failed;
641 }
642 while (1) {
643 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
644 if (pcmcia_get_tuple_data(link, &tuple) != 0)
645 goto next_entry;
646 if (pcmcia_parse_tuple(&tuple, &parse) != 0)
647 goto next_entry;
648
649 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
650 dflt = *cfg;
651 if (cfg->index == 0)
652 goto next_entry;
653 link->conf.ConfigIndex = cfg->index;
654
655 /* Does this card need audio output? */
656 if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
657 link->conf.Attributes |= CONF_ENABLE_SPKR;
658 link->conf.Status = CCSR_AUDIO_ENA;
659 }
660
661 /* Do we need to allocate an interrupt? */
662 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
663 link->conf.Attributes |= CONF_ENABLE_IRQ;
664
665 /* IO window settings */
666 link->io.NumPorts1 = link->io.NumPorts2 = 0;
667 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
668 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
669 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
670 if (!(io->flags & CISTPL_IO_8BIT))
671 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
672 if (!(io->flags & CISTPL_IO_16BIT))
673 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
674 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
675 link->io.BasePort1 = io->win[0].base;
676 link->io.NumPorts1 = io->win[0].len;
677 if (io->nwin > 1) {
678 link->io.Attributes2 = link->io.Attributes1;
679 link->io.BasePort2 = io->win[1].base;
680 link->io.NumPorts2 = io->win[1].len;
681 }
682 /* This reserves IO space but doesn't actually enable it */
683 if (pcmcia_request_io(link, &link->io) != 0)
684 goto next_entry;
685 }
686
687 if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
688 cistpl_mem_t *mem =
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530689 (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800690 req.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM;
691 req.Attributes |= WIN_ENABLE;
692 req.Base = mem->win[0].host_addr;
693 req.Size = mem->win[0].len;
694 if (req.Size < 0x1000)
695 req.Size = 0x1000;
696 req.AccessSpeed = 0;
697 if (pcmcia_request_window(&link, &req, &link->win))
698 goto next_entry;
699 map.Page = 0;
700 map.CardOffset = mem->win[0].card_addr;
701 if (pcmcia_map_mem_page(link->win, &map))
702 goto next_entry;
703 }
704 /* If we got this far, we're cool! */
705 break;
706
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530707next_entry:
Bill Pembertonc3744132009-04-22 21:11:47 -0400708
709 last_ret = pcmcia_get_next_tuple(link, &tuple);
710 if (last_ret) {
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800711 cs_error(link, GetNextTuple, last_ret);
712 goto cs_failed;
713 }
714 }
715
716 /*
717 Allocate an interrupt line. Note that this does not assign a
718 handler to the interrupt, unless the 'Handler' member of the
719 irq structure is initialized.
720 */
Bill Pembertonc3744132009-04-22 21:11:47 -0400721 if (link->conf.Attributes & CONF_ENABLE_IRQ) {
722 last_ret = pcmcia_request_irq(link, &link->irq);
723 if (last_ret) {
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800724 cs_error(link, RequestIRQ, last_ret);
725 goto cs_failed;
726 }
Bill Pembertonc3744132009-04-22 21:11:47 -0400727 }
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800728
729 /*
730 This actually configures the PCMCIA socket -- setting up
731 the I/O windows and the interrupt mapping, and putting the
732 card and host interface into "Memory and IO" mode.
733 */
Bill Pembertonc3744132009-04-22 21:11:47 -0400734 last_ret = pcmcia_request_configuration(link, &link->conf);
735 if (last_ret != 0) {
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800736 cs_error(link, RequestConfiguration, last_ret);
737 goto cs_failed;
738 }
739
740 /*
741 At this point, the dev_node_t structure(s) need to be
742 initialized and arranged in a linked list at link->dev.
743 */
744 sprintf(dev->node.dev_name, "ni_daq_700");
745 dev->node.major = dev->node.minor = 0;
746 link->dev_node = &dev->node;
747
748 /* Finally, report what we've done */
749 printk(KERN_INFO "%s: index 0x%02x",
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530750 dev->node.dev_name, link->conf.ConfigIndex);
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800751 if (link->conf.Attributes & CONF_ENABLE_IRQ)
752 printk(", irq %d", link->irq.AssignedIRQ);
753 if (link->io.NumPorts1)
754 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530755 link->io.BasePort1 + link->io.NumPorts1 - 1);
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800756 if (link->io.NumPorts2)
757 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530758 link->io.BasePort2 + link->io.NumPorts2 - 1);
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800759 if (link->win)
760 printk(", mem 0x%06lx-0x%06lx", req.Base,
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530761 req.Base + req.Size - 1);
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800762 printk("\n");
763
764 return;
765
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530766cs_failed:
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800767 printk(KERN_INFO "ni_daq_700 cs failed");
768 dio700_release(link);
769
770} /* dio700_config */
771
772static void dio700_release(struct pcmcia_device *link)
773{
774 DEBUG(0, "dio700_release(0x%p)\n", link);
775
776 pcmcia_disable_device(link);
777} /* dio700_release */
778
779/*======================================================================
780
781 The card status event handler. Mostly, this schedules other
782 stuff to run after an event is received.
783
784 When a CARD_REMOVAL event is received, we immediately set a
785 private flag to block future accesses to this device. All the
786 functions that actually access the device should check this flag
787 to make sure the card is still present.
788
789======================================================================*/
790
791static int dio700_cs_suspend(struct pcmcia_device *link)
792{
Bill Pemberton30570f02009-03-19 17:59:39 -0400793 struct local_info_t *local = link->priv;
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800794
795 /* Mark the device as stopped, to block IO until later */
796 local->stop = 1;
797 return 0;
798} /* dio700_cs_suspend */
799
800static int dio700_cs_resume(struct pcmcia_device *link)
801{
Bill Pemberton30570f02009-03-19 17:59:39 -0400802 struct local_info_t *local = link->priv;
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800803
804 local->stop = 0;
805 return 0;
806} /* dio700_cs_resume */
807
808/*====================================================================*/
809
810static struct pcmcia_device_id dio700_cs_ids[] = {
811 /* N.B. These IDs should match those in dio700_boards */
812 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4743), /* daqcard-700 */
813 PCMCIA_DEVICE_NULL
814};
815
816MODULE_LICENSE("GPL");
817MODULE_DEVICE_TABLE(pcmcia, dio700_cs_ids);
818
819struct pcmcia_driver dio700_cs_driver = {
820 .probe = dio700_cs_attach,
821 .remove = dio700_cs_detach,
822 .suspend = dio700_cs_suspend,
823 .resume = dio700_cs_resume,
824 .id_table = dio700_cs_ids,
825 .owner = THIS_MODULE,
826 .drv = {
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530827 .name = dev_info,
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800828 },
829};
830
831static int __init init_dio700_cs(void)
832{
833 printk("ni_daq_700: cs-init \n");
834 DEBUG(0, "%s\n", version);
835 pcmcia_register_driver(&dio700_cs_driver);
836 return 0;
837}
838
839static void __exit exit_dio700_cs(void)
840{
841 DEBUG(0, "ni_daq_700: unloading\n");
842 pcmcia_unregister_driver(&dio700_cs_driver);
843}
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530844
Fred Brooks1f9bbbe2009-02-19 10:05:01 -0800845int __init init_module(void)
846{
847 int ret;
848
849 ret = init_dio700_cs();
850 if (ret < 0)
851 return ret;
852
853 return comedi_driver_register(&driver_dio700);
854}
855
856void __exit cleanup_module(void)
857{
858 exit_dio700_cs();
859 comedi_driver_unregister(&driver_dio700);
860}