Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.12 636 lines 19 kB view raw
1/* orinoco_cs.c (formerly known as dldwd_cs.c) 2 * 3 * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such 4 * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/ 5 * EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and others). 6 * It should also be usable on various Prism II based cards such as the 7 * Linksys, D-Link and Farallon Skyline. It should also work on Symbol 8 * cards such as the 3Com AirConnect and Ericsson WLAN. 9 * 10 * Copyright notice & release notes in file orinoco.c 11 */ 12 13#define DRIVER_NAME "orinoco_cs" 14#define PFX DRIVER_NAME ": " 15 16#include <linux/config.h> 17#ifdef __IN_PCMCIA_PACKAGE__ 18#include <pcmcia/k_compat.h> 19#endif /* __IN_PCMCIA_PACKAGE__ */ 20 21#include <linux/module.h> 22#include <linux/kernel.h> 23#include <linux/init.h> 24#include <linux/sched.h> 25#include <linux/ptrace.h> 26#include <linux/slab.h> 27#include <linux/string.h> 28#include <linux/ioport.h> 29#include <linux/netdevice.h> 30#include <linux/if_arp.h> 31#include <linux/etherdevice.h> 32#include <linux/wireless.h> 33 34#include <pcmcia/version.h> 35#include <pcmcia/cs_types.h> 36#include <pcmcia/cs.h> 37#include <pcmcia/cistpl.h> 38#include <pcmcia/cisreg.h> 39#include <pcmcia/ds.h> 40 41#include <asm/uaccess.h> 42#include <asm/io.h> 43#include <asm/system.h> 44 45#include "orinoco.h" 46 47/********************************************************************/ 48/* Module stuff */ 49/********************************************************************/ 50 51MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>"); 52MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco, Prism II based and similar wireless cards"); 53MODULE_LICENSE("Dual MPL/GPL"); 54 55/* Module parameters */ 56 57/* Some D-Link cards have buggy CIS. They do work at 5v properly, but 58 * don't have any CIS entry for it. This workaround it... */ 59static int ignore_cis_vcc; /* = 0 */ 60module_param(ignore_cis_vcc, int, 0); 61MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket"); 62 63/********************************************************************/ 64/* Magic constants */ 65/********************************************************************/ 66 67/* 68 * The dev_info variable is the "key" that is used to match up this 69 * device driver with appropriate cards, through the card 70 * configuration database. 71 */ 72static dev_info_t dev_info = DRIVER_NAME; 73 74/********************************************************************/ 75/* Data structures */ 76/********************************************************************/ 77 78/* PCMCIA specific device information (goes in the card field of 79 * struct orinoco_private */ 80struct orinoco_pccard { 81 dev_link_t link; 82 dev_node_t node; 83 84 /* Used to handle hard reset */ 85 /* yuck, we need this hack to work around the insanity of the 86 * PCMCIA layer */ 87 unsigned long hard_reset_in_progress; 88}; 89 90/* 91 * A linked list of "instances" of the device. Each actual PCMCIA 92 * card corresponds to one device instance, and is described by one 93 * dev_link_t structure (defined in ds.h). 94 */ 95static dev_link_t *dev_list; /* = NULL */ 96 97/********************************************************************/ 98/* Function prototypes */ 99/********************************************************************/ 100 101/* device methods */ 102static int orinoco_cs_hard_reset(struct orinoco_private *priv); 103 104/* PCMCIA gumpf */ 105static void orinoco_cs_config(dev_link_t * link); 106static void orinoco_cs_release(dev_link_t * link); 107static int orinoco_cs_event(event_t event, int priority, 108 event_callback_args_t * args); 109 110static dev_link_t *orinoco_cs_attach(void); 111static void orinoco_cs_detach(dev_link_t *); 112 113/********************************************************************/ 114/* Device methods */ 115/********************************************************************/ 116 117static int 118orinoco_cs_hard_reset(struct orinoco_private *priv) 119{ 120 struct orinoco_pccard *card = priv->card; 121 dev_link_t *link = &card->link; 122 int err; 123 124 /* We need atomic ops here, because we're not holding the lock */ 125 set_bit(0, &card->hard_reset_in_progress); 126 127 err = pcmcia_reset_card(link->handle, NULL); 128 if (err) 129 return err; 130 131 msleep(100); 132 clear_bit(0, &card->hard_reset_in_progress); 133 134 return 0; 135} 136 137/********************************************************************/ 138/* PCMCIA stuff */ 139/********************************************************************/ 140 141/* 142 * This creates an "instance" of the driver, allocating local data 143 * structures for one device. The device is registered with Card 144 * Services. 145 * 146 * The dev_link structure is initialized, but we don't actually 147 * configure the card at this point -- we wait until we receive a card 148 * insertion event. */ 149static dev_link_t * 150orinoco_cs_attach(void) 151{ 152 struct net_device *dev; 153 struct orinoco_private *priv; 154 struct orinoco_pccard *card; 155 dev_link_t *link; 156 client_reg_t client_reg; 157 int ret; 158 159 dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset); 160 if (! dev) 161 return NULL; 162 priv = netdev_priv(dev); 163 card = priv->card; 164 165 /* Link both structures together */ 166 link = &card->link; 167 link->priv = dev; 168 169 /* Interrupt setup */ 170 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; 171 link->irq.IRQInfo1 = IRQ_LEVEL_ID; 172 link->irq.Handler = orinoco_interrupt; 173 link->irq.Instance = dev; 174 175 /* General socket configuration defaults can go here. In this 176 * client, we assume very little, and rely on the CIS for 177 * almost everything. In most clients, many details (i.e., 178 * number, sizes, and attributes of IO windows) are fixed by 179 * the nature of the device, and can be hard-wired here. */ 180 link->conf.Attributes = 0; 181 link->conf.IntType = INT_MEMORY_AND_IO; 182 183 /* Register with Card Services */ 184 /* FIXME: need a lock? */ 185 link->next = dev_list; 186 dev_list = link; 187 188 client_reg.dev_info = &dev_info; 189 client_reg.EventMask = 190 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | 191 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | 192 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; 193 client_reg.event_handler = &orinoco_cs_event; 194 client_reg.Version = 0x0210; /* FIXME: what does this mean? */ 195 client_reg.event_callback_args.client_data = link; 196 197 ret = pcmcia_register_client(&link->handle, &client_reg); 198 if (ret != CS_SUCCESS) { 199 cs_error(link->handle, RegisterClient, ret); 200 orinoco_cs_detach(link); 201 return NULL; 202 } 203 204 return link; 205} /* orinoco_cs_attach */ 206 207/* 208 * This deletes a driver "instance". The device is de-registered with 209 * Card Services. If it has been released, all local data structures 210 * are freed. Otherwise, the structures will be freed when the device 211 * is released. 212 */ 213static void orinoco_cs_detach(dev_link_t *link) 214{ 215 dev_link_t **linkp; 216 struct net_device *dev = link->priv; 217 218 /* Locate device structure */ 219 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) 220 if (*linkp == link) 221 break; 222 223 BUG_ON(*linkp == NULL); 224 225 if (link->state & DEV_CONFIG) 226 orinoco_cs_release(link); 227 228 /* Break the link with Card Services */ 229 if (link->handle) 230 pcmcia_deregister_client(link->handle); 231 232 /* Unlink device structure, and free it */ 233 *linkp = link->next; 234 DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev); 235 if (link->dev) { 236 DEBUG(0, PFX "About to unregister net device %p\n", 237 dev); 238 unregister_netdev(dev); 239 } 240 free_orinocodev(dev); 241} /* orinoco_cs_detach */ 242 243/* 244 * orinoco_cs_config() is scheduled to run after a CARD_INSERTION 245 * event is received, to configure the PCMCIA socket, and to make the 246 * device available to the system. 247 */ 248 249#define CS_CHECK(fn, ret) do { \ 250 last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \ 251 } while (0) 252 253static void 254orinoco_cs_config(dev_link_t *link) 255{ 256 struct net_device *dev = link->priv; 257 client_handle_t handle = link->handle; 258 struct orinoco_private *priv = netdev_priv(dev); 259 struct orinoco_pccard *card = priv->card; 260 hermes_t *hw = &priv->hw; 261 int last_fn, last_ret; 262 u_char buf[64]; 263 config_info_t conf; 264 cisinfo_t info; 265 tuple_t tuple; 266 cisparse_t parse; 267 void __iomem *mem; 268 269 CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info)); 270 271 /* 272 * This reads the card's CONFIG tuple to find its 273 * configuration registers. 274 */ 275 tuple.DesiredTuple = CISTPL_CONFIG; 276 tuple.Attributes = 0; 277 tuple.TupleData = buf; 278 tuple.TupleDataMax = sizeof(buf); 279 tuple.TupleOffset = 0; 280 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); 281 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); 282 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); 283 link->conf.ConfigBase = parse.config.base; 284 link->conf.Present = parse.config.rmask[0]; 285 286 /* Configure card */ 287 link->state |= DEV_CONFIG; 288 289 /* Look up the current Vcc */ 290 CS_CHECK(GetConfigurationInfo, 291 pcmcia_get_configuration_info(handle, &conf)); 292 link->conf.Vcc = conf.Vcc; 293 294 /* 295 * In this loop, we scan the CIS for configuration table 296 * entries, each of which describes a valid card 297 * configuration, including voltage, IO window, memory window, 298 * and interrupt settings. 299 * 300 * We make no assumptions about the card to be configured: we 301 * use just the information available in the CIS. In an ideal 302 * world, this would work for any PCMCIA card, but it requires 303 * a complete and accurate CIS. In practice, a driver usually 304 * "knows" most of these things without consulting the CIS, 305 * and most client drivers will only use the CIS to fill in 306 * implementation-defined details. 307 */ 308 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 309 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); 310 while (1) { 311 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); 312 cistpl_cftable_entry_t dflt = { .index = 0 }; 313 314 if ( (pcmcia_get_tuple_data(handle, &tuple) != 0) 315 || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0)) 316 goto next_entry; 317 318 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) 319 dflt = *cfg; 320 if (cfg->index == 0) 321 goto next_entry; 322 link->conf.ConfigIndex = cfg->index; 323 324 /* Does this card need audio output? */ 325 if (cfg->flags & CISTPL_CFTABLE_AUDIO) { 326 link->conf.Attributes |= CONF_ENABLE_SPKR; 327 link->conf.Status = CCSR_AUDIO_ENA; 328 } 329 330 /* Use power settings for Vcc and Vpp if present */ 331 /* Note that the CIS values need to be rescaled */ 332 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { 333 if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) { 334 DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); 335 if (!ignore_cis_vcc) 336 goto next_entry; 337 } 338 } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { 339 if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) { 340 DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000); 341 if(!ignore_cis_vcc) 342 goto next_entry; 343 } 344 } 345 346 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) 347 link->conf.Vpp1 = link->conf.Vpp2 = 348 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; 349 else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) 350 link->conf.Vpp1 = link->conf.Vpp2 = 351 dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; 352 353 /* Do we need to allocate an interrupt? */ 354 link->conf.Attributes |= CONF_ENABLE_IRQ; 355 356 /* IO window settings */ 357 link->io.NumPorts1 = link->io.NumPorts2 = 0; 358 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { 359 cistpl_io_t *io = 360 (cfg->io.nwin) ? &cfg->io : &dflt.io; 361 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; 362 if (!(io->flags & CISTPL_IO_8BIT)) 363 link->io.Attributes1 = 364 IO_DATA_PATH_WIDTH_16; 365 if (!(io->flags & CISTPL_IO_16BIT)) 366 link->io.Attributes1 = 367 IO_DATA_PATH_WIDTH_8; 368 link->io.IOAddrLines = 369 io->flags & CISTPL_IO_LINES_MASK; 370 link->io.BasePort1 = io->win[0].base; 371 link->io.NumPorts1 = io->win[0].len; 372 if (io->nwin > 1) { 373 link->io.Attributes2 = 374 link->io.Attributes1; 375 link->io.BasePort2 = io->win[1].base; 376 link->io.NumPorts2 = io->win[1].len; 377 } 378 379 /* This reserves IO space but doesn't actually enable it */ 380 if (pcmcia_request_io(link->handle, &link->io) != 0) 381 goto next_entry; 382 } 383 384 385 /* If we got this far, we're cool! */ 386 387 break; 388 389 next_entry: 390 if (link->io.NumPorts1) 391 pcmcia_release_io(link->handle, &link->io); 392 last_ret = pcmcia_get_next_tuple(handle, &tuple); 393 if (last_ret == CS_NO_MORE_ITEMS) { 394 printk(KERN_ERR PFX "GetNextTuple(): No matching " 395 "CIS configuration. Maybe you need the " 396 "ignore_cis_vcc=1 parameter.\n"); 397 goto cs_failed; 398 } 399 } 400 401 /* 402 * Allocate an interrupt line. Note that this does not assign 403 * a handler to the interrupt, unless the 'Handler' member of 404 * the irq structure is initialized. 405 */ 406 CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); 407 408 /* We initialize the hermes structure before completing PCMCIA 409 * configuration just in case the interrupt handler gets 410 * called. */ 411 mem = ioport_map(link->io.BasePort1, link->io.NumPorts1); 412 if (!mem) 413 goto cs_failed; 414 415 hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING); 416 417 /* 418 * This actually configures the PCMCIA socket -- setting up 419 * the I/O windows and the interrupt mapping, and putting the 420 * card and host interface into "Memory and IO" mode. 421 */ 422 CS_CHECK(RequestConfiguration, 423 pcmcia_request_configuration(link->handle, &link->conf)); 424 425 /* Ok, we have the configuration, prepare to register the netdev */ 426 dev->base_addr = link->io.BasePort1; 427 dev->irq = link->irq.AssignedIRQ; 428 SET_MODULE_OWNER(dev); 429 card->node.major = card->node.minor = 0; 430 431 SET_NETDEV_DEV(dev, &handle_to_dev(handle)); 432 /* Tell the stack we exist */ 433 if (register_netdev(dev) != 0) { 434 printk(KERN_ERR PFX "register_netdev() failed\n"); 435 goto failed; 436 } 437 438 /* At this point, the dev_node_t structure(s) needs to be 439 * initialized and arranged in a linked list at link->dev. */ 440 strcpy(card->node.dev_name, dev->name); 441 link->dev = &card->node; /* link->dev being non-NULL is also 442 used to indicate that the 443 net_device has been registered */ 444 link->state &= ~DEV_CONFIG_PENDING; 445 446 /* Finally, report what we've done */ 447 printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d", 448 dev->name, link->conf.ConfigIndex, 449 link->conf.Vcc / 10, link->conf.Vcc % 10); 450 if (link->conf.Vpp1) 451 printk(", Vpp %d.%d", link->conf.Vpp1 / 10, 452 link->conf.Vpp1 % 10); 453 printk(", irq %d", link->irq.AssignedIRQ); 454 if (link->io.NumPorts1) 455 printk(", io 0x%04x-0x%04x", link->io.BasePort1, 456 link->io.BasePort1 + link->io.NumPorts1 - 1); 457 if (link->io.NumPorts2) 458 printk(" & 0x%04x-0x%04x", link->io.BasePort2, 459 link->io.BasePort2 + link->io.NumPorts2 - 1); 460 printk("\n"); 461 462 return; 463 464 cs_failed: 465 cs_error(link->handle, last_fn, last_ret); 466 467 failed: 468 orinoco_cs_release(link); 469} /* orinoco_cs_config */ 470 471/* 472 * After a card is removed, orinoco_cs_release() will unregister the 473 * device, and release the PCMCIA configuration. If the device is 474 * still open, this will be postponed until it is closed. 475 */ 476static void 477orinoco_cs_release(dev_link_t *link) 478{ 479 struct net_device *dev = link->priv; 480 struct orinoco_private *priv = netdev_priv(dev); 481 unsigned long flags; 482 483 /* We're committed to taking the device away now, so mark the 484 * hardware as unavailable */ 485 spin_lock_irqsave(&priv->lock, flags); 486 priv->hw_unavailable++; 487 spin_unlock_irqrestore(&priv->lock, flags); 488 489 /* Don't bother checking to see if these succeed or not */ 490 pcmcia_release_configuration(link->handle); 491 if (link->io.NumPorts1) 492 pcmcia_release_io(link->handle, &link->io); 493 if (link->irq.AssignedIRQ) 494 pcmcia_release_irq(link->handle, &link->irq); 495 link->state &= ~DEV_CONFIG; 496 if (priv->hw.iobase) 497 ioport_unmap(priv->hw.iobase); 498} /* orinoco_cs_release */ 499 500/* 501 * The card status event handler. Mostly, this schedules other stuff 502 * to run after an event is received. 503 */ 504static int 505orinoco_cs_event(event_t event, int priority, 506 event_callback_args_t * args) 507{ 508 dev_link_t *link = args->client_data; 509 struct net_device *dev = link->priv; 510 struct orinoco_private *priv = netdev_priv(dev); 511 struct orinoco_pccard *card = priv->card; 512 int err = 0; 513 unsigned long flags; 514 515 switch (event) { 516 case CS_EVENT_CARD_REMOVAL: 517 link->state &= ~DEV_PRESENT; 518 if (link->state & DEV_CONFIG) { 519 unsigned long flags; 520 521 spin_lock_irqsave(&priv->lock, flags); 522 netif_device_detach(dev); 523 priv->hw_unavailable++; 524 spin_unlock_irqrestore(&priv->lock, flags); 525 } 526 break; 527 528 case CS_EVENT_CARD_INSERTION: 529 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; 530 orinoco_cs_config(link); 531 break; 532 533 case CS_EVENT_PM_SUSPEND: 534 link->state |= DEV_SUSPEND; 535 /* Fall through... */ 536 case CS_EVENT_RESET_PHYSICAL: 537 /* Mark the device as stopped, to block IO until later */ 538 if (link->state & DEV_CONFIG) { 539 /* This is probably racy, but I can't think of 540 a better way, short of rewriting the PCMCIA 541 layer to not suck :-( */ 542 if (! test_bit(0, &card->hard_reset_in_progress)) { 543 spin_lock_irqsave(&priv->lock, flags); 544 545 err = __orinoco_down(dev); 546 if (err) 547 printk(KERN_WARNING "%s: %s: Error %d downing interface\n", 548 dev->name, 549 event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL", 550 err); 551 552 netif_device_detach(dev); 553 priv->hw_unavailable++; 554 555 spin_unlock_irqrestore(&priv->lock, flags); 556 } 557 558 pcmcia_release_configuration(link->handle); 559 } 560 break; 561 562 case CS_EVENT_PM_RESUME: 563 link->state &= ~DEV_SUSPEND; 564 /* Fall through... */ 565 case CS_EVENT_CARD_RESET: 566 if (link->state & DEV_CONFIG) { 567 /* FIXME: should we double check that this is 568 * the same card as we had before */ 569 pcmcia_request_configuration(link->handle, &link->conf); 570 571 if (! test_bit(0, &card->hard_reset_in_progress)) { 572 err = orinoco_reinit_firmware(dev); 573 if (err) { 574 printk(KERN_ERR "%s: Error %d re-initializing firmware\n", 575 dev->name, err); 576 break; 577 } 578 579 spin_lock_irqsave(&priv->lock, flags); 580 581 netif_device_attach(dev); 582 priv->hw_unavailable--; 583 584 if (priv->open && ! priv->hw_unavailable) { 585 err = __orinoco_up(dev); 586 if (err) 587 printk(KERN_ERR "%s: Error %d restarting card\n", 588 dev->name, err); 589 590 } 591 592 spin_unlock_irqrestore(&priv->lock, flags); 593 } 594 } 595 break; 596 } 597 598 return err; 599} /* orinoco_cs_event */ 600 601/********************************************************************/ 602/* Module initialization */ 603/********************************************************************/ 604 605/* Can't be declared "const" or the whole __initdata section will 606 * become const */ 607static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION 608 " (David Gibson <hermes@gibson.dropbear.id.au>, " 609 "Pavel Roskin <proski@gnu.org>, et al)"; 610 611static struct pcmcia_driver orinoco_driver = { 612 .owner = THIS_MODULE, 613 .drv = { 614 .name = DRIVER_NAME, 615 }, 616 .attach = orinoco_cs_attach, 617 .detach = orinoco_cs_detach, 618}; 619 620static int __init 621init_orinoco_cs(void) 622{ 623 printk(KERN_DEBUG "%s\n", version); 624 625 return pcmcia_register_driver(&orinoco_driver); 626} 627 628static void __exit 629exit_orinoco_cs(void) 630{ 631 pcmcia_unregister_driver(&orinoco_driver); 632 BUG_ON(dev_list != NULL); 633} 634 635module_init(init_orinoco_cs); 636module_exit(exit_orinoco_cs);