das08_cs.c revision da91b2692e0939b307f9047192d2b9fe07793e7a
1/* 2 comedi/drivers/das08_cs.c 3 DAS08 driver 4 5 COMEDI - Linux Control and Measurement Device Interface 6 Copyright (C) 2000 David A. Schleef <ds@schleef.org> 7 Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net> 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*/ 26/* 27Driver: das08_cs 28Description: DAS-08 PCMCIA boards 29Author: Warren Jasper, ds, Frank Hess 30Devices: [ComputerBoards] PCM-DAS08 (pcm-das08) 31Status: works 32 33This is the PCMCIA-specific support split off from the 34das08 driver. 35 36Options (for pcm-das08): 37 NONE 38 39Command support does not exist, but could be added for this board. 40*/ 41 42#include "../comedidev.h" 43 44#include <linux/delay.h> 45#include <linux/pci.h> 46 47#include "das08.h" 48 49/* pcmcia includes */ 50#include <pcmcia/cs_types.h> 51#include <pcmcia/cs.h> 52#include <pcmcia/cistpl.h> 53#include <pcmcia/ds.h> 54 55static struct pcmcia_device *cur_dev = NULL; 56 57#define thisboard ((const struct das08_board_struct *)dev->board_ptr) 58 59static int das08_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it); 60 61static struct comedi_driver driver_das08_cs = { 62 driver_name:"das08_cs", 63 module:THIS_MODULE, 64 attach:das08_cs_attach, 65 detach:das08_common_detach, 66 board_name:&das08_cs_boards[0].name, 67 num_names:sizeof(das08_cs_boards) / 68 sizeof(struct das08_board_struct), 69 offset:sizeof(struct das08_board_struct), 70}; 71 72static int das08_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it) 73{ 74 int ret; 75 unsigned long iobase; 76 struct pcmcia_device *link = cur_dev; /* XXX hack */ 77 78 if ((ret = alloc_private(dev, sizeof(struct das08_private_struct))) < 0) 79 return ret; 80 81 printk("comedi%d: das08_cs: ", dev->minor); 82 /* deal with a pci board */ 83 84 if (thisboard->bustype == pcmcia) { 85 if (link == NULL) { 86 printk(" no pcmcia cards found\n"); 87 return -EIO; 88 } 89 iobase = link->io.BasePort1; 90 } else { 91 printk(" bug! board does not have PCMCIA bustype\n"); 92 return -EINVAL; 93 } 94 95 printk("\n"); 96 97 return das08_common_attach(dev, iobase); 98} 99 100/*====================================================================== 101 102 The following pcmcia code for the pcm-das08 is adapted from the 103 dummy_cs.c driver of the Linux PCMCIA Card Services package. 104 105 The initial developer of the original code is David A. Hinds 106 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds 107 are Copyright (C) 1999 David A. Hinds. All Rights Reserved. 108 109======================================================================*/ 110 111/* 112 All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If 113 you do not define PCMCIA_DEBUG at all, all the debug code will be 114 left out. If you compile with PCMCIA_DEBUG=0, the debug code will 115 be present but disabled -- but it can then be enabled for specific 116 modules at load time with a 'pc_debug=#' option to insmod. 117*/ 118 119#ifdef PCMCIA_DEBUG 120static int pc_debug = PCMCIA_DEBUG; 121module_param(pc_debug, int, 0644); 122#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) 123static const char *version = 124 "das08.c pcmcia code (Frank Hess), modified from dummy_cs.c 1.31 2001/08/24 12:13:13 (David Hinds)"; 125#else 126#define DEBUG(n, args...) 127#endif 128 129/*====================================================================*/ 130static void das08_pcmcia_config(struct pcmcia_device *link); 131static void das08_pcmcia_release(struct pcmcia_device *link); 132static int das08_pcmcia_suspend(struct pcmcia_device *p_dev); 133static int das08_pcmcia_resume(struct pcmcia_device *p_dev); 134 135/* 136 The attach() and detach() entry points are used to create and destroy 137 "instances" of the driver, where each instance represents everything 138 needed to manage one actual PCMCIA card. 139*/ 140 141static int das08_pcmcia_attach(struct pcmcia_device *); 142static void das08_pcmcia_detach(struct pcmcia_device *); 143 144/* 145 You'll also need to prototype all the functions that will actually 146 be used to talk to your device. See 'memory_cs' for a good example 147 of a fully self-sufficient driver; the other drivers rely more or 148 less on other parts of the kernel. 149*/ 150 151/* 152 The dev_info variable is the "key" that is used to match up this 153 device driver with appropriate cards, through the card configuration 154 database. 155*/ 156 157static const dev_info_t dev_info = "pcm-das08"; 158 159struct local_info_t { 160 struct pcmcia_device *link; 161 dev_node_t node; 162 int stop; 163 struct bus_operations *bus; 164}; 165 166/*====================================================================== 167 168 das08_pcmcia_attach() creates an "instance" of the driver, allocating 169 local data structures for one device. The device is registered 170 with Card Services. 171 172 The dev_link structure is initialized, but we don't actually 173 configure the card at this point -- we wait until we receive a 174 card insertion event. 175 176======================================================================*/ 177 178static int das08_pcmcia_attach(struct pcmcia_device *link) 179{ 180 struct local_info_t *local; 181 182 DEBUG(0, "das08_pcmcia_attach()\n"); 183 184 /* Allocate space for private device-specific data */ 185 local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL); 186 if (!local) 187 return -ENOMEM; 188 local->link = link; 189 link->priv = local; 190 191 /* Interrupt setup */ 192 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; 193 link->irq.IRQInfo1 = IRQ_LEVEL_ID; 194 link->irq.Handler = NULL; 195 196 /* 197 General socket configuration defaults can go here. In this 198 client, we assume very little, and rely on the CIS for almost 199 everything. In most clients, many details (i.e., number, sizes, 200 and attributes of IO windows) are fixed by the nature of the 201 device, and can be hard-wired here. 202 */ 203 link->conf.Attributes = 0; 204 link->conf.IntType = INT_MEMORY_AND_IO; 205 206 cur_dev = link; 207 208 das08_pcmcia_config(link); 209 210 return 0; 211} /* das08_pcmcia_attach */ 212 213/*====================================================================== 214 215 This deletes a driver "instance". The device is de-registered 216 with Card Services. If it has been released, all local data 217 structures are freed. Otherwise, the structures will be freed 218 when the device is released. 219 220======================================================================*/ 221 222static void das08_pcmcia_detach(struct pcmcia_device *link) 223{ 224 225 DEBUG(0, "das08_pcmcia_detach(0x%p)\n", link); 226 227 if (link->dev_node) { 228 ((struct local_info_t *) link->priv)->stop = 1; 229 das08_pcmcia_release(link); 230 } 231 232 /* This points to the parent struct local_info_t struct */ 233 if (link->priv) 234 kfree(link->priv); 235 236} /* das08_pcmcia_detach */ 237 238/*====================================================================== 239 240 das08_pcmcia_config() is scheduled to run after a CARD_INSERTION event 241 is received, to configure the PCMCIA socket, and to make the 242 device available to the system. 243 244======================================================================*/ 245 246static void das08_pcmcia_config(struct pcmcia_device *link) 247{ 248 struct local_info_t *dev = link->priv; 249 tuple_t tuple; 250 cisparse_t parse; 251 int last_fn, last_ret; 252 u_char buf[64]; 253 cistpl_cftable_entry_t dflt = { 0 }; 254 255 DEBUG(0, "das08_pcmcia_config(0x%p)\n", link); 256 257 /* 258 This reads the card's CONFIG tuple to find its configuration 259 registers. 260 */ 261 tuple.DesiredTuple = CISTPL_CONFIG; 262 tuple.Attributes = 0; 263 tuple.TupleData = buf; 264 tuple.TupleDataMax = sizeof(buf); 265 tuple.TupleOffset = 0; 266 last_fn = GetFirstTuple; 267 if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0) 268 goto cs_failed; 269 last_fn = GetTupleData; 270 if ((last_ret = pcmcia_get_tuple_data(link, &tuple)) != 0) 271 goto cs_failed; 272 last_fn = ParseTuple; 273 if ((last_ret = pcmcia_parse_tuple(&tuple, &parse)) != 0) 274 goto cs_failed; 275 link->conf.ConfigBase = parse.config.base; 276 link->conf.Present = parse.config.rmask[0]; 277 278 /* 279 In this loop, we scan the CIS for configuration table entries, 280 each of which describes a valid card configuration, including 281 voltage, IO window, memory window, and interrupt settings. 282 283 We make no assumptions about the card to be configured: we use 284 just the information available in the CIS. In an ideal world, 285 this would work for any PCMCIA card, but it requires a complete 286 and accurate CIS. In practice, a driver usually "knows" most of 287 these things without consulting the CIS, and most client drivers 288 will only use the CIS to fill in implementation-defined details. 289 */ 290 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 291 last_fn = GetFirstTuple; 292 if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0) 293 goto cs_failed; 294 while (1) { 295 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); 296 if ((last_ret = pcmcia_get_tuple_data(link, &tuple)) != 0) 297 goto next_entry; 298 if ((last_ret = pcmcia_parse_tuple(&tuple, &parse)) != 0) 299 goto next_entry; 300 301 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) 302 dflt = *cfg; 303 if (cfg->index == 0) 304 goto next_entry; 305 link->conf.ConfigIndex = cfg->index; 306 307 /* Does this card need audio output? */ 308/* if (cfg->flags & CISTPL_CFTABLE_AUDIO) { 309 link->conf.Attributes |= CONF_ENABLE_SPKR; 310 link->conf.Status = CCSR_AUDIO_ENA; 311 } 312*/ 313 /* Do we need to allocate an interrupt? */ 314 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) 315 link->conf.Attributes |= CONF_ENABLE_IRQ; 316 317 /* IO window settings */ 318 link->io.NumPorts1 = link->io.NumPorts2 = 0; 319 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { 320 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; 321 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; 322 if (!(io->flags & CISTPL_IO_8BIT)) 323 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; 324 if (!(io->flags & CISTPL_IO_16BIT)) 325 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; 326 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; 327 link->io.BasePort1 = io->win[0].base; 328 link->io.NumPorts1 = io->win[0].len; 329 if (io->nwin > 1) { 330 link->io.Attributes2 = link->io.Attributes1; 331 link->io.BasePort2 = io->win[1].base; 332 link->io.NumPorts2 = io->win[1].len; 333 } 334 /* This reserves IO space but doesn't actually enable it */ 335 if (pcmcia_request_io(link, &link->io) != 0) 336 goto next_entry; 337 } 338 339 /* If we got this far, we're cool! */ 340 break; 341 342 next_entry: 343 last_fn = GetNextTuple; 344 if ((last_ret = pcmcia_get_next_tuple(link, &tuple)) != 0) 345 goto cs_failed; 346 } 347 348 if (link->conf.Attributes & CONF_ENABLE_IRQ) { 349 last_fn = RequestIRQ; 350 if ((last_ret = pcmcia_request_irq(link, &link->irq)) != 0) 351 goto cs_failed; 352 } 353 354 /* 355 This actually configures the PCMCIA socket -- setting up 356 the I/O windows and the interrupt mapping, and putting the 357 card and host interface into "Memory and IO" mode. 358 */ 359 last_fn = RequestConfiguration; 360 if ((last_ret = pcmcia_request_configuration(link, &link->conf)) != 0) 361 goto cs_failed; 362 363 /* 364 At this point, the dev_node_t structure(s) need to be 365 initialized and arranged in a linked list at link->dev. 366 */ 367 sprintf(dev->node.dev_name, "pcm-das08"); 368 dev->node.major = dev->node.minor = 0; 369 link->dev_node = &dev->node; 370 371 /* Finally, report what we've done */ 372 printk(KERN_INFO "%s: index 0x%02x", 373 dev->node.dev_name, link->conf.ConfigIndex); 374 if (link->conf.Attributes & CONF_ENABLE_IRQ) 375 printk(", irq %u", link->irq.AssignedIRQ); 376 if (link->io.NumPorts1) 377 printk(", io 0x%04x-0x%04x", link->io.BasePort1, 378 link->io.BasePort1 + link->io.NumPorts1 - 1); 379 if (link->io.NumPorts2) 380 printk(" & 0x%04x-0x%04x", link->io.BasePort2, 381 link->io.BasePort2 + link->io.NumPorts2 - 1); 382 printk("\n"); 383 384 return; 385 386 cs_failed: 387 cs_error(link, last_fn, last_ret); 388 das08_pcmcia_release(link); 389 390} /* das08_pcmcia_config */ 391 392/*====================================================================== 393 394 After a card is removed, das08_pcmcia_release() will unregister the 395 device, and release the PCMCIA configuration. If the device is 396 still open, this will be postponed until it is closed. 397 398======================================================================*/ 399 400static void das08_pcmcia_release(struct pcmcia_device *link) 401{ 402 DEBUG(0, "das08_pcmcia_release(0x%p)\n", link); 403 pcmcia_disable_device(link); 404} /* das08_pcmcia_release */ 405 406/*====================================================================== 407 408 The card status event handler. Mostly, this schedules other 409 stuff to run after an event is received. 410 411 When a CARD_REMOVAL event is received, we immediately set a 412 private flag to block future accesses to this device. All the 413 functions that actually access the device should check this flag 414 to make sure the card is still present. 415 416======================================================================*/ 417 418static int das08_pcmcia_suspend(struct pcmcia_device *link) 419{ 420 struct local_info_t *local = link->priv; 421 /* Mark the device as stopped, to block IO until later */ 422 local->stop = 1; 423 424 return 0; 425} /* das08_pcmcia_suspend */ 426 427static int das08_pcmcia_resume(struct pcmcia_device *link) 428{ 429 struct local_info_t *local = link->priv; 430 431 local->stop = 0; 432 return 0; 433} /* das08_pcmcia_resume */ 434 435/*====================================================================*/ 436 437static struct pcmcia_device_id das08_cs_id_table[] = { 438 PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4001), 439 PCMCIA_DEVICE_NULL 440}; 441 442MODULE_DEVICE_TABLE(pcmcia, das08_cs_id_table); 443 444struct pcmcia_driver das08_cs_driver = { 445 .probe = das08_pcmcia_attach, 446 .remove = das08_pcmcia_detach, 447 .suspend = das08_pcmcia_suspend, 448 .resume = das08_pcmcia_resume, 449 .id_table = das08_cs_id_table, 450 .owner = THIS_MODULE, 451 .drv = { 452 .name = dev_info, 453 }, 454}; 455 456static int __init init_das08_pcmcia_cs(void) 457{ 458 DEBUG(0, "%s\n", version); 459 pcmcia_register_driver(&das08_cs_driver); 460 return 0; 461} 462 463static void __exit exit_das08_pcmcia_cs(void) 464{ 465 DEBUG(0, "das08_pcmcia_cs: unloading\n"); 466 pcmcia_unregister_driver(&das08_cs_driver); 467} 468 469static int __init das08_cs_init_module(void) 470{ 471 int ret; 472 473 ret = init_das08_pcmcia_cs(); 474 if (ret < 0) 475 return ret; 476 477 return comedi_driver_register(&driver_das08_cs); 478} 479 480static void __exit das08_cs_exit_module(void) 481{ 482 exit_das08_pcmcia_cs(); 483 comedi_driver_unregister(&driver_das08_cs); 484} 485 486MODULE_LICENSE("GPL"); 487module_init(das08_cs_init_module); 488module_exit(das08_cs_exit_module); 489