网卡驱动8-MII接口以及linux内核对MII的支持

首先,向大家推荐一些文章。

http://blog.chinaunix.net/uid-24148050-id-131084.html

http://hi.baidu.com/lds102/item/eae3262c77b897de0f37f966

http://blog.csdn.net/zyboy2000/article/details/4525726

 

这上面说了MIIRMIISMIIGMII等一系列的接口。

网口一般是这样

MacàPhyà网络变压器àRJ45口

但是只是从电路上不一定看得这么清楚,应为有些是集成的,例如DM9000就是mac+phy,还有很多网络变压器和RJ45口在一起。对于我们写驱动,要知道的是Mac和Pht之间的接口,其他的还是比较透明的。而它们的接口就是上面提的一些。

 

MII是(Medium Independent Interface)的意思,是指不用考虑媒体是铜轴、光纤、电缆等,因为这些媒体处理的相关工作都有PHY或者叫做MAC的芯片完成。   MII支持10兆和100兆的操作,不支持1000兆。

我们看一下MII的接口图(分别相对于mac和 phy)


前16位是数据传输,MDC和MDIO是SMI总线的东西,用于管理phy。这篇文章主要就是看linux内核对SMI总线的使用。

上面有篇文章是这么说的:

MacPhy的管理是使用SMISerialManagement Interface)总线通过读写PHY的寄存器来完成的。PHY里面的部分寄存器是IEEE定义的,这样PHY把自己的目前的状态反映到寄存器里面,MAC通过SMI总线不断的读取PHY的状态寄存器以得知目前PHY的状态,例如连接速度,双工的能力等。

上面让我在意的是PHY里面的部分寄存器是IEEE定义的。那我们看看内核里的定义吧.linux-3.0.8

include/linux/mii.h

/* Generic MII registers. */

#define MII_BMCR            0x00        /* Basic mode control register */
#define MII_BMSR            0x01        /* Basic mode status register  */
#define MII_PHYSID1         0x02        /* PHYS ID 1                   */
#define MII_PHYSID2         0x03        /* PHYS ID 2                   */
#define MII_ADVERTISE       0x04        /* Advertisement control reg   */
#define MII_LPA             0x05        /* Link partner ability reg    */
#define MII_EXPANSION       0x06        /* Expansion register          */
#define MII_CTRL1000        0x09        /* 1000BASE-T control          */
#define MII_STAT1000        0x0a        /* 1000BASE-T status           */
#define MII_ESTATUS	        0x0f	    /* Extended Status             */
#define MII_DCOUNTER        0x12        /* Disconnect counter          */
#define MII_FCSCOUNTER      0x13        /* False carrier counter       */
#define MII_NWAYTEST        0x14        /* N-way auto-neg test reg     */
#define MII_RERRCOUNTER     0x15        /* Receive error counter       */
#define MII_SREVISION       0x16        /* Silicon revision            */
#define MII_RESV1           0x17        /* Reserved...                 */
#define MII_LBRERROR        0x18        /* Lpback, rx, bypass error    */
#define MII_PHYADDR         0x19        /* PHY address                 */
#define MII_RESV2           0x1a        /* Reserved...                 */
#define MII_TPISTATUS       0x1b        /* TPI status for 10mbps       */
#define MII_NCONFIG         0x1c        /* Network interface config    */

我们在看看DM9000的定义:

不是所有都支持。

例如我们要启动自动协商机制,只要把control寄存器的的第12位置1就可以了。

 

现在摆在我们的面前有两个问题

1.      DM9000如何操作去写或读。

2.       linux提供了什么样的接口。

 

先看第一个问题:下面是DM9000的几个寄存器

网卡驱动8-MII接口以及linux内核对MII的支持_第1张图片

网卡驱动8-MII接口以及linux内核对MII的支持_第2张图片上面可以看成是4个寄存器

EPCR: phy控制寄存器

EPAR: phy地址寄存器

EPDRL:phy数据寄存器低8位

EPDRH:phy数据寄存器高8位

读:

1.       先写入寄存器的地址(就是上面的MII Register Description上面的。你可以在mii.h中看到定义)到EPAR寄存器。

2.       把EPCR的ERPRR位(读命令)和EPOS(选择PHY)置位。

3.       读EEPROM用的是等待EPCR的ERRE变为0,为1表示正在进行。读PHY用的是延时1m秒。看一下uboot,都是用延时等待。

4.       清除EPCR的ERPRR位。

5.       读EPDRL和EPDRH。

 

写:

1.       先写入寄存器的地址到EPAR寄存器。

2.       写数据到ERDRL和EPDRH。

3.       把EPCR的ERPRW(写命令)和EPOS(选择PHY)置位。

4.       延时1m秒,等待完成。

5.       清除EPCR的ERPRR位。

 

下面我们看linux内核提供的接口。

struct mii_if_info {
	int phy_id;
	int advertising;
	int phy_id_mask;
	int reg_num_mask;

	unsigned int full_duplex : 1;	/* is full duplex? */
	unsigned int force_media : 1;	/* is autoneg. disabled? */
	unsigned int supports_gmii : 1; /* are GMII registers supported? */

	struct net_device *dev;
	int (*mdio_read) (struct net_device *dev, int phy_id, int location);
	void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val);
};

看一下dm9000网卡的初始化:

	db->mii.phy_id_mask  = 0x1f;//这个给驱动用,dm9000没用,是考虑smi总线上有多个phy时。
	db->mii.reg_num_mask = 0x1f;//寄存器mask
	db->mii.force_media  = 0;
	db->mii.full_duplex  = 0;
	db->mii.dev	     = ndev;
	db->mii.mdio_read    = dm9000_phy_read;
	db->mii.mdio_write   = dm9000_phy_write;

dm9000不支持gmii,所以没对它初始化

如果你提供了这些,对phy的操作就可以同drivers/net/mii.c中的函数去操作,不用再去看那些mii的寄存器了(当然有些非标准的要自己写)。我看看mii.c提供的

EXPORT_SYMBOL(mii_link_ok);
EXPORT_SYMBOL(mii_nway_restart);
EXPORT_SYMBOL(mii_ethtool_gset);
EXPORT_SYMBOL(mii_ethtool_sset);
EXPORT_SYMBOL(mii_check_link);
EXPORT_SYMBOL(mii_check_media);
EXPORT_SYMBOL(mii_check_gmii_support);
EXPORT_SYMBOL(generic_mii_ioctl);
我们上次说的ethtool很多要依赖它们。
mii_link_ok:读链接状态
mii_nway_restart: 重启接口的自动协商机制
mii_ethtool_gset:获取接口设置。查看结构体struct ethtool_cmd有什么设置,上篇文章说过。
mii_ethtool_sset:设置接口设置。
mii_check_link:检测MII链接状态。这个会调用netif_carrier_on/off上报内核。
mii_check_media:检查双工改变。Full or Half
mii_check_gmii_support:是否支持gmii,这个是1000M的支持
generic_mii_ioctl:ioctl接口。这个可以放在驱动的ioctl里面,用户可以通过socket的ioctl调用。

下次我们说一个千兆的网卡,对phy的控制。


你可能感兴趣的:(linux,内核,网卡,ARM,linux内核)