1、MAC控制器、網卡、PHY、MDIO、mii、gmii、rgmii概念掃盲
網卡在功能上包含OSI模型的兩個層,數據鏈路層和物理層。物理層定義了數據傳送與接收所需要的電與光信號、線路狀態、時鍾基准、數據編碼和電路等,並向數據鏈路層設備提供標准接口。數據鏈路層則提供尋址機構、數據幀的構建、數據差錯檢查、傳送控制、向網絡層提供標准的數據接口等功能。網卡中負責數據鏈路的芯片叫做MAC控制器,負責物理層的芯片叫做PHY。所以,一個網卡由MAC控制器和PHY組成。
MAC控制器與PHY連接使用MII(Medium independent interface)媒體獨立接口,這個接口是IEEE-802.3定義的以太網行業標准定義的接口,包括一個數據接口和一個MAC和PHY之間的管理接口即MDIO。MII標准接口用於連接MAC和PHY,媒體獨立表示不對MAC硬件重新設計或替換的情況下,任何類型的PHY設備接到當前MAC控制器上都可以正常工作。
MII支持10M和100M的網絡速率,由於網卡的速率不同,所以在其他速率下工作的與MII等效的接口有:AUI(10M 以太網)、GMII(Gigabit 以太網)和XAUI(10-Gigabit 以太網)。此外還有RMII、RGMII、SMII、SGMII等。所有這些接口都是由MII而來。MII支持10兆和100兆的操作,一個接口由14根線組成。 RMII是簡化的MII接口,在數據的收發上它比MII接口少了一倍的信號線。SMII是由思科提出的一種媒體接口,它有比RMII更少的信號線數目,S表示串行的意思。因為它只用一根信號線傳送發送數據,一根信號線傳輸接受數據,所以在時鍾上為了滿足100的需求,它的時鍾頻率很高,達到了125兆,為什么用125兆,是因為數據線里面會傳送一些控制信息。GMII采用8位接口數據,工作時鍾125MHz,因此傳輸速率可達1000Mbps。同時兼容MII所規定的10/100 Mbps工作方式。RGMII又是GMII接口的精簡版。SGMII又是GMII的串行版。
MAC控制器和PHY除了數據傳輸的交流外,MAC和PHY控制信息的交流通過MDIO(管理數據輸入輸出)接口來完成。具體MAC控制器進行PHY檢測、MAC控制器回去PHY當前狀態、MAC控制器控制PHY速率等操作就通過MDIO來完成。
2. xilinx uboot網卡驅動分析
xilinx網卡模式比較靈活,可以外接PHY芯片也可以用FPGA做PHY芯片。
以zynqmp_zcu102為例,在其dts中定義的網卡設備樹為
&gem3 { status = "okay"; local-mac-address = [00 0a 35 00 02 90]; phy-handle = <&phy0>; phy-mode = "rgmii-id"; phy0: phy@21 { reg = <21>; ti,rx-internal-delay = <0x8>; ti,tx-internal-delay = <0xa>; ti,fifo-depth = <0x1>; }; };
uboot加載設備樹種的信息創建device后,與driver匹配后執行zynq_gem_probe函數。
在uboot中管理整個網卡驅動的結構為
struct zynq_gem_priv { struct emac_bd *tx_bd; struct emac_bd *rx_bd; char *rxbuffers; u32 rxbd_current; u32 rx_first_buf; int phyaddr; u32 emio; int init; struct zynq_gem_regs *iobase; phy_interface_t interface; struct phy_device *phydev; int phy_of_handle; struct mii_dev *bus; };
由變量名可知,它包含了所有操作網卡需要的信息。
zynq_gem_probe(struct udevice *dev)函數中具體做的操作有: priv->rxbuffers = memalign(ARCH_DMA_MINALIGN, RX_BUF * PKTSIZE_ALIGN); 為priv分配接收buffers priv->tx_bd = (struct emac_bd *)bd_space; //分配tx_bd的空間 priv->rx_bd = (struct emac_bd *)((ulong)bd_space + BD_SEPRN_SPACE);//分配rx_bd的空間 priv->bus = mdio_alloc();//分配mdio bus,主要是初始化了一個bus鏈表 priv->bus->read = zynq_gem_miiphy_read; //mdio總線讀函數,用於讀取phy信息 priv->bus->write = zynq_gem_miiphy_write;//mdio寫總線函數 priv->bus->priv = priv; strcpy(priv->bus->name, "gem");//總線名為gem ret = mdio_register(priv->bus);//注冊mdio,主要進行的操作是list_add_tail(&bus->link, &mii_devs); return zynq_phy_init(dev); //phy初始化
接下來看下 zynq_phy_init函數里干了啥。
zynq_phy_init(struct udevice *dev)
writel(ZYNQ_GEM_NWCTRL_MDEN_MASK, ®s->nwctrl);寫MAC控制器寄存器,Enable MDIO bus
ret = phy_detection(dev);//通過MDIO來檢測phy,通過phyread函數檢測正確的phy地址,如果沒有檢測到,zynq_phy_init將會退出,后面的初始化就不會有,網卡就不能使用,在調試的時候可以注意下這個過程。
priv->phydev = phy_connect(priv->bus, priv->phyaddr, dev,priv->interface);
本文轉載自: https://blog.csdn.net/u012075739/article/details/52966751