162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci#define PRISM2_PCCARD 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/module.h> 562306a36Sopenharmony_ci#include <linux/if.h> 662306a36Sopenharmony_ci#include <linux/slab.h> 762306a36Sopenharmony_ci#include <linux/wait.h> 862306a36Sopenharmony_ci#include <linux/timer.h> 962306a36Sopenharmony_ci#include <linux/skbuff.h> 1062306a36Sopenharmony_ci#include <linux/netdevice.h> 1162306a36Sopenharmony_ci#include <linux/workqueue.h> 1262306a36Sopenharmony_ci#include <linux/wireless.h> 1362306a36Sopenharmony_ci#include <net/iw_handler.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <pcmcia/cistpl.h> 1662306a36Sopenharmony_ci#include <pcmcia/cisreg.h> 1762306a36Sopenharmony_ci#include <pcmcia/ds.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <asm/io.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include "hostap_wlan.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic char *dev_info = "hostap_cs"; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ciMODULE_AUTHOR("Jouni Malinen"); 2762306a36Sopenharmony_ciMODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN " 2862306a36Sopenharmony_ci "cards (PC Card)."); 2962306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic int ignore_cis_vcc; 3362306a36Sopenharmony_cimodule_param(ignore_cis_vcc, int, 0444); 3462306a36Sopenharmony_ciMODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry"); 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* struct local_info::hw_priv */ 3862306a36Sopenharmony_cistruct hostap_cs_priv { 3962306a36Sopenharmony_ci struct pcmcia_device *link; 4062306a36Sopenharmony_ci int sandisk_connectplus; 4162306a36Sopenharmony_ci}; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#ifdef PRISM2_IO_DEBUG 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistatic inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci struct hostap_interface *iface; 4962306a36Sopenharmony_ci local_info_t *local; 5062306a36Sopenharmony_ci unsigned long flags; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci iface = netdev_priv(dev); 5362306a36Sopenharmony_ci local = iface->local; 5462306a36Sopenharmony_ci spin_lock_irqsave(&local->lock, flags); 5562306a36Sopenharmony_ci prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v); 5662306a36Sopenharmony_ci outb(v, dev->base_addr + a); 5762306a36Sopenharmony_ci spin_unlock_irqrestore(&local->lock, flags); 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic inline u8 hfa384x_inb_debug(struct net_device *dev, int a) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci struct hostap_interface *iface; 6362306a36Sopenharmony_ci local_info_t *local; 6462306a36Sopenharmony_ci unsigned long flags; 6562306a36Sopenharmony_ci u8 v; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci iface = netdev_priv(dev); 6862306a36Sopenharmony_ci local = iface->local; 6962306a36Sopenharmony_ci spin_lock_irqsave(&local->lock, flags); 7062306a36Sopenharmony_ci v = inb(dev->base_addr + a); 7162306a36Sopenharmony_ci prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v); 7262306a36Sopenharmony_ci spin_unlock_irqrestore(&local->lock, flags); 7362306a36Sopenharmony_ci return v; 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v) 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci struct hostap_interface *iface; 7962306a36Sopenharmony_ci local_info_t *local; 8062306a36Sopenharmony_ci unsigned long flags; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci iface = netdev_priv(dev); 8362306a36Sopenharmony_ci local = iface->local; 8462306a36Sopenharmony_ci spin_lock_irqsave(&local->lock, flags); 8562306a36Sopenharmony_ci prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v); 8662306a36Sopenharmony_ci outw(v, dev->base_addr + a); 8762306a36Sopenharmony_ci spin_unlock_irqrestore(&local->lock, flags); 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic inline u16 hfa384x_inw_debug(struct net_device *dev, int a) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci struct hostap_interface *iface; 9362306a36Sopenharmony_ci local_info_t *local; 9462306a36Sopenharmony_ci unsigned long flags; 9562306a36Sopenharmony_ci u16 v; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci iface = netdev_priv(dev); 9862306a36Sopenharmony_ci local = iface->local; 9962306a36Sopenharmony_ci spin_lock_irqsave(&local->lock, flags); 10062306a36Sopenharmony_ci v = inw(dev->base_addr + a); 10162306a36Sopenharmony_ci prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v); 10262306a36Sopenharmony_ci spin_unlock_irqrestore(&local->lock, flags); 10362306a36Sopenharmony_ci return v; 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic inline void hfa384x_outsw_debug(struct net_device *dev, int a, 10762306a36Sopenharmony_ci u8 *buf, int wc) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci struct hostap_interface *iface; 11062306a36Sopenharmony_ci local_info_t *local; 11162306a36Sopenharmony_ci unsigned long flags; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci iface = netdev_priv(dev); 11462306a36Sopenharmony_ci local = iface->local; 11562306a36Sopenharmony_ci spin_lock_irqsave(&local->lock, flags); 11662306a36Sopenharmony_ci prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTSW, a, wc); 11762306a36Sopenharmony_ci outsw(dev->base_addr + a, buf, wc); 11862306a36Sopenharmony_ci spin_unlock_irqrestore(&local->lock, flags); 11962306a36Sopenharmony_ci} 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cistatic inline void hfa384x_insw_debug(struct net_device *dev, int a, 12262306a36Sopenharmony_ci u8 *buf, int wc) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci struct hostap_interface *iface; 12562306a36Sopenharmony_ci local_info_t *local; 12662306a36Sopenharmony_ci unsigned long flags; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci iface = netdev_priv(dev); 12962306a36Sopenharmony_ci local = iface->local; 13062306a36Sopenharmony_ci spin_lock_irqsave(&local->lock, flags); 13162306a36Sopenharmony_ci prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INSW, a, wc); 13262306a36Sopenharmony_ci insw(dev->base_addr + a, buf, wc); 13362306a36Sopenharmony_ci spin_unlock_irqrestore(&local->lock, flags); 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v)) 13762306a36Sopenharmony_ci#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a)) 13862306a36Sopenharmony_ci#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v)) 13962306a36Sopenharmony_ci#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a)) 14062306a36Sopenharmony_ci#define HFA384X_OUTSW(a, buf, wc) hfa384x_outsw_debug(dev, (a), (buf), (wc)) 14162306a36Sopenharmony_ci#define HFA384X_INSW(a, buf, wc) hfa384x_insw_debug(dev, (a), (buf), (wc)) 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci#else /* PRISM2_IO_DEBUG */ 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci#define HFA384X_OUTB(v,a) outb((v), dev->base_addr + (a)) 14662306a36Sopenharmony_ci#define HFA384X_INB(a) inb(dev->base_addr + (a)) 14762306a36Sopenharmony_ci#define HFA384X_OUTW(v,a) outw((v), dev->base_addr + (a)) 14862306a36Sopenharmony_ci#define HFA384X_INW(a) inw(dev->base_addr + (a)) 14962306a36Sopenharmony_ci#define HFA384X_INSW(a, buf, wc) insw(dev->base_addr + (a), buf, wc) 15062306a36Sopenharmony_ci#define HFA384X_OUTSW(a, buf, wc) outsw(dev->base_addr + (a), buf, wc) 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci#endif /* PRISM2_IO_DEBUG */ 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf, 15662306a36Sopenharmony_ci int len) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci u16 d_off; 15962306a36Sopenharmony_ci u16 *pos; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF; 16262306a36Sopenharmony_ci pos = (u16 *) buf; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci if (len / 2) 16562306a36Sopenharmony_ci HFA384X_INSW(d_off, buf, len / 2); 16662306a36Sopenharmony_ci pos += len / 2; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci if (len & 1) 16962306a36Sopenharmony_ci *((char *) pos) = HFA384X_INB(d_off); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci return 0; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_cistatic int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci u16 d_off; 17862306a36Sopenharmony_ci u16 *pos; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF; 18162306a36Sopenharmony_ci pos = (u16 *) buf; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci if (len / 2) 18462306a36Sopenharmony_ci HFA384X_OUTSW(d_off, buf, len / 2); 18562306a36Sopenharmony_ci pos += len / 2; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci if (len & 1) 18862306a36Sopenharmony_ci HFA384X_OUTB(*((char *) pos), d_off); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci return 0; 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci/* FIX: This might change at some point.. */ 19562306a36Sopenharmony_ci#include "hostap_hw.c" 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_cistatic void prism2_detach(struct pcmcia_device *p_dev); 20062306a36Sopenharmony_cistatic void prism2_release(u_long arg); 20162306a36Sopenharmony_cistatic int prism2_config(struct pcmcia_device *link); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic int prism2_pccard_card_present(local_info_t *local) 20562306a36Sopenharmony_ci{ 20662306a36Sopenharmony_ci struct hostap_cs_priv *hw_priv = local->hw_priv; 20762306a36Sopenharmony_ci if (hw_priv != NULL && hw_priv->link != NULL && pcmcia_dev_present(hw_priv->link)) 20862306a36Sopenharmony_ci return 1; 20962306a36Sopenharmony_ci return 0; 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci/* 21462306a36Sopenharmony_ci * SanDisk CompactFlash WLAN Flashcard - Product Manual v1.0 21562306a36Sopenharmony_ci * Document No. 20-10-00058, January 2004 21662306a36Sopenharmony_ci * http://www.sandisk.com/pdf/industrial/ProdManualCFWLANv1.0.pdf 21762306a36Sopenharmony_ci */ 21862306a36Sopenharmony_ci#define SANDISK_WLAN_ACTIVATION_OFF 0x40 21962306a36Sopenharmony_ci#define SANDISK_HCR_OFF 0x42 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic void sandisk_set_iobase(local_info_t *local) 22362306a36Sopenharmony_ci{ 22462306a36Sopenharmony_ci int res; 22562306a36Sopenharmony_ci struct hostap_cs_priv *hw_priv = local->hw_priv; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci res = pcmcia_write_config_byte(hw_priv->link, 0x10, 22862306a36Sopenharmony_ci hw_priv->link->resource[0]->start & 0x00ff); 22962306a36Sopenharmony_ci if (res != 0) { 23062306a36Sopenharmony_ci printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -" 23162306a36Sopenharmony_ci " res=%d\n", res); 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci udelay(10); 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci res = pcmcia_write_config_byte(hw_priv->link, 0x12, 23662306a36Sopenharmony_ci (hw_priv->link->resource[0]->start >> 8) & 0x00ff); 23762306a36Sopenharmony_ci if (res != 0) { 23862306a36Sopenharmony_ci printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -" 23962306a36Sopenharmony_ci " res=%d\n", res); 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistatic void sandisk_write_hcr(local_info_t *local, int hcr) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci struct net_device *dev = local->dev; 24762306a36Sopenharmony_ci int i; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci HFA384X_OUTB(0x80, SANDISK_WLAN_ACTIVATION_OFF); 25062306a36Sopenharmony_ci udelay(50); 25162306a36Sopenharmony_ci for (i = 0; i < 10; i++) { 25262306a36Sopenharmony_ci HFA384X_OUTB(hcr, SANDISK_HCR_OFF); 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci udelay(55); 25562306a36Sopenharmony_ci HFA384X_OUTB(0x45, SANDISK_WLAN_ACTIVATION_OFF); 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistatic int sandisk_enable_wireless(struct net_device *dev) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci int res, ret = 0; 26262306a36Sopenharmony_ci struct hostap_interface *iface = netdev_priv(dev); 26362306a36Sopenharmony_ci local_info_t *local = iface->local; 26462306a36Sopenharmony_ci struct hostap_cs_priv *hw_priv = local->hw_priv; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci if (resource_size(hw_priv->link->resource[0]) < 0x42) { 26762306a36Sopenharmony_ci /* Not enough ports to be SanDisk multi-function card */ 26862306a36Sopenharmony_ci ret = -ENODEV; 26962306a36Sopenharmony_ci goto done; 27062306a36Sopenharmony_ci } 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci if (hw_priv->link->manf_id != 0xd601 || hw_priv->link->card_id != 0x0101) { 27362306a36Sopenharmony_ci /* No SanDisk manfid found */ 27462306a36Sopenharmony_ci ret = -ENODEV; 27562306a36Sopenharmony_ci goto done; 27662306a36Sopenharmony_ci } 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if (hw_priv->link->socket->functions < 2) { 27962306a36Sopenharmony_ci /* No multi-function links found */ 28062306a36Sopenharmony_ci ret = -ENODEV; 28162306a36Sopenharmony_ci goto done; 28262306a36Sopenharmony_ci } 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci printk(KERN_DEBUG "%s: Multi-function SanDisk ConnectPlus detected" 28562306a36Sopenharmony_ci " - using vendor-specific initialization\n", dev->name); 28662306a36Sopenharmony_ci hw_priv->sandisk_connectplus = 1; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR, 28962306a36Sopenharmony_ci COR_SOFT_RESET); 29062306a36Sopenharmony_ci if (res != 0) { 29162306a36Sopenharmony_ci printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n", 29262306a36Sopenharmony_ci dev->name, res); 29362306a36Sopenharmony_ci goto done; 29462306a36Sopenharmony_ci } 29562306a36Sopenharmony_ci mdelay(5); 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci /* 29862306a36Sopenharmony_ci * Do not enable interrupts here to avoid some bogus events. Interrupts 29962306a36Sopenharmony_ci * will be enabled during the first cor_sreset call. 30062306a36Sopenharmony_ci */ 30162306a36Sopenharmony_ci res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR, 30262306a36Sopenharmony_ci (COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE | 30362306a36Sopenharmony_ci COR_FUNC_ENA)); 30462306a36Sopenharmony_ci if (res != 0) { 30562306a36Sopenharmony_ci printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n", 30662306a36Sopenharmony_ci dev->name, res); 30762306a36Sopenharmony_ci goto done; 30862306a36Sopenharmony_ci } 30962306a36Sopenharmony_ci mdelay(5); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci sandisk_set_iobase(local); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci HFA384X_OUTB(0xc5, SANDISK_WLAN_ACTIVATION_OFF); 31462306a36Sopenharmony_ci udelay(10); 31562306a36Sopenharmony_ci HFA384X_OUTB(0x4b, SANDISK_WLAN_ACTIVATION_OFF); 31662306a36Sopenharmony_ci udelay(10); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_cidone: 31962306a36Sopenharmony_ci return ret; 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_cistatic void prism2_pccard_cor_sreset(local_info_t *local) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci int res; 32662306a36Sopenharmony_ci u8 val; 32762306a36Sopenharmony_ci struct hostap_cs_priv *hw_priv = local->hw_priv; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci if (!prism2_pccard_card_present(local)) 33062306a36Sopenharmony_ci return; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci res = pcmcia_read_config_byte(hw_priv->link, CISREG_COR, &val); 33362306a36Sopenharmony_ci if (res != 0) { 33462306a36Sopenharmony_ci printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n", 33562306a36Sopenharmony_ci res); 33662306a36Sopenharmony_ci return; 33762306a36Sopenharmony_ci } 33862306a36Sopenharmony_ci printk(KERN_DEBUG "prism2_pccard_cor_sreset: original COR %02x\n", 33962306a36Sopenharmony_ci val); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci val |= COR_SOFT_RESET; 34262306a36Sopenharmony_ci res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR, val); 34362306a36Sopenharmony_ci if (res != 0) { 34462306a36Sopenharmony_ci printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n", 34562306a36Sopenharmony_ci res); 34662306a36Sopenharmony_ci return; 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci mdelay(hw_priv->sandisk_connectplus ? 5 : 2); 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci val &= ~COR_SOFT_RESET; 35262306a36Sopenharmony_ci if (hw_priv->sandisk_connectplus) 35362306a36Sopenharmony_ci val |= COR_IREQ_ENA; 35462306a36Sopenharmony_ci res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR, val); 35562306a36Sopenharmony_ci if (res != 0) { 35662306a36Sopenharmony_ci printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n", 35762306a36Sopenharmony_ci res); 35862306a36Sopenharmony_ci return; 35962306a36Sopenharmony_ci } 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci mdelay(hw_priv->sandisk_connectplus ? 5 : 2); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci if (hw_priv->sandisk_connectplus) 36462306a36Sopenharmony_ci sandisk_set_iobase(local); 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_cistatic void prism2_pccard_genesis_reset(local_info_t *local, int hcr) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci int res; 37162306a36Sopenharmony_ci u8 old_cor; 37262306a36Sopenharmony_ci struct hostap_cs_priv *hw_priv = local->hw_priv; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci if (!prism2_pccard_card_present(local)) 37562306a36Sopenharmony_ci return; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci if (hw_priv->sandisk_connectplus) { 37862306a36Sopenharmony_ci sandisk_write_hcr(local, hcr); 37962306a36Sopenharmony_ci return; 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci res = pcmcia_read_config_byte(hw_priv->link, CISREG_COR, &old_cor); 38362306a36Sopenharmony_ci if (res != 0) { 38462306a36Sopenharmony_ci printk(KERN_DEBUG "%s failed 1 (%d)\n", __func__, res); 38562306a36Sopenharmony_ci return; 38662306a36Sopenharmony_ci } 38762306a36Sopenharmony_ci printk(KERN_DEBUG "%s: original COR %02x\n", __func__, old_cor); 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR, 39062306a36Sopenharmony_ci old_cor | COR_SOFT_RESET); 39162306a36Sopenharmony_ci if (res != 0) { 39262306a36Sopenharmony_ci printk(KERN_DEBUG "%s failed 2 (%d)\n", __func__, res); 39362306a36Sopenharmony_ci return; 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci mdelay(10); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci /* Setup Genesis mode */ 39962306a36Sopenharmony_ci res = pcmcia_write_config_byte(hw_priv->link, CISREG_CCSR, hcr); 40062306a36Sopenharmony_ci if (res != 0) { 40162306a36Sopenharmony_ci printk(KERN_DEBUG "%s failed 3 (%d)\n", __func__, res); 40262306a36Sopenharmony_ci return; 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci mdelay(10); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR, 40762306a36Sopenharmony_ci old_cor & ~COR_SOFT_RESET); 40862306a36Sopenharmony_ci if (res != 0) { 40962306a36Sopenharmony_ci printk(KERN_DEBUG "%s failed 4 (%d)\n", __func__, res); 41062306a36Sopenharmony_ci return; 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci mdelay(10); 41462306a36Sopenharmony_ci} 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic struct prism2_helper_functions prism2_pccard_funcs = 41862306a36Sopenharmony_ci{ 41962306a36Sopenharmony_ci .card_present = prism2_pccard_card_present, 42062306a36Sopenharmony_ci .cor_sreset = prism2_pccard_cor_sreset, 42162306a36Sopenharmony_ci .genesis_reset = prism2_pccard_genesis_reset, 42262306a36Sopenharmony_ci .hw_type = HOSTAP_HW_PCCARD, 42362306a36Sopenharmony_ci}; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci/* allocate local data and register with CardServices 42762306a36Sopenharmony_ci * initialize dev_link structure, but do not configure the card yet */ 42862306a36Sopenharmony_cistatic int hostap_cs_probe(struct pcmcia_device *p_dev) 42962306a36Sopenharmony_ci{ 43062306a36Sopenharmony_ci int ret; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info); 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci ret = prism2_config(p_dev); 43562306a36Sopenharmony_ci if (ret) { 43662306a36Sopenharmony_ci PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n"); 43762306a36Sopenharmony_ci } 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci return ret; 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_cistatic void prism2_detach(struct pcmcia_device *link) 44462306a36Sopenharmony_ci{ 44562306a36Sopenharmony_ci PDEBUG(DEBUG_FLOW, "prism2_detach\n"); 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci prism2_release((u_long)link); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci /* release net devices */ 45062306a36Sopenharmony_ci if (link->priv) { 45162306a36Sopenharmony_ci struct hostap_cs_priv *hw_priv; 45262306a36Sopenharmony_ci struct net_device *dev; 45362306a36Sopenharmony_ci struct hostap_interface *iface; 45462306a36Sopenharmony_ci dev = link->priv; 45562306a36Sopenharmony_ci iface = netdev_priv(dev); 45662306a36Sopenharmony_ci hw_priv = iface->local->hw_priv; 45762306a36Sopenharmony_ci prism2_free_local_data(dev); 45862306a36Sopenharmony_ci kfree(hw_priv); 45962306a36Sopenharmony_ci } 46062306a36Sopenharmony_ci} 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_cistatic int prism2_config_check(struct pcmcia_device *p_dev, void *priv_data) 46462306a36Sopenharmony_ci{ 46562306a36Sopenharmony_ci if (p_dev->config_index == 0) 46662306a36Sopenharmony_ci return -EINVAL; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci return pcmcia_request_io(p_dev); 46962306a36Sopenharmony_ci} 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_cistatic int prism2_config(struct pcmcia_device *link) 47262306a36Sopenharmony_ci{ 47362306a36Sopenharmony_ci struct net_device *dev; 47462306a36Sopenharmony_ci struct hostap_interface *iface; 47562306a36Sopenharmony_ci local_info_t *local; 47662306a36Sopenharmony_ci int ret; 47762306a36Sopenharmony_ci struct hostap_cs_priv *hw_priv; 47862306a36Sopenharmony_ci unsigned long flags; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci PDEBUG(DEBUG_FLOW, "prism2_config()\n"); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL); 48362306a36Sopenharmony_ci if (hw_priv == NULL) { 48462306a36Sopenharmony_ci ret = -ENOMEM; 48562306a36Sopenharmony_ci goto failed; 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci /* Look for an appropriate configuration table entry in the CIS */ 48962306a36Sopenharmony_ci link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | 49062306a36Sopenharmony_ci CONF_AUTO_CHECK_VCC | CONF_AUTO_SET_IO | CONF_ENABLE_IRQ; 49162306a36Sopenharmony_ci if (ignore_cis_vcc) 49262306a36Sopenharmony_ci link->config_flags &= ~CONF_AUTO_CHECK_VCC; 49362306a36Sopenharmony_ci ret = pcmcia_loop_config(link, prism2_config_check, NULL); 49462306a36Sopenharmony_ci if (ret) { 49562306a36Sopenharmony_ci if (!ignore_cis_vcc) 49662306a36Sopenharmony_ci printk(KERN_ERR "GetNextTuple(): No matching " 49762306a36Sopenharmony_ci "CIS configuration. Maybe you need the " 49862306a36Sopenharmony_ci "ignore_cis_vcc=1 parameter.\n"); 49962306a36Sopenharmony_ci goto failed; 50062306a36Sopenharmony_ci } 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci /* Need to allocate net_device before requesting IRQ handler */ 50362306a36Sopenharmony_ci dev = prism2_init_local_data(&prism2_pccard_funcs, 0, 50462306a36Sopenharmony_ci &link->dev); 50562306a36Sopenharmony_ci if (!dev) { 50662306a36Sopenharmony_ci ret = -ENOMEM; 50762306a36Sopenharmony_ci goto failed; 50862306a36Sopenharmony_ci } 50962306a36Sopenharmony_ci link->priv = dev; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci iface = netdev_priv(dev); 51262306a36Sopenharmony_ci local = iface->local; 51362306a36Sopenharmony_ci local->hw_priv = hw_priv; 51462306a36Sopenharmony_ci hw_priv->link = link; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci /* 51762306a36Sopenharmony_ci * We enable IRQ here, but IRQ handler will not proceed 51862306a36Sopenharmony_ci * until dev->base_addr is set below. This protect us from 51962306a36Sopenharmony_ci * receive interrupts when driver is not initialized. 52062306a36Sopenharmony_ci */ 52162306a36Sopenharmony_ci ret = pcmcia_request_irq(link, prism2_interrupt); 52262306a36Sopenharmony_ci if (ret) 52362306a36Sopenharmony_ci goto failed; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci ret = pcmcia_enable_device(link); 52662306a36Sopenharmony_ci if (ret) 52762306a36Sopenharmony_ci goto failed; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci spin_lock_irqsave(&local->irq_init_lock, flags); 53062306a36Sopenharmony_ci dev->irq = link->irq; 53162306a36Sopenharmony_ci dev->base_addr = link->resource[0]->start; 53262306a36Sopenharmony_ci spin_unlock_irqrestore(&local->irq_init_lock, flags); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci local->shutdown = 0; 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci sandisk_enable_wireless(dev); 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci ret = prism2_hw_config(dev, 1); 53962306a36Sopenharmony_ci if (!ret) 54062306a36Sopenharmony_ci ret = hostap_hw_ready(dev); 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci return ret; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci failed: 54562306a36Sopenharmony_ci kfree(hw_priv); 54662306a36Sopenharmony_ci prism2_release((u_long)link); 54762306a36Sopenharmony_ci return ret; 54862306a36Sopenharmony_ci} 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_cistatic void prism2_release(u_long arg) 55262306a36Sopenharmony_ci{ 55362306a36Sopenharmony_ci struct pcmcia_device *link = (struct pcmcia_device *)arg; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci PDEBUG(DEBUG_FLOW, "prism2_release\n"); 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci if (link->priv) { 55862306a36Sopenharmony_ci struct net_device *dev = link->priv; 55962306a36Sopenharmony_ci struct hostap_interface *iface; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci iface = netdev_priv(dev); 56262306a36Sopenharmony_ci prism2_hw_shutdown(dev, 0); 56362306a36Sopenharmony_ci iface->local->shutdown = 1; 56462306a36Sopenharmony_ci } 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci pcmcia_disable_device(link); 56762306a36Sopenharmony_ci PDEBUG(DEBUG_FLOW, "release - done\n"); 56862306a36Sopenharmony_ci} 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_cistatic int hostap_cs_suspend(struct pcmcia_device *link) 57162306a36Sopenharmony_ci{ 57262306a36Sopenharmony_ci struct net_device *dev = (struct net_device *) link->priv; 57362306a36Sopenharmony_ci int dev_open = 0; 57462306a36Sopenharmony_ci struct hostap_interface *iface = NULL; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci if (!dev) 57762306a36Sopenharmony_ci return -ENODEV; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci iface = netdev_priv(dev); 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info); 58262306a36Sopenharmony_ci if (iface && iface->local) 58362306a36Sopenharmony_ci dev_open = iface->local->num_dev_open > 0; 58462306a36Sopenharmony_ci if (dev_open) { 58562306a36Sopenharmony_ci netif_stop_queue(dev); 58662306a36Sopenharmony_ci netif_device_detach(dev); 58762306a36Sopenharmony_ci } 58862306a36Sopenharmony_ci prism2_suspend(dev); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci return 0; 59162306a36Sopenharmony_ci} 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_cistatic int hostap_cs_resume(struct pcmcia_device *link) 59462306a36Sopenharmony_ci{ 59562306a36Sopenharmony_ci struct net_device *dev = (struct net_device *) link->priv; 59662306a36Sopenharmony_ci int dev_open = 0; 59762306a36Sopenharmony_ci struct hostap_interface *iface = NULL; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci if (!dev) 60062306a36Sopenharmony_ci return -ENODEV; 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci iface = netdev_priv(dev); 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info); 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci if (iface && iface->local) 60762306a36Sopenharmony_ci dev_open = iface->local->num_dev_open > 0; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci prism2_hw_shutdown(dev, 1); 61062306a36Sopenharmony_ci prism2_hw_config(dev, dev_open ? 0 : 1); 61162306a36Sopenharmony_ci if (dev_open) { 61262306a36Sopenharmony_ci netif_device_attach(dev); 61362306a36Sopenharmony_ci netif_start_queue(dev); 61462306a36Sopenharmony_ci } 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci return 0; 61762306a36Sopenharmony_ci} 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_cistatic const struct pcmcia_device_id hostap_cs_ids[] = { 62062306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), 62162306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), 62262306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), 62362306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), 62462306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), 62562306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x3301), 62662306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), 62762306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030b), 62862306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), 62962306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), 63062306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), 63162306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), 63262306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0x02d2, 0x0001), 63362306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x0001), 63462306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), 63562306a36Sopenharmony_ci/* PCMCIA_DEVICE_MANF_CARD(0xc00f, 0x0000), conflict with pcnet_cs */ 63662306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), 63762306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), 63862306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), 63962306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0010), 64062306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0x0126, 0x0002), 64162306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0xd601, 0x0005, "ADLINK 345 CF", 64262306a36Sopenharmony_ci 0x2d858104), 64362306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "INTERSIL", 64462306a36Sopenharmony_ci 0x74c5e40d), 64562306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "Intersil", 64662306a36Sopenharmony_ci 0x4b801a17), 64762306a36Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD_PROD_ID3(0x0156, 0x0002, "Version 01.02", 64862306a36Sopenharmony_ci 0x4b74baa0), 64962306a36Sopenharmony_ci PCMCIA_MFC_DEVICE_PROD_ID12(0, "SanDisk", "ConnectPlus", 65062306a36Sopenharmony_ci 0x7a954bd9, 0x74be00c6), 65162306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID123( 65262306a36Sopenharmony_ci "Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02", 65362306a36Sopenharmony_ci 0xe6ec52ce, 0x08649af2, 0x4b74baa0), 65462306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID123( 65562306a36Sopenharmony_ci "Canon", "Wireless LAN CF Card K30225", "Version 01.00", 65662306a36Sopenharmony_ci 0x96ef6fe2, 0x263fcbab, 0xa57adb8c), 65762306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID123( 65862306a36Sopenharmony_ci "D", "Link DWL-650 11Mbps WLAN Card", "Version 01.02", 65962306a36Sopenharmony_ci 0x71b18589, 0xb6f1b0ab, 0x4b74baa0), 66062306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID123( 66162306a36Sopenharmony_ci "Instant Wireless ", " Network PC CARD", "Version 01.02", 66262306a36Sopenharmony_ci 0x11d901af, 0x6e9bd926, 0x4b74baa0), 66362306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID123( 66462306a36Sopenharmony_ci "SMC", "SMC2632W", "Version 01.02", 66562306a36Sopenharmony_ci 0xc4f8b18b, 0x474a1f2a, 0x4b74baa0), 66662306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 66762306a36Sopenharmony_ci 0x2decece3, 0x82067c18), 66862306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 66962306a36Sopenharmony_ci 0x54f7c49c, 0x15a75e5b), 67062306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 67162306a36Sopenharmony_ci 0x74c5e40d, 0xdb472a18), 67262306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 67362306a36Sopenharmony_ci 0x0733cc81, 0x0c52f395), 67462306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID12( 67562306a36Sopenharmony_ci "ZoomAir 11Mbps High", "Rate wireless Networking", 67662306a36Sopenharmony_ci 0x273fe3db, 0x32a1eaee), 67762306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 67862306a36Sopenharmony_ci 0xa37434e9, 0x9762e8f1), 67962306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID123( 68062306a36Sopenharmony_ci "Pretec", "CompactWLAN Card 802.11b", "2.5", 68162306a36Sopenharmony_ci 0x1cadd3e5, 0xe697636c, 0x7a5bfcf1), 68262306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID123( 68362306a36Sopenharmony_ci "U.S. Robotics", "IEEE 802.11b PC-CARD", "Version 01.02", 68462306a36Sopenharmony_ci 0xc7b8df9d, 0x1700d087, 0x4b74baa0), 68562306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID123( 68662306a36Sopenharmony_ci "Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 68762306a36Sopenharmony_ci "Ver. 1.00", 68862306a36Sopenharmony_ci 0x5cd01705, 0x4271660f, 0x9d08ee12), 68962306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID123( 69062306a36Sopenharmony_ci "Wireless LAN" , "11Mbps PC Card", "Version 01.02", 69162306a36Sopenharmony_ci 0x4b8870ff, 0x70e946d1, 0x4b74baa0), 69262306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092), 69362306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2), 69462306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b), 69562306a36Sopenharmony_ci PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39), 69662306a36Sopenharmony_ci PCMCIA_DEVICE_NULL 69762306a36Sopenharmony_ci}; 69862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids); 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_cistatic struct pcmcia_driver hostap_driver = { 70262306a36Sopenharmony_ci .name = "hostap_cs", 70362306a36Sopenharmony_ci .probe = hostap_cs_probe, 70462306a36Sopenharmony_ci .remove = prism2_detach, 70562306a36Sopenharmony_ci .owner = THIS_MODULE, 70662306a36Sopenharmony_ci .id_table = hostap_cs_ids, 70762306a36Sopenharmony_ci .suspend = hostap_cs_suspend, 70862306a36Sopenharmony_ci .resume = hostap_cs_resume, 70962306a36Sopenharmony_ci}; 71062306a36Sopenharmony_cimodule_pcmcia_driver(hostap_driver); 711