linux/drivers/net/wireless/intersil/hostap/hostap_cs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2#define PRISM2_PCCARD
   3
   4#include <linux/module.h>
   5#include <linux/if.h>
   6#include <linux/slab.h>
   7#include <linux/wait.h>
   8#include <linux/timer.h>
   9#include <linux/skbuff.h>
  10#include <linux/netdevice.h>
  11#include <linux/workqueue.h>
  12#include <linux/wireless.h>
  13#include <net/iw_handler.h>
  14
  15#include <pcmcia/cistpl.h>
  16#include <pcmcia/cisreg.h>
  17#include <pcmcia/ds.h>
  18
  19#include <asm/io.h>
  20
  21#include "hostap_wlan.h"
  22
  23
  24static char *dev_info = "hostap_cs";
  25
  26MODULE_AUTHOR("Jouni Malinen");
  27MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
  28                   "cards (PC Card).");
  29MODULE_LICENSE("GPL");
  30
  31
  32static int ignore_cis_vcc;
  33module_param(ignore_cis_vcc, int, 0444);
  34MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry");
  35
  36
  37/* struct local_info::hw_priv */
  38struct hostap_cs_priv {
  39        struct pcmcia_device *link;
  40        int sandisk_connectplus;
  41};
  42
  43
  44#ifdef PRISM2_IO_DEBUG
  45
  46static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
  47{
  48        struct hostap_interface *iface;
  49        local_info_t *local;
  50        unsigned long flags;
  51
  52        iface = netdev_priv(dev);
  53        local = iface->local;
  54        spin_lock_irqsave(&local->lock, flags);
  55        prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
  56        outb(v, dev->base_addr + a);
  57        spin_unlock_irqrestore(&local->lock, flags);
  58}
  59
  60static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
  61{
  62        struct hostap_interface *iface;
  63        local_info_t *local;
  64        unsigned long flags;
  65        u8 v;
  66
  67        iface = netdev_priv(dev);
  68        local = iface->local;
  69        spin_lock_irqsave(&local->lock, flags);
  70        v = inb(dev->base_addr + a);
  71        prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v);
  72        spin_unlock_irqrestore(&local->lock, flags);
  73        return v;
  74}
  75
  76static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
  77{
  78        struct hostap_interface *iface;
  79        local_info_t *local;
  80        unsigned long flags;
  81
  82        iface = netdev_priv(dev);
  83        local = iface->local;
  84        spin_lock_irqsave(&local->lock, flags);
  85        prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
  86        outw(v, dev->base_addr + a);
  87        spin_unlock_irqrestore(&local->lock, flags);
  88}
  89
  90static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
  91{
  92        struct hostap_interface *iface;
  93        local_info_t *local;
  94        unsigned long flags;
  95        u16 v;
  96
  97        iface = netdev_priv(dev);
  98        local = iface->local;
  99        spin_lock_irqsave(&local->lock, flags);
 100        v = inw(dev->base_addr + a);
 101        prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v);
 102        spin_unlock_irqrestore(&local->lock, flags);
 103        return v;
 104}
 105
 106static inline void hfa384x_outsw_debug(struct net_device *dev, int a,
 107                                       u8 *buf, int wc)
 108{
 109        struct hostap_interface *iface;
 110        local_info_t *local;
 111        unsigned long flags;
 112
 113        iface = netdev_priv(dev);
 114        local = iface->local;
 115        spin_lock_irqsave(&local->lock, flags);
 116        prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTSW, a, wc);
 117        outsw(dev->base_addr + a, buf, wc);
 118        spin_unlock_irqrestore(&local->lock, flags);
 119}
 120
 121static inline void hfa384x_insw_debug(struct net_device *dev, int a,
 122                                      u8 *buf, int wc)
 123{
 124        struct hostap_interface *iface;
 125        local_info_t *local;
 126        unsigned long flags;
 127
 128        iface = netdev_priv(dev);
 129        local = iface->local;
 130        spin_lock_irqsave(&local->lock, flags);
 131        prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INSW, a, wc);
 132        insw(dev->base_addr + a, buf, wc);
 133        spin_unlock_irqrestore(&local->lock, flags);
 134}
 135
 136#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v))
 137#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a))
 138#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v))
 139#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a))
 140#define HFA384X_OUTSW(a, buf, wc) hfa384x_outsw_debug(dev, (a), (buf), (wc))
 141#define HFA384X_INSW(a, buf, wc) hfa384x_insw_debug(dev, (a), (buf), (wc))
 142
 143#else /* PRISM2_IO_DEBUG */
 144
 145#define HFA384X_OUTB(v,a) outb((v), dev->base_addr + (a))
 146#define HFA384X_INB(a) inb(dev->base_addr + (a))
 147#define HFA384X_OUTW(v,a) outw((v), dev->base_addr + (a))
 148#define HFA384X_INW(a) inw(dev->base_addr + (a))
 149#define HFA384X_INSW(a, buf, wc) insw(dev->base_addr + (a), buf, wc)
 150#define HFA384X_OUTSW(a, buf, wc) outsw(dev->base_addr + (a), buf, wc)
 151
 152#endif /* PRISM2_IO_DEBUG */
 153
 154
 155static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf,
 156                            int len)
 157{
 158        u16 d_off;
 159        u16 *pos;
 160
 161        d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
 162        pos = (u16 *) buf;
 163
 164        if (len / 2)
 165                HFA384X_INSW(d_off, buf, len / 2);
 166        pos += len / 2;
 167
 168        if (len & 1)
 169                *((char *) pos) = HFA384X_INB(d_off);
 170
 171        return 0;
 172}
 173
 174
 175static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
 176{
 177        u16 d_off;
 178        u16 *pos;
 179
 180        d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
 181        pos = (u16 *) buf;
 182
 183        if (len / 2)
 184                HFA384X_OUTSW(d_off, buf, len / 2);
 185        pos += len / 2;
 186
 187        if (len & 1)
 188                HFA384X_OUTB(*((char *) pos), d_off);
 189
 190        return 0;
 191}
 192
 193
 194/* FIX: This might change at some point.. */
 195#include "hostap_hw.c"
 196
 197
 198
 199static void prism2_detach(struct pcmcia_device *p_dev);
 200static void prism2_release(u_long arg);
 201static int prism2_config(struct pcmcia_device *link);
 202
 203
 204static int prism2_pccard_card_present(local_info_t *local)
 205{
 206        struct hostap_cs_priv *hw_priv = local->hw_priv;
 207        if (hw_priv != NULL && hw_priv->link != NULL && pcmcia_dev_present(hw_priv->link))
 208                return 1;
 209        return 0;
 210}
 211
 212
 213/*
 214 * SanDisk CompactFlash WLAN Flashcard - Product Manual v1.0
 215 * Document No. 20-10-00058, January 2004
 216 * http://www.sandisk.com/pdf/industrial/ProdManualCFWLANv1.0.pdf
 217 */
 218#define SANDISK_WLAN_ACTIVATION_OFF 0x40
 219#define SANDISK_HCR_OFF 0x42
 220
 221
 222static void sandisk_set_iobase(local_info_t *local)
 223{
 224        int res;
 225        struct hostap_cs_priv *hw_priv = local->hw_priv;
 226
 227        res = pcmcia_write_config_byte(hw_priv->link, 0x10,
 228                                hw_priv->link->resource[0]->start & 0x00ff);
 229        if (res != 0) {
 230                printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -"
 231                       " res=%d\n", res);
 232        }
 233        udelay(10);
 234
 235        res = pcmcia_write_config_byte(hw_priv->link, 0x12,
 236                                (hw_priv->link->resource[0]->start >> 8) & 0x00ff);
 237        if (res != 0) {
 238                printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -"
 239                       " res=%d\n", res);
 240        }
 241}
 242
 243
 244static void sandisk_write_hcr(local_info_t *local, int hcr)
 245{
 246        struct net_device *dev = local->dev;
 247        int i;
 248
 249        HFA384X_OUTB(0x80, SANDISK_WLAN_ACTIVATION_OFF);
 250        udelay(50);
 251        for (i = 0; i < 10; i++) {
 252                HFA384X_OUTB(hcr, SANDISK_HCR_OFF);
 253        }
 254        udelay(55);
 255        HFA384X_OUTB(0x45, SANDISK_WLAN_ACTIVATION_OFF);
 256}
 257
 258
 259static int sandisk_enable_wireless(struct net_device *dev)
 260{
 261        int res, ret = 0;
 262        struct hostap_interface *iface = netdev_priv(dev);
 263        local_info_t *local = iface->local;
 264        struct hostap_cs_priv *hw_priv = local->hw_priv;
 265
 266        if (resource_size(hw_priv->link->resource[0]) < 0x42) {
 267                /* Not enough ports to be SanDisk multi-function card */
 268                ret = -ENODEV;
 269                goto done;
 270        }
 271
 272        if (hw_priv->link->manf_id != 0xd601 || hw_priv->link->card_id != 0x0101) {
 273                /* No SanDisk manfid found */
 274                ret = -ENODEV;
 275                goto done;
 276        }
 277
 278        if (hw_priv->link->socket->functions < 2) {
 279                /* No multi-function links found */
 280                ret = -ENODEV;
 281                goto done;
 282        }
 283
 284        printk(KERN_DEBUG "%s: Multi-function SanDisk ConnectPlus detected"
 285               " - using vendor-specific initialization\n", dev->name);
 286        hw_priv->sandisk_connectplus = 1;
 287
 288        res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR,
 289                                COR_SOFT_RESET);
 290        if (res != 0) {
 291                printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
 292                       dev->name, res);
 293                goto done;
 294        }
 295        mdelay(5);
 296
 297        /*
 298         * Do not enable interrupts here to avoid some bogus events. Interrupts
 299         * will be enabled during the first cor_sreset call.
 300         */
 301        res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR,
 302                                (COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE |
 303                                        COR_FUNC_ENA));
 304        if (res != 0) {
 305                printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
 306                       dev->name, res);
 307                goto done;
 308        }
 309        mdelay(5);
 310
 311        sandisk_set_iobase(local);
 312
 313        HFA384X_OUTB(0xc5, SANDISK_WLAN_ACTIVATION_OFF);
 314        udelay(10);
 315        HFA384X_OUTB(0x4b, SANDISK_WLAN_ACTIVATION_OFF);
 316        udelay(10);
 317
 318done:
 319        return ret;
 320}
 321
 322
 323static void prism2_pccard_cor_sreset(local_info_t *local)
 324{
 325        int res;
 326        u8 val;
 327        struct hostap_cs_priv *hw_priv = local->hw_priv;
 328
 329        if (!prism2_pccard_card_present(local))
 330               return;
 331
 332        res = pcmcia_read_config_byte(hw_priv->link, CISREG_COR, &val);
 333        if (res != 0) {
 334                printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n",
 335                       res);
 336                return;
 337        }
 338        printk(KERN_DEBUG "prism2_pccard_cor_sreset: original COR %02x\n",
 339                val);
 340
 341        val |= COR_SOFT_RESET;
 342        res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR, val);
 343        if (res != 0) {
 344                printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n",
 345                       res);
 346                return;
 347        }
 348
 349        mdelay(hw_priv->sandisk_connectplus ? 5 : 2);
 350
 351        val &= ~COR_SOFT_RESET;
 352        if (hw_priv->sandisk_connectplus)
 353                val |= COR_IREQ_ENA;
 354        res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR, val);
 355        if (res != 0) {
 356                printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n",
 357                       res);
 358                return;
 359        }
 360
 361        mdelay(hw_priv->sandisk_connectplus ? 5 : 2);
 362
 363        if (hw_priv->sandisk_connectplus)
 364                sandisk_set_iobase(local);
 365}
 366
 367
 368static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
 369{
 370        int res;
 371        u8 old_cor;
 372        struct hostap_cs_priv *hw_priv = local->hw_priv;
 373
 374        if (!prism2_pccard_card_present(local))
 375               return;
 376
 377        if (hw_priv->sandisk_connectplus) {
 378                sandisk_write_hcr(local, hcr);
 379                return;
 380        }
 381
 382        res = pcmcia_read_config_byte(hw_priv->link, CISREG_COR, &old_cor);
 383        if (res != 0) {
 384                printk(KERN_DEBUG "%s failed 1 (%d)\n", __func__, res);
 385                return;
 386        }
 387        printk(KERN_DEBUG "%s: original COR %02x\n", __func__, old_cor);
 388
 389        res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR,
 390                                old_cor | COR_SOFT_RESET);
 391        if (res != 0) {
 392                printk(KERN_DEBUG "%s failed 2 (%d)\n", __func__, res);
 393                return;
 394        }
 395
 396        mdelay(10);
 397
 398        /* Setup Genesis mode */
 399        res = pcmcia_write_config_byte(hw_priv->link, CISREG_CCSR, hcr);
 400        if (res != 0) {
 401                printk(KERN_DEBUG "%s failed 3 (%d)\n", __func__, res);
 402                return;
 403        }
 404        mdelay(10);
 405
 406        res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR,
 407                                old_cor & ~COR_SOFT_RESET);
 408        if (res != 0) {
 409                printk(KERN_DEBUG "%s failed 4 (%d)\n", __func__, res);
 410                return;
 411        }
 412
 413        mdelay(10);
 414}
 415
 416
 417static struct prism2_helper_functions prism2_pccard_funcs =
 418{
 419        .card_present   = prism2_pccard_card_present,
 420        .cor_sreset     = prism2_pccard_cor_sreset,
 421        .genesis_reset  = prism2_pccard_genesis_reset,
 422        .hw_type        = HOSTAP_HW_PCCARD,
 423};
 424
 425
 426/* allocate local data and register with CardServices
 427 * initialize dev_link structure, but do not configure the card yet */
 428static int hostap_cs_probe(struct pcmcia_device *p_dev)
 429{
 430        int ret;
 431
 432        PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info);
 433
 434        ret = prism2_config(p_dev);
 435        if (ret) {
 436                PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n");
 437        }
 438
 439        return ret;
 440}
 441
 442
 443static void prism2_detach(struct pcmcia_device *link)
 444{
 445        PDEBUG(DEBUG_FLOW, "prism2_detach\n");
 446
 447        prism2_release((u_long)link);
 448
 449        /* release net devices */
 450        if (link->priv) {
 451                struct hostap_cs_priv *hw_priv;
 452                struct net_device *dev;
 453                struct hostap_interface *iface;
 454                dev = link->priv;
 455                iface = netdev_priv(dev);
 456                hw_priv = iface->local->hw_priv;
 457                prism2_free_local_data(dev);
 458                kfree(hw_priv);
 459        }
 460}
 461
 462
 463static int prism2_config_check(struct pcmcia_device *p_dev, void *priv_data)
 464{
 465        if (p_dev->config_index == 0)
 466                return -EINVAL;
 467
 468        return pcmcia_request_io(p_dev);
 469}
 470
 471static int prism2_config(struct pcmcia_device *link)
 472{
 473        struct net_device *dev;
 474        struct hostap_interface *iface;
 475        local_info_t *local;
 476        int ret;
 477        struct hostap_cs_priv *hw_priv;
 478        unsigned long flags;
 479
 480        PDEBUG(DEBUG_FLOW, "prism2_config()\n");
 481
 482        hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL);
 483        if (hw_priv == NULL) {
 484                ret = -ENOMEM;
 485                goto failed;
 486        }
 487
 488        /* Look for an appropriate configuration table entry in the CIS */
 489        link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO |
 490                CONF_AUTO_CHECK_VCC | CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
 491        if (ignore_cis_vcc)
 492                link->config_flags &= ~CONF_AUTO_CHECK_VCC;
 493        ret = pcmcia_loop_config(link, prism2_config_check, NULL);
 494        if (ret) {
 495                if (!ignore_cis_vcc)
 496                        printk(KERN_ERR "GetNextTuple(): No matching "
 497                               "CIS configuration.  Maybe you need the "
 498                               "ignore_cis_vcc=1 parameter.\n");
 499                goto failed;
 500        }
 501
 502        /* Need to allocate net_device before requesting IRQ handler */
 503        dev = prism2_init_local_data(&prism2_pccard_funcs, 0,
 504                                     &link->dev);
 505        if (!dev) {
 506                ret = -ENOMEM;
 507                goto failed;
 508        }
 509        link->priv = dev;
 510
 511        iface = netdev_priv(dev);
 512        local = iface->local;
 513        local->hw_priv = hw_priv;
 514        hw_priv->link = link;
 515
 516        /*
 517         * We enable IRQ here, but IRQ handler will not proceed
 518         * until dev->base_addr is set below. This protect us from
 519         * receive interrupts when driver is not initialized.
 520         */
 521        ret = pcmcia_request_irq(link, prism2_interrupt);
 522        if (ret)
 523                goto failed;
 524
 525        ret = pcmcia_enable_device(link);
 526        if (ret)
 527                goto failed;
 528
 529        spin_lock_irqsave(&local->irq_init_lock, flags);
 530        dev->irq = link->irq;
 531        dev->base_addr = link->resource[0]->start;
 532        spin_unlock_irqrestore(&local->irq_init_lock, flags);
 533
 534        local->shutdown = 0;
 535
 536        sandisk_enable_wireless(dev);
 537
 538        ret = prism2_hw_config(dev, 1);
 539        if (!ret)
 540                ret = hostap_hw_ready(dev);
 541
 542        return ret;
 543
 544 failed:
 545        kfree(hw_priv);
 546        prism2_release((u_long)link);
 547        return ret;
 548}
 549
 550
 551static void prism2_release(u_long arg)
 552{
 553        struct pcmcia_device *link = (struct pcmcia_device *)arg;
 554
 555        PDEBUG(DEBUG_FLOW, "prism2_release\n");
 556
 557        if (link->priv) {
 558                struct net_device *dev = link->priv;
 559                struct hostap_interface *iface;
 560
 561                iface = netdev_priv(dev);
 562                prism2_hw_shutdown(dev, 0);
 563                iface->local->shutdown = 1;
 564        }
 565
 566        pcmcia_disable_device(link);
 567        PDEBUG(DEBUG_FLOW, "release - done\n");
 568}
 569
 570static int hostap_cs_suspend(struct pcmcia_device *link)
 571{
 572        struct net_device *dev = (struct net_device *) link->priv;
 573        int dev_open = 0;
 574        struct hostap_interface *iface = NULL;
 575
 576        if (!dev)
 577                return -ENODEV;
 578
 579        iface = netdev_priv(dev);
 580
 581        PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
 582        if (iface && iface->local)
 583                dev_open = iface->local->num_dev_open > 0;
 584        if (dev_open) {
 585                netif_stop_queue(dev);
 586                netif_device_detach(dev);
 587        }
 588        prism2_suspend(dev);
 589
 590        return 0;
 591}
 592
 593static int hostap_cs_resume(struct pcmcia_device *link)
 594{
 595        struct net_device *dev = (struct net_device *) link->priv;
 596        int dev_open = 0;
 597        struct hostap_interface *iface = NULL;
 598
 599        if (!dev)
 600                return -ENODEV;
 601
 602        iface = netdev_priv(dev);
 603
 604        PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
 605
 606        if (iface && iface->local)
 607                dev_open = iface->local->num_dev_open > 0;
 608
 609        prism2_hw_shutdown(dev, 1);
 610        prism2_hw_config(dev, dev_open ? 0 : 1);
 611        if (dev_open) {
 612                netif_device_attach(dev);
 613                netif_start_queue(dev);
 614        }
 615
 616        return 0;
 617}
 618
 619static const struct pcmcia_device_id hostap_cs_ids[] = {
 620        PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100),
 621        PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300),
 622        PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777),
 623        PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000),
 624        PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002),
 625        PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x3301),
 626        PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002),
 627        PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030b),
 628        PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612),
 629        PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613),
 630        PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002),
 631        PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002),
 632        PCMCIA_DEVICE_MANF_CARD(0x02d2, 0x0001),
 633        PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x0001),
 634        PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300),
 635/*      PCMCIA_DEVICE_MANF_CARD(0xc00f, 0x0000),    conflict with pcnet_cs */
 636        PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002),
 637        PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002),
 638        PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005),
 639        PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0010),
 640        PCMCIA_DEVICE_MANF_CARD(0x0126, 0x0002),
 641        PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0xd601, 0x0005, "ADLINK 345 CF",
 642                                         0x2d858104),
 643        PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "INTERSIL",
 644                                         0x74c5e40d),
 645        PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "Intersil",
 646                                         0x4b801a17),
 647        PCMCIA_DEVICE_MANF_CARD_PROD_ID3(0x0156, 0x0002, "Version 01.02",
 648                                         0x4b74baa0),
 649        PCMCIA_MFC_DEVICE_PROD_ID12(0, "SanDisk", "ConnectPlus",
 650                                    0x7a954bd9, 0x74be00c6),
 651        PCMCIA_DEVICE_PROD_ID123(
 652                "Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02",
 653                0xe6ec52ce, 0x08649af2, 0x4b74baa0),
 654        PCMCIA_DEVICE_PROD_ID123(
 655                "Canon", "Wireless LAN CF Card K30225", "Version 01.00",
 656                0x96ef6fe2, 0x263fcbab, 0xa57adb8c),
 657        PCMCIA_DEVICE_PROD_ID123(
 658                "D", "Link DWL-650 11Mbps WLAN Card", "Version 01.02",
 659                0x71b18589, 0xb6f1b0ab, 0x4b74baa0),
 660        PCMCIA_DEVICE_PROD_ID123(
 661                "Instant Wireless ", " Network PC CARD", "Version 01.02",
 662                0x11d901af, 0x6e9bd926, 0x4b74baa0),
 663        PCMCIA_DEVICE_PROD_ID123(
 664                "SMC", "SMC2632W", "Version 01.02",
 665                0xc4f8b18b, 0x474a1f2a, 0x4b74baa0),
 666        PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 
 667                                0x2decece3, 0x82067c18),
 668        PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card",
 669                                0x54f7c49c, 0x15a75e5b),
 670        PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE",
 671                                0x74c5e40d, 0xdb472a18),
 672        PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card",
 673                                0x0733cc81, 0x0c52f395),
 674        PCMCIA_DEVICE_PROD_ID12(
 675                "ZoomAir 11Mbps High", "Rate wireless Networking",
 676                0x273fe3db, 0x32a1eaee),
 677        PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card",
 678                0xa37434e9, 0x9762e8f1),
 679        PCMCIA_DEVICE_PROD_ID123(
 680                "Pretec", "CompactWLAN Card 802.11b", "2.5",
 681                0x1cadd3e5, 0xe697636c, 0x7a5bfcf1),
 682        PCMCIA_DEVICE_PROD_ID123(
 683                "U.S. Robotics", "IEEE 802.11b PC-CARD", "Version 01.02",
 684                0xc7b8df9d, 0x1700d087, 0x4b74baa0),
 685        PCMCIA_DEVICE_PROD_ID123(
 686                "Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio",
 687                "Ver. 1.00",
 688                0x5cd01705, 0x4271660f, 0x9d08ee12),
 689        PCMCIA_DEVICE_PROD_ID123(
 690                "Wireless LAN" , "11Mbps PC Card", "Version 01.02",
 691                0x4b8870ff, 0x70e946d1, 0x4b74baa0),
 692        PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092),
 693        PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2),
 694        PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b),
 695        PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39),
 696        PCMCIA_DEVICE_NULL
 697};
 698MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids);
 699
 700
 701static struct pcmcia_driver hostap_driver = {
 702        .name           = "hostap_cs",
 703        .probe          = hostap_cs_probe,
 704        .remove         = prism2_detach,
 705        .owner          = THIS_MODULE,
 706        .id_table       = hostap_cs_ids,
 707        .suspend        = hostap_cs_suspend,
 708        .resume         = hostap_cs_resume,
 709};
 710module_pcmcia_driver(hostap_driver);
 711