ni_daq_700.c revision 2e9b981a7c63ee8278df6823f8389d69dad1a499
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 void *priv_data) 534{ 535 if (p_dev->config_index == 0) 536 return -EINVAL; 537 538 return pcmcia_request_io(p_dev); 539} 540 541static void dio700_config(struct pcmcia_device *link) 542{ 543 win_req_t req; 544 int ret; 545 546 printk(KERN_INFO "ni_daq_700: cs-config\n"); 547 548 dev_dbg(&link->dev, "dio700_config\n"); 549 550 link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO | 551 CONF_AUTO_SET_IO; 552 553 ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, NULL); 554 if (ret) { 555 dev_warn(&link->dev, "no configuration found\n"); 556 goto failed; 557 } 558 559 if (!link->irq) 560 goto failed; 561 562 /* 563 This actually configures the PCMCIA socket -- setting up 564 the I/O windows and the interrupt mapping, and putting the 565 card and host interface into "Memory and IO" mode. 566 */ 567 ret = pcmcia_enable_device(link); 568 if (ret != 0) 569 goto failed; 570 571 return; 572 573failed: 574 printk(KERN_INFO "ni_daq_700 cs failed"); 575 dio700_release(link); 576 577} /* dio700_config */ 578 579static void dio700_release(struct pcmcia_device *link) 580{ 581 dev_dbg(&link->dev, "dio700_release\n"); 582 583 pcmcia_disable_device(link); 584} /* dio700_release */ 585 586/*====================================================================== 587 588 The card status event handler. Mostly, this schedules other 589 stuff to run after an event is received. 590 591 When a CARD_REMOVAL event is received, we immediately set a 592 private flag to block future accesses to this device. All the 593 functions that actually access the device should check this flag 594 to make sure the card is still present. 595 596======================================================================*/ 597 598static int dio700_cs_suspend(struct pcmcia_device *link) 599{ 600 struct local_info_t *local = link->priv; 601 602 /* Mark the device as stopped, to block IO until later */ 603 local->stop = 1; 604 return 0; 605} /* dio700_cs_suspend */ 606 607static int dio700_cs_resume(struct pcmcia_device *link) 608{ 609 struct local_info_t *local = link->priv; 610 611 local->stop = 0; 612 return 0; 613} /* dio700_cs_resume */ 614 615/*====================================================================*/ 616 617static struct pcmcia_device_id dio700_cs_ids[] = { 618 /* N.B. These IDs should match those in dio700_boards */ 619 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4743), /* daqcard-700 */ 620 PCMCIA_DEVICE_NULL 621}; 622 623 624MODULE_DEVICE_TABLE(pcmcia, dio700_cs_ids); 625MODULE_AUTHOR("Fred Brooks <nsaspook@nsaspook.com>"); 626MODULE_DESCRIPTION("Comedi driver for National Instruments " 627 "PCMCIA DAQCard-700 DIO"); 628MODULE_LICENSE("GPL"); 629 630struct pcmcia_driver dio700_cs_driver = { 631 .probe = dio700_cs_attach, 632 .remove = dio700_cs_detach, 633 .suspend = dio700_cs_suspend, 634 .resume = dio700_cs_resume, 635 .id_table = dio700_cs_ids, 636 .owner = THIS_MODULE, 637 .name = "ni_daq_700", 638}; 639 640static int __init init_dio700_cs(void) 641{ 642 pcmcia_register_driver(&dio700_cs_driver); 643 return 0; 644} 645 646static void __exit exit_dio700_cs(void) 647{ 648 pr_debug("ni_daq_700: unloading\n"); 649 pcmcia_unregister_driver(&dio700_cs_driver); 650} 651 652int __init init_module(void) 653{ 654 int ret; 655 656 ret = init_dio700_cs(); 657 if (ret < 0) 658 return ret; 659 660 return comedi_driver_register(&driver_dio700); 661} 662 663void __exit cleanup_module(void) 664{ 665 exit_dio700_cs(); 666 comedi_driver_unregister(&driver_dio700); 667} 668