ni_daq_dio24.c revision cf4c8d1b8f59ae5591bba0936f378e52df09aa04
1/*
2    comedi/drivers/ni_daq_dio24.c
3    Driver for National Instruments PCMCIA DAQ-Card DIO-24
4    Copyright (C) 2002 Daniel Vecino Castel <dvecino@able.es>
5
6    PCMCIA crap at end of file is adapted from dummy_cs.c 1.31 2001/08/24 12:13:13
7    from the pcmcia package.
8    The initial developer of the pcmcia dummy_cs.c code is David A. Hinds
9    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
10    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 2 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
26************************************************************************
27*/
28/*
29Driver: ni_daq_dio24
30Description: National Instruments PCMCIA DAQ-Card DIO-24
31Author: Daniel Vecino Castel <dvecino@able.es>
32Devices: [National Instruments] PCMCIA DAQ-Card DIO-24 (ni_daq_dio24)
33Status: ?
34Updated: Thu, 07 Nov 2002 21:53:06 -0800
35
36This is just a wrapper around the 8255.o driver to properly handle
37the PCMCIA interface.
38*/
39
40//#define LABPC_DEBUG   // enable debugging messages
41#undef LABPC_DEBUG
42
43#include "../comedidev.h"
44
45#include <linux/ioport.h>
46
47#include "8255.h"
48
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
57#define DIO24_SIZE 4		// size of io region used by board
58
59static int dio24_attach(struct comedi_device * dev, struct comedi_devconfig * it);
60static int dio24_detach(struct comedi_device * dev);
61
62enum dio24_bustype { pcmcia_bustype };
63
64struct dio24_board_struct {
65	const char *name;
66	int device_id;		// device id for pcmcia board
67	enum dio24_bustype bustype;	// PCMCIA
68	int have_dio;		// have 8255 chip
69	// function pointers so we can use inb/outb or readb/writeb as appropriate
70	unsigned int (*read_byte) (unsigned int address);
71	void (*write_byte) (unsigned int byte, unsigned int address);
72};
73
74static const struct dio24_board_struct dio24_boards[] = {
75	{
76	      name:	"daqcard-dio24",
77	      device_id:0x475c,// 0x10b is manufacturer id, 0x475c is device id
78	      bustype:	pcmcia_bustype,
79	      have_dio:1,
80		},
81	{
82	      name:	"ni_daq_dio24",
83	      device_id:0x475c,// 0x10b is manufacturer id, 0x475c is device id
84	      bustype:	pcmcia_bustype,
85	      have_dio:1,
86		},
87};
88
89/*
90 * Useful for shorthand access to the particular board structure
91 */
92#define thisboard ((const struct dio24_board_struct *)dev->board_ptr)
93
94struct dio24_private {
95
96	int data;		/* number of data points left to be taken */
97};
98
99
100#define devpriv ((struct dio24_private *)dev->private)
101
102static struct comedi_driver driver_dio24 = {
103      driver_name:"ni_daq_dio24",
104      module:THIS_MODULE,
105      attach:dio24_attach,
106      detach:dio24_detach,
107      num_names:sizeof(dio24_boards) / sizeof(struct dio24_board_struct),
108      board_name:&dio24_boards[0].name,
109      offset:sizeof(struct dio24_board_struct),
110};
111
112static int dio24_attach(struct comedi_device * dev, struct comedi_devconfig * it)
113{
114	struct comedi_subdevice *s;
115	unsigned long iobase = 0;
116#ifdef incomplete
117	unsigned int irq = 0;
118#endif
119	struct pcmcia_device *link;
120
121	/* allocate and initialize dev->private */
122	if (alloc_private(dev, sizeof(struct dio24_private)) < 0)
123		return -ENOMEM;
124
125	// get base address, irq etc. based on bustype
126	switch (thisboard->bustype) {
127	case pcmcia_bustype:
128		link = pcmcia_cur_dev;	/* XXX hack */
129		if (!link)
130			return -EIO;
131		iobase = link->io.BasePort1;
132#ifdef incomplete
133		irq = link->irq.AssignedIRQ;
134#endif
135		break;
136	default:
137		printk("bug! couldn't determine board type\n");
138		return -EINVAL;
139		break;
140	}
141	printk("comedi%d: ni_daq_dio24: %s, io 0x%lx", dev->minor,
142		thisboard->name, iobase);
143#ifdef incomplete
144	if (irq) {
145		printk(", irq %u", irq);
146	}
147#endif
148
149	printk("\n");
150
151	if (iobase == 0) {
152		printk("io base address is zero!\n");
153		return -EINVAL;
154	}
155
156	dev->iobase = iobase;
157
158#ifdef incomplete
159	/* grab our IRQ */
160	dev->irq = irq;
161#endif
162
163	dev->board_name = thisboard->name;
164
165	if (alloc_subdevices(dev, 1) < 0)
166		return -ENOMEM;
167
168	/* 8255 dio */
169	s = dev->subdevices + 0;
170	subdev_8255_init(dev, s, NULL, dev->iobase);
171
172	return 0;
173};
174
175static int dio24_detach(struct comedi_device * dev)
176{
177	printk("comedi%d: ni_daq_dio24: remove\n", dev->minor);
178
179	if (dev->subdevices)
180		subdev_8255_cleanup(dev, dev->subdevices + 0);
181
182	if (thisboard->bustype != pcmcia_bustype && dev->iobase)
183		release_region(dev->iobase, DIO24_SIZE);
184	if (dev->irq)
185		comedi_free_irq(dev->irq, dev);
186
187	return 0;
188};
189
190// PCMCIA crap
191
192/*
193   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
194   you do not define PCMCIA_DEBUG at all, all the debug code will be
195   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will
196   be present but disabled -- but it can then be enabled for specific
197   modules at load time with a 'pc_debug=#' option to insmod.
198*/
199#ifdef PCMCIA_DEBUG
200static int pc_debug = PCMCIA_DEBUG;
201module_param(pc_debug, int, 0644);
202#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
203static char *version = "ni_daq_dio24.c, based on dummy_cs.c";
204#else
205#define DEBUG(n, args...)
206#endif
207
208/*====================================================================*/
209
210static void dio24_config(struct pcmcia_device *link);
211static void dio24_release(struct pcmcia_device *link);
212static int dio24_cs_suspend(struct pcmcia_device *p_dev);
213static int dio24_cs_resume(struct pcmcia_device *p_dev);
214
215/*
216   The attach() and detach() entry points are used to create and destroy
217   "instances" of the driver, where each instance represents everything
218   needed to manage one actual PCMCIA card.
219*/
220
221static int dio24_cs_attach(struct pcmcia_device *);
222static void dio24_cs_detach(struct pcmcia_device *);
223
224/*
225   You'll also need to prototype all the functions that will actually
226   be used to talk to your device.  See 'memory_cs' for a good example
227   of a fully self-sufficient driver; the other drivers rely more or
228   less on other parts of the kernel.
229*/
230
231/*
232   The dev_info variable is the "key" that is used to match up this
233   device driver with appropriate cards, through the card configuration
234   database.
235*/
236
237static const dev_info_t dev_info = "ni_daq_dio24";
238
239typedef struct local_info_t {
240	struct pcmcia_device *link;
241	dev_node_t node;
242	int stop;
243	struct bus_operations *bus;
244} local_info_t;
245
246/*======================================================================
247
248    dio24_cs_attach() creates an "instance" of the driver, allocating
249    local data structures for one device.  The device is registered
250    with Card Services.
251
252    The dev_link structure is initialized, but we don't actually
253    configure the card at this point -- we wait until we receive a
254    card insertion event.
255
256======================================================================*/
257
258static int dio24_cs_attach(struct pcmcia_device *link)
259{
260	local_info_t *local;
261
262	printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - CS-attach!\n");
263
264	DEBUG(0, "dio24_cs_attach()\n");
265
266	/* Allocate space for private device-specific data */
267	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
268	if (!local)
269		return -ENOMEM;
270	local->link = link;
271	link->priv = local;
272
273	/* Interrupt setup */
274	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
275	link->irq.IRQInfo1 = IRQ_LEVEL_ID;
276	link->irq.Handler = NULL;
277
278	/*
279	   General socket configuration defaults can go here.  In this
280	   client, we assume very little, and rely on the CIS for almost
281	   everything.  In most clients, many details (i.e., number, sizes,
282	   and attributes of IO windows) are fixed by the nature of the
283	   device, and can be hard-wired here.
284	 */
285	link->conf.Attributes = 0;
286	link->conf.IntType = INT_MEMORY_AND_IO;
287
288	pcmcia_cur_dev = link;
289
290	dio24_config(link);
291
292	return 0;
293}				/* dio24_cs_attach */
294
295/*======================================================================
296
297    This deletes a driver "instance".  The device is de-registered
298    with Card Services.  If it has been released, all local data
299    structures are freed.  Otherwise, the structures will be freed
300    when the device is released.
301
302======================================================================*/
303
304static void dio24_cs_detach(struct pcmcia_device *link)
305{
306
307	printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - cs-detach!\n");
308
309	DEBUG(0, "dio24_cs_detach(0x%p)\n", link);
310
311	if (link->dev_node) {
312		((local_info_t *) link->priv)->stop = 1;
313		dio24_release(link);
314	}
315
316	/* This points to the parent local_info_t struct */
317	if (link->priv)
318		kfree(link->priv);
319
320}				/* dio24_cs_detach */
321
322/*======================================================================
323
324    dio24_config() is scheduled to run after a CARD_INSERTION event
325    is received, to configure the PCMCIA socket, and to make the
326    device available to the system.
327
328======================================================================*/
329
330static void dio24_config(struct pcmcia_device *link)
331{
332	local_info_t *dev = link->priv;
333	tuple_t tuple;
334	cisparse_t parse;
335	int last_ret;
336	u_char buf[64];
337	win_req_t req;
338	memreq_t map;
339	cistpl_cftable_entry_t dflt = { 0 };
340
341	printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO! - config\n");
342
343	DEBUG(0, "dio24_config(0x%p)\n", link);
344
345	/*
346	   This reads the card's CONFIG tuple to find its configuration
347	   registers.
348	 */
349	tuple.DesiredTuple = CISTPL_CONFIG;
350	tuple.Attributes = 0;
351	tuple.TupleData = buf;
352	tuple.TupleDataMax = sizeof(buf);
353	tuple.TupleOffset = 0;
354	if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0) {
355		cs_error(link, GetFirstTuple, last_ret);
356		goto cs_failed;
357	}
358	if ((last_ret = pcmcia_get_tuple_data(link, &tuple)) != 0) {
359		cs_error(link, GetTupleData, last_ret);
360		goto cs_failed;
361	}
362	if ((last_ret = pcmcia_parse_tuple(&tuple, &parse)) != 0) {
363		cs_error(link, ParseTuple, last_ret);
364		goto cs_failed;
365	}
366	link->conf.ConfigBase = parse.config.base;
367	link->conf.Present = parse.config.rmask[0];
368
369	/*
370	   In this loop, we scan the CIS for configuration table entries,
371	   each of which describes a valid card configuration, including
372	   voltage, IO window, memory window, and interrupt settings.
373
374	   We make no assumptions about the card to be configured: we use
375	   just the information available in the CIS.  In an ideal world,
376	   this would work for any PCMCIA card, but it requires a complete
377	   and accurate CIS.  In practice, a driver usually "knows" most of
378	   these things without consulting the CIS, and most client drivers
379	   will only use the CIS to fill in implementation-defined details.
380	 */
381	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
382	if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0) {
383		cs_error(link, GetFirstTuple, last_ret);
384		goto cs_failed;
385	}
386	while (1) {
387		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
388		if (pcmcia_get_tuple_data(link, &tuple) != 0)
389			goto next_entry;
390		if (pcmcia_parse_tuple(&tuple, &parse) != 0)
391			goto next_entry;
392
393		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
394			dflt = *cfg;
395		if (cfg->index == 0)
396			goto next_entry;
397		link->conf.ConfigIndex = cfg->index;
398
399		/* Does this card need audio output? */
400		if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
401			link->conf.Attributes |= CONF_ENABLE_SPKR;
402			link->conf.Status = CCSR_AUDIO_ENA;
403		}
404
405		/* Do we need to allocate an interrupt? */
406		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
407			link->conf.Attributes |= CONF_ENABLE_IRQ;
408
409		/* IO window settings */
410		link->io.NumPorts1 = link->io.NumPorts2 = 0;
411		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
412			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
413			link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
414			if (!(io->flags & CISTPL_IO_8BIT))
415				link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
416			if (!(io->flags & CISTPL_IO_16BIT))
417				link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
418			link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
419			link->io.BasePort1 = io->win[0].base;
420			link->io.NumPorts1 = io->win[0].len;
421			if (io->nwin > 1) {
422				link->io.Attributes2 = link->io.Attributes1;
423				link->io.BasePort2 = io->win[1].base;
424				link->io.NumPorts2 = io->win[1].len;
425			}
426			/* This reserves IO space but doesn't actually enable it */
427			if (pcmcia_request_io(link, &link->io) != 0)
428				goto next_entry;
429		}
430
431		if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
432			cistpl_mem_t *mem =
433				(cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
434			req.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM;
435			req.Attributes |= WIN_ENABLE;
436			req.Base = mem->win[0].host_addr;
437			req.Size = mem->win[0].len;
438			if (req.Size < 0x1000)
439				req.Size = 0x1000;
440			req.AccessSpeed = 0;
441			if (pcmcia_request_window(&link, &req, &link->win))
442				goto next_entry;
443			map.Page = 0;
444			map.CardOffset = mem->win[0].card_addr;
445			if (pcmcia_map_mem_page(link->win, &map))
446				goto next_entry;
447		}
448		/* If we got this far, we're cool! */
449		break;
450
451	      next_entry:
452		if ((last_ret = pcmcia_get_next_tuple(link, &tuple)) != 0) {
453			cs_error(link, GetNextTuple, last_ret);
454			goto cs_failed;
455		}
456	}
457
458	/*
459	   Allocate an interrupt line.  Note that this does not assign a
460	   handler to the interrupt, unless the 'Handler' member of the
461	   irq structure is initialized.
462	 */
463	if (link->conf.Attributes & CONF_ENABLE_IRQ)
464		if ((last_ret = pcmcia_request_irq(link, &link->irq)) != 0) {
465			cs_error(link, RequestIRQ, last_ret);
466			goto cs_failed;
467		}
468
469	/*
470	   This actually configures the PCMCIA socket -- setting up
471	   the I/O windows and the interrupt mapping, and putting the
472	   card and host interface into "Memory and IO" mode.
473	 */
474	if ((last_ret = pcmcia_request_configuration(link, &link->conf)) != 0) {
475		cs_error(link, RequestConfiguration, last_ret);
476		goto cs_failed;
477	}
478
479	/*
480	   At this point, the dev_node_t structure(s) need to be
481	   initialized and arranged in a linked list at link->dev.
482	 */
483	sprintf(dev->node.dev_name, "ni_daq_dio24");
484	dev->node.major = dev->node.minor = 0;
485	link->dev_node = &dev->node;
486
487	/* Finally, report what we've done */
488	printk(KERN_INFO "%s: index 0x%02x",
489		dev->node.dev_name, link->conf.ConfigIndex);
490	if (link->conf.Attributes & CONF_ENABLE_IRQ)
491		printk(", irq %d", link->irq.AssignedIRQ);
492	if (link->io.NumPorts1)
493		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
494			link->io.BasePort1 + link->io.NumPorts1 - 1);
495	if (link->io.NumPorts2)
496		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
497			link->io.BasePort2 + link->io.NumPorts2 - 1);
498	if (link->win)
499		printk(", mem 0x%06lx-0x%06lx", req.Base,
500			req.Base + req.Size - 1);
501	printk("\n");
502
503	return;
504
505      cs_failed:
506	printk(KERN_INFO "Fallo");
507	dio24_release(link);
508
509}				/* dio24_config */
510
511static void dio24_release(struct pcmcia_device *link)
512{
513	DEBUG(0, "dio24_release(0x%p)\n", link);
514
515	pcmcia_disable_device(link);
516}				/* dio24_release */
517
518/*======================================================================
519
520    The card status event handler.  Mostly, this schedules other
521    stuff to run after an event is received.
522
523    When a CARD_REMOVAL event is received, we immediately set a
524    private flag to block future accesses to this device.  All the
525    functions that actually access the device should check this flag
526    to make sure the card is still present.
527
528======================================================================*/
529
530static int dio24_cs_suspend(struct pcmcia_device *link)
531{
532	local_info_t *local = link->priv;
533
534	/* Mark the device as stopped, to block IO until later */
535	local->stop = 1;
536	return 0;
537}				/* dio24_cs_suspend */
538
539static int dio24_cs_resume(struct pcmcia_device *link)
540{
541	local_info_t *local = link->priv;
542
543	local->stop = 0;
544	return 0;
545}				/* dio24_cs_resume */
546
547/*====================================================================*/
548
549static struct pcmcia_device_id dio24_cs_ids[] = {
550	/* N.B. These IDs should match those in dio24_boards */
551	PCMCIA_DEVICE_MANF_CARD(0x010b, 0x475c),	/* daqcard-dio24 */
552	PCMCIA_DEVICE_NULL
553};
554
555MODULE_DEVICE_TABLE(pcmcia, dio24_cs_ids);
556
557struct pcmcia_driver dio24_cs_driver = {
558	.probe = dio24_cs_attach,
559	.remove = dio24_cs_detach,
560	.suspend = dio24_cs_suspend,
561	.resume = dio24_cs_resume,
562	.id_table = dio24_cs_ids,
563	.owner = THIS_MODULE,
564	.drv = {
565			.name = dev_info,
566		},
567};
568
569static int __init init_dio24_cs(void)
570{
571	printk("ni_daq_dio24: HOLA SOY YO!\n");
572	DEBUG(0, "%s\n", version);
573	pcmcia_register_driver(&dio24_cs_driver);
574	return 0;
575}
576
577static void __exit exit_dio24_cs(void)
578{
579	DEBUG(0, "ni_dio24: unloading\n");
580	pcmcia_unregister_driver(&dio24_cs_driver);
581}
582
583int __init init_module(void)
584{
585	int ret;
586
587	ret = init_dio24_cs();
588	if (ret < 0)
589		return ret;
590
591	return comedi_driver_register(&driver_dio24);
592}
593
594void __exit cleanup_module(void)
595{
596	exit_dio24_cs();
597	comedi_driver_unregister(&driver_dio24);
598}
599