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