ni_daq_dio24.c revision 8629efa4cbf6f89a54a85af4b8bc31762af01800
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 = ARRAY_SIZE(dio24_boards),
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
239struct local_info_t {
240	struct pcmcia_device *link;
241	dev_node_t node;
242	int stop;
243	struct bus_operations *bus;
244};
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	struct 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(struct 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		((struct 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	struct 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
355	last_ret = pcmcia_get_first_tuple(link, &tuple);
356	if (last_ret) {
357		cs_error(link, GetFirstTuple, last_ret);
358		goto cs_failed;
359	}
360
361	last_ret = pcmcia_get_tuple_data(link, &tuple);
362	if (last_ret) {
363		cs_error(link, GetTupleData, last_ret);
364		goto cs_failed;
365	}
366
367	last_ret = pcmcia_parse_tuple(&tuple, &parse);
368	if (last_ret) {
369		cs_error(link, ParseTuple, last_ret);
370		goto cs_failed;
371	}
372	link->conf.ConfigBase = parse.config.base;
373	link->conf.Present = parse.config.rmask[0];
374
375	/*
376	   In this loop, we scan the CIS for configuration table entries,
377	   each of which describes a valid card configuration, including
378	   voltage, IO window, memory window, and interrupt settings.
379
380	   We make no assumptions about the card to be configured: we use
381	   just the information available in the CIS.  In an ideal world,
382	   this would work for any PCMCIA card, but it requires a complete
383	   and accurate CIS.  In practice, a driver usually "knows" most of
384	   these things without consulting the CIS, and most client drivers
385	   will only use the CIS to fill in implementation-defined details.
386	 */
387	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
388
389	last_ret = pcmcia_get_first_tuple(link, &tuple);
390	if (last_ret) {
391		cs_error(link, GetFirstTuple, last_ret);
392		goto cs_failed;
393	}
394	while (1) {
395		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
396		if (pcmcia_get_tuple_data(link, &tuple) != 0)
397			goto next_entry;
398		if (pcmcia_parse_tuple(&tuple, &parse) != 0)
399			goto next_entry;
400
401		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
402			dflt = *cfg;
403		if (cfg->index == 0)
404			goto next_entry;
405		link->conf.ConfigIndex = cfg->index;
406
407		/* Does this card need audio output? */
408		if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
409			link->conf.Attributes |= CONF_ENABLE_SPKR;
410			link->conf.Status = CCSR_AUDIO_ENA;
411		}
412
413		/* Do we need to allocate an interrupt? */
414		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
415			link->conf.Attributes |= CONF_ENABLE_IRQ;
416
417		/* IO window settings */
418		link->io.NumPorts1 = link->io.NumPorts2 = 0;
419		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
420			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
421			link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
422			if (!(io->flags & CISTPL_IO_8BIT))
423				link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
424			if (!(io->flags & CISTPL_IO_16BIT))
425				link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
426			link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
427			link->io.BasePort1 = io->win[0].base;
428			link->io.NumPorts1 = io->win[0].len;
429			if (io->nwin > 1) {
430				link->io.Attributes2 = link->io.Attributes1;
431				link->io.BasePort2 = io->win[1].base;
432				link->io.NumPorts2 = io->win[1].len;
433			}
434			/* This reserves IO space but doesn't actually enable it */
435			if (pcmcia_request_io(link, &link->io) != 0)
436				goto next_entry;
437		}
438
439		if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
440			cistpl_mem_t *mem =
441				(cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
442			req.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM;
443			req.Attributes |= WIN_ENABLE;
444			req.Base = mem->win[0].host_addr;
445			req.Size = mem->win[0].len;
446			if (req.Size < 0x1000)
447				req.Size = 0x1000;
448			req.AccessSpeed = 0;
449			if (pcmcia_request_window(&link, &req, &link->win))
450				goto next_entry;
451			map.Page = 0;
452			map.CardOffset = mem->win[0].card_addr;
453			if (pcmcia_map_mem_page(link->win, &map))
454				goto next_entry;
455		}
456		/* If we got this far, we're cool! */
457		break;
458
459	      next_entry:
460
461		last_ret = pcmcia_get_next_tuple(link, &tuple);
462		if (last_ret) {
463			cs_error(link, GetNextTuple, last_ret);
464			goto cs_failed;
465		}
466	}
467
468	/*
469	   Allocate an interrupt line.  Note that this does not assign a
470	   handler to the interrupt, unless the 'Handler' member of the
471	   irq structure is initialized.
472	 */
473	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
474		last_ret = pcmcia_request_irq(link, &link->irq);
475		if (last_ret) {
476			cs_error(link, RequestIRQ, last_ret);
477			goto cs_failed;
478		}
479	}
480
481	/*
482	   This actually configures the PCMCIA socket -- setting up
483	   the I/O windows and the interrupt mapping, and putting the
484	   card and host interface into "Memory and IO" mode.
485	 */
486	last_ret = pcmcia_request_configuration(link, &link->conf);
487	if (last_ret) {
488		cs_error(link, RequestConfiguration, last_ret);
489		goto cs_failed;
490	}
491
492	/*
493	   At this point, the dev_node_t structure(s) need to be
494	   initialized and arranged in a linked list at link->dev.
495	 */
496	sprintf(dev->node.dev_name, "ni_daq_dio24");
497	dev->node.major = dev->node.minor = 0;
498	link->dev_node = &dev->node;
499
500	/* Finally, report what we've done */
501	printk(KERN_INFO "%s: index 0x%02x",
502		dev->node.dev_name, link->conf.ConfigIndex);
503	if (link->conf.Attributes & CONF_ENABLE_IRQ)
504		printk(", irq %d", link->irq.AssignedIRQ);
505	if (link->io.NumPorts1)
506		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
507			link->io.BasePort1 + link->io.NumPorts1 - 1);
508	if (link->io.NumPorts2)
509		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
510			link->io.BasePort2 + link->io.NumPorts2 - 1);
511	if (link->win)
512		printk(", mem 0x%06lx-0x%06lx", req.Base,
513			req.Base + req.Size - 1);
514	printk("\n");
515
516	return;
517
518      cs_failed:
519	printk(KERN_INFO "Fallo");
520	dio24_release(link);
521
522}				/* dio24_config */
523
524static void dio24_release(struct pcmcia_device *link)
525{
526	DEBUG(0, "dio24_release(0x%p)\n", link);
527
528	pcmcia_disable_device(link);
529}				/* dio24_release */
530
531/*======================================================================
532
533    The card status event handler.  Mostly, this schedules other
534    stuff to run after an event is received.
535
536    When a CARD_REMOVAL event is received, we immediately set a
537    private flag to block future accesses to this device.  All the
538    functions that actually access the device should check this flag
539    to make sure the card is still present.
540
541======================================================================*/
542
543static int dio24_cs_suspend(struct pcmcia_device *link)
544{
545	struct local_info_t *local = link->priv;
546
547	/* Mark the device as stopped, to block IO until later */
548	local->stop = 1;
549	return 0;
550}				/* dio24_cs_suspend */
551
552static int dio24_cs_resume(struct pcmcia_device *link)
553{
554	struct local_info_t *local = link->priv;
555
556	local->stop = 0;
557	return 0;
558}				/* dio24_cs_resume */
559
560/*====================================================================*/
561
562static struct pcmcia_device_id dio24_cs_ids[] = {
563	/* N.B. These IDs should match those in dio24_boards */
564	PCMCIA_DEVICE_MANF_CARD(0x010b, 0x475c),	/* daqcard-dio24 */
565	PCMCIA_DEVICE_NULL
566};
567
568MODULE_DEVICE_TABLE(pcmcia, dio24_cs_ids);
569
570struct pcmcia_driver dio24_cs_driver = {
571	.probe = dio24_cs_attach,
572	.remove = dio24_cs_detach,
573	.suspend = dio24_cs_suspend,
574	.resume = dio24_cs_resume,
575	.id_table = dio24_cs_ids,
576	.owner = THIS_MODULE,
577	.drv = {
578			.name = dev_info,
579		},
580};
581
582static int __init init_dio24_cs(void)
583{
584	printk("ni_daq_dio24: HOLA SOY YO!\n");
585	DEBUG(0, "%s\n", version);
586	pcmcia_register_driver(&dio24_cs_driver);
587	return 0;
588}
589
590static void __exit exit_dio24_cs(void)
591{
592	DEBUG(0, "ni_dio24: unloading\n");
593	pcmcia_unregister_driver(&dio24_cs_driver);
594}
595
596int __init init_module(void)
597{
598	int ret;
599
600	ret = init_dio24_cs();
601	if (ret < 0)
602		return ret;
603
604	return comedi_driver_register(&driver_dio24);
605}
606
607void __exit cleanup_module(void)
608{
609	exit_dio24_cs();
610	comedi_driver_unregister(&driver_dio24);
611}
612