DM9000网卡驱动源码分析系列06 - open && stop
2015-12-09 16:19
211 查看
static void dm9000_mask_interrupts(struct board_info *db) { iow(db, DM9000_IMR, IMR_PAR); } 屏蔽中断 static void dm9000_unmask_interrupts(struct board_info *db) { iow(db, DM9000_IMR, db->imr_all); } 恢复中断
/*
* Open the interface.
* The interface is opened whenever "ifconfig" actives it.
*/
static int dm9000_open(struct net_device *dev)
{
struct board_info *db = netdev_priv(dev);
unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;
if (netif_msg_ifup(db))
dev_dbg(db->dev, "enabling %s\n", dev->name);
/* If there is no IRQ type specified, default to something that
* may work, and tell the user that this is a problem */
if (irqflags == IRQF_TRIGGER_NONE)
irqflags = irq_get_trigger_type(dev->irq);
if (irqflags == IRQF_TRIGGER_NONE)
dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");
irqflags |= IRQF_SHARED;
/* GPIO0 on pre-activate PHY, Reg 1F is not set by reset */
iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */
mdelay(1); /* delay needs by DM9000B */
/* Initialize DM9000 board */
dm9000_init_dm9000(dev);
if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev))
return -EAGAIN;
/* Now that we have an interrupt handler hooked up we can unmask
* our interrupts
*/
dm9000_unmask_interrupts(db);
/* Init driver variable */
db->dbug_cnt = 0;
mii_check_media(&db->mii, netif_msg_link(db), 1);
netif_start_queue(dev);
/* Poll initial link status */
schedule_delayed_work(&db->phy_poll, 1);
return 0;
}
在probe后,系统已经知道了有这么一个网络设备可以用,至于什么时候用它,就是在dm9000_netdev_ops定义的一系列函数里操作
关于open函数的调用LDD3 P(515)里有一段话,我就直接摘抄下来
When ifconfig is used to assign an address to the interface, it performs two tasks.
First, it assigns the address by means of ioctl(SIOCSIFADDR) (Socket I/O Control Set
Interface Address). Then it sets the IFF_UP bit in dev->flag by means of
ioctl(SIOCSIFFLAGS) (Socket I/O Control Set Interface Flags) to turn the interface on.
As far as the device is concerned, ioctl(SIOCSIFADDR) does nothing. No driver func-
tion is invoked—the task is device independent, and the kernel performs it. The lat-
ter command ( ioctl(SIOCSIFFLAGS) ), however, calls the open method for the device.
Similarly, when the interface is shut down, ifconfig uses ioctl(SIOCSIFFLAGS) to clear
IFF_UP , and the stop method is called.
用ifconfig操作设备时,某些操作会触发open 和 stop函数的调用
probe后设备状态是available, open后设备状态是running
#define netif_msg_ifup(p) ((p)->msg_enable & NETIF_MSG_IFUP)
netif_msg_xxx这些宏在 include/linux/netdevice.h里有定义
我开始还奇怪,怎么函数可以直接操作自定义的结构体,原来是宏定义
dm9000_init_dm9000初始化函数,稍后再分析
request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev)中断申请,中断处理函数稍后分析
dm9000_unmask_interrupts函数,不再屏蔽中断
netif_start_queue启动队列,这时候就可以正常收发包了
schedule_delayed_work delay_work稍后分析
static void dm9000_shutdown(struct net_device *dev)
{
struct board_info *db = netdev_priv(dev);
/* RESET device */
dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */
iow(db, DM9000_GPR, 0x01); /* Power-Down PHY */
dm9000_mask_interrupts(db);
iow(db, DM9000_RCR, 0x00); /* Disable RX */
}
dm9000_mask_interrupts屏蔽中断
/*
* Stop the interface.
* The interface is stopped when it is brought.
*/
static int dm9000_stop(struct net_device *ndev)
{
struct board_info *db = netdev_priv(ndev);
if (netif_msg_ifdown(db))
dev_dbg(db->dev, "shutting down %s\n", ndev->name);
cancel_delayed_work_sync(&db->phy_poll);
netif_stop_queue(ndev);
netif_carrier_off(ndev);
/* free interrupt */
free_irq(ndev->irq, ndev);
dm9000_shutdown(ndev);
return 0;
}
open函数的一些反操作,取消delaywork,暂停队列,网卡状态置关闭,释放中断号,等等
/*
* Initialize dm9000 board
*/
static void dm9000_init_dm9000(struct net_device *dev)
{
struct board_info *db = netdev_priv(dev);
unsigned int imr;
unsigned int ncr;
dm9000_dbg(db, 1, "entering %s\n", __func__);
dm9000_reset(db);
dm9000_mask_interrupts(db);
/* I/O mode */
db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */
/* Checksum mode */
if (dev->hw_features & NETIF_F_RXCSUM)
iow(db, DM9000_RCSR,
(dev->features & NETIF_F_RXCSUM) ? RCSR_CSUM : 0);
iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */
iow(db, DM9000_GPR, 0);
/* If we are dealing with DM9000B, some extra steps are required: a
* manual phy reset, and setting init params.
*/
if (db->type == TYPE_DM9000B) {
dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET);
dm9000_phy_write(dev, 0, MII_DM_DSPCR, DSPCR_INIT_PARAM);
}
ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0;
/* if wol is needed, then always set NCR_WAKEEN otherwise we end
* up dumping the wake events if we disable this. There is already
* a wake-mask in DM9000_WCR */
if (db->wake_supported)
ncr |= NCR_WAKEEN;
iow(db, DM9000_NCR, ncr);
/* Program operating register */
iow(db, DM9000_TCR, 0); /* TX Polling clear */
iow(db, DM9000_BPTR, 0x3f); /* Less 3Kb, 200us */
iow(db, DM9000_FCR, 0xff); /* Flow Control */
iow(db, DM9000_SMCR, 0); /* Special Mode */
/* clear TX status */
iow(db, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */
/* Set address filter table */
dm9000_hash_table_unlocked(dev);
imr = IMR_PAR | IMR_PTM | IMR_PRM;
if (db->type != TYPE_DM9000E)
imr |= IMR_LNKCHNG;
db->imr_all = imr;
/* Init Driver variable */
db->tx_pkt_cnt = 0;
db->queue_pkt_len = 0;
dev->trans_start = jiffies;
}
初始化寄存器及变量的值
相关文章推荐
- 关于BASH中变量内容的删除、取代与替换
- 架构设计(重业务:后期制作不同业务的sdk)
- docker 1.9.1使用 iso虚拟光驱一键式安装方法
- linux shell if
- apache 实现备份服务器-热备份(hot standby)
- Linux学习笔记(二十、历史命令)
- Canopy聚类算法与Mahout中的实现
- How To Install Apache Kafka on Ubuntu 14.04
- 修复开机进入grub
- Linux命令(3):wc命令
- tomcat7的相关脚本,获益匪浅,总结一下
- linux 上挂载硬盘或者读取u盘数据
- VC SDI程序在英文版系统不能运行
- linux学习笔记2015-12-09
- 目标检测学习_1(用opencv自带hog实现行人检测)
- 试用 OPENVMS V8.4-1H1
- 常见的shell 命令
- Office 365管理员指引 19——Sharepoint 网站快速访问链接
- linux centos 修改ip地址细节介绍
- 网站漏洞检测工具