ath9k compat wireless代码结构2011.09
02
ATH9k compat wireless关键代码结构简析
代码结构与madwifi类似,madwifi的代码结构参照:http://www./papperdetails_tech.php?pid=41&tit=madwifi+%E7%AE%80%E8%A6%81%E5%88%86%E6%9E%90+
static struct pci_driver ath_pci_driver = {
.name = "ath9k",
.id_table = ath_pci_id_table,
.probe = ath_pci_probe,
.remove = ath_pci_remove,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
.driver.pm = ATH9K_PM_OPS,
#elif defined(CONFIG_PM)
.suspend = ath_pci_suspend_compat,
.resume = ath_pci_resume_compat,
#endif
};
struct ieee80211_ops ath9k_ops = {
.tx = ath9k_tx,
.start = ath9k_start,
.stop = ath9k_stop,
.add_interface = ath9k_add_interface,
.change_interface = ath9k_change_interface,
.remove_interface = ath9k_remove_interface,
.config = ath9k_config,
.configure_filter = ath9k_configure_filter,
.sta_add = ath9k_sta_add,
.sta_remove = ath9k_sta_remove,
.sta_notify = ath9k_sta_notify,
.conf_tx = ath9k_conf_tx,
.bss_info_changed = ath9k_bss_info_changed,
.set_key = ath9k_set_key,
.get_tsf = ath9k_get_tsf,
.set_tsf = ath9k_set_tsf,
.reset_tsf = ath9k_reset_tsf,
.ampdu_action = ath9k_ampdu_action,
.get_survey = ath9k_get_survey,
.rfkill_poll = ath9k_rfkill_poll_state,
.set_coverage_class = ath9k_set_coverage_class,
.flush = ath9k_flush,
.tx_frames_pending = ath9k_tx_frames_pending,
.tx_last_beacon = ath9k_tx_last_beacon,
};
static const struct net_device_ops ieee80211_dataif_ops = {
.ndo_open = ieee80211_open,
.ndo_stop = ieee80211_stop,
.ndo_uninit = ieee80211_teardown_sdata,
.ndo_start_xmit = ieee80211_subif_start_xmit, -
-> ieee80211_xmit
-> ieee80211_tx
-> __ieee80211_tx
-> drv_tx
-> ath9k_tx
-> ath_tx_start
-> ath_tx_start_dma
-> ath_tx_send_normal
-> ath_tx_txqaddbuf
-> REG_WRITE
.ndo_set_multicast_list = ieee80211_set_multicast_list,
.ndo_change_mtu = ieee80211_change_mtu,
.ndo_set_mac_address = ieee80211_change_mac,
.ndo_select_queue = ieee80211_netdev_select_queue,
};
Pci.c : static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
if (!hw) {
dev_err(&pdev->dev, "No memory for ieee80211_hw\n");
ret = -ENOMEM;
goto err_alloc_hw;
}
ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc);
if (ret) {
dev_err(&pdev->dev, "request_irq failed\n");
goto err_irq;
}
ret = ath9k_init_device(id->device, sc, subsysid, &ath_pci_bus_ops);
if (ret) {
dev_err(&pdev->dev, "Failed to initialize device\n");
goto err_init;
}
} mac80211/Main.c: struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
const struct ieee80211_ops *ops)
{
tasklet_init(&local->tasklet,
ieee80211_tasklet_handler,
(unsigned long) local);
}
irqreturn_t ath_isr(int irq, void *dev)
{
if (status & ATH9K_INT_SWBA)
tasklet_schedule(&sc->bcon_tasklet);
if (sched) {
/* turn off every interrupt */
ath9k_hw_disable_interrupts(ah);
tasklet_schedule(&sc->intr_tq);
}
}
int ath_tx_init(struct ath_softc *sc, int nbufs)
{
ath_descdma_setup
INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work);
} int ath_rx_init(struct ath_softc *sc, int nbufs)
{
}
////////////////////////////////////////////////////////////////////////////////////
tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); //在中断中被调用
tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
(unsigned long)sc);
ath9k_tasklet( )
{
ath_rx_tasklet(sc, 0, false); à ieee80211_rx
ath_tx_tasklet(sc);
}
ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
__ieee80211_rx_handle_packet(hw, skb);
}
void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
struct sk_buff *skb)
{
ieee80211_prepare_and_rx_handle(&rx, skb, false);
}
/*
* This function returns whether or not the SKB * was destined for RX processing or not, which, * if consume is true, is equivalent to whether * or not the skb was consumed.
*/
static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
struct sk_buff *skb, bool consume)
{
prepare_for_handlers
ieee80211_invoke_rx_handlers(rx);
}
/* main receive path */
static int prepare_for_handlers(struct ieee80211_rx_data *rx,
struct ieee80211_hdr *hdr)
{
//check data type & mac address
}
static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
{
ieee80211_rx_h_passive_scan
ieee80211_rx_h_check
/*
* Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns
* true if the MPDU was buffered, false if it should be processed. QoS
*/
ieee80211_rx_reorder_ampdu
ieee80211_rx_handlers
}
static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx)
{
CALL_RXH(ieee80211_rx_h_decrypt)
CALL_RXH(ieee80211_rx_h_check_more_data)
CALL_RXH(ieee80211_rx_h_sta_process)
CALL_RXH(ieee80211_rx_h_defragment)
CALL_RXH(ieee80211_rx_h_ps_poll)
CALL_RXH(ieee80211_rx_h_michael_mic_verify)
/* must be after MMIC verify so header is counted in MPDU mic */
CALL_RXH(ieee80211_rx_h_remove_qos_control)
CALL_RXH(ieee80211_rx_h_amsdu)
#ifdef CONFIG_MAC80211_MESH
if (ieee80211_vif_is_mesh(&rx->sdata->vif))
CALL_RXH(ieee80211_rx_h_mesh_fwding);
#endif
CALL_RXH(ieee80211_rx_h_data)
à __ieee80211_data_to_8023(rx, &port_control);
ieee80211_deliver_skb(rx);
netif_receive_skb() or dev_queue_xmit()
CALL_RXH(ieee80211_rx_h_ctrl);
CALL_RXH(ieee80211_rx_h_mgmt_check)
CALL_RXH(ieee80211_rx_h_action)
CALL_RXH(ieee80211_rx_h_userspace_mgmt)
CALL_RXH(ieee80211_rx_h_action_return)
CALL_RXH(ieee80211_rx_h_mgmt)
rxh_next:
ieee80211_rx_handlers_result(rx, res);
}
|
|