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