这里使用的是ath9k网卡驱动,硬件平台是TP-link TL-WR841N V7.1 路由器
int ath_pci_init(void)
{
return pci_register_driver(&ath_pci_driver);
}static struct pci_driver ath_pci_driver = {
.name = "ath9k",
.id_table = ath_pci_id_table,
.probe = ath_pci_probe,
.remove = ath_pci_remove,
.driver.pm = ATH9K_PM_OPS,
};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;
}
SET_IEEE80211_DEV(hw, &pdev->dev);
pci_set_drvdata(pdev, hw);
sc = hw->priv;
sc->hw = hw;
sc->dev = &pdev->dev;
sc->mem = mem;
/* Will be cleared in ath9k_start() */
sc->sc_flags |= SC_OP_INVALID;
ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc);
if (ret) {
dev_err(&pdev->dev, "request_irq failed\n");
goto err_irq;
}
sc->irq = pdev->irq;
ret = ath9k_init_device(id->device, sc, &ath_pci_bus_ops);
if (ret) {
dev_err(&pdev->dev, "Failed to initialize device\n");
goto err_init;
}
…
}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,
.get_stats = ath9k_get_stats,
.set_antenna = ath9k_set_antenna,
.get_antenna = ath9k_get_antenna,
};struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, const struct ieee80211_ops *ops)
{
struct ieee80211_local *local;
int priv_size, i;
struct wiphy *wiphy;
bool use_chanctx;
…
/* Ensure 32-byte alignment of our private data and hw private data.
* We use the wiphy priv data for both our ieee80211_local and for
* the driver‘s private data
*
* In memory it‘ll be like this:
*
* +-------------------------+
* | struct wiphy |
* +-------------------------+
* | struct ieee80211_local |
* +-------------------------+
* | driver‘s private data |
* +-------------------------+
*
*/
priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len;
// 注意这里的mac80211_config_ops
// 以其中的scan成员为例,scan时就会触发对应的函数ieee80211_scan()
wiphy = wiphy_new(&mac80211_config_ops, priv_size); // 注意这里的mac80211_config_ops
if (!wiphy)
return NULL;
…
// 这里的local->ops就变成传进来的参数ath9k_ops
local->ops = ops;
…
// 这个工作队列很重要, sw scan的情况下会schedule这个工作队列来做scan
INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
…
// 这个tasklet跟接受数据紧密相关,后面会提到
tasklet_init(&local->tasklet,
ieee80211_tasklet_handler,
(unsigned long) local);
…
return &local->hw;
}
EXPORT_SYMBOL(ieee80211_alloc_hw);int ath9k_init_device(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops)
{
struct ieee80211_hw *hw = sc->hw;
struct ath_common *common;
struct ath_hw *ah;
int error = 0;
struct ath_regulatory *reg;
/* Bring up device */
error = ath9k_init_softc(devid, sc, bus_ops);
if (error != 0)
goto error_init;
ah = sc->sc_ah;
common = ath9k_hw_common(ah);
ath9k_set_hw_capab(sc, hw);
/* Initialize regulatory */
error = ath_regd_init(&common->regulatory, sc->hw->wiphy,
ath9k_reg_notifier);
if (error)
goto error_regd;
reg = &common->regulatory;
/* Setup TX DMA */
error = ath_tx_init(sc, ATH_TXBUF);
if (error != 0)
goto error_tx;
/* Setup RX DMA */
error = ath_rx_init(sc, ATH_RXBUF);
if (error != 0)
goto error_rx;
ath9k_init_txpower_limits(sc);
…
error = ieee80211_register_hw(hw);
if (error)
goto error_register;
error = ath9k_init_debug(ah);
if (error) {
ath_err(common, "Unable to create debugfs files\n");
goto error_world;
}
…
}static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops)
{
…
tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
(unsigned long)sc);
…
}
/* Setup TX DMA */ error = ath_tx_init(sc, ATH_TXBUF); if (error != 0) goto error_tx; /* Setup RX DMA */ error = ath_rx_init(sc, ATH_RXBUF); if (error != 0) goto error_rx;
error = ieee80211_register_hw(hw);
hdu1384 poj1202 Intervals --- 差分约束,布布扣,bubuko.com
hdu1384 poj1202 Intervals --- 差分约束
原文:http://blog.csdn.net/u011032846/article/details/24499667