[patch]Add the MII core

发布于 2022-09-18 05:20:01 字数 9186 浏览 16 评论 0

网卡驱动开发,所涉及到的主要内容就是对EMAC和PHY的操作,EMAC和PHY通过MII接口进行通信,通过对比DM9000和AT91SAM9263网卡驱动我们可以发现,
不管EMAC和PHY是集成的还是外接的,PHY对外提供的接口(MII register)是一致的,所不同的只是EMAC对PHY操作方法,因此,可以在g-bios中抽象出一层
MII CORE层,MII CORE层封装了一些基本的PHY操作,比如reset phy, power off phy,get link status等,驱动层只要把操作PHY寄存器的具体方法作为函
数指针传递给MII CORE层的数据结构,就无须关心PHY内部的实现。

signed-off-by: Jack Jiang <voidjack.jiang@gmail.com>
--------------------------------------------------------------------------------------------------------
From 4245fe23e3d491af2dbe81ef17a1bfcda1c497e3 Mon Sep 17 00:00:00 2001
From: Jack Jiang <voidjack.jiang@gmail.com>
Date: Mon, 16 Nov 2009 23:16:18 +0800
Subject: [PATCH 1/2] Add mii core

---
device/net/Makefile   |    2 +-
device/net/mii_core.c |  123 +++++++++++++++++++++++++++++++++++++++++++++++++
include/net/mii.h     |   32 ++++++++++++-
3 files changed, 155 insertions(+), 2 deletions(-)
create mode 100644 device/net/mii_core.c

diff --git a/device/net/Makefile b/device/net/Makefile
index 88b5c83..548e6c7 100644
--- a/device/net/Makefile
+++ b/device/net/Makefile
@@ -3,7 +3,7 @@ obj-$(CONF_DM9000) += dm9000.o
obj-$(CONF_CS8900) += cs8900.o
obj-$(CONF_AT91SAM9263) += eth_at91.o

-OBJS_C = tftp.o net_core.o socket.o $(obj-y)
+OBJS_C = tftp.o net_core.o socket.o mii_core.o $(obj-y)
SRCS_C := $(OBJS_C:.o=.c)

all: $(BUILT_IN_OBJ)
diff --git a/device/net/mii_core.c b/device/net/mii_core.c
new file mode 100644
index 0000000..708fd89
--- /dev/null
+++ b/device/net/mii_core.c
@@ -0,0 +1,123 @@
+#include <stdio.h>
+#include <malloc.h>
+#include <core/errno.h>
+#include <net/net.h>
+#include <net/mii.h>
+
+#define TIME_OUT 100
+
+static struct PhyDevice *g_PhyDev;
+
+static unsigned short GkPhyGetPhyAddr(struct PhyDevice *pPhyDev)
+{
+        BYTE bPhyIndex;
+
+        for (bPhyIndex = 0; bPhyIndex < MAX_PHY_NUM; bPhyIndex++)
+        {
+                if (PHY_ID1 == pPhyDev->PhyRead(bPhyIndex, MII_REG_ID1))
+                {
+                        printf("Find the active PHY, PHY index is %d\n", bPhyIndex);
+
+                        return bPhyIndex;
+                }
+        }
+
+        printf("Can't find active PHY!\n");
+
+        return -EIO;
+}
+
+struct PhyDevice *GkPhyDevNew(void)
+{
+        struct PhyDevice *pPhyDev;
+
+        pPhyDev = (struct PhyDevice *)zalloc(sizeof(*pPhyDev));
+        if (!pPhyDev)
+        {
+                printf("Alloc PhyDev failed!\n");
+                return NULL;
+        }
+
+        return pPhyDev;
+}
+
+int GkPhyDevRegister(struct PhyDevice *pPhyDev)
+{
+        BYTE  bPhyIndex;
+
+        if (!pPhyDev->PhyRead || !pPhyDev->PhyWrite)
+        {
+                return -EINVAL;
+        }
+
+        bPhyIndex = GkPhyGetPhyAddr(pPhyDev);
+        if (bPhyIndex < 0)
+        {
+                return -EIO;
+        }
+
+        pPhyDev->bPhyIndex = bPhyIndex;
+
+        g_PhyDev = pPhyDev;
+
+        return 0;
+}
+
+int GkPhyResetPhy(void)
+{
+        g_PhyDev->PhyWrite(MII_PHY_RESET, g_PhyDev->bPhyIndex, MII_REG_BMC);
+
+        while (g_PhyDev->PhyRead(g_PhyDev->bPhyIndex, MII_REG_BMC) & MII_PHY_RESET);
+
+        printf("Phy reset OK!\n");
+
+        return 0;
+}
+
+int GkPhyClosePhy(void)
+{
+        g_PhyDev->PhyWrite(MII_PHY_POWERDOWN, g_PhyDev->bPhyIndex, MII_REG_BMC);
+}
+
+int GkPhyGetLinkStatus(void)
+{
+        int iTimeOut;
+
+        for (iTimeOut = 0; iTimeOut < TIME_OUT; iTimeOut++)
+        {
+                if (g_PhyDev->PhyRead(g_PhyDev->bPhyIndex, MII_REG_BMS) & MII_PHY_AUTONEG_COMP)
+                {
+                        printf("Auto-negotiation complete!\n");
+                        goto L1;
+                }
+                udelay(100000);
+        }
+
+        if (TIME_OUT == iTimeOut)
+        {
+                printf("Time out, Auto-negotiation failed!\n");
+                return -EIO;
+        }
+
+L1:
+        switch (g_PhyDev->PhyRead(g_PhyDev->bPhyIndex, MII_REG_STAT) >> 12)
+        {
+        case 1:
+                return ETHER_SPEED_10M_HD;
+
+        case 2:
+                return ETHER_SPEED_10M_FD;
+
+        case 4:
+                return ETHER_SPEED_100M_HD;
+
+        case 8:
+                return ETHER_SPEED_100M_FD;
+
+        default:
+                break;
+        }
+
+        return ETHER_SPEED_UNKNOW;
+}
+
diff --git a/include/net/mii.h b/include/net/mii.h
index 7838353..0c30eac 100644
--- a/include/net/mii.h
+++ b/include/net/mii.h
@@ -13,5 +13,35 @@
#define MII_REG_ESTATUS                0x0f
#endif

-#define MII_PHY_RESET   0x8000
+#define MII_REG_DSC            16
+#define MII_REG_STAT           17

+
+#define MII_PHY_RESET            1 << 15
+#define MII_PHY_POWERDOWN        1 << 11
+#define MII_PHY_ENABLE_AUTONEG   1 << 12
+#define MII_PHY_RESTART_AUTONEG  1 << 9
+#define MII_PHY_AUTONEG_COMP     1 << 5
+
+#define MAX_PHY_NUM     32
+#define PHY_REG_NUM     32
+
+#define PHY_ID1         0x181 //fix me, should be from the autoconf.h
+#define PHY_ID2
+
+struct PhyDevice
+{
+        BYTE bPhyIndex;
+        unsigned short (*PhyRead)(BYTE bPhyAddr, BYTE bPhyRegIndex);
+        void (*PhyWrite)(unsigned short hVal, BYTE bPhyAddr, BYTE bPhyRegIndex);
+};
+
+struct PhyDevice *GkPhyDevNew(void);
+
+int GkPhyDevRegister(struct PhyDevice *pPhyDev);
+
+int GkPhyResetPhy(void);
+
+int GkPhyClosePhy(void);
+
+int GkPhyGetLinkStatus(void);
--
1.6.3.3

[ 本帖最后由 voidjackjiang 于 2009-11-17 10:55 编辑 ]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

七禾 2022-09-25 05:20:01

g-bios添加了MII CORE层后,修改了DM9000E网卡驱动相关代码。

signed-off-by: voidjackjiang <voidjack@163.com>
--------------------------------------------------------------------------------------
From ebcc33a032664ffb5bd955ad574e15efec4e62c6 Mon Sep 17 00:00:00 2001
From: Jack Jiang <voidjack.jiang@gmail.com>
Date: Mon, 16 Nov 2009 23:55:22 +0800
Subject: [PATCH 2/2] Add mii function for DM9000E

---
device/net/dm9000.c |   68 ++++++++++++++++----------------------------------
1 files changed, 22 insertions(+), 46 deletions(-)

diff --git a/device/net/dm9000.c b/device/net/dm9000.c
index fd884d7..8ed4fec 100644
--- a/device/net/dm9000.c
+++ b/device/net/dm9000.c
@@ -15,9 +15,6 @@
#include "dm9000.h"

-static int DM9000GetLinkStatus(void);
-
-
static BYTE DM9000Read(BYTE bRegIdx)
{
        WriteByte(bRegIdx, DM9000_INDEX_PORT);
@@ -32,11 +29,11 @@ static void DM9000Write(BYTE bRegIdx, BYTE bValue)
}

-static UINT16 DM9000PhyRead(BYTE bRegIdx)
+static UINT16 DM9000PhyRead(BYTE bPhyAddr, BYTE bRegIdx)
{
        UINT16 hVal;

-        DM9000Write(DM9000_EPAR, DM9000_PHY_INTER | bRegIdx);
+        DM9000Write(DM9000_EPAR, bPhyAddr << 6 | bRegIdx);
        DM9000Write(DM9000_EPCR, DM9000_PHY_SELECT | DM9000_PHY_READ);

        while (DM9000Read(DM9000_EPCR) & DM9000_PHY_BUSY);
@@ -49,9 +46,9 @@ static UINT16 DM9000PhyRead(BYTE bRegIdx)
}

-static void DM9000PhyWrite(BYTE bRegIdx, UINT16 hVal)
+static void DM9000PhyWrite(UINT16 hVal, BYTE bPhyAddr, BYTE bRegIdx)
{
-        DM9000Write(DM9000_EPAR, DM9000_PHY_INTER | bRegIdx);
+        DM9000Write(DM9000_EPAR, bPhyAddr << 6 | bRegIdx);
        DM9000Write(DM9000_EPDRL, hVal & 0xff);
        DM9000Write(DM9000_EPDRH, (hVal >> 8) & 0xff);

@@ -202,43 +199,6 @@ static int DM9000RecvPacket(void)
}

-static int DM9000GetLinkStatus(void)
-{
-        int i;
-
-        for(i = 0; i < 30; i++)
-        {
-                 if (DM9000PhyRead(MII_REG_BMS) & 0x20)
-                        goto L1;
-
-                mdelay(100);
-        }
-
-        return -EIO;
-
-L1:
-        switch (DM9000PhyRead(MII_REG_STAT) >> 12)
-        {
-        case 1:
-                return ETHER_SPEED_10M_HD;
-
-        case 2:
-                return ETHER_SPEED_10M_FD;
-
-        case 4:
-                return ETHER_SPEED_100M_HD;
-
-        case 8:
-                return ETHER_SPEED_100M_FD;
-
-        default:
-                break;
-        }
-
-        return ETHER_SPEED_UNKNOW;
-}
-
-
static int DM9000Isr(void *pDev)
{
        BYTE bStat;
@@ -268,9 +228,9 @@ static int __INIT__ DM9000Init(void)
        BYTE bRev;
        BYTE   bStat;
        struct NetDevice *pNetDev;
+        struct PhyDevice *pPhyDev;
        const char *pcChipName;

-
        hVID = (DM9000Read(DM9000_VIDH) << 8) | DM9000Read(DM9000_VIDL);
        hPID = (DM9000Read(DM9000_PIDH) << 8) | DM9000Read(DM9000_PIDL);

@@ -299,9 +259,25 @@ static int __INIT__ DM9000Init(void)

        DM9000Reset();

+        pPhyDev = GkPhyDevNew();
+        if (!pPhyDev)
+        {
+                return -EIO;
+        }
+
+        pPhyDev->PhyRead = DM9000PhyRead;
+        pPhyDev->PhyWrite = DM9000PhyWrite;
+
+        if (GkPhyDevRegister(pPhyDev) < 0)
+        {
+                return -EIO;
+        }
+
+        GkPhyResetPhy();
+
        printf("Detecting ethernet speed ... ");

-        iSpeed = DM9000GetLinkStatus();
+        iSpeed = GkPhyGetLinkStatus();

        if (iSpeed < 0)
        {
--
1.6.3.3

失去的东西太少 2022-09-25 05:20:01

g-bios添加了MII CORE层后,修改了AT91SAM9263网卡驱动相关代码。

signed-off-by: voidjackjiang <voidjack@163.com>
--------------------------------------------------------------------------------------
From 25fd823fa78accd54cb06741955727f896fee39a Mon Sep 17 00:00:00 2001
From: Jack Jiang <voidjack.jiang@gmail.com>
Date: Tue, 17 Nov 2009 22:51:33 +0800
Subject: [PATCH 3/3] Add mii function for AT92SAM9263's EMAC

---
device/net/eth_at91.c |   90 +++++++++++++++++++++++++++----------------------
1 files changed, 50 insertions(+), 40 deletions(-)

diff --git a/device/net/eth_at91.c b/device/net/eth_at91.c
index c7388c0..3465191 100644
--- a/device/net/eth_at91.c
+++ b/device/net/eth_at91.c
@@ -1,5 +1,6 @@
#include <stdio.h>
#include <core/types.h>
+#include <core/errno.h>
#include <core/io.h>
#include <core/init.h>
#include <core/list.h>
@@ -142,13 +143,12 @@ static int EmacRecv(struct NetDevice * pNetDev)
        return 0;
}

-static UINT16 EmacMdioRead(UINT32 nReg)
+static UINT16 EmacMdioRead(UINT8 bPhyAddr, UINT8 bPhyReg)
{
        UINT32 dwNetCtrl;
        UINT32 dwFrame;

-
-        dwFrame = (1 << 30) | (2 << 28) | (0 << 23) | (nReg << 18) | (2 << 16);
+        dwFrame = (1 << 30) | (2 << 28) | (bPhyAddr << 23) | (bPhyReg << 18) | (2 << 16);
        EmacWrite(EMAC_MAN, dwFrame);

        while (!(EmacRead(EMAC_NSR) & EMAC_IDLE));
@@ -158,13 +158,11 @@ static UINT16 EmacMdioRead(UINT32 nReg)
        return (UINT16)(dwFrame & 0xffff);
}

-static int EmacMdioWrite(UINT32 nReg, UINT16 hVal)
+static void EmacMdioWrite(UINT16 hVal, UINT8 bPhyAddr, UINT8 bPhyReg)
{
-        EmacWrite(EMAC_MAN, (1 << 30) | (1 << 28) | (0 << 23) | (nReg << 18) | (2 << 16) | hVal);
+        EmacWrite(EMAC_MAN, (1 << 30) | (1 << 28) | (bPhyAddr << 23) | (bPhyReg << 18) | (2 << 16) | hVal);

        while (!(EmacRead(EMAC_NSR) & EMAC_IDLE));
-
-        return 0;
}

static int __INIT__ EmacInitRingBuff(struct At91Emac *pEmac)
@@ -205,7 +203,7 @@ static int __INIT__ EmacInitRingBuff(struct At91Emac *pEmac)
        EmacWrite(EMAC_TBQP, (UINT32)pEmac->pTxQueue);

        DPRINT("RX buff = 0x%08x, TX buff = 0x%08x\n",
-                pEmac->pRxQueue, pEmac->pTxQueue);
+                        pEmac->pRxQueue, pEmac->pTxQueue);

        return 0;
}
@@ -236,26 +234,6 @@ static void __INIT__ EmacInit(struct At91Emac *pEmac)
        EmacWrite(EMAC_USRIO, 0x3);
}

-static void __INIT__ EmacPhyReset(void)
-{
-        UINT16 hVal;
-        int nTimeOut = 100;
-
-        EmacMdioWrite(MII_REG_BMC, MII_PHY_RESET);
-
-        while (nTimeOut > 0)
-        {
-                hVal = EmacMdioRead(MII_REG_BMC);
-                if (!(hVal & MII_PHY_RESET))
-                        return;
-
-                udelay(10);
-                nTimeOut--;
-        }
-
-        printf("PHY reset failed!\n");
-}
-
static int EmacSetMacAddr(struct NetDevice *pNetDev, const BYTE vbMacAddr[])
{
        EmacWrite(EMAC_SA1B, *(UINT32 *)pNetDev->vbMacAddr);
@@ -268,9 +246,9 @@ static int __INIT__ EmacProbe(void)
{
        UINT16 hSpeed, hMode;
        struct NetDevice *pNetDev;
+        struct PhyDevice *pPhyDev;
        struct At91Emac *pEmac;

-
        pNetDev = GkNetDevNew(sizeof(*pEmac));
        pEmac = pNetDev->pChip;

@@ -278,23 +256,55 @@ static int __INIT__ EmacProbe(void)

        EmacInit(pEmac);

-        EmacPhyReset();
+        pPhyDev = GkPhyDevNew();
+        if (!pPhyDev)
+        {
+                return -EIO;
+        }

-        while (1) // fixme
+        pPhyDev->PhyRead  = EmacMdioRead;
+        pPhyDev->PhyWrite = EmacMdioWrite;
+
+        if (GkPhyDevRegister(pPhyDev) < 0)
        {
-                hMode = EmacMdioRead(MII_REG_BMS);
-                if (hMode & 0x24)
-                        break;
+                return -EIO;
        }

-        if(hMode & 0x20)
-                printf("Auto negotiation ok!\n");
-        if(hMode & 0x4)
-                printf("Link ok!\n");
+        GkPhyResetPhy();

-        hSpeed = EmacMdioRead(MII_REG_STAT);
+        printf("Detecting ethernet speed ... ");

-        printf("hSpeed = 0x%04x\n", hSpeed);
+        hSpeed = GkPhyGetLinkStatus();
+
+        if (hSpeed < 0)
+        {
+                printf("NOT linked, please check the cable!\n");
+        }
+        else
+        {
+                switch(hSpeed)
+                {
+                case ETHER_SPEED_10M_HD:
+                        printf("10M Half Duplex activated!\n");
+                        break;
+
+                case ETHER_SPEED_10M_FD:
+                        printf("10M Full Duplex activated!\n");
+                        break;
+
+                case ETHER_SPEED_100M_HD:
+                        printf("100M Half Duplex activated!\n");
+                        break;
+
+                case ETHER_SPEED_100M_FD:
+                        printf("100M Full Duplex activated!\n");
+                        break;
+
+                default:
+                        printf("Unknown speed (%d)!\n", hSpeed);
+                        break;
+                }
+        }

        pNetDev->SendPacket = EmacSendPacket;
        pNetDev->SetMacAddr = EmacSetMacAddr;
--
1.6.3.3

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文