1#define PRISM2_PCI 2 3/* Host AP driver's support for Intersil Prism2.5 PCI cards is based on 4 * driver patches from Reyk Floeter <reyk@vantronix.net> and 5 * Andy Warner <andyw@pobox.com> */ 6 7#include <linux/module.h> 8#include <linux/init.h> 9#include <linux/if.h> 10#include <linux/skbuff.h> 11#include <linux/netdevice.h> 12#include <linux/workqueue.h> 13#include <linux/wireless.h> 14#include <net/iw_handler.h> 15 16#include <linux/ioport.h> 17#include <linux/pci.h> 18#include <asm/io.h> 19 20#include "hostap_wlan.h" 21 22 23static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)"; 24static char *dev_info = "hostap_pci"; 25 26 27MODULE_AUTHOR("Jouni Malinen"); 28MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN " 29 "PCI cards."); 30MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards"); 31MODULE_LICENSE("GPL"); 32MODULE_VERSION(PRISM2_VERSION); 33 34 35/* struct local_info::hw_priv */ 36struct hostap_pci_priv { 37 void __iomem *mem_start; 38}; 39 40 41/* FIX: do we need mb/wmb/rmb with memory operations? */ 42 43 44static struct pci_device_id prism2_pci_id_table[] __devinitdata = { 45 /* Intersil Prism3 ISL3872 11Mb/s WLAN Controller */ 46 { 0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID }, 47 /* Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller */ 48 { 0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID }, 49 /* Samsung MagicLAN SWL-2210P */ 50 { 0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID }, 51 { 0 } 52}; 53 54 55#ifdef PRISM2_IO_DEBUG 56 57static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v) 58{ 59 struct hostap_interface *iface; 60 struct hostap_pci_priv *hw_priv; 61 local_info_t *local; 62 unsigned long flags; 63 64 iface = netdev_priv(dev); 65 local = iface->local; 66 hw_priv = local->hw_priv; 67 68 spin_lock_irqsave(&local->lock, flags); 69 prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v); 70 writeb(v, hw_priv->mem_start + a); 71 spin_unlock_irqrestore(&local->lock, flags); 72} 73 74static inline u8 hfa384x_inb_debug(struct net_device *dev, int a) 75{ 76 struct hostap_interface *iface; 77 struct hostap_pci_priv *hw_priv; 78 local_info_t *local; 79 unsigned long flags; 80 u8 v; 81 82 iface = netdev_priv(dev); 83 local = iface->local; 84 hw_priv = local->hw_priv; 85 86 spin_lock_irqsave(&local->lock, flags); 87 v = readb(hw_priv->mem_start + a); 88 prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v); 89 spin_unlock_irqrestore(&local->lock, flags); 90 return v; 91} 92 93static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v) 94{ 95 struct hostap_interface *iface; 96 struct hostap_pci_priv *hw_priv; 97 local_info_t *local; 98 unsigned long flags; 99 100 iface = netdev_priv(dev); 101 local = iface->local; 102 hw_priv = local->hw_priv; 103 104 spin_lock_irqsave(&local->lock, flags); 105 prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v); 106 writew(v, hw_priv->mem_start + a); 107 spin_unlock_irqrestore(&local->lock, flags); 108} 109 110static inline u16 hfa384x_inw_debug(struct net_device *dev, int a) 111{ 112 struct hostap_interface *iface; 113 struct hostap_pci_priv *hw_priv; 114 local_info_t *local; 115 unsigned long flags; 116 u16 v; 117 118 iface = netdev_priv(dev); 119 local = iface->local; 120 hw_priv = local->hw_priv; 121 122 spin_lock_irqsave(&local->lock, flags); 123 v = readw(hw_priv->mem_start + a); 124 prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v); 125 spin_unlock_irqrestore(&local->lock, flags); 126 return v; 127} 128 129#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v)) 130#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a)) 131#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v)) 132#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a)) 133#define HFA384X_OUTW_DATA(v,a) hfa384x_outw_debug(dev, (a), cpu_to_le16((v))) 134#define HFA384X_INW_DATA(a) (u16) le16_to_cpu(hfa384x_inw_debug(dev, (a))) 135 136#else /* PRISM2_IO_DEBUG */ 137 138static inline void hfa384x_outb(struct net_device *dev, int a, u8 v) 139{ 140 struct hostap_interface *iface; 141 struct hostap_pci_priv *hw_priv; 142 iface = netdev_priv(dev); 143 hw_priv = iface->local->hw_priv; 144 writeb(v, hw_priv->mem_start + a); 145} 146 147static inline u8 hfa384x_inb(struct net_device *dev, int a) 148{ 149 struct hostap_interface *iface; 150 struct hostap_pci_priv *hw_priv; 151 iface = netdev_priv(dev); 152 hw_priv = iface->local->hw_priv; 153 return readb(hw_priv->mem_start + a); 154} 155 156static inline void hfa384x_outw(struct net_device *dev, int a, u16 v) 157{ 158 struct hostap_interface *iface; 159 struct hostap_pci_priv *hw_priv; 160 iface = netdev_priv(dev); 161 hw_priv = iface->local->hw_priv; 162 writew(v, hw_priv->mem_start + a); 163} 164 165static inline u16 hfa384x_inw(struct net_device *dev, int a) 166{ 167 struct hostap_interface *iface; 168 struct hostap_pci_priv *hw_priv; 169 iface = netdev_priv(dev); 170 hw_priv = iface->local->hw_priv; 171 return readw(hw_priv->mem_start + a); 172} 173 174#define HFA384X_OUTB(v,a) hfa384x_outb(dev, (a), (v)) 175#define HFA384X_INB(a) hfa384x_inb(dev, (a)) 176#define HFA384X_OUTW(v,a) hfa384x_outw(dev, (a), (v)) 177#define HFA384X_INW(a) hfa384x_inw(dev, (a)) 178#define HFA384X_OUTW_DATA(v,a) hfa384x_outw(dev, (a), cpu_to_le16((v))) 179#define HFA384X_INW_DATA(a) (u16) le16_to_cpu(hfa384x_inw(dev, (a))) 180 181#endif /* PRISM2_IO_DEBUG */ 182 183 184static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf, 185 int len) 186{ 187 u16 d_off; 188 u16 *pos; 189 190 d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF; 191 pos = (u16 *) buf; 192 193 for ( ; len > 1; len -= 2) 194 *pos++ = HFA384X_INW_DATA(d_off); 195 196 if (len & 1) 197 *((char *) pos) = HFA384X_INB(d_off); 198 199 return 0; 200} 201 202 203static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len) 204{ 205 u16 d_off; 206 u16 *pos; 207 208 d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF; 209 pos = (u16 *) buf; 210 211 for ( ; len > 1; len -= 2) 212 HFA384X_OUTW_DATA(*pos++, d_off); 213 214 if (len & 1) 215 HFA384X_OUTB(*((char *) pos), d_off); 216 217 return 0; 218} 219 220 221/* FIX: This might change at some point.. */ 222#include "hostap_hw.c" 223 224static void prism2_pci_cor_sreset(local_info_t *local) 225{ 226 struct net_device *dev = local->dev; 227 u16 reg; 228 229 reg = HFA384X_INB(HFA384X_PCICOR_OFF); 230 printk(KERN_DEBUG "%s: Original COR value: 0x%0x\n", dev->name, reg); 231 232 /* linux-wlan-ng uses extremely long hold and settle times for 233 * COR sreset. A comment in the driver code mentions that the long 234 * delays appear to be necessary. However, at least IBM 22P6901 seems 235 * to work fine with shorter delays. 236 * 237 * Longer delays can be configured by uncommenting following line: */ 238/* #define PRISM2_PCI_USE_LONG_DELAYS */ 239 240#ifdef PRISM2_PCI_USE_LONG_DELAYS 241 int i; 242 243 HFA384X_OUTW(reg | 0x0080, HFA384X_PCICOR_OFF); 244 mdelay(250); 245 246 HFA384X_OUTW(reg & ~0x0080, HFA384X_PCICOR_OFF); 247 mdelay(500); 248 249 /* Wait for f/w to complete initialization (CMD:BUSY == 0) */ 250 i = 2000000 / 10; 251 while ((HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) && --i) 252 udelay(10); 253 254#else /* PRISM2_PCI_USE_LONG_DELAYS */ 255 256 HFA384X_OUTW(reg | 0x0080, HFA384X_PCICOR_OFF); 257 mdelay(2); 258 HFA384X_OUTW(reg & ~0x0080, HFA384X_PCICOR_OFF); 259 mdelay(2); 260 261#endif /* PRISM2_PCI_USE_LONG_DELAYS */ 262 263 if (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) { 264 printk(KERN_DEBUG "%s: COR sreset timeout\n", dev->name); 265 } 266} 267 268 269static void prism2_pci_genesis_reset(local_info_t *local, int hcr) 270{ 271 struct net_device *dev = local->dev; 272 273 HFA384X_OUTW(0x00C5, HFA384X_PCICOR_OFF); 274 mdelay(10); 275 HFA384X_OUTW(hcr, HFA384X_PCIHCR_OFF); 276 mdelay(10); 277 HFA384X_OUTW(0x0045, HFA384X_PCICOR_OFF); 278 mdelay(10); 279} 280 281 282static struct prism2_helper_functions prism2_pci_funcs = 283{ 284 .card_present = NULL, 285 .cor_sreset = prism2_pci_cor_sreset, 286 .genesis_reset = prism2_pci_genesis_reset, 287 .hw_type = HOSTAP_HW_PCI, 288}; 289 290 291static int prism2_pci_probe(struct pci_dev *pdev, 292 const struct pci_device_id *id) 293{ 294 unsigned long phymem; 295 void __iomem *mem = NULL; 296 local_info_t *local = NULL; 297 struct net_device *dev = NULL; 298 static int cards_found /* = 0 */; 299 int irq_registered = 0; 300 struct hostap_interface *iface; 301 struct hostap_pci_priv *hw_priv; 302 303 hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL); 304 if (hw_priv == NULL) 305 return -ENOMEM; 306 307 if (pci_enable_device(pdev)) 308 goto err_out_free; 309 310 phymem = pci_resource_start(pdev, 0); 311 312 if (!request_mem_region(phymem, pci_resource_len(pdev, 0), "Prism2")) { 313 printk(KERN_ERR "prism2: Cannot reserve PCI memory region\n"); 314 goto err_out_disable; 315 } 316 317 mem = ioremap(phymem, pci_resource_len(pdev, 0)); 318 if (mem == NULL) { 319 printk(KERN_ERR "prism2: Cannot remap PCI memory region\n") ; 320 goto fail; 321 } 322 323 dev = prism2_init_local_data(&prism2_pci_funcs, cards_found, 324 &pdev->dev); 325 if (dev == NULL) 326 goto fail; 327 iface = netdev_priv(dev); 328 local = iface->local; 329 local->hw_priv = hw_priv; 330 cards_found++; 331 332 dev->irq = pdev->irq; 333 hw_priv->mem_start = mem; 334 335 prism2_pci_cor_sreset(local); 336 337 pci_set_drvdata(pdev, dev); 338 339 if (request_irq(dev->irq, prism2_interrupt, IRQF_SHARED, dev->name, 340 dev)) { 341 printk(KERN_WARNING "%s: request_irq failed\n", dev->name); 342 goto fail; 343 } else 344 irq_registered = 1; 345 346 if (!local->pri_only && prism2_hw_config(dev, 1)) { 347 printk(KERN_DEBUG "%s: hardware initialization failed\n", 348 dev_info); 349 goto fail; 350 } 351 352 printk(KERN_INFO "%s: Intersil Prism2.5 PCI: " 353 "mem=0x%lx, irq=%d\n", dev->name, phymem, dev->irq); 354 355 return hostap_hw_ready(dev); 356 357 fail: 358 if (irq_registered && dev) 359 free_irq(dev->irq, dev); 360 361 if (mem) 362 iounmap(mem); 363 364 release_mem_region(phymem, pci_resource_len(pdev, 0)); 365 366 err_out_disable: 367 pci_disable_device(pdev); 368 prism2_free_local_data(dev); 369 370 err_out_free: 371 kfree(hw_priv); 372 373 return -ENODEV; 374} 375 376 377static void prism2_pci_remove(struct pci_dev *pdev) 378{ 379 struct net_device *dev; 380 struct hostap_interface *iface; 381 void __iomem *mem_start; 382 struct hostap_pci_priv *hw_priv; 383 384 dev = pci_get_drvdata(pdev); 385 iface = netdev_priv(dev); 386 hw_priv = iface->local->hw_priv; 387 388 /* Reset the hardware, and ensure interrupts are disabled. */ 389 prism2_pci_cor_sreset(iface->local); 390 hfa384x_disable_interrupts(dev); 391 392 if (dev->irq) 393 free_irq(dev->irq, dev); 394 395 mem_start = hw_priv->mem_start; 396 prism2_free_local_data(dev); 397 kfree(hw_priv); 398 399 iounmap(mem_start); 400 401 release_mem_region(pci_resource_start(pdev, 0), 402 pci_resource_len(pdev, 0)); 403 pci_disable_device(pdev); 404} 405 406 407#ifdef CONFIG_PM 408static int prism2_pci_suspend(struct pci_dev *pdev, pm_message_t state) 409{ 410 struct net_device *dev = pci_get_drvdata(pdev); 411 412 if (netif_running(dev)) { 413 netif_stop_queue(dev); 414 netif_device_detach(dev); 415 } 416 prism2_suspend(dev); 417 pci_save_state(pdev); 418 pci_disable_device(pdev); 419 pci_set_power_state(pdev, PCI_D3hot); 420 421 return 0; 422} 423 424static int prism2_pci_resume(struct pci_dev *pdev) 425{ 426 struct net_device *dev = pci_get_drvdata(pdev); 427 int err; 428 429 err = pci_enable_device(pdev); 430 if (err) { 431 printk(KERN_ERR "%s: pci_enable_device failed on resume\n", 432 dev->name); 433 return err; 434 } 435 pci_restore_state(pdev); 436 prism2_hw_config(dev, 0); 437 if (netif_running(dev)) { 438 netif_device_attach(dev); 439 netif_start_queue(dev); 440 } 441 442 return 0; 443} 444#endif /* CONFIG_PM */ 445 446 447MODULE_DEVICE_TABLE(pci, prism2_pci_id_table); 448 449static struct pci_driver prism2_pci_drv_id = { 450 .name = "hostap_pci", 451 .id_table = prism2_pci_id_table, 452 .probe = prism2_pci_probe, 453 .remove = prism2_pci_remove, 454#ifdef CONFIG_PM 455 .suspend = prism2_pci_suspend, 456 .resume = prism2_pci_resume, 457#endif /* CONFIG_PM */ 458 /* Linux 2.4.6 added save_state and enable_wake that are not used here 459 */ 460}; 461 462 463static int __init init_prism2_pci(void) 464{ 465 printk(KERN_INFO "%s: %s\n", dev_info, version); 466 467 return pci_register_driver(&prism2_pci_drv_id); 468} 469 470 471static void __exit exit_prism2_pci(void) 472{ 473 pci_unregister_driver(&prism2_pci_drv_id); 474 printk(KERN_INFO "%s: Driver unloaded\n", dev_info); 475} 476 477 478module_init(init_prism2_pci); 479module_exit(exit_prism2_pci); 480