以太网PHY 开发与解析

目录

1.PHY芯片介绍

1.1 芯片引脚定义和说明

1.2 PHY芯片功能说明

1.3 供电管理

1.4 寄存器说明

1.4.1 控制寄存器

1.4.2 状态寄存器

1.4.3 PHY ID寄存器

1.4.4 自协商广播寄存器

1.4.5 自动协商链接合作伙伴能力寄存器

1.4.6 自动协商扩展寄存器

1.4.7 AVICOM指定的配置寄存器

1.4.8 DAVICOM指定的配置和状态寄存器

1.4.9 10BASE-T配置/状态

1.4.10 掉电控制寄存器

1.4.11 其他寄存器

2.PHY编程说明

2.1 phy_def.h

2.2 phy.h

2.3 phy.c


1.PHY芯片介绍

1.1 芯片引脚定义和说明

PHY供电口

MII RMII GMII 引脚MAP

MII引脚

状态模式显示

外部收发差分接口

LED接口,用于驱动网线口灯

另外LED口复用选择了Media的类型

1.2 PHY芯片功能说明

MII接口说明

TXD(传输数据)是半字节(4位)的数据,由和解子层相对于TXCLK同步驱动。 对于每个TXCLK周期,TXEN被声明,TXD(3:0)被接受由PHY传输。

TXCLK(发送时钟)输出到MAC协调表子层是提供时序的连续时钟TXEN,TXD和TXER传输的参考信号。

TXEN 从MAC协调子层输入的TXEN(发送使能)指示在MII上存在半字节以在物理介质上进行传输

TXER(发送编码错误)转换相对于TXCLK是同步的。 如果在一个或多个时钟周期内断言了TXER,并且断言了TXEN,则PHY将发出一个或多个符号,这些符号不属于正在传输的帧中某处设置的有效数据定界符。

CRS 当发送或接收介质为非空闲时,PHY会声明CRS(载波侦听),而当发送和接收介质处于空闲状态时,会由PHY取消声明CRS(载波侦听)。 图7-2描述了10Base-T和100Base-TX传输期间CRS的行为。

针对RX,同TX,不做过多说明。

1.3 供电管理

信号检测电路始终打开,以监视介质上是否有任何信号。 如果电缆断开连接,DM9161A将自动关闭电源并进入省电模式,无论其操作模式是N向自动协商还是强制模式。 在省电模式下,发送电路将以最小的功耗继续发送快速链接脉冲。 如果从介质中检测到有效信号(可能是N路快速链接脉冲,10Base-T常规链接脉冲或100Base-TX MLT3信号),则设备将唤醒并恢复正常操作模式。

可以通过将Reg.16.4写入零来禁用自动降低功耗模式

通过将Reg.0.11设置为1 或将PWRDWN引脚拉高,可以进入掉电模式,这将禁用所有发送和接收功能以及MDC / MDIO管理接口以外的MII接口功能。

通过在其TX侧设计1.25:1匝数比磁通,并在BGRES和BGRESG引脚上使用8.5KΩ电阻,以及将TX + / TX-拉高电阻从50Ω变为78Ω,可以进一步降低发射功率。 这种配置可以减少约20%的发射功率。

DM9161A支持自动检测电缆连接类型,当设置为自动时,由16位LFSR产生MDI / MDIX控制时序的极性。 开关周期时间从200ms到420ms。 极性控制始终处于切换状态,直到检测到接收到的信号为止。 选择MDI或MDIX之后,可以通过寄存器位(20.7)读取极性状态。

1.4 寄存器说明

寄存器说明部分,可以通过英文解释了解,其中中文部分,部分参考 https://blog.csdn.net/ZCShouCSDN/article/details/80090802,方便理解。

1.4.1 控制寄存器

Reset

通过将位0.15设置为逻辑1来完成复位PHY。 该操作应将状态和控制寄存器设置为其默认状态。 因此,此操作可能会改变PHY的内部状态以及与PHY关联的物理链路的状态。复位过程中Bit15保持为1,复位完成之后该位应该自动清零。 在复位过程完成之前,PHY不需要接受对控制寄存器的写入操作,并且在复位过程完成之前写入0.15以外的控制寄存器位可能不起作用。 复位过程应在0.15位设置的0.5 s内完成。
(1)一般要改变端口的工作模式(如速率、双工、流控或协商信息等)时,在设置完相应位置的寄存器之后,需要通过Reset位复位PHY来使配置生效。
(2)该比特位的默认值为 0。

Loopback

当位0.14被设置为逻辑1时,PHY应置于环回操作模式。 当位0.14置位时,PHY接收电路应与网络介质隔离,并且MII或GMII处的TX_EN断言不应导致网络介质上的数据传输。 当位0.14置位时,PHY应接受来自MII或GMII发送数据路径的数据,并将其返回给MII或GMII接收数据路径,以响应TX_EN的断言。 当位0.14置位时,从断言TX_EN到断言RX_DV的延迟应小于512 BT。 当位0.14置位时,除非设置了位0.7,否则COL信号应始终保持无效,在这种情况下,COL信号的行为应如22.2.4.1.9所述。 清0.14位为零允许正常操作。
  Loopback是一个调试以及故障诊断中常用的功能,Bit14置1之后,PHY和外部MDI的连接在逻辑上将被断开,从MAC经过MII/GMII(也可能是其他的MAC/PHY接口)发送过来的数据将不会被发送到MDI上,而是在PHY内部(一般在PCS)回环到本端口的MII/GMII接收通道上,通过Loopback功能可以检查MII/GMII以及PHY接口部分是否工作正常,对于端口不通的情况可用于故障定位。
(1)需要注意的是,很多时候PHY设置Loopback后端口可能就Link down了,MAC无法向该端口发帧,这时就需要通过设置端口Force Link up才能使用Loopback功能。
(2)该比特位的默认值为 0。

Speed Selection

Bit13和Bit6两位联合实现对端口的速率控制功能。链接速度可以通过自动协商过程或手动速度选择来选择。 通过将位0.12清零来禁用自动协商时,允许手动速度选择。
当禁用自动协商并将位0.6清除为逻辑0时,将位0.13设置为逻辑1将PHY配置为100 Mb / s操作,并将位0.13清除为逻辑0将PHY配置为10 Mb / s操作 。
当禁用自动协商并将位0.6设置为逻辑1时,将位0.13清零为逻辑0会选择1000 Mb / s的操作。 将位0.6和0.13设置为逻辑1的组合保留用于未来的标准化。
当使能自动协商时,可以读取或写入位0.6和0.13,但位0.6和位0.13的状态对链路配置没有影响,位0.6和位0.13不需要反映当它被读取时链接。如果PHY通过比特1.15:9和比特15.15:12报告它不能工作在所有速度时,则比特0.6和0.13的值应该与PHY可以操作的速度相对应。并且任何试图将该位设置为无效的操作均将被忽略。

(1)对Speed Selection的修改设置,往往需要复位端口才能配置生效。因此在设置该位置的时候需要检查自动协商的设置并通过Bit15复位端口。
(2)位0.6和0.13的默认值是根据位1.15:9和15.15:12所指示的PHY可以操作的***最高数据速率***的编码组合。

Auto-Negotiation Enable

自动协商过程应通过将位0.12设置为逻辑1来启用。 如果位0.12设置为逻辑1,则位0.13、0.8和0.6不应对链路配置和除了自动协商协议规定之外的站操作产生影响。 如果将位0.12清零为逻辑0,则无论链路配置和自动协商过程的先前状态如何,位0.13、0.8和0.6都将确定链路配置。如果PHY通过位1.3报告它缺乏执行自动协商的能力,则PHY应在位0.12返回零值。 如果PHY通过位1.3报告它缺乏执行自动协商的能力,则位0.12应该始终写为0,并且任何尝试将1写入位0.12都应该被忽略。必须注意的是,对于1000BASE-T接口,自动协商必须打开。

Power Down

通过将位0.11设置为逻辑1,可以将PHY置于低功耗状态。 清0.11位为零允许正常操作。 PHY在掉电状态下的具体行为是特定实现的。 处于掉电状态时,PHY应响应管理事务。 在转换到掉电状态期间和处于掉电状态期间,PHY不应在MII或GMII上产生寄生信号。
  当位0.11或位0.10被设置为逻辑1时,PHY不需要满足RX_CLK和TX_CLK信号功能要求。 在位0.11和0.10清零后,PHY应在0.5 s内满足22.2.2中定义的RX_CLK和TX_CLK信号功能要求。
(1)Power Down模式一般在软件shut down端口的时候使用,需要注意的是端口从Power Down模式恢复,需要复位端口以保证端口可靠的连接。
(2)该位的默认值为 0。

Isolate

通过将位0.10设置为逻辑1,PHY可能被迫将其数据路径与MII或GMII电隔离。 清零位0.10允许正常操作。 当PHY与MII或GMII隔离时,它不会响应TXD数据包和TX_EN,TX_ER、GTX_CLK的输入。并且它的TX_CLK,RX_CLK,RX_DV,RX_ER,RXD数据包、COL和CRS输出均应为高阻态。 当PHY与MII或GMII隔离时,它将响应管理事务(MDC/MDIO接口的信号)。
(1)IEEE802.3没有对Isolate 时MDI接口的状态进行规范,此时MDI端可能还在正常运行。Isolate在实际应用中并没有用到。
(2)由于目前很多百兆的PHY芯片其MAC接口主流的都是SMII/S3MII,8个端口的接口是相互关联的,一个端口设置Isolate可能会影响其他端口的正常使用,因此在使用中注意不要随意更改bit10的状态。

Restart Auto-Negotiation

如果PHY通过位1.3报告它缺乏执行自动协商的能力,或者如果自动协商被禁用,则PHY应在位0.9返回零值。 如果PHY通过位1.3报告它缺乏执行自动协商的能力,或者如果禁用了自动协商,则应将位0.9始终写为0,并且任何尝试将1写入位0.9应被忽略。Bit9置1将重新启动端口的自动协商进程,当然前提是Auto-Negotiation Enable是使能的。一般在修改端口的自动协商能力信息之后通过Bit9置1重新启动自动协商来使端口按照新的配置建立link。

Duplex Mode

可以通过自动协商过程或手动双面选择来选择双工模式。 通过将位0.12清零来禁用自动协商时,允许手动双面选择。
当禁用自动协商时,将位0.8设置为逻辑1将PHY配置为全双工操作,并将位0.8清零以将逻辑0配置为用于半双工操作的PHY。
当启用自动协商时,可以读取或写入位0.8,但位0.8的状态对链路配置没有影响。如果PHY通过位1.15:9和15.15:12报告它只能在一个双工模式下工作,则位0.8的值应该与PHY可以工作的模式相对应,并且任何尝试改变将该位0.8修改为无效指的操作应被忽略。对Duplex Mode的修改配置也需要复位端口才能生效。

Collision Test

冲突信号(COL)测试开关。在需要对COL信号进行测试时,可以通过Bit7置1,这时PHY将输出一个COL脉冲以供测试。实际测试操作中也可以将端口配置为半双工状态,通过发帧冲突来测试COL信号,因此该配置实用价值不大。
Unidirectional enable

如果PHY通过比特1.7报告它不具备编码和传输来自媒体独立接口的数据的能力,而不管PHY是否确定已建立有效链路,则PHY应在比特0.5中返回零值,并且 任何尝试写一个到位0.5应该被忽略。

1.4.2 状态寄存器

100BASE-T4 ability

当读为逻辑1时,位1.15指示PHY有能力使用100BASE-T4信令规范执行链路发送和接收。 当读为逻辑0时,位1.15表示PHY缺乏使用100BASE-T4信令规范执行链路发送和接收的能力。

100BASE-X full duplex ability

当读为逻辑1时,位1.14指示PHY有能力使用100BASE-X信令规范执行全双工链路传输和接收。 当作为逻辑0读取时,bit1.14表示PHY缺乏使用100BASE-X信令规范执行全双工链路传输和接收的能力。

100BASE-X half duplex ability

当读为逻辑1时,位1.13指示PHY有能力使用100BASE-X信令规范执行半双工链路传输和接收。 当读为逻辑0时,位1.13指示PHY缺乏使用100BASE-X信令规范执行半双工链路传输和接收的能力。
其他同类型的值意义基本与上面几个相同:指示PHY所具有的工作模式能力,不再一一说明。

Unidirectional ability

当读为逻辑1时,位1.7指示PHY具有编码和传输来自媒体独立接口的数据的能力,而不管PHY是否确定已建立有效链路。 当读为逻辑0时,位1.7指示PHY只有在PHY确定已建立有效链路时才能从媒体独立接口传输数据。

MF preamble suppression ability

当读为逻辑1时,位1.6指示PHY能够接受管理帧,而不管它们是否在22.2.4.5.2中描述的前导码模式之前。 当读为逻辑0时,位1.6指示PHY不能接受管理帧,除非它们之前是22.2.4.5.2中描述的前导码模式。

Auto-Negotiation Complete

当读为逻辑1时,位1.5指示自动协商过程已完成,并且由自动协商协议(条款28或条款37)实施的扩展寄存器的内容是有效的。 当读为逻辑0时,位1.5指示自动协商过程尚未完成,并且扩展寄存器的内容由自动协商协议的当前状态定义,或者为手动配置写入。 如果自动协商通过清除位0.12禁用,则PHY应在位1.5返回零值。 如果PHY缺乏执行自动协商的能力,它还应在位1.5返回零值。
在调试以及异常故障处理时,可以通过该位寄存器的状态判断AN是否成功,从而进一步的检查AN相关的设置是否正确,或者芯片的AN功能是否正常等。

Remote Fault

当读为逻辑1时,位1.4表示检测到远程故障状态。 故障类型以及故障检测的标准和方法是PHY特定的。 远程故障位必须使用锁存功能来实现,以便发生远程故障将导致远程故障位置位,并保持置位状态直至被​​清除。 每当通过管理接口读取寄存器1时,远程故障位应清零,并且还应通过PHY复位清零。
  远端错误指示位。Bit4=1代表连接对端(Link Partner)出错,至于出错的具体类型以及错误检测机制在规范中并没有定义,由PHY的制造商自由发挥,一般的厂商都会在其他的寄存器(Register16-31由厂商自行定义)指示比较详细的错误类型。在与端口相关的故障查证中,Remote Fault是一个重要的指示信息,通过互联双方的Remote Fault信息(可能要加上其他的具体错误指示),可以帮助定位故障原因。
Auto-Negotiation ability

当读为逻辑1时,位1.3指示PHY有能力执行自动协商。 当读为逻辑0时,位1.3指示PHY缺乏执行自动协商的能力。
Link Status: 当读为逻辑1时,位1.2指示PHY已经确定已建立有效链路。 当作为逻辑0读取时,位1.2指示该链接无效。 确定链路有效性的标准是PHY特定的。 链路状态位应该使用锁存功能来实现,以便发生链路故障情况将导致链路状态位清零并保持清零,直到通过管理接口读取。 此状态指示旨在支持在30.5.1.1.4,aMediaAvailable中定义的管理属性。
  实际应用中一般都是通过Bit2来判断端口的状态。而且,一般的MAC芯片也是通过轮询PHY的这个寄存器值来判断端口的Link状态的(这个过程可能有不同的名称,比如BCM叫做Link Scan,而Marvell叫做PHY Polling。)如前所述,在AN Enable的情况下,Link Status的信息只有在Auto-Negotiation Complete指示已经完成的情况下才是正确可靠的,否则有可能出错。
Jabber Detect: 当作为逻辑1读取时,位1.1指示已经检测到爆音条件。 此状态指示旨在支持30.5.1.1.6中定义的管理属性,aJabber和30.5.1.3.1 nJabber中定义的MAU通知。 检测Jabber条件的标准是PHY特定的。 Jabber检测位应该使用锁存功能来实现,以便发生Jabber条件将导致Jabber检测位置位,并保持置位状态直至被​​清除。 每次通过管理接口读取寄存器1时,Jabber检测位应清零,并且还应通过PHY复位清零。
  IEEE802.3对Jabber的解释是“A condition wherein a station transmits for a period of time longer than the maximum permissible packet length, usually due to a fault condition”。这一位指示的是Link Partner发送的时间超过了规定的最大长度。值得注意的是,Jabber Detect只有在10BASE-T模式下才有意义,100和1000M模式是没有定义Jabber这一功能的。

1.4.3 PHY ID寄存器

不做过多解释

1.4.4 自协商广播寄存器

该寄存器包含此DM9161A设备的广播(广告)能力,因为它们将在自动协商期间传输到其链接伙伴

1.4.5 自动协商链接合作伙伴能力寄存器

1.4.6 自动协商扩展寄存器

1.4.7 AVICOM指定的配置寄存器

这里主要注意速度的选择

1.4.8 DAVICOM指定的配置和状态寄存器

选择工作模式,全双工 半双工

1.4.9 10BASE-T配置/状态

1.4.10 掉电控制寄存器

1.4.11 其他寄存器

2.PHY编程说明

2.1 phy_def.h

#ifndef  NET_PHY_DEF_MODULE_PRESENT
#define  NET_PHY_DEF_MODULE_PRESENT


#define  NET_PHY_SPD_0                                     0    /* Link speed unknown, or link down                     */
#define  NET_PHY_SPD_10                                   10    /* Link speed = 10mbps                                  */
#define  NET_PHY_SPD_100                                 100    /* Link speed = 100mbps                                 */
#define  NET_PHY_SPD_1000                               1000    /* Link speed = 1000mbps                                */

#define  NET_PHY_DUPLEX_UNKNOWN                            0    /* Duplex uknown or auto-neg incomplete                 */
#define  NET_PHY_DUPLEX_HALF                               1    /* Duplex = Half Duplex                                 */
#define  NET_PHY_DUPLEX_FULL                               2    /* Duplex = Full Duplex                                 */


#define  NET_PHY_ERR_NONE                              12000

#endif         

2.2 phy.h

#ifndef _NET_PHY_H
#define _NET_PHY_H

/*
*****************************************************************************************
*                                               INCLUDES
*****************************************************************************************
*/

/*
*****************************************************************************************
*                                               DEFINES
*****************************************************************************************
*/

#define  DM9161AE_INIT_AUTO_NEG_RETRIES        3

#define  DM9161AE_OUI                   0x00606E
#define  DM9161AE_VNDR_MDL                  0x08

/*
*****************************************************************************************
*                                       DM9161AE REGISTER DEFINES
*****************************************************************************************
*/
                                                                /* ------- 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_ANAR                           0x04                /* Advertisement control reg                */
#define  MII_ANLPAR                         0x05                /* Link partner ability reg                 */
#define  MII_ANER                           0x06                /* Expansion register                       */

                                                                /* ---------- Extended registers ---------- */
#define  DM9161_DSCR                        0x10                /* DAVICOM specified configuration          */
#define  DM9161_DSCSR                       0x11                /* DAVICOM specified configuration & status */
#define  DM9161_PWDOR                       0x13                /* Power down control register              */
#define  DM9161_SCR                         0x14                /* Specified configuration                  */
#define  DM9161_MDINTR                      0x15                /* DAVICOM Specified interrupt register     */
#define  DM9161_RECR                        0x16                /* DAVICOM specified RX error counter reg.  */
#define  DM9161_DISCR                       0x17                /* DAVICOM specified disconnect cntr. reg.  */
#define  DM9161_RLSR                        0x18                /* DAVICOM hardware reset latch state reg.  */

/*
*****************************************************************************************
*                                         DM9161AE REGISTER BITS
*****************************************************************************************
*/
                                                                /* -------- MII_BMCR Register Bits -------- */
#define  BMCR_RESV                         0x007F               /* Unused...                                */
#define  BMCR_CTST                       DEF_BIT_07             /* Collision test                           */
#define  BMCR_FULLDPLX                   DEF_BIT_08             /* Full duplex                              */
#define  BMCR_ANRESTART                  DEF_BIT_09             /* Auto negotiation restart                 */
#define  BMCR_ISOLATE                    DEF_BIT_10             /* Disconnect DP83840 from MII              */
#define  BMCR_PDOWN                      DEF_BIT_11             /* Powerdown the DP83840                    */
#define  BMCR_ANENABLE                   DEF_BIT_12             /* Enable auto negotiation                  */
#define  BMCR_SPEED100                   DEF_BIT_13             /* Select 100Mbps                           */
#define  BMCR_LOOPBACK                   DEF_BIT_14             /* TXD loopback bits                        */
#define  BMCR_RESET                      DEF_BIT_15             /* Reset the DP83840                        */

                                                                /* -------- MII_BMSR Register Bits -------- */
#define  BMSR_ERCAP                      DEF_BIT_00             /* Ext-reg capability                       */
#define  BMSR_JCD                        DEF_BIT_01             /* Jabber detected                          */
#define  BMSR_LSTATUS                    DEF_BIT_02             /* Link status                              */
#define  BMSR_ANEGCAPABLE                DEF_BIT_03             /* Able to do auto-negotiation              */
#define  BMSR_RFAULT                     DEF_BIT_04             /* Remote fault detected                    */
#define  BMSR_ANEGCOMPLETE               DEF_BIT_05             /* Auto-negotiation complete                */
#define  BMSR_RESV                         0x07C0               /* Unused...                                */
#define  BMSR_10HALF                     DEF_BIT_11             /* Can do 10mbps, half-duplex               */
#define  BMSR_10FULL                     DEF_BIT_12             /* Can do 10mbps, full-duplex               */
#define  BMSR_100HALF                    DEF_BIT_13             /* Can do 100mbps, half-duplex              */
#define  BMSR_100FULL                    DEF_BIT_14             /* Can do 100mbps, full-duplex              */
#define  BMSR_100BASE4                   DEF_BIT_15             /* Can do 100mbps, 4k packets               */

                                                                /* -------- MII_ANAR Register Bits -------- */
#define  ANAR_SLCT                         0x001F               /* Selector bits                            */
#define  ANAR_CSMA                       DEF_BIT_04             /* Only selector supported                  */
#define  ANAR_10HALF                     DEF_BIT_05             /* Try for 10mbps half-duplex               */
#define  ANAR_10FULL                     DEF_BIT_06             /* Try for 10mbps full-duplex               */
#define  ANAR_100HALF                    DEF_BIT_07             /* Try for 100mbps half-duplex              */
#define  ANAR_100FULL                    DEF_BIT_08             /* Try for 100mbps full-duplex              */
#define  ANAR_100BASE4                   DEF_BIT_09             /* Try for 100mbps 4k packets               */
#define  ANAR_RESV                         0x1C00               /* Unused...                                */
#define  ANAR_RFAULT                     DEF_BIT_13             /* Say we can detect faults                 */
#define  ANAR_LPACK                      DEF_BIT_14             /* Ack link partners response               */
#define  ANAR_NPAGE                      DEF_BIT_15             /* Next page bit                            */

#define  ANAR_FULL       (ANAR_100FULL | ANAR_10FULL | ANAR_CSMA)
#define  ANAR_ALL        (ANAR_100FULL | ANAR_10FULL | ANAR_100HALF | ANAR_10HALF)

                                                                /* ------- MII_ANLPAR Register Bits ------- */
#define  ANLPAR_SLCT                       0x001F               /* Same as advertise selector               */
#define  ANLPAR_10HALF                   DEF_BIT_05             /* Can do 10mbps half-duplex                */
#define  ANLPAR_10FULL                   DEF_BIT_06             /* Can do 10mbps full-duplex                */
#define  ANLPAR_100HALF                  DEF_BIT_07             /* Can do 100mbps half-duplex               */
#define  ANLPAR_100FULL                  DEF_BIT_08             /* Can do 100mbps full-duplex               */
#define  ANLPAR_100BASE4                 DEF_BIT_09             /* Can do 100mbps 4k packets                */
#define  ANLPAR_RESV                       0x1C00               /* Unused...                                */
#define  ANLPAR_RFAULT                   DEF_BIT_13             /* Link partner faulted                     */
#define  ANLPAR_LPACK                    DEF_BIT_14             /* Link partner acked us                    */
#define  ANLPAR_NPAGE                    DEF_BIT_15             /* Next page bit                            */

#define  ANLPAR_DUPLEX   (ANLPAR_10FULL  | ANLPAR_100FULL)
#define  ANLPAR_100	     (ANLPAR_100FULL | ANLPAR_100HALF | ANLPAR_100BASE4)

                                                                /* -------- MII_ANER Register Bits -------- */
#define  ANER_NWAY                       DEF_BIT_00             /* Can do N-way auto-nego                   */
#define  ANER_LCWP                       DEF_BIT_01             /* Got new RX page code word                */
#define  ANER_ENABLENPAGE                DEF_BIT_02             /* This enables npage words                 */
#define  ANER_NPCAPABLE                  DEF_BIT_03             /* Link partner supports npage              */
#define  ANER_MFAULTS                    DEF_BIT_04             /* Multiple faults detected                 */
#define  ANER_RESV                         0xFFE0               /* Unused...                                */

                                                                /* ------ DM9161_MDINTR Register Bits ----- */
#define  MDINTR_INTR_PEND                DEF_BIT_15             /* Interrupt pending                        */
#define  MDINTER_FDX_MSK                 DEF_BIT_11             /* Full-duplex interrupt mask               */
#define  MDINTER_SPD_MSK                 DEF_BIT_10             /* Speed       interrupt mask               */
#define  MDINTER_LINK_MSK                DEF_BIT_09             /* Link        interrupt mask               */
#define  MDINTER_INTR_MSK                DEF_BIT_08             /* Master      interrupt mask               */
#define  MDINTER_FDX_CHG                 DEF_BIT_04             /* Full-duplex change                       */
#define  MDINTER_SPD_CHG                 DEF_BIT_03             /* Speed       change                       */
#define  MDINTER_LINK_CHG                DEF_BIT_02             /* Link        change                       */
#define  MDINTER_INTR_STAT               DEF_BIT_00             /* Interrupt status                         */

/*
*****************************************************************************************
*                                   PHY ERROR CODES 12,000 -> 13,000
*****************************************************************************************
*/

#define  NET_PHY_ERR_REGRD_TIMEOUT         12010
#define  NET_PHY_ERR_REGWR_TIMEOUT         12020
#define  NET_PHY_ERR_AUTONEG_TIMEOUT       12030


/*
*****************************************************************************************
*                                         FUNCTION PROTOTYPES
*****************************************************************************************
*/

void         NetNIC_PhyInit          (NET_ERR      *perr);

void         NetNIC_PhyAutoNeg       (void);                    /* Do link auto-negotiation                             */

#if (EMAC_CFG_PHY_INT == DEF_ON)
void         NetNIC_PhyISR_Handler   (void);                    /* Decode & handle PHY ISRs.                            */
#endif
                                                                /* -----------------PHY STATUS FNCTS ------------------ */
CPU_BOOLEAN  NetNIC_PhyAutoNegState  (void);                    /* Get PHY auto-negotiation state                       */

CPU_BOOLEAN  NetNIC_PhyLinkState     (void);                    /* Get PHY link state                                   */

CPU_INT32U   NetNIC_PhyLinkSpeed     (void);                    /* Get PHY link speed                                   */

CPU_INT32U   NetNIC_PhyLinkDuplex    (void);                    /* Get PHY duplex mode                                  */


/*
*****************************************************************************************
*                                         FUNCTION PROTOTYPES
*                                    DEFINED IN PRODUCT'S  net_bsp.c
*****************************************************************************************
*/

void         NetNIC_LinkUp           (void);                    /* Message from NIC that the ethernet link is up.       */
                                                                /* Called in interruption context most of the time.     */

void         NetNIC_LinkDown         (void);                    /* Message from NIC that the ethernet link is down.     */
                                                                /* Called in interruption context most of the time.     */

void         DM9161AE_DlyAutoNegAck  (void);                    /* Implement 1.5 s dly.                                 */
                                                                /*   MUST use OS dly to preempt.                        */

/*
*****************************************************************************************
*                                         FUNCTION PROTOTYPES
*                                    DEFINED IN PRODUCT'S  net_isr.c
*****************************************************************************************
*/

#if (NET_NIC_CFG_INT_CTRL_EN == DEF_ENABLED)
#if (EMAC_CFG_PHY_INT == DEF_ON)
void         NetNIC_PhyIntInit       (void);                    /* Init int ctrl'r.                                     */

void         NetNIC_PhyIntClr        (void);                    /* Clr  int ctrl'r src(s).                              */

void         NetNIC_PhyIntEnter      (void);                    /* Enter ISR              [see Note #2].                */
#endif
#endif


/*
*****************************************************************************************
*                                        CONFIGURATION ERRORS
*****************************************************************************************
*/

#ifndef  NET_NIC_CFG_INT_CTRL_EN
#error  "NET_NIC_CFG_INT_CTRL_EN           not #define'd in 'net_cfg.h'"
#error  "                            [MUST be  DEF_DISABLED]           "
#error  "                            [     ||  DEF_ENABLED ]           "
#elif  ((NET_NIC_CFG_INT_CTRL_EN != DEF_DISABLED) && \
        (NET_NIC_CFG_INT_CTRL_EN != DEF_ENABLED ))
#error  "NET_NIC_CFG_INT_CTRL_EN     illegally #define'd in 'net_cfg.h'"
#error  "                            [MUST be  DEF_DISABLED]           "
#error  "                            [     ||  DEF_ENABLED ]           "
#endif

#ifndef   EMAC_CFG_PHY_ADDR
#error   "EMAC_CFG_PHY_ADDR           not #define'd in 'net_bsp.h'"
#endif

#ifndef   EMAC_CFG_RMII
#error   "EMAC_CFG_RMII               not #define'd in 'net_bsp.h'"
#error   "                            [MUST be  DEF_YES   ]"
#error   "                            [     ||  DEF_NO    ]"
#elif   ((EMAC_CFG_RMII != DEF_YES) && \
         (EMAC_CFG_RMII != DEF_NO ))
#error   "EMAC_CFG_RMII               illegally #define'd in 'net_bsp.h'"
#error   "                            [MUST be  DEF_YES]"
#error   "                            [     ||  DEF_NO ]"
#endif


#endif

2.3 phy.c

/*
*********************************************************************************************************
*
*                                        NETWORK PHYSICAL LAYER
*
*                                               DM9161AE
*
* Filename      : phy.c
* Version       : V1.0
*********************************************************************************************************
* Note(s)       : (1) Supports DM9161AE '3.3V Dual-Speed Fast Ethernet Transceiver' as described in
*
*                         
*                         (a) DM9161AE  
*
*                 (2) The MII interface port is assumed to be part of the host EMAC; consequently,
*                     reads from and writes to the PHY are made through the EMAC.  The functions
*                     NetNIC_PhyRegRd() and NetNIC_PhyRegWr(), which are used to access the PHY, should
*                     be provided in the EMAC driver.
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                            INCLUDE FILES
*********************************************************************************************************
*/

/*#include  <net.h>*/
#include  <phy.h>
#include  <phy_def.h>

/*
*********************************************************************************************************
*********************************************************************************************************
*                                            GLOBAL FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                         NetNIC_PhyInit()
*
* Description : Initialize phyter (ethernet link controller)
*               This instance configures the Davicom DM9161AE PHY
*
* Argument(s) : none.
*
* Return(s)   : 1 for OK, 0 for error
*
* Caller(s)   : EMAC_Init()
*
* Note(s)     : Assumes the MDI port as already been enabled for the PHY.
*********************************************************************************************************
*/

void  NetNIC_PhyInit (NET_ERR *perr)
{
    volatile  CPU_INT16U  reg_val;


#if (!defined(EMAC_CFG_RMII)) || (EMAC_CFG_RMII <= 0)
    reg_val     =  NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMCR, perr);  /* Read the Basic Mode Control Register (twice)             */
    reg_val     =  NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMCR, perr);  /* Read the Basic Mode Control Register (twice)             */

    if (*perr  != NET_PHY_ERR_NONE) {
        return;
    }

    reg_val    &= ~BMCR_ISOLATE;                                        /* Mask off 'Disconnect from MII bit (BMCR_ISOLATE)         */
    NetNIC_PhyRegWr(EMAC_CFG_PHY_ADDR, MII_BMCR, reg_val, perr);        /* Put the PHY into MII mode                                */

    if (*perr  != NET_PHY_ERR_NONE) {
        return;
    }
#endif

    NetNIC_PhyAutoNeg();                                                /* Perform auto-negotiation                                 */

    NetNIC_ConnStatus = NetNIC_PhyLinkState();                          /* Set NetNIC_ConnStatus according to link state            */

    if (NetNIC_ConnStatus == DEF_ON) {
        NetNIC_LinkUp();
    } else {
        NetNIC_LinkDown();
    }

#if (EMAC_CFG_PHY_INT == DEF_ON)
    NetNIC_PhyIntInit();

    reg_val     = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, DM9161_MDINTR, perr); /* Clear interrupts                                         */
    reg_val    |= MDINTER_FDX_MSK | MDINTER_SPD_MSK | MDINTER_LINK_MSK | MDINTER_INTR_MSK;
    reg_val    &= ~(MDINTER_SPD_MSK | MDINTER_LINK_MSK | MDINTER_INTR_MSK);

    NetNIC_PhyRegWr(EMAC_CFG_PHY_ADDR, DM9161_MDINTR, reg_val, perr);   /* Enable link change interrupt                             */
#endif
}


/*
*********************************************************************************************************
*                                        NetNIC_PhyAutoNeg()
*
* Description : Do link auto-negotiation
*
* Argument(s) : None.
*
* Return(s)   : None.
*
* Caller(s)   : NetNIC_PhyInit().
*
* Note(s)     : none.
*********************************************************************************************************
*/

void  NetNIC_PhyAutoNeg (void)
{
    CPU_INT16U   i;
    CPU_INT16U   reg_val;
    CPU_BOOLEAN  link;
    NET_ERR      err;


    i               = DM9161AE_INIT_AUTO_NEG_RETRIES;                   /* Set the # of retries before declaring a timeout  */
    link            = NetNIC_PhyLinkState();                            /* Get the current link state. 1=linked, 0=no link  */

    if (link == DEF_OFF) {
#if (!defined(EMAC_CFG_RMII)) || (EMAC_CFG_RMII <= 0)
        reg_val     = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMCR, &err);   /* Get current control register value           */
        reg_val    |= DEF_BIT_09;                                       /* Set the auto-negotiation start bit               */

        NetNIC_PhyRegWr(AT91C_PHY_ADDR, MII_BMCR, reg_val, &err);       /* Initiate auto-negotiation                        */
#endif

        do {                                                            /* Do while auto-neg incomplete, or retries expired */
            DM9161AE_DlyAutoNegAck();                                   /* Wait for a while auto-neg to proceed (net_bsp.c) */
            reg_val = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err);   /* Read the Basic Mode Status Register          */
            reg_val = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err);   /* Read the Basic Mode Status Register          */
            i--;
        } while (((reg_val & BMSR_LSTATUS) == 0) && (i > 0));           /* While link not established and retries remain    */
    }
}


/*
*********************************************************************************************************
*                                    NetNIC_PhyAutoNegState()
*
* Description : Returns state of auto-negotiation
*               This instance probe the Davicom DM9161AE '3.3V Dual-Speed Fast Ethernet Transceiver'
*
* Argument(s) : none.
*
* Return(s)   : State of auto-negociation (DEF_OFF = not completed, DEF_ON = completed).
*
* Caller(s)   : NetNIC_PhyInit().
*
* Note(s)     : If any error is encountered while reading the PHY, this function
*               will return Auto Negotiation State = DEF_OFF (incomplete).
*********************************************************************************************************
*/

CPU_BOOLEAN  NetNIC_PhyAutoNegState (void)
{
    CPU_INT32U  reg_val;
    NET_ERR     err;


    reg_val     = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err);
    reg_val     = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err);

    if (err   != NET_PHY_ERR_NONE) {
        reg_val = 0;
    }

    if ((reg_val & BMSR_ANEGCOMPLETE) == BMSR_ANEGCOMPLETE) {   /* DM9161AE register 0x01: Basic Status Register #1      */
        return (DEF_ON);                                        /* BIT 5 Signal the result of the auto negotiation       */
    } else {                                                    /* 1 = complete, 0 = incomplete                          */
        return (DEF_OFF);
    }
}


/*
*********************************************************************************************************
*                                     NetNIC_PhyLinkState()
*
* Description : Returns state of ethernet link
*               This instance probe the Davicom DM9161AE '3.3V Dual-Speed Fast Ethernet Transceiver'
*
* Argument(s) : none.
*
* Return(s)   : State of ethernet link (DEF_OFF = link down, DEF_ON = link up).
*
* Caller(s)   : NetNIC_PhyISR_Handler().
*
* Note(s)     : If any error is encountered while reading the PHY, this function
*               will return link state = DEF_OFF.
*********************************************************************************************************
*/

CPU_BOOLEAN  NetNIC_PhyLinkState (void)
{
    NET_ERR     err;
    CPU_INT16U  reg_val;

                                                                /* DM9161AE register 0x01: Basic Status Register #1      */
                                                                /* BIT 2 , Link Status, 1 = linked, 0 = not linked.      */
    reg_val      = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err);
    reg_val      = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err);

    if (err   != NET_PHY_ERR_NONE) {
        reg_val  = 0;
    }

    reg_val     &= BMSR_LSTATUS;

    if (reg_val == BMSR_LSTATUS) {
        return (DEF_ON);
    } else {
        return (DEF_OFF);
    }
}


/*
*********************************************************************************************************
*                                     NetPHY_GetLinkSpeed()
*
* Description : Returns the speed of the current Ethernet link
*               This probes the Davicom DM9161AE '3.3V Dual-Speed Fast Ethernet Transceiver'
*
* Argument(s) : none.
*
* Return(s)   : 0 = No Link, 10 = 10mbps, 100 = 100mbps
*
* Caller(s)   : EMAC_Init()
*
* Note(s)     : none.
*********************************************************************************************************
*/

CPU_INT32U  NetNIC_PhyLinkSpeed (void)
{
	CPU_INT32U  bmsr;
    CPU_INT32U  bmcr;
    CPU_INT32U  lpa;
    NET_ERR     err;


    bmsr    = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err);       /* Get Link Status from PHY status reg. Requires 2 reads    */
	bmsr    = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err);       /* Get Link Status from PHY status reg. Requires 2 reads    */

    if ((bmsr & BMSR_LSTATUS) == 0) {
        return (NET_PHY_SPD_0);                                         /* No link                                                  */
    }

	bmcr    = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMCR, &err);       /* Read the PHY Control Register                            */
	
    if ((bmcr & BMCR_ANENABLE) == BMCR_ANENABLE) {		                /* If AutoNegotiation is enabled                            */
        if ((bmsr & BMSR_ANEGCOMPLETE) == 0) {                          /* If AutoNegotiation is not complete                       */
			return (NET_PHY_SPD_0);       					            /* AutoNegotitation in progress                             */
        }

		lpa = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_ANLPAR, &err);     /* Read the Link Partner Ability Register                   */

        if (((lpa & ANLPAR_100FULL) == ANLPAR_100FULL) || ((lpa & ANLPAR_100HALF) == ANLPAR_100HALF)) {
			return (NET_PHY_SPD_100);
        } else {
			return (NET_PHY_SPD_10);
        }
	} else {                                                            /* Auto-negotiation not enabled, get speed from BMCR        */
        if ((bmcr & BMCR_SPEED100) == BMCR_SPEED100) {
            return (NET_PHY_SPD_100);
        } else {
            return (NET_PHY_SPD_10);
        }
	}
}


/*
*********************************************************************************************************
*                                     NetPHY_GetDuplex()
*
* Description : Returns the duplex mode of the current Ethernet link
*               This probes the Davicom DM9161AE '3.3V Dual-Speed Fast Ethernet Transceiver'
*
* Argument(s) : none.
*
* Return(s)   : 0 = Unknown (Auto-Neg in progress), 1 = Half Duplex, 2 = Full Duplex
*
* Caller(s)   : EMAC_Init()
*
* Note(s)     : none.
*********************************************************************************************************
*/

CPU_INT32U  NetNIC_PhyLinkDuplex (void)
{
    CPU_INT32U  bmcr;
    CPU_INT32U  bmsr;
    CPU_INT32U  lpa;
    NET_ERR     err;


    bmsr    = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err);       /* Get Link Status from PHY status reg. Requires 2 reads    */
	bmsr    = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err);       /* Get Link Status from PHY status reg. Requires 2 reads    */


    if ((bmsr & BMSR_LSTATUS) == 0) {
        return (NET_PHY_DUPLEX_UNKNOWN);                                /* No link, return 'Duplex Uknown'                          */
    }

	bmcr    = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMCR, &err);       /* Read the PHY Control Register                            */
	
    if ((bmcr & BMCR_ANENABLE) == BMCR_ANENABLE) {		                /* If AutoNegotiation is enabled                            */
        if ((bmsr & BMSR_ANEGCOMPLETE) == 0) {                          /* If AutoNegotiation is not complete                       */
			return (NET_PHY_DUPLEX_UNKNOWN);      			            /* AutoNegotitation in progress                             */
        }

		lpa = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_ANLPAR, &err);     /* Read the Link Partner Ability Register                   */

        if (((lpa & ANLPAR_100FULL) == ANLPAR_100FULL) || ((lpa & ANLPAR_10FULL) == ANLPAR_10FULL)) {
			return (NET_PHY_DUPLEX_FULL);
        } else {
            return (NET_PHY_DUPLEX_HALF);
        }
	} else {                                                            /* Auto-negotiation not enabled, get duplex from BMCR       */
        if ((bmcr & BMCR_FULLDPLX) == BMCR_FULLDPLX) {
            return (NET_PHY_DUPLEX_FULL);
        } else {
            return (NET_PHY_DUPLEX_HALF);
        }
	}
}

/*
*********************************************************************************************************
*********************************************************************************************************
*                                    GLOBAL FUNCTIONS: PHY INTERRUPTS
*********************************************************************************************************
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                        NetNIC_ISR_Handler()
*
* Description : (1) Update NetNIC_ConnStatus according to link state
*
* Argument(s) : none.
*
* Return(s)   : none.
*********************************************************************************************************
*/

#if (EMAC_CFG_PHY_INT == DEF_ON)
void  NetNIC_PhyISR_Handler (void)
{
    volatile  CPU_INT16U  reg_val;
              NET_ERR     err;


    NetNIC_PhyIntEnter();

    NetNIC_ConnStatus = NetNIC_PhyLinkState();                          /* Set NetNIC_ConnStatus according to link state            */

    if (NetNIC_ConnStatus == DEF_ON) {
        NetNIC_LinkUp();
    } else {
        NetNIC_LinkDown();
    }

    reg_val     = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, DM9161_MDINTR, &err);  /* Clear interrupts                                     */

    NetNIC_PhyIntClr();
}
#endif

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值