cb_das16_cs.c revision 25436dc9d84f1be60ff549c9ab712bba2835f284
1/* 2 comedi/drivers/das16cs.c 3 Driver for Computer Boards PC-CARD DAS16/16. 4 5 COMEDI - Linux Control and Measurement Device Interface 6 Copyright (C) 2000, 2001, 2002 David A. Schleef <ds@schleef.org> 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 22*/ 23/* 24Driver: cb_das16_cs 25Description: Computer Boards PC-CARD DAS16/16 26Devices: [ComputerBoards] PC-CARD DAS16/16 (cb_das16_cs), PC-CARD DAS16/16-AO 27Author: ds 28Updated: Mon, 04 Nov 2002 20:04:21 -0800 29Status: experimental 30 31 32*/ 33 34#include <linux/interrupt.h> 35#include "../comedidev.h" 36#include <linux/delay.h> 37#include <linux/pci.h> 38 39#include <pcmcia/cs_types.h> 40#include <pcmcia/cs.h> 41#include <pcmcia/cistpl.h> 42#include <pcmcia/ds.h> 43 44#include "8253.h" 45 46#define DAS16CS_SIZE 18 47 48#define DAS16CS_ADC_DATA 0 49#define DAS16CS_DIO_MUX 2 50#define DAS16CS_MISC1 4 51#define DAS16CS_MISC2 6 52#define DAS16CS_CTR0 8 53#define DAS16CS_CTR1 10 54#define DAS16CS_CTR2 12 55#define DAS16CS_CTR_CONTROL 14 56#define DAS16CS_DIO 16 57 58struct das16cs_board { 59 const char *name; 60 int device_id; 61 int n_ao_chans; 62}; 63static const struct das16cs_board das16cs_boards[] = { 64 { 65 .device_id = 0x0000,/* unknown */ 66 .name = "PC-CARD DAS16/16", 67 .n_ao_chans = 0, 68 }, 69 { 70 .device_id = 0x0039, 71 .name = "PC-CARD DAS16/16-AO", 72 .n_ao_chans = 2, 73 }, 74 { 75 .device_id = 0x4009, 76 .name = "PCM-DAS16s/16", 77 .n_ao_chans = 0, 78 }, 79}; 80 81#define n_boards (sizeof(das16cs_boards)/sizeof(das16cs_boards[0])) 82#define thisboard ((const struct das16cs_board *)dev->board_ptr) 83 84struct das16cs_private { 85 struct pcmcia_device *link; 86 87 unsigned int ao_readback[2]; 88 unsigned short status1; 89 unsigned short status2; 90}; 91#define devpriv ((struct das16cs_private *)dev->private) 92 93static int das16cs_attach(struct comedi_device *dev, struct comedi_devconfig *it); 94static int das16cs_detach(struct comedi_device *dev); 95static struct comedi_driver driver_das16cs = { 96 .driver_name = "cb_das16_cs", 97 .module = THIS_MODULE, 98 .attach = das16cs_attach, 99 .detach = das16cs_detach, 100}; 101 102static struct pcmcia_device *cur_dev = NULL; 103 104static const struct comedi_lrange das16cs_ai_range = { 4, { 105 RANGE(-10, 10), 106 RANGE(-5, 5), 107 RANGE(-2.5, 2.5), 108 RANGE(-1.25, 1.25), 109 } 110}; 111 112static irqreturn_t das16cs_interrupt(int irq, void *d); 113static int das16cs_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 114 struct comedi_insn *insn, unsigned int *data); 115static int das16cs_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s); 116static int das16cs_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, 117 struct comedi_cmd *cmd); 118static int das16cs_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, 119 struct comedi_insn *insn, unsigned int *data); 120static int das16cs_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 121 struct comedi_insn *insn, unsigned int *data); 122static int das16cs_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, 123 struct comedi_insn *insn, unsigned int *data); 124static int das16cs_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, 125 struct comedi_insn *insn, unsigned int *data); 126static int das16cs_timer_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, 127 struct comedi_insn *insn, unsigned int *data); 128static int das16cs_timer_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, 129 struct comedi_insn *insn, unsigned int *data); 130 131static int get_prodid(struct comedi_device *dev, struct pcmcia_device *link) 132{ 133 tuple_t tuple; 134 u_short buf[128]; 135 int prodid = 0; 136 137 tuple.TupleData = (cisdata_t *) buf; 138 tuple.TupleOffset = 0; 139 tuple.TupleDataMax = 255; 140 tuple.DesiredTuple = CISTPL_MANFID; 141 tuple.Attributes = TUPLE_RETURN_COMMON; 142 if ((pcmcia_get_first_tuple(link, &tuple) == 0) && 143 (pcmcia_get_tuple_data(link, &tuple) == 0)) { 144 prodid = le16_to_cpu(buf[1]); 145 } 146 147 return prodid; 148} 149 150static const struct das16cs_board *das16cs_probe(struct comedi_device * dev, 151 struct pcmcia_device *link) 152{ 153 int id; 154 int i; 155 156 id = get_prodid(dev, link); 157 158 for (i = 0; i < n_boards; i++) { 159 if (das16cs_boards[i].device_id == id) { 160 return das16cs_boards + i; 161 } 162 } 163 164 printk("unknown board!\n"); 165 166 return NULL; 167} 168 169static int das16cs_attach(struct comedi_device *dev, struct comedi_devconfig *it) 170{ 171 struct pcmcia_device *link; 172 struct comedi_subdevice *s; 173 int ret; 174 int i; 175 176 printk("comedi%d: cb_das16_cs: ", dev->minor); 177 178 link = cur_dev; /* XXX hack */ 179 if (!link) 180 return -EIO; 181 182 dev->iobase = link->io.BasePort1; 183 printk("I/O base=0x%04lx ", dev->iobase); 184 185 printk("fingerprint:\n"); 186 for (i = 0; i < 48; i += 2) { 187 printk("%04x ", inw(dev->iobase + i)); 188 } 189 printk("\n"); 190 191 ret = request_irq(link->irq.AssignedIRQ, das16cs_interrupt, 192 IRQF_SHARED, "cb_das16_cs", dev); 193 if (ret < 0) { 194 return ret; 195 } 196 dev->irq = link->irq.AssignedIRQ; 197 printk("irq=%u ", dev->irq); 198 199 dev->board_ptr = das16cs_probe(dev, link); 200 if (!dev->board_ptr) 201 return -EIO; 202 203 dev->board_name = thisboard->name; 204 205 if (alloc_private(dev, sizeof(struct das16cs_private)) < 0) 206 return -ENOMEM; 207 208 if (alloc_subdevices(dev, 4) < 0) 209 return -ENOMEM; 210 211 s = dev->subdevices + 0; 212 dev->read_subdev = s; 213 /* analog input subdevice */ 214 s->type = COMEDI_SUBD_AI; 215 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; 216 s->n_chan = 16; 217 s->maxdata = 0xffff; 218 s->range_table = &das16cs_ai_range; 219 s->len_chanlist = 16; 220 s->insn_read = das16cs_ai_rinsn; 221 s->do_cmd = das16cs_ai_cmd; 222 s->do_cmdtest = das16cs_ai_cmdtest; 223 224 s = dev->subdevices + 1; 225 /* analog output subdevice */ 226 if (thisboard->n_ao_chans) { 227 s->type = COMEDI_SUBD_AO; 228 s->subdev_flags = SDF_WRITABLE; 229 s->n_chan = thisboard->n_ao_chans; 230 s->maxdata = 0xffff; 231 s->range_table = &range_bipolar10; 232 s->insn_write = &das16cs_ao_winsn; 233 s->insn_read = &das16cs_ao_rinsn; 234 } 235 236 s = dev->subdevices + 2; 237 /* digital i/o subdevice */ 238 if (1) { 239 s->type = COMEDI_SUBD_DIO; 240 s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 241 s->n_chan = 8; 242 s->maxdata = 1; 243 s->range_table = &range_digital; 244 s->insn_bits = das16cs_dio_insn_bits; 245 s->insn_config = das16cs_dio_insn_config; 246 } else { 247 s->type = COMEDI_SUBD_UNUSED; 248 } 249 250 s = dev->subdevices + 3; 251 /* timer subdevice */ 252 if (0) { 253 s->type = COMEDI_SUBD_TIMER; 254 s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 255 s->n_chan = 1; 256 s->maxdata = 0xff; 257 s->range_table = &range_unknown; 258 s->insn_read = das16cs_timer_insn_read; 259 s->insn_config = das16cs_timer_insn_config; 260 } else { 261 s->type = COMEDI_SUBD_UNUSED; 262 } 263 264 printk("attached\n"); 265 266 return 1; 267} 268 269static int das16cs_detach(struct comedi_device *dev) 270{ 271 printk("comedi%d: das16cs: remove\n", dev->minor); 272 273 if (dev->irq) { 274 free_irq(dev->irq, dev); 275 } 276 277 return 0; 278} 279 280static irqreturn_t das16cs_interrupt(int irq, void *d) 281{ 282 /* struct comedi_device *dev = d; */ 283 return IRQ_HANDLED; 284} 285 286/* 287 * "instructions" read/write data in "one-shot" or "software-triggered" 288 * mode. 289 */ 290static int das16cs_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 291 struct comedi_insn *insn, unsigned int *data) 292{ 293 int i; 294 int to; 295 int aref; 296 int range; 297 int chan; 298 static int range_bits[] = { 0x800, 0x000, 0x100, 0x200 }; 299 300 chan = CR_CHAN(insn->chanspec); 301 aref = CR_AREF(insn->chanspec); 302 range = CR_RANGE(insn->chanspec); 303 304 outw(chan, dev->iobase + 2); 305 306 devpriv->status1 &= ~0xf320; 307 devpriv->status1 |= (aref == AREF_DIFF) ? 0 : 0x0020; 308 outw(devpriv->status1, dev->iobase + 4); 309 310 devpriv->status2 &= ~0xff00; 311 devpriv->status2 |= range_bits[range]; 312 outw(devpriv->status2, dev->iobase + 6); 313 314 for (i = 0; i < insn->n; i++) { 315 outw(0, dev->iobase); 316 317#define TIMEOUT 1000 318 for (to = 0; to < TIMEOUT; to++) { 319 if (inw(dev->iobase + 4) & 0x0080) 320 break; 321 } 322 if (to == TIMEOUT) { 323 printk("cb_das16_cs: ai timeout\n"); 324 return -ETIME; 325 } 326 data[i] = (unsigned short)inw(dev->iobase + 0); 327 } 328 329 return i; 330} 331 332static int das16cs_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 333{ 334 return -EINVAL; 335} 336 337static int das16cs_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, 338 struct comedi_cmd *cmd) 339{ 340 int err = 0; 341 int tmp; 342 343 /* cmdtest tests a particular command to see if it is valid. 344 * Using the cmdtest ioctl, a user can create a valid cmd 345 * and then have it executes by the cmd ioctl. 346 * 347 * cmdtest returns 1,2,3,4 or 0, depending on which tests 348 * the command passes. */ 349 350 /* step 1: make sure trigger sources are trivially valid */ 351 352 tmp = cmd->start_src; 353 cmd->start_src &= TRIG_NOW; 354 if (!cmd->start_src || tmp != cmd->start_src) 355 err++; 356 357 tmp = cmd->scan_begin_src; 358 cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; 359 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 360 err++; 361 362 tmp = cmd->convert_src; 363 cmd->convert_src &= TRIG_TIMER | TRIG_EXT; 364 if (!cmd->convert_src || tmp != cmd->convert_src) 365 err++; 366 367 tmp = cmd->scan_end_src; 368 cmd->scan_end_src &= TRIG_COUNT; 369 if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 370 err++; 371 372 tmp = cmd->stop_src; 373 cmd->stop_src &= TRIG_COUNT | TRIG_NONE; 374 if (!cmd->stop_src || tmp != cmd->stop_src) 375 err++; 376 377 if (err) 378 return 1; 379 380 /* step 2: make sure trigger sources are unique and mutually compatible */ 381 382 /* note that mutual compatiblity is not an issue here */ 383 if (cmd->scan_begin_src != TRIG_TIMER && 384 cmd->scan_begin_src != TRIG_EXT) 385 err++; 386 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) 387 err++; 388 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) 389 err++; 390 391 if (err) 392 return 2; 393 394 /* step 3: make sure arguments are trivially compatible */ 395 396 if (cmd->start_arg != 0) { 397 cmd->start_arg = 0; 398 err++; 399 } 400#define MAX_SPEED 10000 /* in nanoseconds */ 401#define MIN_SPEED 1000000000 /* in nanoseconds */ 402 403 if (cmd->scan_begin_src == TRIG_TIMER) { 404 if (cmd->scan_begin_arg < MAX_SPEED) { 405 cmd->scan_begin_arg = MAX_SPEED; 406 err++; 407 } 408 if (cmd->scan_begin_arg > MIN_SPEED) { 409 cmd->scan_begin_arg = MIN_SPEED; 410 err++; 411 } 412 } else { 413 /* external trigger */ 414 /* should be level/edge, hi/lo specification here */ 415 /* should specify multiple external triggers */ 416 if (cmd->scan_begin_arg > 9) { 417 cmd->scan_begin_arg = 9; 418 err++; 419 } 420 } 421 if (cmd->convert_src == TRIG_TIMER) { 422 if (cmd->convert_arg < MAX_SPEED) { 423 cmd->convert_arg = MAX_SPEED; 424 err++; 425 } 426 if (cmd->convert_arg > MIN_SPEED) { 427 cmd->convert_arg = MIN_SPEED; 428 err++; 429 } 430 } else { 431 /* external trigger */ 432 /* see above */ 433 if (cmd->convert_arg > 9) { 434 cmd->convert_arg = 9; 435 err++; 436 } 437 } 438 439 if (cmd->scan_end_arg != cmd->chanlist_len) { 440 cmd->scan_end_arg = cmd->chanlist_len; 441 err++; 442 } 443 if (cmd->stop_src == TRIG_COUNT) { 444 if (cmd->stop_arg > 0x00ffffff) { 445 cmd->stop_arg = 0x00ffffff; 446 err++; 447 } 448 } else { 449 /* TRIG_NONE */ 450 if (cmd->stop_arg != 0) { 451 cmd->stop_arg = 0; 452 err++; 453 } 454 } 455 456 if (err) 457 return 3; 458 459 /* step 4: fix up any arguments */ 460 461 if (cmd->scan_begin_src == TRIG_TIMER) { 462 unsigned int div1, div2; 463 464 tmp = cmd->scan_begin_arg; 465 i8253_cascade_ns_to_timer(100, &div1, &div2, 466 &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); 467 if (tmp != cmd->scan_begin_arg) 468 err++; 469 } 470 if (cmd->convert_src == TRIG_TIMER) { 471 unsigned int div1, div2; 472 473 tmp = cmd->convert_arg; 474 i8253_cascade_ns_to_timer(100, &div1, &div2, 475 &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); 476 if (tmp != cmd->convert_arg) 477 err++; 478 if (cmd->scan_begin_src == TRIG_TIMER && 479 cmd->scan_begin_arg < 480 cmd->convert_arg * cmd->scan_end_arg) { 481 cmd->scan_begin_arg = 482 cmd->convert_arg * cmd->scan_end_arg; 483 err++; 484 } 485 } 486 487 if (err) 488 return 4; 489 490 return 0; 491} 492 493static int das16cs_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, 494 struct comedi_insn *insn, unsigned int *data) 495{ 496 int i; 497 int chan = CR_CHAN(insn->chanspec); 498 unsigned short status1; 499 unsigned short d; 500 int bit; 501 502 for (i = 0; i < insn->n; i++) { 503 devpriv->ao_readback[chan] = data[i]; 504 d = data[i]; 505 506 outw(devpriv->status1, dev->iobase + 4); 507 udelay(1); 508 509 status1 = devpriv->status1 & ~0xf; 510 if (chan) 511 status1 |= 0x0001; 512 else 513 status1 |= 0x0008; 514 515/* printk("0x%04x\n",status1);*/ 516 outw(status1, dev->iobase + 4); 517 udelay(1); 518 519 for (bit = 15; bit >= 0; bit--) { 520 int b = (d >> bit) & 0x1; 521 b <<= 1; 522/* printk("0x%04x\n",status1 | b | 0x0000);*/ 523 outw(status1 | b | 0x0000, dev->iobase + 4); 524 udelay(1); 525/* printk("0x%04x\n",status1 | b | 0x0004);*/ 526 outw(status1 | b | 0x0004, dev->iobase + 4); 527 udelay(1); 528 } 529/* make high both DAC0CS and DAC1CS to load 530 new data and update analog output*/ 531 outw(status1 | 0x9, dev->iobase + 4); 532 } 533 534 return i; 535} 536 537/* AO subdevices should have a read insn as well as a write insn. 538 * Usually this means copying a value stored in devpriv. */ 539static int das16cs_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 540 struct comedi_insn *insn, unsigned int *data) 541{ 542 int i; 543 int chan = CR_CHAN(insn->chanspec); 544 545 for (i = 0; i < insn->n; i++) 546 data[i] = devpriv->ao_readback[chan]; 547 548 return i; 549} 550 551/* DIO devices are slightly special. Although it is possible to 552 * implement the insn_read/insn_write interface, it is much more 553 * useful to applications if you implement the insn_bits interface. 554 * This allows packed reading/writing of the DIO channels. The 555 * comedi core can convert between insn_bits and insn_read/write */ 556static int das16cs_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, 557 struct comedi_insn *insn, unsigned int *data) 558{ 559 if (insn->n != 2) 560 return -EINVAL; 561 562 if (data[0]) { 563 s->state &= ~data[0]; 564 s->state |= data[0] & data[1]; 565 566 outw(s->state, dev->iobase + 16); 567 } 568 569 /* on return, data[1] contains the value of the digital 570 * input and output lines. */ 571 data[1] = inw(dev->iobase + 16); 572 573 return 2; 574} 575 576static int das16cs_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, 577 struct comedi_insn *insn, unsigned int *data) 578{ 579 int chan = CR_CHAN(insn->chanspec); 580 int bits; 581 582 if (chan < 4) 583 bits = 0x0f; 584 else 585 bits = 0xf0; 586 587 switch (data[0]) { 588 case INSN_CONFIG_DIO_OUTPUT: 589 s->io_bits |= bits; 590 break; 591 case INSN_CONFIG_DIO_INPUT: 592 s->io_bits &= bits; 593 break; 594 case INSN_CONFIG_DIO_QUERY: 595 data[1] = 596 (s-> 597 io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; 598 return insn->n; 599 break; 600 default: 601 return -EINVAL; 602 break; 603 } 604 605 devpriv->status2 &= ~0x00c0; 606 devpriv->status2 |= (s->io_bits & 0xf0) ? 0x0080 : 0; 607 devpriv->status2 |= (s->io_bits & 0x0f) ? 0x0040 : 0; 608 609 outw(devpriv->status2, dev->iobase + 6); 610 611 return insn->n; 612} 613 614static int das16cs_timer_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, 615 struct comedi_insn *insn, unsigned int *data) 616{ 617 return -EINVAL; 618} 619 620static int das16cs_timer_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, 621 struct comedi_insn *insn, unsigned int *data) 622{ 623 return -EINVAL; 624} 625 626/* PCMCIA stuff */ 627 628/*====================================================================== 629 630 The following pcmcia code for the pcm-das08 is adapted from the 631 dummy_cs.c driver of the Linux PCMCIA Card Services package. 632 633 The initial developer of the original code is David A. Hinds 634 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds 635 are Copyright (C) 1999 David A. Hinds. All Rights Reserved. 636 637======================================================================*/ 638 639/* 640 All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If 641 you do not define PCMCIA_DEBUG at all, all the debug code will be 642 left out. If you compile with PCMCIA_DEBUG=0, the debug code will 643 be present but disabled -- but it can then be enabled for specific 644 modules at load time with a 'pc_debug=#' option to insmod. 645*/ 646#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) 647 648#ifdef PCMCIA_DEBUG 649static int pc_debug = PCMCIA_DEBUG; 650module_param(pc_debug, int, 0644); 651#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) 652static char *version = 653 "cb_das16_cs.c pcmcia code (David Schleef), modified from dummy_cs.c 1.31 2001/08/24 12:13:13 (David Hinds)"; 654#else 655#define DEBUG(n, args...) 656#endif 657 658/*====================================================================*/ 659 660static void das16cs_pcmcia_config(struct pcmcia_device *link); 661static void das16cs_pcmcia_release(struct pcmcia_device *link); 662static int das16cs_pcmcia_suspend(struct pcmcia_device *p_dev); 663static int das16cs_pcmcia_resume(struct pcmcia_device *p_dev); 664 665/* 666 The attach() and detach() entry points are used to create and destroy 667 "instances" of the driver, where each instance represents everything 668 needed to manage one actual PCMCIA card. 669*/ 670 671static int das16cs_pcmcia_attach(struct pcmcia_device *); 672static void das16cs_pcmcia_detach(struct pcmcia_device *); 673 674/* 675 You'll also need to prototype all the functions that will actually 676 be used to talk to your device. See 'memory_cs' for a good example 677 of a fully self-sufficient driver; the other drivers rely more or 678 less on other parts of the kernel. 679*/ 680 681/* 682 The dev_info variable is the "key" that is used to match up this 683 device driver with appropriate cards, through the card configuration 684 database. 685*/ 686 687static dev_info_t dev_info = "cb_das16_cs"; 688 689struct local_info_t { 690 struct pcmcia_device *link; 691 dev_node_t node; 692 int stop; 693 struct bus_operations *bus; 694}; 695 696/*====================================================================== 697 698 das16cs_pcmcia_attach() creates an "instance" of the driver, allocating 699 local data structures for one device. The device is registered 700 with Card Services. 701 702 The dev_link structure is initialized, but we don't actually 703 configure the card at this point -- we wait until we receive a 704 card insertion event. 705 706======================================================================*/ 707 708static int das16cs_pcmcia_attach(struct pcmcia_device *link) 709{ 710 struct local_info_t *local; 711 712 DEBUG(0, "das16cs_pcmcia_attach()\n"); 713 714 /* Allocate space for private device-specific data */ 715 local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL); 716 if (!local) 717 return -ENOMEM; 718 local->link = link; 719 link->priv = local; 720 721 /* Initialize the pcmcia_device structure */ 722 /* Interrupt setup */ 723 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; 724 link->irq.IRQInfo1 = IRQ_LEVEL_ID; 725 link->irq.Handler = NULL; 726 727 link->conf.Attributes = 0; 728 link->conf.IntType = INT_MEMORY_AND_IO; 729 730 cur_dev = link; 731 732 das16cs_pcmcia_config(link); 733 734 return 0; 735} /* das16cs_pcmcia_attach */ 736 737static void das16cs_pcmcia_detach(struct pcmcia_device *link) 738{ 739 DEBUG(0, "das16cs_pcmcia_detach(0x%p)\n", link); 740 741 if (link->dev_node) { 742 ((struct local_info_t *) link->priv)->stop = 1; 743 das16cs_pcmcia_release(link); 744 } 745 /* This points to the parent struct local_info_t struct */ 746 if (link->priv) 747 kfree(link->priv); 748} /* das16cs_pcmcia_detach */ 749 750static void das16cs_pcmcia_config(struct pcmcia_device *link) 751{ 752 struct local_info_t *dev = link->priv; 753 tuple_t tuple; 754 cisparse_t parse; 755 int last_fn, last_ret; 756 u_char buf[64]; 757 cistpl_cftable_entry_t dflt = { 0 }; 758 759 DEBUG(0, "das16cs_pcmcia_config(0x%p)\n", link); 760 761 /* 762 This reads the card's CONFIG tuple to find its configuration 763 registers. 764 */ 765 tuple.DesiredTuple = CISTPL_CONFIG; 766 tuple.Attributes = 0; 767 tuple.TupleData = buf; 768 tuple.TupleDataMax = sizeof(buf); 769 tuple.TupleOffset = 0; 770 771 last_fn = GetFirstTuple; 772 last_ret = pcmcia_get_first_tuple(link, &tuple); 773 if (last_ret != 0) 774 goto cs_failed; 775 776 last_fn = GetTupleData; 777 last_ret = pcmcia_get_tuple_data(link, &tuple); 778 if (last_ret != 0) 779 goto cs_failed; 780 781 last_fn = ParseTuple; 782 last_ret = pcmcia_parse_tuple(&tuple, &parse); 783 if (last_ret != 0) 784 goto cs_failed; 785 786 link->conf.ConfigBase = parse.config.base; 787 link->conf.Present = parse.config.rmask[0]; 788 789 /* 790 In this loop, we scan the CIS for configuration table entries, 791 each of which describes a valid card configuration, including 792 voltage, IO window, memory window, and interrupt settings. 793 794 We make no assumptions about the card to be configured: we use 795 just the information available in the CIS. In an ideal world, 796 this would work for any PCMCIA card, but it requires a complete 797 and accurate CIS. In practice, a driver usually "knows" most of 798 these things without consulting the CIS, and most client drivers 799 will only use the CIS to fill in implementation-defined details. 800 */ 801 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 802 last_fn = GetFirstTuple; 803 804 last_ret = pcmcia_get_first_tuple(link, &tuple); 805 if (last_ret) 806 goto cs_failed; 807 808 while (1) { 809 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); 810 if (pcmcia_get_tuple_data(link, &tuple)) 811 goto next_entry; 812 if (pcmcia_parse_tuple(&tuple, &parse)) 813 goto next_entry; 814 815 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) 816 dflt = *cfg; 817 if (cfg->index == 0) 818 goto next_entry; 819 link->conf.ConfigIndex = cfg->index; 820 821 /* Does this card need audio output? */ 822/* if (cfg->flags & CISTPL_CFTABLE_AUDIO) { 823 link->conf.Attributes |= CONF_ENABLE_SPKR; 824 link->conf.Status = CCSR_AUDIO_ENA; 825 } 826*/ 827 /* Do we need to allocate an interrupt? */ 828 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) 829 link->conf.Attributes |= CONF_ENABLE_IRQ; 830 831 /* IO window settings */ 832 link->io.NumPorts1 = link->io.NumPorts2 = 0; 833 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { 834 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; 835 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; 836 if (!(io->flags & CISTPL_IO_8BIT)) 837 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; 838 if (!(io->flags & CISTPL_IO_16BIT)) 839 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; 840 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; 841 link->io.BasePort1 = io->win[0].base; 842 link->io.NumPorts1 = io->win[0].len; 843 if (io->nwin > 1) { 844 link->io.Attributes2 = link->io.Attributes1; 845 link->io.BasePort2 = io->win[1].base; 846 link->io.NumPorts2 = io->win[1].len; 847 } 848 /* This reserves IO space but doesn't actually enable it */ 849 if (pcmcia_request_io(link, &link->io)) 850 goto next_entry; 851 } 852 853 /* If we got this far, we're cool! */ 854 break; 855 856 next_entry: 857 last_fn = GetNextTuple; 858 859 last_ret = pcmcia_get_next_tuple(link, &tuple); 860 if (last_ret) 861 goto cs_failed; 862 } 863 864 /* 865 Allocate an interrupt line. Note that this does not assign a 866 handler to the interrupt, unless the 'Handler' member of the 867 irq structure is initialized. 868 */ 869 if (link->conf.Attributes & CONF_ENABLE_IRQ) { 870 last_fn = RequestIRQ; 871 872 last_ret = pcmcia_request_irq(link, &link->irq); 873 if (last_ret) 874 goto cs_failed; 875 } 876 /* 877 This actually configures the PCMCIA socket -- setting up 878 the I/O windows and the interrupt mapping, and putting the 879 card and host interface into "Memory and IO" mode. 880 */ 881 last_fn = RequestConfiguration; 882 last_ret = pcmcia_request_configuration(link, &link->conf); 883 if (last_ret) 884 goto cs_failed; 885 886 /* 887 At this point, the dev_node_t structure(s) need to be 888 initialized and arranged in a linked list at link->dev. 889 */ 890 sprintf(dev->node.dev_name, "cb_das16_cs"); 891 dev->node.major = dev->node.minor = 0; 892 link->dev_node = &dev->node; 893 894 /* Finally, report what we've done */ 895 printk(KERN_INFO "%s: index 0x%02x", 896 dev->node.dev_name, link->conf.ConfigIndex); 897 if (link->conf.Attributes & CONF_ENABLE_IRQ) 898 printk(", irq %u", link->irq.AssignedIRQ); 899 if (link->io.NumPorts1) 900 printk(", io 0x%04x-0x%04x", link->io.BasePort1, 901 link->io.BasePort1 + link->io.NumPorts1 - 1); 902 if (link->io.NumPorts2) 903 printk(" & 0x%04x-0x%04x", link->io.BasePort2, 904 link->io.BasePort2 + link->io.NumPorts2 - 1); 905 printk("\n"); 906 907 return; 908 909 cs_failed: 910 cs_error(link, last_fn, last_ret); 911 das16cs_pcmcia_release(link); 912} /* das16cs_pcmcia_config */ 913 914static void das16cs_pcmcia_release(struct pcmcia_device *link) 915{ 916 DEBUG(0, "das16cs_pcmcia_release(0x%p)\n", link); 917 pcmcia_disable_device(link); 918} /* das16cs_pcmcia_release */ 919 920static int das16cs_pcmcia_suspend(struct pcmcia_device *link) 921{ 922 struct local_info_t *local = link->priv; 923 924 /* Mark the device as stopped, to block IO until later */ 925 local->stop = 1; 926 927 return 0; 928} /* das16cs_pcmcia_suspend */ 929 930static int das16cs_pcmcia_resume(struct pcmcia_device *link) 931{ 932 struct local_info_t *local = link->priv; 933 934 local->stop = 0; 935 return 0; 936} /* das16cs_pcmcia_resume */ 937 938/*====================================================================*/ 939 940static struct pcmcia_device_id das16cs_id_table[] = { 941 PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x0039), 942 PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4009), 943 PCMCIA_DEVICE_NULL 944}; 945 946MODULE_DEVICE_TABLE(pcmcia, das16cs_id_table); 947 948struct pcmcia_driver das16cs_driver = { 949 .probe = das16cs_pcmcia_attach, 950 .remove = das16cs_pcmcia_detach, 951 .suspend = das16cs_pcmcia_suspend, 952 .resume = das16cs_pcmcia_resume, 953 .id_table = das16cs_id_table, 954 .owner = THIS_MODULE, 955 .drv = { 956 .name = dev_info, 957 }, 958}; 959 960static int __init init_das16cs_pcmcia_cs(void) 961{ 962 DEBUG(0, "%s\n", version); 963 pcmcia_register_driver(&das16cs_driver); 964 return 0; 965} 966 967static void __exit exit_das16cs_pcmcia_cs(void) 968{ 969 DEBUG(0, "das16cs_pcmcia_cs: unloading\n"); 970 pcmcia_unregister_driver(&das16cs_driver); 971} 972 973int __init init_module(void) 974{ 975 int ret; 976 977 ret = init_das16cs_pcmcia_cs(); 978 if (ret < 0) 979 return ret; 980 981 return comedi_driver_register(&driver_das16cs); 982} 983 984void __exit cleanup_module(void) 985{ 986 exit_das16cs_pcmcia_cs(); 987 comedi_driver_unregister(&driver_das16cs); 988} 989 990#else 991COMEDI_INITCLEANUP(driver_das16cs); 992#endif /* CONFIG_PCMCIA */ 993