Linux device driver for ADMtek ADM8211

硬件抽象层:通过多种case处理不同型号的射频/基带芯片,提高驱动兼容性

DMA环形缓冲区:使用双环形缓冲区结构高效处理数据收发

中断驱动设计:充分利用硬件中断机制实现高效的数据处理

EEPROM管理:动态适配不同容量的EEPROM芯片(93C46/93C66)

电源管理:通过SYNRF寄存器控制射频模块的电源状态

速率适配:支持多种802.11b速率,包括短前导码配置

// SPDX-License-Identifier: GPL-2.0-only
/*

  • Linux device driver for ADMtek ADM8211 (IEEE 802.11b MAC/BBP)
  • Copyright © 2003, Jouni Malinen j@w1.fi
  • Copyright © 2004-2007, Michael Wu flamingice@sourmilk.net
  • Some parts copyright © 2003 by David Young dyoung@pobox.com
  • and used with permission.
  • Much thanks to Infineon-ADMtek for their support of this driver.
    */

/* 包含必要的头文件 */
#include <linux/interrupt.h>
#include <linux/if.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/etherdevice.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/crc32.h>
#include <linux/eeprom_93cx6.h>
#include <linux/module.h>
#include <net/mac80211.h>
#include “adm8211.h”

/* 模块元信息 */
MODULE_AUTHOR(“Michael Wu flamingice@sourmilk.net”);
MODULE_AUTHOR(“Jouni Malinen j@w1.fi”);
MODULE_DESCRIPTION(“Driver for IEEE 802.11b wireless cards based on ADMtek ADM8211”);
MODULE_LICENSE(“GPL”);

/* 环形缓冲区大小模块参数(默认值16) */
static unsigned int tx_ring_size __read_mostly = 16;
static unsigned int rx_ring_size __read_mostly = 16;
module_param(tx_ring_size, uint, 0); // 发送缓冲区大小
module_param(rx_ring_size, uint, 0); // 接收缓冲区大小

/* PCI设备ID表,匹配支持的设备 /
static const struct pci_device_id adm8211_pci_id_table[] = {
{ PCI_DEVICE(0x10B7, 0x6000) }, /
3Com 3CRSHPW796 /
{ PCI_DEVICE(0x1200, 0x8201) }, /
未知厂商 /
{ PCI_DEVICE(0x1317, 0x8201) }, /
ADM8211A /
{ PCI_DEVICE(0x1317, 0x8211) }, /
ADM8211B/C */
{ 0 }
};

/* 支持的速率表(802.11b) */
static struct ieee80211_rate adm8211_rates[] = {
{ .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 220, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, // 可能为特殊配置
};

/* 支持的2.4GHz信道列表 */
static const struct ieee80211_channel adm8211_channels[] = {
{ .center_freq = 2412}, // 信道1
// … 中间信道省略 …
{ .center_freq = 2484}, // 信道14
};

/* EEPROM读取函数 */
static void adm8211_eeprom_register_read(struct eeprom_93cx6 *eeprom) {
struct adm8211_priv *priv = eeprom->data;
u32 reg = ADM8211_CSR_READ(SPR); // 读取SPR寄存器
// 解析寄存器中的各个位状态
eeprom->reg_data_in = reg & ADM8211_SPR_SDI;
eeprom->reg_data_out = reg & ADM8211_SPR_SDO;
eeprom->reg_data_clock = reg & ADM8211_SPR_SCLK;
eeprom->reg_chip_select = reg & ADM8211_SPR_SCS;
}

/* EEPROM写入函数 */
static void adm8211_eeprom_register_write(struct eeprom_93cx6 *eeprom) {
struct adm8211_priv *priv = eeprom->data;
u32 reg = 0x4000 | ADM8211_SPR_SRS; // 基础寄存器配置
// 根据eeprom结构设置各个控制位
if (eeprom->reg_data_in) reg |= ADM8211_SPR_SDI;
// … 类似处理其他位 …
ADM8211_CSR_WRITE(SPR, reg); // 写入配置到SPR寄存器
ADM8211_CSR_READ(SPR); // 确保写入完成
}

/* 完整EEPROM读取流程 */
static int adm8211_read_eeprom(struct ieee80211_hw *dev) {
struct adm8211_priv *priv = dev->priv;
struct eeprom_93cx6 eeprom = {
.data = priv,
.register_read = adm8211_eeprom_register_read,
.register_write = adm8211_eeprom_register_write
};
// 根据硬件版本确定EEPROM大小
if (ADM8211_CSR_READ(CSR_TEST0) & ADM8211_CSR_TEST0_EPTYP) {
eeprom.width = PCI_EEPROM_WIDTH_93C66; // 512字节
} else {
eeprom.width = PCI_EEPROM_WIDTH_93C46; // 128字节
}
// 分配内存并读取EEPROM数据
priv->eeprom = kmalloc(priv->eeprom_len, GFP_KERNEL);
eeprom_93cx6_multiread(&eeprom, 0, (__le16 *)priv->eeprom, words);
// 解析RF类型、BBP类型等硬件信息
priv->rf_type = (cr49 >> 3) & 0x7;
// … 其他硬件信息解析 …
}

/* SRAM写入函数 */
static inline void adm8211_write_sram(struct ieee80211_hw *dev, u32 addr, u32 data) {
struct adm8211_priv *priv = dev->priv;
// 配置SRAM访问寄存器
ADM8211_CSR_WRITE(WEPCTL, addr | ADM8211_WEPCTL_TABLE_WR | …);
ADM8211_CSR_READ(WEPCTL); // 确保配置生效
msleep(1); // 等待硬件响应
// 写入数据到SRAM
ADM8211_CSR_WRITE(WESK, data);
ADM8211_CSR_READ(WESK);
msleep(1);
}

/* 中断处理函数 */
static irqreturn_t adm8211_interrupt(int irq, void *dev_id) {
struct ieee80211_hw *dev = dev_id;
struct adm8211_priv *priv = dev->priv;
u32 stsr = ADM8211_CSR_READ(STSR); // 读取中断状态寄存器
// 处理接收完成中断
if (stsr & ADM8211_STSR_RCI) {
adm8211_interrupt_rci(dev); // 接收处理
}
// 处理发送完成中断
if (stsr & ADM8211_STSR_TCI) {
adm8211_interrupt_tci(dev); // 发送处理
}
// 其他中断处理逻辑…
return IRQ_HANDLED;
}

/* 射频配置函数 */
static int adm8211_rf_set_channel(struct ieee80211_hw *dev, unsigned int chan) {
struct adm8211_priv *priv = dev->priv;
// 根据不同的射频芯片类型配置寄存器
switch (priv->transceiver_type) {
case ADM8211_RFMD2958:
adm8211_rf_write_syn_rfmd2958(dev, 0x00, 0x04007);
// … 其他寄存器配置 …
break;
case ADM8211_MAX2820:
adm8211_rf_write_syn_max2820(dev, 0x3, …);
break;
// 其他射频芯片处理…
}
// 更新硬件当前信道
reg = ADM8211_CSR_READ(CAP0);
reg &= ~0xF;
reg |= chan;
ADM8211_CSR_WRITE(CAP0, reg);
return 0;
}

/* 硬件初始化函数 */
static void adm8211_hw_init(struct ieee80211_hw *dev) {
struct adm8211_priv *priv = dev->priv;
// 配置DMA参数
ADM8211_CSR_WRITE(PAR, reg | ADM8211_PAR_MRLE | ADM8211_PAR_MRME);
// 设置速率相关参数
adm8211_set_rate(dev);
// 初始化基带处理器
adm8211_hw_init_bbp(dev);
// 配置中断
ADM8211_CSR_WRITE(IER, ADM8211_IER_NIE | ADM8211_IER_AIE | …);
}

/* PCI设备探测函数 */
static int adm8211_probe(struct pci_dev *pdev, const struct pci_device_id *id) {
struct ieee80211_hw *dev;
struct adm8211_priv *priv;
// 启用PCI设备
pci_enable_device(pdev);
// 分配IEEE80211硬件结构
dev = ieee80211_alloc_hw(sizeof(*priv), &adm8211_ops);
// 映射硬件寄存器
priv->map = pci_iomap(pdev, 1, mem_len);
// 读取EEPROM获取MAC地址
*(__le32 *)perm_addr = cpu_to_le32(ADM8211_CSR_READ(PAR0));
// 注册设备到mac80211
ieee80211_register_hw(dev);
return 0;
}

/* PCI设备移除函数 */
static void adm8211_remove(struct pci_dev *pdev) {
struct ieee80211_hw *dev = pci_get_drvdata(pdev);
// 取消注册设备
ieee80211_unregister_hw(dev);
// 释放资源
dma_free_coherent(…);
pci_iounmap(pdev, priv->map);
pci_release_regions(pdev);
pci_disable_device(pdev);
ieee80211_free_hw(dev);
}

/* PCI驱动定义 */
static struct pci_driver adm8211_driver = {
.name = “adm8211”,
.id_table = adm8211_pci_id_table,
.probe = adm8211_probe,
.remove = adm8211_remove,
.driver.pm = &adm8211_pm_ops,
};

module_pci_driver(adm8211_driver);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值