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