ni_daq_700.c revision 00990e7ce0b0e596fe41d9c64d6933ea70084003
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				void *priv_data)
534{
535	if (p_dev->config_index == 0)
536		return -EINVAL;
537
538	return pcmcia_request_io(p_dev);
539}
540
541static void dio700_config(struct pcmcia_device *link)
542{
543	win_req_t req;
544	int ret;
545
546	printk(KERN_INFO "ni_daq_700:  cs-config\n");
547
548	dev_dbg(&link->dev, "dio700_config\n");
549
550	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO |
551		CONF_AUTO_SET_IO;
552
553	ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, NULL);
554	if (ret) {
555		dev_warn(&link->dev, "no configuration found\n");
556		goto failed;
557	}
558
559	if (!link->irq)
560		goto failed;
561
562	/*
563	   This actually configures the PCMCIA socket -- setting up
564	   the I/O windows and the interrupt mapping, and putting the
565	   card and host interface into "Memory and IO" mode.
566	 */
567	ret = pcmcia_enable_device(link);
568	if (ret != 0)
569		goto failed;
570
571	/* Finally, report what we've done */
572	dev_info(&link->dev, "index 0x%02x", link->config_index);
573	printk(", irq %d", link->irq);
574	if (link->resource[0])
575		printk(", io %pR", link->resource[0]);
576	if (link->resource[1])
577		printk(" & %pR", link->resource[1]);
578	printk("\n");
579
580	return;
581
582failed:
583	printk(KERN_INFO "ni_daq_700 cs failed");
584	dio700_release(link);
585
586}				/* dio700_config */
587
588static void dio700_release(struct pcmcia_device *link)
589{
590	dev_dbg(&link->dev, "dio700_release\n");
591
592	pcmcia_disable_device(link);
593}				/* dio700_release */
594
595/*======================================================================
596
597    The card status event handler.  Mostly, this schedules other
598    stuff to run after an event is received.
599
600    When a CARD_REMOVAL event is received, we immediately set a
601    private flag to block future accesses to this device.  All the
602    functions that actually access the device should check this flag
603    to make sure the card is still present.
604
605======================================================================*/
606
607static int dio700_cs_suspend(struct pcmcia_device *link)
608{
609	struct local_info_t *local = link->priv;
610
611	/* Mark the device as stopped, to block IO until later */
612	local->stop = 1;
613	return 0;
614}				/* dio700_cs_suspend */
615
616static int dio700_cs_resume(struct pcmcia_device *link)
617{
618	struct local_info_t *local = link->priv;
619
620	local->stop = 0;
621	return 0;
622}				/* dio700_cs_resume */
623
624/*====================================================================*/
625
626static struct pcmcia_device_id dio700_cs_ids[] = {
627	/* N.B. These IDs should match those in dio700_boards */
628	PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4743),	/* daqcard-700 */
629	PCMCIA_DEVICE_NULL
630};
631
632
633MODULE_DEVICE_TABLE(pcmcia, dio700_cs_ids);
634MODULE_AUTHOR("Fred Brooks <nsaspook@nsaspook.com>");
635MODULE_DESCRIPTION("Comedi driver for National Instruments "
636		   "PCMCIA DAQCard-700 DIO");
637MODULE_LICENSE("GPL");
638
639struct pcmcia_driver dio700_cs_driver = {
640	.probe = dio700_cs_attach,
641	.remove = dio700_cs_detach,
642	.suspend = dio700_cs_suspend,
643	.resume = dio700_cs_resume,
644	.id_table = dio700_cs_ids,
645	.owner = THIS_MODULE,
646	.drv = {
647		.name = "ni_daq_700",
648		},
649};
650
651static int __init init_dio700_cs(void)
652{
653	pcmcia_register_driver(&dio700_cs_driver);
654	return 0;
655}
656
657static void __exit exit_dio700_cs(void)
658{
659	pr_debug("ni_daq_700: unloading\n");
660	pcmcia_unregister_driver(&dio700_cs_driver);
661}
662
663int __init init_module(void)
664{
665	int ret;
666
667	ret = init_dio700_cs();
668	if (ret < 0)
669		return ret;
670
671	return comedi_driver_register(&driver_dio700);
672}
673
674void __exit cleanup_module(void)
675{
676	exit_dio700_cs();
677	comedi_driver_unregister(&driver_dio700);
678}
679