您的位置:首页 > 运维架构

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;
}
初始化寄存器及变量的值
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: