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