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