ni_daq_700.c revision 1ac71e5a35eebee60cdcf15b3980bd94498f037b
1/*
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
44#include <linux/interrupt.h>
45#include <linux/slab.h>
46#include "../comedidev.h"
47
48#include <linux/ioport.h>
49
50#include <pcmcia/cistpl.h>
51#include <pcmcia/cisreg.h>
52#include <pcmcia/ds.h>
53
54static struct pcmcia_device *pcmcia_cur_dev = NULL;
55
56#define DIO700_SIZE 8		/*  size of io region used by board */
57
58static int dio700_attach(struct comedi_device *dev,
59			 struct comedi_devconfig *it);
60static int dio700_detach(struct comedi_device *dev);
61
62enum dio700_bustype { pcmcia_bustype };
63
64struct dio700_board {
65	const char *name;
66	int device_id;		/*  device id for pcmcia board */
67	enum dio700_bustype bustype;	/*  PCMCIA */
68	int have_dio;		/*  have daqcard-700 dio */
69	/*  function pointers so we can use inb/outb or readb/writeb */
70	/*  as appropriate */
71	unsigned int (*read_byte) (unsigned int address);
72	void (*write_byte) (unsigned int byte, unsigned int address);
73};
74
75static const struct dio700_board dio700_boards[] = {
76	{
77	 .name = "daqcard-700",
78	  /*  0x10b is manufacturer id, 0x4743 is device id */
79	 .device_id = 0x4743,
80	 .bustype = pcmcia_bustype,
81	 .have_dio = 1,
82	 },
83	{
84	 .name = "ni_daq_700",
85	  /*  0x10b is manufacturer id, 0x4743 is device id */
86	 .device_id = 0x4743,
87	 .bustype = pcmcia_bustype,
88	 .have_dio = 1,
89	 },
90};
91
92/*
93 * Useful for shorthand access to the particular board structure
94 */
95#define thisboard ((const struct dio700_board *)dev->board_ptr)
96
97struct dio700_private {
98
99	int data;		/* number of data points left to be taken */
100};
101
102#define devpriv ((struct dio700_private *)dev->private)
103
104static struct comedi_driver driver_dio700 = {
105	.driver_name = "ni_daq_700",
106	.module = THIS_MODULE,
107	.attach = dio700_attach,
108	.detach = dio700_detach,
109	.num_names = ARRAY_SIZE(dio700_boards),
110	.board_name = &dio700_boards[0].name,
111	.offset = sizeof(struct dio700_board),
112};
113
114/*	the real driver routines	*/
115
116#define _700_SIZE 8
117
118#define _700_DATA 0
119
120#define DIO_W		0x04
121#define DIO_R		0x05
122
123struct subdev_700_struct {
124	unsigned long cb_arg;
125	int (*cb_func) (int, int, int, unsigned long);
126	int have_irq;
127};
128
129#define CALLBACK_ARG	(((struct subdev_700_struct *)s->private)->cb_arg)
130#define CALLBACK_FUNC	(((struct subdev_700_struct *)s->private)->cb_func)
131#define subdevpriv	((struct subdev_700_struct *)s->private)
132
133static void do_config(struct comedi_device *dev, struct comedi_subdevice *s);
134
135void subdev_700_interrupt(struct comedi_device *dev, struct comedi_subdevice *s)
136{
137	short d;
138
139	d = CALLBACK_FUNC(0, _700_DATA, 0, CALLBACK_ARG);
140
141	comedi_buf_put(s->async, d);
142	s->async->events |= COMEDI_CB_EOS;
143
144	comedi_event(dev, s);
145}
146EXPORT_SYMBOL(subdev_700_interrupt);
147
148static int subdev_700_cb(int dir, int port, int data, unsigned long arg)
149{
150	/* port is always A for output and B for input (8255 emu) */
151	unsigned long iobase = arg;
152
153	if (dir) {
154		outb(data, iobase + DIO_W);
155		return 0;
156	} else {
157		return inb(iobase + DIO_R);
158	}
159}
160
161static int subdev_700_insn(struct comedi_device *dev,
162			   struct comedi_subdevice *s, struct comedi_insn *insn,
163			   unsigned int *data)
164{
165	if (data[0]) {
166		s->state &= ~data[0];
167		s->state |= (data[0] & data[1]);
168
169		if (data[0] & 0xff)
170			CALLBACK_FUNC(1, _700_DATA, s->state & 0xff,
171				      CALLBACK_ARG);
172	}
173
174	data[1] = s->state & 0xff;
175	data[1] |= CALLBACK_FUNC(0, _700_DATA, 0, CALLBACK_ARG) << 8;
176
177	return 2;
178}
179
180static int subdev_700_insn_config(struct comedi_device *dev,
181				  struct comedi_subdevice *s,
182				  struct comedi_insn *insn, unsigned int *data)
183{
184
185	switch (data[0]) {
186	case INSN_CONFIG_DIO_INPUT:
187		break;
188	case INSN_CONFIG_DIO_OUTPUT:
189		break;
190	case INSN_CONFIG_DIO_QUERY:
191		data[1] =
192		    (s->
193		     io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
194		    COMEDI_INPUT;
195		return insn->n;
196		break;
197	default:
198		return -EINVAL;
199	}
200
201	return 1;
202}
203
204static void do_config(struct comedi_device *dev, struct comedi_subdevice *s)
205{				/* use powerup defaults */
206	return;
207}
208
209static int subdev_700_cmdtest(struct comedi_device *dev,
210			      struct comedi_subdevice *s,
211			      struct comedi_cmd *cmd)
212{
213	int err = 0;
214	unsigned int tmp;
215
216	/* step 1 */
217
218	tmp = cmd->start_src;
219	cmd->start_src &= TRIG_NOW;
220	if (!cmd->start_src || tmp != cmd->start_src)
221		err++;
222
223	tmp = cmd->scan_begin_src;
224	cmd->scan_begin_src &= TRIG_EXT;
225	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
226		err++;
227
228	tmp = cmd->convert_src;
229	cmd->convert_src &= TRIG_FOLLOW;
230	if (!cmd->convert_src || tmp != cmd->convert_src)
231		err++;
232
233	tmp = cmd->scan_end_src;
234	cmd->scan_end_src &= TRIG_COUNT;
235	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
236		err++;
237
238	tmp = cmd->stop_src;
239	cmd->stop_src &= TRIG_NONE;
240	if (!cmd->stop_src || tmp != cmd->stop_src)
241		err++;
242
243	if (err)
244		return 1;
245
246	/* step 2 */
247
248	if (err)
249		return 2;
250
251	/* step 3 */
252
253	if (cmd->start_arg != 0) {
254		cmd->start_arg = 0;
255		err++;
256	}
257	if (cmd->scan_begin_arg != 0) {
258		cmd->scan_begin_arg = 0;
259		err++;
260	}
261	if (cmd->convert_arg != 0) {
262		cmd->convert_arg = 0;
263		err++;
264	}
265	if (cmd->scan_end_arg != 1) {
266		cmd->scan_end_arg = 1;
267		err++;
268	}
269	if (cmd->stop_arg != 0) {
270		cmd->stop_arg = 0;
271		err++;
272	}
273
274	if (err)
275		return 3;
276
277	/* step 4 */
278
279	if (err)
280		return 4;
281
282	return 0;
283}
284
285static int subdev_700_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
286{
287	/* FIXME */
288
289	return 0;
290}
291
292static int subdev_700_cancel(struct comedi_device *dev,
293			     struct comedi_subdevice *s)
294{
295	/* FIXME */
296
297	return 0;
298}
299
300int subdev_700_init(struct comedi_device *dev, struct comedi_subdevice *s,
301		    int (*cb) (int, int, int, unsigned long), unsigned long arg)
302{
303	s->type = COMEDI_SUBD_DIO;
304	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
305	s->n_chan = 16;
306	s->range_table = &range_digital;
307	s->maxdata = 1;
308
309	s->private = kmalloc(sizeof(struct subdev_700_struct), GFP_KERNEL);
310	if (!s->private)
311		return -ENOMEM;
312
313	CALLBACK_ARG = arg;
314	if (cb == NULL)
315		CALLBACK_FUNC = subdev_700_cb;
316	 else
317		CALLBACK_FUNC = cb;
318
319	s->insn_bits = subdev_700_insn;
320	s->insn_config = subdev_700_insn_config;
321
322	s->state = 0;
323	s->io_bits = 0x00ff;
324	do_config(dev, s);
325
326	return 0;
327}
328EXPORT_SYMBOL(subdev_700_init);
329
330int subdev_700_init_irq(struct comedi_device *dev, struct comedi_subdevice *s,
331			int (*cb) (int, int, int, unsigned long),
332			unsigned long arg)
333{
334	int ret;
335
336	ret = subdev_700_init(dev, s, cb, arg);
337	if (ret < 0)
338		return ret;
339
340	s->do_cmdtest = subdev_700_cmdtest;
341	s->do_cmd = subdev_700_cmd;
342	s->cancel = subdev_700_cancel;
343
344	subdevpriv->have_irq = 1;
345
346	return 0;
347}
348EXPORT_SYMBOL(subdev_700_init_irq);
349
350void subdev_700_cleanup(struct comedi_device *dev, struct comedi_subdevice *s)
351{
352	if (s->private)
353		if (subdevpriv->have_irq)
354
355			kfree(s->private);
356}
357EXPORT_SYMBOL(subdev_700_cleanup);
358
359static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
360{
361	struct comedi_subdevice *s;
362	unsigned long iobase = 0;
363#ifdef incomplete
364	unsigned int irq = 0;
365#endif
366	struct pcmcia_device *link;
367
368	/* allocate and initialize dev->private */
369	if (alloc_private(dev, sizeof(struct dio700_private)) < 0)
370		return -ENOMEM;
371
372	/*  get base address, irq etc. based on bustype */
373	switch (thisboard->bustype) {
374	case pcmcia_bustype:
375		link = pcmcia_cur_dev;	/* XXX hack */
376		if (!link)
377			return -EIO;
378		iobase = link->resource[0]->start;
379#ifdef incomplete
380		irq = link->irq;
381#endif
382		break;
383	default:
384		printk("bug! couldn't determine board type\n");
385		return -EINVAL;
386		break;
387	}
388	printk("comedi%d: ni_daq_700: %s, io 0x%lx", dev->minor,
389	       thisboard->name, iobase);
390#ifdef incomplete
391	if (irq)
392		printk(", irq %u", irq);
393
394#endif
395
396	printk("\n");
397
398	if (iobase == 0) {
399		printk("io base address is zero!\n");
400		return -EINVAL;
401	}
402
403	dev->iobase = iobase;
404
405#ifdef incomplete
406	/* grab our IRQ */
407	dev->irq = irq;
408#endif
409
410	dev->board_name = thisboard->name;
411
412	if (alloc_subdevices(dev, 1) < 0)
413		return -ENOMEM;
414
415	/* DAQCard-700 dio */
416	s = dev->subdevices + 0;
417	subdev_700_init(dev, s, NULL, dev->iobase);
418
419	return 0;
420};
421
422static int dio700_detach(struct comedi_device *dev)
423{
424	printk("comedi%d: ni_daq_700: cs-remove\n", dev->minor);
425
426	if (dev->subdevices)
427		subdev_700_cleanup(dev, dev->subdevices + 0);
428
429	if (thisboard->bustype != pcmcia_bustype && dev->iobase)
430		release_region(dev->iobase, DIO700_SIZE);
431	if (dev->irq)
432		free_irq(dev->irq, dev);
433
434	return 0;
435};
436
437/* PCMCIA crap -- watch your words, please! */
438
439static void dio700_config(struct pcmcia_device *link);
440static void dio700_release(struct pcmcia_device *link);
441static int dio700_cs_suspend(struct pcmcia_device *p_dev);
442static int dio700_cs_resume(struct pcmcia_device *p_dev);
443
444/*
445   The attach() and detach() entry points are used to create and destroy
446   "instances" of the driver, where each instance represents everything
447   needed to manage one actual PCMCIA card.
448*/
449
450static int dio700_cs_attach(struct pcmcia_device *);
451static void dio700_cs_detach(struct pcmcia_device *);
452
453/*
454   You'll also need to prototype all the functions that will actually
455   be used to talk to your device.  See 'memory_cs' for a good example
456   of a fully self-sufficient driver; the other drivers rely more or
457   less on other parts of the kernel.
458*/
459
460struct local_info_t {
461	struct pcmcia_device *link;
462	int stop;
463	struct bus_operations *bus;
464};
465
466/*======================================================================
467
468    dio700_cs_attach() creates an "instance" of the driver, allocating
469    local data structures for one device.  The device is registered
470    with Card Services.
471
472    The dev_link structure is initialized, but we don't actually
473    configure the card at this point -- we wait until we receive a
474    card insertion event.
475
476======================================================================*/
477
478static int dio700_cs_attach(struct pcmcia_device *link)
479{
480	struct local_info_t *local;
481
482	printk(KERN_INFO "ni_daq_700:  cs-attach\n");
483
484	dev_dbg(&link->dev, "dio700_cs_attach()\n");
485
486	/* Allocate space for private device-specific data */
487	local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
488	if (!local)
489		return -ENOMEM;
490	local->link = link;
491	link->priv = local;
492
493	pcmcia_cur_dev = link;
494
495	dio700_config(link);
496
497	return 0;
498}				/* dio700_cs_attach */
499
500/*======================================================================
501
502    This deletes a driver "instance".  The device is de-registered
503    with Card Services.  If it has been released, all local data
504    structures are freed.  Otherwise, the structures will be freed
505    when the device is released.
506
507======================================================================*/
508
509static void dio700_cs_detach(struct pcmcia_device *link)
510{
511
512	printk(KERN_INFO "ni_daq_700: cs-detach!\n");
513
514	dev_dbg(&link->dev, "dio700_cs_detach\n");
515
516	((struct local_info_t *)link->priv)->stop = 1;
517	dio700_release(link);
518
519	/* This points to the parent struct local_info_t struct */
520	kfree(link->priv);
521
522}				/* dio700_cs_detach */
523
524/*======================================================================
525
526    dio700_config() is scheduled to run after a CARD_INSERTION event
527    is received, to configure the PCMCIA socket, and to make the
528    device available to the system.
529
530======================================================================*/
531
532static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
533				cistpl_cftable_entry_t *cfg,
534				cistpl_cftable_entry_t *dflt,
535				unsigned int vcc,
536				void *priv_data)
537{
538	if (cfg->index == 0)
539		return -ENODEV;
540
541	/* Does this card need audio output? */
542	if (cfg->flags & CISTPL_CFTABLE_AUDIO)
543		p_dev->config_flags |= CONF_ENABLE_SPKR;
544
545	/* Do we need to allocate an interrupt? */
546	p_dev->config_flags |= CONF_ENABLE_IRQ;
547
548	/* IO window settings */
549	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
550	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
551		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
552		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
553		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
554		p_dev->resource[0]->flags |=
555			pcmcia_io_cfg_data_width(io->flags);
556		p_dev->resource[0]->start = io->win[0].base;
557		p_dev->resource[0]->end = io->win[0].len;
558		if (io->nwin > 1) {
559			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
560			p_dev->resource[1]->start = io->win[1].base;
561			p_dev->resource[1]->end = io->win[1].len;
562		}
563		/* This reserves IO space but doesn't actually enable it */
564		if (pcmcia_request_io(p_dev) != 0)
565			return -ENODEV;
566	}
567
568	/* If we got this far, we're cool! */
569	return 0;
570}
571
572static void dio700_config(struct pcmcia_device *link)
573{
574	win_req_t req;
575	int ret;
576
577	printk(KERN_INFO "ni_daq_700:  cs-config\n");
578
579	dev_dbg(&link->dev, "dio700_config\n");
580
581	ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, NULL);
582	if (ret) {
583		dev_warn(&link->dev, "no configuration found\n");
584		goto failed;
585	}
586
587	if (!link->irq)
588		goto failed;
589
590	/*
591	   This actually configures the PCMCIA socket -- setting up
592	   the I/O windows and the interrupt mapping, and putting the
593	   card and host interface into "Memory and IO" mode.
594	 */
595	ret = pcmcia_enable_device(link);
596	if (ret != 0)
597		goto failed;
598
599	/* Finally, report what we've done */
600	dev_info(&link->dev, "index 0x%02x", link->config_index);
601	printk(", irq %d", link->irq);
602	if (link->resource[0])
603		printk(", io %pR", link->resource[0]);
604	if (link->resource[1])
605		printk(" & %pR", link->resource[1]);
606	printk("\n");
607
608	return;
609
610failed:
611	printk(KERN_INFO "ni_daq_700 cs failed");
612	dio700_release(link);
613
614}				/* dio700_config */
615
616static void dio700_release(struct pcmcia_device *link)
617{
618	dev_dbg(&link->dev, "dio700_release\n");
619
620	pcmcia_disable_device(link);
621}				/* dio700_release */
622
623/*======================================================================
624
625    The card status event handler.  Mostly, this schedules other
626    stuff to run after an event is received.
627
628    When a CARD_REMOVAL event is received, we immediately set a
629    private flag to block future accesses to this device.  All the
630    functions that actually access the device should check this flag
631    to make sure the card is still present.
632
633======================================================================*/
634
635static int dio700_cs_suspend(struct pcmcia_device *link)
636{
637	struct local_info_t *local = link->priv;
638
639	/* Mark the device as stopped, to block IO until later */
640	local->stop = 1;
641	return 0;
642}				/* dio700_cs_suspend */
643
644static int dio700_cs_resume(struct pcmcia_device *link)
645{
646	struct local_info_t *local = link->priv;
647
648	local->stop = 0;
649	return 0;
650}				/* dio700_cs_resume */
651
652/*====================================================================*/
653
654static struct pcmcia_device_id dio700_cs_ids[] = {
655	/* N.B. These IDs should match those in dio700_boards */
656	PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4743),	/* daqcard-700 */
657	PCMCIA_DEVICE_NULL
658};
659
660
661MODULE_DEVICE_TABLE(pcmcia, dio700_cs_ids);
662MODULE_AUTHOR("Fred Brooks <nsaspook@nsaspook.com>");
663MODULE_DESCRIPTION("Comedi driver for National Instruments "
664		   "PCMCIA DAQCard-700 DIO");
665MODULE_LICENSE("GPL");
666
667struct pcmcia_driver dio700_cs_driver = {
668	.probe = dio700_cs_attach,
669	.remove = dio700_cs_detach,
670	.suspend = dio700_cs_suspend,
671	.resume = dio700_cs_resume,
672	.id_table = dio700_cs_ids,
673	.owner = THIS_MODULE,
674	.drv = {
675		.name = "ni_daq_700",
676		},
677};
678
679static int __init init_dio700_cs(void)
680{
681	pcmcia_register_driver(&dio700_cs_driver);
682	return 0;
683}
684
685static void __exit exit_dio700_cs(void)
686{
687	pr_debug("ni_daq_700: unloading\n");
688	pcmcia_unregister_driver(&dio700_cs_driver);
689}
690
691int __init init_module(void)
692{
693	int ret;
694
695	ret = init_dio700_cs();
696	if (ret < 0)
697		return ret;
698
699	return comedi_driver_register(&driver_dio700);
700}
701
702void __exit cleanup_module(void)
703{
704	exit_dio700_cs();
705	comedi_driver_unregister(&driver_dio700);
706}
707