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.24-rc8 928 lines 26 kB view raw
1/* 2 * Driver for 802.11b cards using RAM-loadable Symbol firmware, such as 3 * Symbol Wireless Networker LA4137, CompactFlash cards by Socket 4 * Communications and Intel PRO/Wireless 2011B. 5 * 6 * The driver implements Symbol firmware download. The rest is handled 7 * in hermes.c and orinoco.c. 8 * 9 * Utilities for downloading the Symbol firmware are available at 10 * http://sourceforge.net/projects/orinoco/ 11 * 12 * Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org> 13 * Portions based on orinoco_cs.c: 14 * Copyright (C) David Gibson, Linuxcare Australia 15 * Portions based on Spectrum24tDnld.c from original spectrum24 driver: 16 * Copyright (C) Symbol Technologies. 17 * 18 * See copyright notice in file orinoco.c. 19 */ 20 21#define DRIVER_NAME "spectrum_cs" 22#define PFX DRIVER_NAME ": " 23 24#include <linux/module.h> 25#include <linux/kernel.h> 26#include <linux/init.h> 27#include <linux/delay.h> 28#include <linux/firmware.h> 29#include <pcmcia/cs_types.h> 30#include <pcmcia/cs.h> 31#include <pcmcia/cistpl.h> 32#include <pcmcia/cisreg.h> 33#include <pcmcia/ds.h> 34 35#include "orinoco.h" 36 37static const char primary_fw_name[] = "symbol_sp24t_prim_fw"; 38static const char secondary_fw_name[] = "symbol_sp24t_sec_fw"; 39 40/********************************************************************/ 41/* Module stuff */ 42/********************************************************************/ 43 44MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>"); 45MODULE_DESCRIPTION("Driver for Symbol Spectrum24 Trilogy cards with firmware downloader"); 46MODULE_LICENSE("Dual MPL/GPL"); 47 48/* Module parameters */ 49 50/* Some D-Link cards have buggy CIS. They do work at 5v properly, but 51 * don't have any CIS entry for it. This workaround it... */ 52static int ignore_cis_vcc; /* = 0 */ 53module_param(ignore_cis_vcc, int, 0); 54MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket"); 55 56/********************************************************************/ 57/* Data structures */ 58/********************************************************************/ 59 60/* PCMCIA specific device information (goes in the card field of 61 * struct orinoco_private */ 62struct orinoco_pccard { 63 struct pcmcia_device *p_dev; 64 dev_node_t node; 65}; 66 67/********************************************************************/ 68/* Function prototypes */ 69/********************************************************************/ 70 71static int spectrum_cs_config(struct pcmcia_device *link); 72static void spectrum_cs_release(struct pcmcia_device *link); 73 74/********************************************************************/ 75/* Firmware downloader */ 76/********************************************************************/ 77 78/* Position of PDA in the adapter memory */ 79#define EEPROM_ADDR 0x3000 80#define EEPROM_LEN 0x200 81#define PDA_OFFSET 0x100 82 83#define PDA_ADDR (EEPROM_ADDR + PDA_OFFSET) 84#define PDA_WORDS ((EEPROM_LEN - PDA_OFFSET) / 2) 85 86/* Constants for the CISREG_CCSR register */ 87#define HCR_RUN 0x07 /* run firmware after reset */ 88#define HCR_IDLE 0x0E /* don't run firmware after reset */ 89#define HCR_MEM16 0x10 /* memory width bit, should be preserved */ 90 91/* 92 * AUX port access. To unlock the AUX port write the access keys to the 93 * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL 94 * register. Then read it and make sure it's HERMES_AUX_ENABLED. 95 */ 96#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */ 97#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */ 98#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */ 99 100#define HERMES_AUX_PW0 0xFE01 101#define HERMES_AUX_PW1 0xDC23 102#define HERMES_AUX_PW2 0xBA45 103 104/* End markers */ 105#define PDI_END 0x00000000 /* End of PDA */ 106#define BLOCK_END 0xFFFFFFFF /* Last image block */ 107#define TEXT_END 0x1A /* End of text header */ 108 109/* 110 * The following structures have little-endian fields denoted by 111 * the leading underscore. Don't access them directly - use inline 112 * functions defined below. 113 */ 114 115/* 116 * The binary image to be downloaded consists of series of data blocks. 117 * Each block has the following structure. 118 */ 119struct dblock { 120 __le32 addr; /* adapter address where to write the block */ 121 __le16 len; /* length of the data only, in bytes */ 122 char data[0]; /* data to be written */ 123} __attribute__ ((packed)); 124 125/* 126 * Plug Data References are located in in the image after the last data 127 * block. They refer to areas in the adapter memory where the plug data 128 * items with matching ID should be written. 129 */ 130struct pdr { 131 __le32 id; /* record ID */ 132 __le32 addr; /* adapter address where to write the data */ 133 __le32 len; /* expected length of the data, in bytes */ 134 char next[0]; /* next PDR starts here */ 135} __attribute__ ((packed)); 136 137 138/* 139 * Plug Data Items are located in the EEPROM read from the adapter by 140 * primary firmware. They refer to the device-specific data that should 141 * be plugged into the secondary firmware. 142 */ 143struct pdi { 144 __le16 len; /* length of ID and data, in words */ 145 __le16 id; /* record ID */ 146 char data[0]; /* plug data */ 147} __attribute__ ((packed)); 148 149 150/* Functions for access to little-endian data */ 151static inline u32 152dblock_addr(const struct dblock *blk) 153{ 154 return le32_to_cpu(blk->addr); 155} 156 157static inline u32 158dblock_len(const struct dblock *blk) 159{ 160 return le16_to_cpu(blk->len); 161} 162 163static inline u32 164pdr_id(const struct pdr *pdr) 165{ 166 return le32_to_cpu(pdr->id); 167} 168 169static inline u32 170pdr_addr(const struct pdr *pdr) 171{ 172 return le32_to_cpu(pdr->addr); 173} 174 175static inline u32 176pdr_len(const struct pdr *pdr) 177{ 178 return le32_to_cpu(pdr->len); 179} 180 181static inline u32 182pdi_id(const struct pdi *pdi) 183{ 184 return le16_to_cpu(pdi->id); 185} 186 187/* Return length of the data only, in bytes */ 188static inline u32 189pdi_len(const struct pdi *pdi) 190{ 191 return 2 * (le16_to_cpu(pdi->len) - 1); 192} 193 194 195/* Set address of the auxiliary port */ 196static inline void 197spectrum_aux_setaddr(hermes_t *hw, u32 addr) 198{ 199 hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7)); 200 hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F)); 201} 202 203 204/* Open access to the auxiliary port */ 205static int 206spectrum_aux_open(hermes_t *hw) 207{ 208 int i; 209 210 /* Already open? */ 211 if (hermes_read_reg(hw, HERMES_CONTROL) == HERMES_AUX_ENABLED) 212 return 0; 213 214 hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0); 215 hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1); 216 hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2); 217 hermes_write_reg(hw, HERMES_CONTROL, HERMES_AUX_ENABLE); 218 219 for (i = 0; i < 20; i++) { 220 udelay(10); 221 if (hermes_read_reg(hw, HERMES_CONTROL) == 222 HERMES_AUX_ENABLED) 223 return 0; 224 } 225 226 return -EBUSY; 227} 228 229 230#define CS_CHECK(fn, ret) \ 231 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 232 233/* 234 * Reset the card using configuration registers COR and CCSR. 235 * If IDLE is 1, stop the firmware, so that it can be safely rewritten. 236 */ 237static int 238spectrum_reset(struct pcmcia_device *link, int idle) 239{ 240 int last_ret, last_fn; 241 conf_reg_t reg; 242 u_int save_cor; 243 244 /* Doing it if hardware is gone is guaranteed crash */ 245 if (!pcmcia_dev_present(link)) 246 return -ENODEV; 247 248 /* Save original COR value */ 249 reg.Function = 0; 250 reg.Action = CS_READ; 251 reg.Offset = CISREG_COR; 252 CS_CHECK(AccessConfigurationRegister, 253 pcmcia_access_configuration_register(link, &reg)); 254 save_cor = reg.Value; 255 256 /* Soft-Reset card */ 257 reg.Action = CS_WRITE; 258 reg.Offset = CISREG_COR; 259 reg.Value = (save_cor | COR_SOFT_RESET); 260 CS_CHECK(AccessConfigurationRegister, 261 pcmcia_access_configuration_register(link, &reg)); 262 udelay(1000); 263 264 /* Read CCSR */ 265 reg.Action = CS_READ; 266 reg.Offset = CISREG_CCSR; 267 CS_CHECK(AccessConfigurationRegister, 268 pcmcia_access_configuration_register(link, &reg)); 269 270 /* 271 * Start or stop the firmware. Memory width bit should be 272 * preserved from the value we've just read. 273 */ 274 reg.Action = CS_WRITE; 275 reg.Offset = CISREG_CCSR; 276 reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16); 277 CS_CHECK(AccessConfigurationRegister, 278 pcmcia_access_configuration_register(link, &reg)); 279 udelay(1000); 280 281 /* Restore original COR configuration index */ 282 reg.Action = CS_WRITE; 283 reg.Offset = CISREG_COR; 284 reg.Value = (save_cor & ~COR_SOFT_RESET); 285 CS_CHECK(AccessConfigurationRegister, 286 pcmcia_access_configuration_register(link, &reg)); 287 udelay(1000); 288 return 0; 289 290 cs_failed: 291 cs_error(link, last_fn, last_ret); 292 return -ENODEV; 293} 294 295 296/* 297 * Scan PDR for the record with the specified RECORD_ID. 298 * If it's not found, return NULL. 299 */ 300static struct pdr * 301spectrum_find_pdr(struct pdr *first_pdr, u32 record_id) 302{ 303 struct pdr *pdr = first_pdr; 304 305 while (pdr_id(pdr) != PDI_END) { 306 /* 307 * PDR area is currently not terminated by PDI_END. 308 * It's followed by CRC records, which have the type 309 * field where PDR has length. The type can be 0 or 1. 310 */ 311 if (pdr_len(pdr) < 2) 312 return NULL; 313 314 /* If the record ID matches, we are done */ 315 if (pdr_id(pdr) == record_id) 316 return pdr; 317 318 pdr = (struct pdr *) pdr->next; 319 } 320 return NULL; 321} 322 323 324/* Process one Plug Data Item - find corresponding PDR and plug it */ 325static int 326spectrum_plug_pdi(hermes_t *hw, struct pdr *first_pdr, struct pdi *pdi) 327{ 328 struct pdr *pdr; 329 330 /* Find the PDI corresponding to this PDR */ 331 pdr = spectrum_find_pdr(first_pdr, pdi_id(pdi)); 332 333 /* No match is found, safe to ignore */ 334 if (!pdr) 335 return 0; 336 337 /* Lengths of the data in PDI and PDR must match */ 338 if (pdi_len(pdi) != pdr_len(pdr)) 339 return -EINVAL; 340 341 /* do the actual plugging */ 342 spectrum_aux_setaddr(hw, pdr_addr(pdr)); 343 hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi)); 344 345 return 0; 346} 347 348 349/* Read PDA from the adapter */ 350static int 351spectrum_read_pda(hermes_t *hw, __le16 *pda, int pda_len) 352{ 353 int ret; 354 int pda_size; 355 356 /* Issue command to read EEPROM */ 357 ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL); 358 if (ret) 359 return ret; 360 361 /* Open auxiliary port */ 362 ret = spectrum_aux_open(hw); 363 if (ret) 364 return ret; 365 366 /* read PDA from EEPROM */ 367 spectrum_aux_setaddr(hw, PDA_ADDR); 368 hermes_read_words(hw, HERMES_AUXDATA, pda, pda_len / 2); 369 370 /* Check PDA length */ 371 pda_size = le16_to_cpu(pda[0]); 372 if (pda_size > pda_len) 373 return -EINVAL; 374 375 return 0; 376} 377 378 379/* Parse PDA and write the records into the adapter */ 380static int 381spectrum_apply_pda(hermes_t *hw, const struct dblock *first_block, 382 __le16 *pda) 383{ 384 int ret; 385 struct pdi *pdi; 386 struct pdr *first_pdr; 387 const struct dblock *blk = first_block; 388 389 /* Skip all blocks to locate Plug Data References */ 390 while (dblock_addr(blk) != BLOCK_END) 391 blk = (struct dblock *) &blk->data[dblock_len(blk)]; 392 393 first_pdr = (struct pdr *) blk; 394 395 /* Go through every PDI and plug them into the adapter */ 396 pdi = (struct pdi *) (pda + 2); 397 while (pdi_id(pdi) != PDI_END) { 398 ret = spectrum_plug_pdi(hw, first_pdr, pdi); 399 if (ret) 400 return ret; 401 402 /* Increment to the next PDI */ 403 pdi = (struct pdi *) &pdi->data[pdi_len(pdi)]; 404 } 405 return 0; 406} 407 408 409/* Load firmware blocks into the adapter */ 410static int 411spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block) 412{ 413 const struct dblock *blk; 414 u32 blkaddr; 415 u32 blklen; 416 417 blk = first_block; 418 blkaddr = dblock_addr(blk); 419 blklen = dblock_len(blk); 420 421 while (dblock_addr(blk) != BLOCK_END) { 422 spectrum_aux_setaddr(hw, blkaddr); 423 hermes_write_bytes(hw, HERMES_AUXDATA, blk->data, 424 blklen); 425 426 blk = (struct dblock *) &blk->data[blklen]; 427 blkaddr = dblock_addr(blk); 428 blklen = dblock_len(blk); 429 } 430 return 0; 431} 432 433 434/* 435 * Process a firmware image - stop the card, load the firmware, reset 436 * the card and make sure it responds. For the secondary firmware take 437 * care of the PDA - read it and then write it on top of the firmware. 438 */ 439static int 440spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link, 441 const unsigned char *image, int secondary) 442{ 443 int ret; 444 const unsigned char *ptr; 445 const struct dblock *first_block; 446 447 /* Plug Data Area (PDA) */ 448 __le16 pda[PDA_WORDS]; 449 450 /* Binary block begins after the 0x1A marker */ 451 ptr = image; 452 while (*ptr++ != TEXT_END); 453 first_block = (const struct dblock *) ptr; 454 455 /* Read the PDA */ 456 if (secondary) { 457 ret = spectrum_read_pda(hw, pda, sizeof(pda)); 458 if (ret) 459 return ret; 460 } 461 462 /* Stop the firmware, so that it can be safely rewritten */ 463 ret = spectrum_reset(link, 1); 464 if (ret) 465 return ret; 466 467 /* Program the adapter with new firmware */ 468 ret = spectrum_load_blocks(hw, first_block); 469 if (ret) 470 return ret; 471 472 /* Write the PDA to the adapter */ 473 if (secondary) { 474 ret = spectrum_apply_pda(hw, first_block, pda); 475 if (ret) 476 return ret; 477 } 478 479 /* Run the firmware */ 480 ret = spectrum_reset(link, 0); 481 if (ret) 482 return ret; 483 484 /* Reset hermes chip and make sure it responds */ 485 ret = hermes_init(hw); 486 487 /* hermes_reset() should return 0 with the secondary firmware */ 488 if (secondary && ret != 0) 489 return -ENODEV; 490 491 /* And this should work with any firmware */ 492 if (!hermes_present(hw)) 493 return -ENODEV; 494 495 return 0; 496} 497 498 499/* 500 * Download the firmware into the card, this also does a PCMCIA soft 501 * reset on the card, to make sure it's in a sane state. 502 */ 503static int 504spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link) 505{ 506 int ret; 507 const struct firmware *fw_entry; 508 509 if (request_firmware(&fw_entry, primary_fw_name, 510 &handle_to_dev(link)) != 0) { 511 printk(KERN_ERR PFX "Cannot find firmware: %s\n", 512 primary_fw_name); 513 return -ENOENT; 514 } 515 516 /* Load primary firmware */ 517 ret = spectrum_dl_image(hw, link, fw_entry->data, 0); 518 release_firmware(fw_entry); 519 if (ret) { 520 printk(KERN_ERR PFX "Primary firmware download failed\n"); 521 return ret; 522 } 523 524 if (request_firmware(&fw_entry, secondary_fw_name, 525 &handle_to_dev(link)) != 0) { 526 printk(KERN_ERR PFX "Cannot find firmware: %s\n", 527 secondary_fw_name); 528 return -ENOENT; 529 } 530 531 /* Load secondary firmware */ 532 ret = spectrum_dl_image(hw, link, fw_entry->data, 1); 533 release_firmware(fw_entry); 534 if (ret) { 535 printk(KERN_ERR PFX "Secondary firmware download failed\n"); 536 } 537 538 return ret; 539} 540 541/********************************************************************/ 542/* Device methods */ 543/********************************************************************/ 544 545static int 546spectrum_cs_hard_reset(struct orinoco_private *priv) 547{ 548 struct orinoco_pccard *card = priv->card; 549 struct pcmcia_device *link = card->p_dev; 550 int err; 551 552 if (!hermes_present(&priv->hw)) { 553 /* The firmware needs to be reloaded */ 554 if (spectrum_dl_firmware(&priv->hw, link) != 0) { 555 printk(KERN_ERR PFX "Firmware download failed\n"); 556 err = -ENODEV; 557 } 558 } else { 559 /* Soft reset using COR and HCR */ 560 spectrum_reset(link, 0); 561 } 562 563 return 0; 564} 565 566/********************************************************************/ 567/* PCMCIA stuff */ 568/********************************************************************/ 569 570/* 571 * This creates an "instance" of the driver, allocating local data 572 * structures for one device. The device is registered with Card 573 * Services. 574 * 575 * The dev_link structure is initialized, but we don't actually 576 * configure the card at this point -- we wait until we receive a card 577 * insertion event. */ 578static int 579spectrum_cs_probe(struct pcmcia_device *link) 580{ 581 struct net_device *dev; 582 struct orinoco_private *priv; 583 struct orinoco_pccard *card; 584 585 dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset); 586 if (! dev) 587 return -ENOMEM; 588 priv = netdev_priv(dev); 589 card = priv->card; 590 591 /* Link both structures together */ 592 card->p_dev = link; 593 link->priv = dev; 594 595 /* Interrupt setup */ 596 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; 597 link->irq.IRQInfo1 = IRQ_LEVEL_ID; 598 link->irq.Handler = orinoco_interrupt; 599 link->irq.Instance = dev; 600 601 /* General socket configuration defaults can go here. In this 602 * client, we assume very little, and rely on the CIS for 603 * almost everything. In most clients, many details (i.e., 604 * number, sizes, and attributes of IO windows) are fixed by 605 * the nature of the device, and can be hard-wired here. */ 606 link->conf.Attributes = 0; 607 link->conf.IntType = INT_MEMORY_AND_IO; 608 609 return spectrum_cs_config(link); 610} /* spectrum_cs_attach */ 611 612/* 613 * This deletes a driver "instance". The device is de-registered with 614 * Card Services. If it has been released, all local data structures 615 * are freed. Otherwise, the structures will be freed when the device 616 * is released. 617 */ 618static void spectrum_cs_detach(struct pcmcia_device *link) 619{ 620 struct net_device *dev = link->priv; 621 622 if (link->dev_node) 623 unregister_netdev(dev); 624 625 spectrum_cs_release(link); 626 627 free_orinocodev(dev); 628} /* spectrum_cs_detach */ 629 630/* 631 * spectrum_cs_config() is scheduled to run after a CARD_INSERTION 632 * event is received, to configure the PCMCIA socket, and to make the 633 * device available to the system. 634 */ 635 636static int 637spectrum_cs_config(struct pcmcia_device *link) 638{ 639 struct net_device *dev = link->priv; 640 struct orinoco_private *priv = netdev_priv(dev); 641 struct orinoco_pccard *card = priv->card; 642 hermes_t *hw = &priv->hw; 643 int last_fn, last_ret; 644 u_char buf[64]; 645 config_info_t conf; 646 tuple_t tuple; 647 cisparse_t parse; 648 void __iomem *mem; 649 650 /* Look up the current Vcc */ 651 CS_CHECK(GetConfigurationInfo, 652 pcmcia_get_configuration_info(link, &conf)); 653 654 /* 655 * In this loop, we scan the CIS for configuration table 656 * entries, each of which describes a valid card 657 * configuration, including voltage, IO window, memory window, 658 * and interrupt settings. 659 * 660 * We make no assumptions about the card to be configured: we 661 * use just the information available in the CIS. In an ideal 662 * world, this would work for any PCMCIA card, but it requires 663 * a complete and accurate CIS. In practice, a driver usually 664 * "knows" most of these things without consulting the CIS, 665 * and most client drivers will only use the CIS to fill in 666 * implementation-defined details. 667 */ 668 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 669 tuple.Attributes = 0; 670 tuple.TupleData = buf; 671 tuple.TupleDataMax = sizeof(buf); 672 tuple.TupleOffset = 0; 673 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); 674 while (1) { 675 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); 676 cistpl_cftable_entry_t dflt = { .index = 0 }; 677 678 if ( (pcmcia_get_tuple_data(link, &tuple) != 0) 679 || (pcmcia_parse_tuple(link, &tuple, &parse) != 0)) 680 goto next_entry; 681 682 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) 683 dflt = *cfg; 684 if (cfg->index == 0) 685 goto next_entry; 686 link->conf.ConfigIndex = cfg->index; 687 688 /* Use power settings for Vcc and Vpp if present */ 689 /* Note that the CIS values need to be rescaled */ 690 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { 691 if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) { 692 DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); 693 if (!ignore_cis_vcc) 694 goto next_entry; 695 } 696 } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { 697 if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) { 698 DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000); 699 if(!ignore_cis_vcc) 700 goto next_entry; 701 } 702 } 703 704 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) 705 link->conf.Vpp = 706 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; 707 else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) 708 link->conf.Vpp = 709 dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; 710 711 /* Do we need to allocate an interrupt? */ 712 link->conf.Attributes |= CONF_ENABLE_IRQ; 713 714 /* IO window settings */ 715 link->io.NumPorts1 = link->io.NumPorts2 = 0; 716 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { 717 cistpl_io_t *io = 718 (cfg->io.nwin) ? &cfg->io : &dflt.io; 719 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; 720 if (!(io->flags & CISTPL_IO_8BIT)) 721 link->io.Attributes1 = 722 IO_DATA_PATH_WIDTH_16; 723 if (!(io->flags & CISTPL_IO_16BIT)) 724 link->io.Attributes1 = 725 IO_DATA_PATH_WIDTH_8; 726 link->io.IOAddrLines = 727 io->flags & CISTPL_IO_LINES_MASK; 728 link->io.BasePort1 = io->win[0].base; 729 link->io.NumPorts1 = io->win[0].len; 730 if (io->nwin > 1) { 731 link->io.Attributes2 = 732 link->io.Attributes1; 733 link->io.BasePort2 = io->win[1].base; 734 link->io.NumPorts2 = io->win[1].len; 735 } 736 737 /* This reserves IO space but doesn't actually enable it */ 738 if (pcmcia_request_io(link, &link->io) != 0) 739 goto next_entry; 740 } 741 742 743 /* If we got this far, we're cool! */ 744 745 break; 746 747 next_entry: 748 pcmcia_disable_device(link); 749 last_ret = pcmcia_get_next_tuple(link, &tuple); 750 if (last_ret == CS_NO_MORE_ITEMS) { 751 printk(KERN_ERR PFX "GetNextTuple(): No matching " 752 "CIS configuration. Maybe you need the " 753 "ignore_cis_vcc=1 parameter.\n"); 754 goto cs_failed; 755 } 756 } 757 758 /* 759 * Allocate an interrupt line. Note that this does not assign 760 * a handler to the interrupt, unless the 'Handler' member of 761 * the irq structure is initialized. 762 */ 763 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); 764 765 /* We initialize the hermes structure before completing PCMCIA 766 * configuration just in case the interrupt handler gets 767 * called. */ 768 mem = ioport_map(link->io.BasePort1, link->io.NumPorts1); 769 if (!mem) 770 goto cs_failed; 771 772 hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING); 773 774 /* 775 * This actually configures the PCMCIA socket -- setting up 776 * the I/O windows and the interrupt mapping, and putting the 777 * card and host interface into "Memory and IO" mode. 778 */ 779 CS_CHECK(RequestConfiguration, 780 pcmcia_request_configuration(link, &link->conf)); 781 782 /* Ok, we have the configuration, prepare to register the netdev */ 783 dev->base_addr = link->io.BasePort1; 784 dev->irq = link->irq.AssignedIRQ; 785 card->node.major = card->node.minor = 0; 786 787 /* Reset card and download firmware */ 788 if (spectrum_cs_hard_reset(priv) != 0) { 789 goto failed; 790 } 791 792 SET_NETDEV_DEV(dev, &handle_to_dev(link)); 793 /* Tell the stack we exist */ 794 if (register_netdev(dev) != 0) { 795 printk(KERN_ERR PFX "register_netdev() failed\n"); 796 goto failed; 797 } 798 799 /* At this point, the dev_node_t structure(s) needs to be 800 * initialized and arranged in a linked list at link->dev_node. */ 801 strcpy(card->node.dev_name, dev->name); 802 link->dev_node = &card->node; /* link->dev_node being non-NULL is also 803 used to indicate that the 804 net_device has been registered */ 805 806 /* Finally, report what we've done */ 807 printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io " 808 "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id, 809 link->irq.AssignedIRQ, link->io.BasePort1, 810 link->io.BasePort1 + link->io.NumPorts1 - 1); 811 812 return 0; 813 814 cs_failed: 815 cs_error(link, last_fn, last_ret); 816 817 failed: 818 spectrum_cs_release(link); 819 return -ENODEV; 820} /* spectrum_cs_config */ 821 822/* 823 * After a card is removed, spectrum_cs_release() will unregister the 824 * device, and release the PCMCIA configuration. If the device is 825 * still open, this will be postponed until it is closed. 826 */ 827static void 828spectrum_cs_release(struct pcmcia_device *link) 829{ 830 struct net_device *dev = link->priv; 831 struct orinoco_private *priv = netdev_priv(dev); 832 unsigned long flags; 833 834 /* We're committed to taking the device away now, so mark the 835 * hardware as unavailable */ 836 spin_lock_irqsave(&priv->lock, flags); 837 priv->hw_unavailable++; 838 spin_unlock_irqrestore(&priv->lock, flags); 839 840 pcmcia_disable_device(link); 841 if (priv->hw.iobase) 842 ioport_unmap(priv->hw.iobase); 843} /* spectrum_cs_release */ 844 845 846static int 847spectrum_cs_suspend(struct pcmcia_device *link) 848{ 849 struct net_device *dev = link->priv; 850 struct orinoco_private *priv = netdev_priv(dev); 851 int err = 0; 852 853 /* Mark the device as stopped, to block IO until later */ 854 spin_lock(&priv->lock); 855 856 err = __orinoco_down(dev); 857 if (err) 858 printk(KERN_WARNING "%s: Error %d downing interface\n", 859 dev->name, err); 860 861 netif_device_detach(dev); 862 priv->hw_unavailable++; 863 864 spin_unlock(&priv->lock); 865 866 return err; 867} 868 869static int 870spectrum_cs_resume(struct pcmcia_device *link) 871{ 872 struct net_device *dev = link->priv; 873 struct orinoco_private *priv = netdev_priv(dev); 874 875 netif_device_attach(dev); 876 priv->hw_unavailable--; 877 schedule_work(&priv->reset_work); 878 879 return 0; 880} 881 882 883/********************************************************************/ 884/* Module initialization */ 885/********************************************************************/ 886 887/* Can't be declared "const" or the whole __initdata section will 888 * become const */ 889static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION 890 " (Pavel Roskin <proski@gnu.org>," 891 " David Gibson <hermes@gibson.dropbear.id.au>, et al)"; 892 893static struct pcmcia_device_id spectrum_cs_ids[] = { 894 PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4137 */ 895 PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */ 896 PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless LAN PC Card", 0x816cc815, 0x6fbf459a), /* 2011B, not 2011 */ 897 PCMCIA_DEVICE_NULL, 898}; 899MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids); 900 901static struct pcmcia_driver orinoco_driver = { 902 .owner = THIS_MODULE, 903 .drv = { 904 .name = DRIVER_NAME, 905 }, 906 .probe = spectrum_cs_probe, 907 .remove = spectrum_cs_detach, 908 .suspend = spectrum_cs_suspend, 909 .resume = spectrum_cs_resume, 910 .id_table = spectrum_cs_ids, 911}; 912 913static int __init 914init_spectrum_cs(void) 915{ 916 printk(KERN_DEBUG "%s\n", version); 917 918 return pcmcia_register_driver(&orinoco_driver); 919} 920 921static void __exit 922exit_spectrum_cs(void) 923{ 924 pcmcia_unregister_driver(&orinoco_driver); 925} 926 927module_init(init_spectrum_cs); 928module_exit(exit_spectrum_cs);