2 * Airgo MIMO wireless driver
4 * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
6 * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
7 * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
14 #include <linux/init.h>
15 #include <linux/etherdevice.h>
16 #include <linux/pci.h>
17 #include <linux/delay.h>
24 MODULE_AUTHOR("Li YanBo <dreamfly281@gmail.com>");
25 MODULE_DESCRIPTION("Airgo MIMO PCI wireless driver");
26 MODULE_LICENSE("GPL");
28 static struct pci_device_id agnx_pci_id_tbl
[] __devinitdata
= {
29 { PCI_DEVICE(0x17cb, 0x0001) }, /* Beklin F5d8010, Netgear WGM511 etc */
30 { PCI_DEVICE(0x17cb, 0x0002) }, /* Netgear Wpnt511 */
34 MODULE_DEVICE_TABLE(pci
, agnx_pci_id_tbl
);
37 static inline void agnx_interrupt_ack(struct agnx_priv
*priv
, u32
*reason
)
39 void __iomem
*ctl
= priv
->ctl
;
42 if ( *reason
& AGNX_STAT_RX
) {
43 /* Mark complete RX */
44 reg
= ioread32(ctl
+ AGNX_CIR_RXCTL
);
46 iowrite32(reg
, ctl
+ AGNX_CIR_RXCTL
);
47 /* disable Rx interrupt */
49 if ( *reason
& AGNX_STAT_TX
) {
50 reg
= ioread32(ctl
+ AGNX_CIR_TXDCTL
);
52 iowrite32(reg
, ctl
+ AGNX_CIR_TXDCTL
);
53 *reason
|= AGNX_STAT_TXD
;
55 reg
= ioread32(ctl
+ AGNX_CIR_TXMCTL
);
57 iowrite32(reg
, ctl
+ AGNX_CIR_TXMCTL
);
58 *reason
|= AGNX_STAT_TXM
;
61 if ( *reason
& AGNX_STAT_X
) {
62 /* reg = ioread32(ctl + AGNX_INT_STAT); */
63 /* iowrite32(reg, ctl + AGNX_INT_STAT); */
64 /* /\* FIXME reinit interrupt mask *\/ */
65 /* reg = 0xc390bf9 & ~IRQ_TX_BEACON; */
66 /* reg &= ~IRQ_TX_DISABLE; */
67 /* iowrite32(reg, ctl + AGNX_INT_MASK); */
68 /* iowrite32(0x800, ctl + AGNX_CIR_BLKCTL); */
70 } /* agnx_interrupt_ack */
72 static irqreturn_t
agnx_interrupt_handler(int irq
, void *dev_id
)
74 struct ieee80211_hw
*dev
= dev_id
;
75 struct agnx_priv
*priv
= dev
->priv
;
76 void __iomem
*ctl
= priv
->ctl
;
77 irqreturn_t ret
= IRQ_NONE
;
80 spin_lock(&priv
->lock
);
82 // printk(KERN_ERR PFX "Get a interrupt %s\n", __func__);
84 if (priv
->init_status
!= AGNX_START
)
87 /* FiXME Here has no lock, Is this will lead to race? */
88 irq_reason
= ioread32(ctl
+ AGNX_CIR_BLKCTL
);
89 if (!(irq_reason
& 0x7))
93 priv
->irq_status
= ioread32(ctl
+ AGNX_INT_STAT
);
95 // printk(PFX "Interrupt reason is 0x%x\n", irq_reason);
96 /* Make sure the txm and txd flags don't conflict with other unknown
97 interrupt flag, maybe is not necessary */
100 disable_rx_interrupt(priv
);
101 /* TODO Make sure the card finished initialized */
102 agnx_interrupt_ack(priv
, &irq_reason
);
104 if ( irq_reason
& AGNX_STAT_RX
)
106 if ( irq_reason
& AGNX_STAT_TXD
)
107 handle_txd_irq(priv
);
108 if ( irq_reason
& AGNX_STAT_TXM
)
109 handle_txm_irq(priv
);
110 if ( irq_reason
& AGNX_STAT_X
)
111 handle_other_irq(priv
);
113 enable_rx_interrupt(priv
);
115 spin_unlock(&priv
->lock
);
117 } /* agnx_interrupt_handler */
121 static int agnx_tx(struct ieee80211_hw
*dev
, struct sk_buff
*skb
)
124 return _agnx_tx(dev
->priv
, skb
);
128 static int agnx_get_mac_address(struct agnx_priv
*priv
)
130 void __iomem
*ctl
= priv
->ctl
;
134 /* Attention! directly read the MAC or other date from EEPROM will
135 lead to cardbus(WGM511) lock up when write to PM PLL register */
136 reg
= agnx_read32(ctl
, 0x3544);
138 reg
= agnx_read32(ctl
, 0x354c);
140 /* Get the mac address */
141 reg
= agnx_read32(ctl
, 0x3544);
145 reg
= cpu_to_le32(reg
);
146 priv
->mac_addr
[0] = ((u8
*)®
)[2];
147 priv
->mac_addr
[1] = ((u8
*)®
)[3];
148 reg
= agnx_read32(ctl
, 0x3548);
150 *((u32
*)(priv
->mac_addr
+ 2)) = cpu_to_le32(reg
);
152 if (!is_valid_ether_addr(priv
->mac_addr
)) {
153 DECLARE_MAC_BUF(mbuf
);
154 printk(KERN_WARNING PFX
"read mac %s\n", print_mac(mbuf
, priv
->mac_addr
));
155 printk(KERN_WARNING PFX
"Invalid hwaddr! Using random hwaddr\n");
156 random_ether_addr(priv
->mac_addr
);
160 } /* agnx_get_mac_address */
162 static int agnx_alloc_rings(struct agnx_priv
*priv
)
167 /* Allocate RX/TXM/TXD rings info */
168 priv
->rx
.size
= AGNX_RX_RING_SIZE
;
169 priv
->txm
.size
= AGNX_TXM_RING_SIZE
;
170 priv
->txd
.size
= AGNX_TXD_RING_SIZE
;
172 len
= priv
->rx
.size
+ priv
->txm
.size
+ priv
->txd
.size
;
174 // priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_KERNEL);
175 priv
->rx
.info
= kzalloc(sizeof(struct agnx_info
) * len
, GFP_ATOMIC
);
178 priv
->txm
.info
= priv
->rx
.info
+ priv
->rx
.size
;
179 priv
->txd
.info
= priv
->txm
.info
+ priv
->txm
.size
;
181 /* Allocate RX/TXM/TXD descriptors */
182 priv
->rx
.desc
= pci_alloc_consistent(priv
->pdev
, sizeof(struct agnx_desc
) * len
,
184 if (!priv
->rx
.desc
) {
185 kfree(priv
->rx
.info
);
189 priv
->txm
.desc
= priv
->rx
.desc
+ priv
->rx
.size
;
190 priv
->txm
.dma
= priv
->rx
.dma
+ sizeof(struct agnx_desc
) * priv
->rx
.size
;
191 priv
->txd
.desc
= priv
->txm
.desc
+ priv
->txm
.size
;
192 priv
->txd
.dma
= priv
->txm
.dma
+ sizeof(struct agnx_desc
) * priv
->txm
.size
;
195 } /* agnx_alloc_rings */
197 static void rings_free(struct agnx_priv
*priv
)
199 unsigned int len
= priv
->rx
.size
+ priv
->txm
.size
+ priv
->txd
.size
;
203 spin_lock_irqsave(&priv
->lock
, flags
);
204 kfree(priv
->rx
.info
);
205 pci_free_consistent(priv
->pdev
, sizeof(struct agnx_desc
) * len
,
206 priv
->rx
.desc
, priv
->rx
.dma
);
207 spin_unlock_irqrestore(&priv
->lock
, flags
);
211 static void agnx_periodic_work_handler(struct work_struct
*work
)
213 struct agnx_priv
*priv
= container_of(work
, struct agnx_priv
,
215 // unsigned long flags;
218 /* fixme: using mutex?? */
219 // spin_lock_irqsave(&priv->lock, flags);
221 /* TODO Recalibrate*/
222 // calibrate_oscillator(priv);
223 // antenna_calibrate(priv);
224 // agnx_send_packet(priv, 997);
226 /* if (debug == 3) */
227 /* delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); */
229 delay
= msecs_to_jiffies(AGNX_PERIODIC_DELAY
);
230 // delay = round_jiffies(HZ * 15);
232 queue_delayed_work(priv
->hw
->workqueue
, &priv
->periodic_work
, delay
);
234 // spin_unlock_irqrestore(&priv->lock, flags);
238 static int agnx_start(struct ieee80211_hw
*dev
)
240 struct agnx_priv
*priv
= dev
->priv
;
241 /* unsigned long delay; */
245 err
= agnx_alloc_rings(priv
);
247 printk(KERN_ERR PFX
"Can't alloc RX/TXM/TXD rings\n");
250 err
= request_irq(priv
->pdev
->irq
, &agnx_interrupt_handler
,
251 IRQF_SHARED
, "agnx_pci", dev
);
253 printk(KERN_ERR PFX
"Failed to register IRQ handler\n");
266 priv
->init_status
= AGNX_START
;
267 /* INIT_DELAYED_WORK(&priv->periodic_work, agnx_periodic_work_handler); */
268 /* delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); */
269 /* queue_delayed_work(priv->hw->workqueue, &priv->periodic_work, delay); */
274 static void agnx_stop(struct ieee80211_hw
*dev
)
276 struct agnx_priv
*priv
= dev
->priv
;
279 priv
->init_status
= AGNX_STOP
;
280 /* make sure hardware will not generate irq */
282 free_irq(priv
->pdev
->irq
, dev
);
283 flush_workqueue(priv
->hw
->workqueue
);
284 // cancel_delayed_work_sync(&priv->periodic_work);
289 static int agnx_config(struct ieee80211_hw
*dev
,
290 struct ieee80211_conf
*conf
)
292 struct agnx_priv
*priv
= dev
->priv
;
293 int channel
= ieee80211_frequency_to_channel(conf
->channel
->center_freq
);
296 spin_lock(&priv
->lock
);
297 /* FIXME need priv lock? */
298 if (channel
!= priv
->channel
) {
299 priv
->channel
= channel
;
300 agnx_set_channel(priv
, priv
->channel
);
303 spin_unlock(&priv
->lock
);
307 static int agnx_config_interface(struct ieee80211_hw
*dev
,
308 struct ieee80211_vif
*vif
,
309 struct ieee80211_if_conf
*conf
)
311 struct agnx_priv
*priv
= dev
->priv
;
312 void __iomem
*ctl
= priv
->ctl
;
315 spin_lock(&priv
->lock
);
317 if (memcmp(conf
->bssid
, priv
->bssid
, ETH_ALEN
)) {
319 agnx_set_bssid(priv
, conf
->bssid
);
320 memcpy(priv
->bssid
, conf
->bssid
, ETH_ALEN
);
321 hash_write(priv
, conf
->bssid
, BSSID_STAID
);
322 sta_init(priv
, BSSID_STAID
);
324 sta_power_init(priv
, BSSID_STAID
);
325 agnx_write32(ctl
, AGNX_BM_MTSM
, 0xff & ~0x1);
327 spin_unlock(&priv
->lock
);
329 } /* agnx_config_interface */
332 static void agnx_configure_filter(struct ieee80211_hw
*dev
,
333 unsigned int changed_flags
,
334 unsigned int *total_flags
,
335 int mc_count
, struct dev_mc_list
*mclist
)
337 unsigned int new_flags
= 0;
339 *total_flags
= new_flags
;
343 static int agnx_add_interface(struct ieee80211_hw
*dev
,
344 struct ieee80211_if_init_conf
*conf
)
346 struct agnx_priv
*priv
= dev
->priv
;
349 spin_lock(&priv
->lock
);
351 if (priv
->mode
!= NL80211_IFTYPE_MONITOR
)
354 switch (conf
->type
) {
355 case NL80211_IFTYPE_STATION
:
356 priv
->mode
= conf
->type
;
362 spin_unlock(&priv
->lock
);
367 static void agnx_remove_interface(struct ieee80211_hw
*dev
,
368 struct ieee80211_if_init_conf
*conf
)
370 struct agnx_priv
*priv
= dev
->priv
;
374 priv
->mode
= NL80211_IFTYPE_MONITOR
;
377 static int agnx_get_stats(struct ieee80211_hw
*dev
,
378 struct ieee80211_low_level_stats
*stats
)
380 struct agnx_priv
*priv
= dev
->priv
;
382 spin_lock(&priv
->lock
);
384 memcpy(stats
, &priv
->stats
, sizeof(*stats
));
385 spin_unlock(&priv
->lock
);
390 static u64
agnx_get_tsft(struct ieee80211_hw
*dev
)
392 void __iomem
*ctl
= ((struct agnx_priv
*)dev
->priv
)->ctl
;
398 tsftl
= ioread32(ctl
+ AGNX_TXM_TIMESTAMPLO
);
399 tsft
= ioread32(ctl
+ AGNX_TXM_TIMESTAMPHI
);
406 static int agnx_get_tx_stats(struct ieee80211_hw
*dev
,
407 struct ieee80211_tx_queue_stats
*stats
)
409 struct agnx_priv
*priv
= dev
->priv
;
412 /* FIXME now we just using txd queue, but should using txm queue too */
413 stats
[0].len
= (priv
->txd
.idx
- priv
->txd
.idx_sent
) / 2;
414 stats
[0].limit
= priv
->txd
.size
- 2;
415 stats
[0].count
= priv
->txd
.idx
/ 2;
420 static struct ieee80211_ops agnx_ops
= {
424 .add_interface
= agnx_add_interface
,
425 .remove_interface
= agnx_remove_interface
,
426 .config
= agnx_config
,
427 .config_interface
= agnx_config_interface
,
428 .configure_filter
= agnx_configure_filter
,
429 .get_stats
= agnx_get_stats
,
430 .get_tx_stats
= agnx_get_tx_stats
,
431 .get_tsf
= agnx_get_tsft
434 static void __devexit
agnx_pci_remove(struct pci_dev
*pdev
)
436 struct ieee80211_hw
*dev
= pci_get_drvdata(pdev
);
437 struct agnx_priv
*priv
= dev
->priv
;
442 ieee80211_unregister_hw(dev
);
443 pci_iounmap(pdev
, priv
->ctl
);
444 pci_iounmap(pdev
, priv
->data
);
445 pci_release_regions(pdev
);
446 pci_disable_device(pdev
);
448 ieee80211_free_hw(dev
);
451 static int __devinit
agnx_pci_probe(struct pci_dev
*pdev
,
452 const struct pci_device_id
*id
)
454 struct ieee80211_hw
*dev
;
455 struct agnx_priv
*priv
;
456 u32 mem_addr0
, mem_len0
;
457 u32 mem_addr1
, mem_len1
;
459 DECLARE_MAC_BUF(mac
);
461 err
= pci_enable_device(pdev
);
463 printk(KERN_ERR PFX
"Can't enable new PCI device\n");
467 /* get pci resource */
468 mem_addr0
= pci_resource_start(pdev
, 0);
469 mem_len0
= pci_resource_len(pdev
, 0);
470 mem_addr1
= pci_resource_start(pdev
, 1);
471 mem_len1
= pci_resource_len(pdev
, 1);
472 printk(KERN_DEBUG PFX
"Memaddr0 is %x, length is %x\n", mem_addr0
, mem_len0
);
473 printk(KERN_DEBUG PFX
"Memaddr1 is %x, length is %x\n", mem_addr1
, mem_len1
);
475 err
= pci_request_regions(pdev
, "agnx-pci");
477 printk(KERN_ERR PFX
"Can't obtain PCI resource\n");
481 if (pci_set_dma_mask(pdev
, DMA_32BIT_MASK
) ||
482 pci_set_consistent_dma_mask(pdev
, DMA_32BIT_MASK
)) {
483 printk(KERN_ERR PFX
"No suitable DMA available\n");
487 pci_set_master(pdev
);
488 printk(KERN_DEBUG PFX
"pdev->irq is %d\n", pdev
->irq
);
490 dev
= ieee80211_alloc_hw(sizeof(*priv
), &agnx_ops
);
492 printk(KERN_ERR PFX
"ieee80211 alloc failed\n");
498 memset(priv
, 0, sizeof(*priv
));
499 priv
->mode
= NL80211_IFTYPE_MONITOR
;
502 spin_lock_init(&priv
->lock
);
503 priv
->init_status
= AGNX_UNINIT
;
505 /* Map mem #1 and #2 */
506 priv
->ctl
= pci_iomap(pdev
, 0, mem_len0
);
507 // printk(KERN_DEBUG PFX"MEM1 mapped address is 0x%p\n", priv->ctl);
509 printk(KERN_ERR PFX
"Can't map device memory\n");
512 priv
->data
= pci_iomap(pdev
, 1, mem_len1
);
513 printk(KERN_DEBUG PFX
"MEM2 mapped address is 0x%p\n", priv
->data
);
515 printk(KERN_ERR PFX
"Can't map device memory\n");
519 pci_read_config_byte(pdev
, PCI_REVISION_ID
, &priv
->revid
);
521 priv
->band
.channels
= (struct ieee80211_channel
*)agnx_channels
;
522 priv
->band
.n_channels
= ARRAY_SIZE(agnx_channels
);
523 priv
->band
.bitrates
= (struct ieee80211_rate
*)agnx_rates_80211g
;
524 priv
->band
.n_bitrates
= ARRAY_SIZE(agnx_rates_80211g
);
526 /* Init ieee802.11 dev */
527 SET_IEEE80211_DEV(dev
, &pdev
->dev
);
528 pci_set_drvdata(pdev
, dev
);
529 dev
->extra_tx_headroom
= sizeof(struct agnx_hdr
);
531 /* FIXME It only include FCS in promious mode but not manage mode */
532 /* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS; */
533 dev
->channel_change_time
= 5000;
534 dev
->max_signal
= 100;
538 agnx_get_mac_address(priv
);
540 SET_IEEE80211_PERM_ADDR(dev
, priv
->mac_addr
);
543 /* for (i = 1; i < NUM_DRIVE_MODES; i++) { */
544 /* err = ieee80211_register_hwmode(dev, &priv->modes[i]); */
546 /* printk(KERN_ERR PFX "Can't register hwmode\n"); */
547 /* goto err_iounmap; */
552 dev
->wiphy
->bands
[IEEE80211_BAND_2GHZ
] = &priv
->band
;
554 err
= ieee80211_register_hw(dev
);
556 printk(KERN_ERR PFX
"Can't register hardware\n");
563 printk(PFX
"%s: hwaddr %s, Rev 0x%02x\n", wiphy_name(dev
->wiphy
),
564 print_mac(mac
, dev
->wiphy
->perm_addr
), priv
->revid
);
568 pci_iounmap(pdev
, priv
->data
);
571 pci_iounmap(pdev
, priv
->ctl
);
574 pci_set_drvdata(pdev
, NULL
);
575 ieee80211_free_hw(dev
);
578 pci_release_regions(pdev
);
580 pci_disable_device(pdev
);
582 } /* agnx_pci_probe*/
586 static int agnx_pci_suspend(struct pci_dev
*pdev
, pm_message_t state
)
588 struct ieee80211_hw
*dev
= pci_get_drvdata(pdev
);
591 ieee80211_stop_queues(dev
);
594 pci_save_state(pdev
);
595 pci_set_power_state(pdev
, pci_choose_state(pdev
, state
));
599 static int agnx_pci_resume(struct pci_dev
*pdev
)
601 struct ieee80211_hw
*dev
= pci_get_drvdata(pdev
);
604 pci_set_power_state(pdev
, PCI_D0
);
605 pci_restore_state(pdev
);
608 ieee80211_wake_queues(dev
);
615 #define agnx_pci_suspend NULL
616 #define agnx_pci_resume NULL
618 #endif /* CONFIG_PM */
621 static struct pci_driver agnx_pci_driver
= {
623 .id_table
= agnx_pci_id_tbl
,
624 .probe
= agnx_pci_probe
,
625 .remove
= __devexit_p(agnx_pci_remove
),
626 .suspend
= agnx_pci_suspend
,
627 .resume
= agnx_pci_resume
,
630 static int __init
agnx_pci_init(void)
633 return pci_register_driver(&agnx_pci_driver
);
636 static void __exit
agnx_pci_exit(void)
639 pci_unregister_driver(&agnx_pci_driver
);
643 module_init(agnx_pci_init
);
644 module_exit(agnx_pci_exit
);