linux 命令 读phy_PHY LINUX (转载整理)

每每分析网络问题的时候,总要梳理层次关系,本想自己写一个关于PHY的文档,找到网上有人写的一篇比较好,所以转载下来,仅供初学者参考。

以太网 MAC(链路层)+PHY(物理层/RTL8201F,88E1111);集成型DM9000,RTL8139CP 由于网络数据传输量较大,不论是分开型还是集成型,通常会在MAC和PHY之间引入DMA,MAC和PHY之所以有分开,是因为MAC属于数字电路部分,而PHY则属于模拟部分,负责将接收到的数据传输给MAC层,MAC层将接收到的数据传输给上层协议,如IP层,IGMP层。PHY层也负责将由MAC层发送过来的数据,转换成差分信号,经过后边的变压器后送入RJ45接头的线缆中。 对应的数据格式为:  前导符+开始位+目的MAC地址+源MAC地址+类型长度+数据+padding(optional)+32bit CRC PHY层负责的任务还是比较多的,比如10M/100M速率的选择;全双工还是半双工;载波侦听和冲突检测,这些工作对应到具体芯片就是内部寄存器的一些设置。

PHY功能模块和MCU的链接采用MII/RMII方式链接,这样就可以使用MCU设置相关的寄存器。MII是16根线,RMII将收发数据线各减到两根,这其中涉及串并转换,即将MCU的类的并行总线最终转换成RJ45线上传输的单bit编码。100M是曼彻斯特编码,10M是NRZ编码,这类编码主要考虑负载均衡和纠错。也带来了额外的网络开销。

PHY层的初始化,主要是两个部分,一个是mdio总线的初始化,一个是PHY驱动初始化,对于通常可以使用缺省内核的PHY驱动程序,但是如果PHY芯片的内部寄存器和802.3定义的并不一样,这就需要自己实现该驱动,像8201这样的百兆速率PHY芯片就可以使用缺省的PHY驱动,但是对于一些功能强一点的集成多个PHY的switch而言,通常驱动可能需要自己实现,switch常用来更高速率传输的或者VLAN这种网络。

PHY层从driver/net/phy/phy_device.c文件开始。

subsys_initcall(phy_init);

module_exit(phy_exit);

又见subsys_initcall,该调用表明其在系统初始化时完成,

static int __init phy_init(void)

{

int rc;

rc = mdio_bus_init();

if (rc)

return rc;

rc = phy_driver_register(&genphy_driver);

if (rc)

mdio_bus_exit();

return rc;

}。

其驱动涉及如下几个重要部分:

总线- sturct mii_bus     (mii stand for media independent interface)

设备- struct phy_device

驱动- struct phy_driver

mdiobus_register  ------probe函数会调用,创建该总线,总线然后扫描其上面的设备,如果发现有,则创建该设备。

_|_

drovers\net\phy\mdio_bus.c                                             drivers\net\phy\phy_device.c

struct phy_device *mdiobus_scan(struct mii_bus * bus, int addr) ----get_phy_device--phy_device_create

|

|    drivers\base\Core.c

----device_register---device_add(kobject_add构建设备树)

驱动会调用phy_driver_register去注册驱动,这是phy驱动也会形成一个链表,这里之所以不是树而上面的设备成为树,是因为

mii可能挂载在pci总线上,当然pci上可能有其它设备,这些设备和phy设备不在一个链表上,而是通过kobject链接管理的,对应的还有 一个kset,kset其实是kobject的一个集合,

相同的kobject对象会指向同一个kset,如USB鼠标、键盘就属于同一个kset集。 上述的总线,设备,以及驱动(假设驱动已经编写好了,驱动中多半会有一个标示符,暂且将其看作为id,

这个id指明了其支持的设备)内; 假设不支持热插拔,那么启动时,系统就会扫描设备,并串联进设备树,当驱动注册(register时),驱动就会去设备树中,找id号和其对 应的相等的,

如果找到,那么这两个就捆绑在一起了,通常为XXX_attcah函数,应用层对该设备的操作就变为调用驱动中对应的read、write、 ioctl等。如果支持热插拔,比上面的就复杂了,因为驱动可能先于设备(总线)存在,

所以当有新硬件连接时,内核会调用XXX_probe函数去 探测,并注册设备,然后去驱动链表中查找驱动,如果找到,则attach。对其操作方法与上述一样。

剩下一个问题就是驱动的编写了。

#define PHY_BASIC_FEATURES (SUPPORTED_10baseT_Half | \ SUPPORTED_10baseT_Full | \ SUPPORTED_100baseT_Half | \ SUPPORTED_100baseT_Full | \ SUPPORTED_Autoneg | \ SUPPORTED_TP | \ SUPPORTED_MII)

static int 8201f_config_init(struct phy_device *phydev)

{

int val; u32 features; /* For now, I'll claim that the generic driver supports * all possible port types */

features =PHY_BASIC_FEATURES ; /* Do we support autonegotiation? */ val = phy_read(phydev, MII_BMSR);

if (val < 0) return val;

if (val & BMSR_ANEGCAPABLE) features |= SUPPORTED_Autoneg;

if (val & BMSR_100FULL) features |= SUPPORTED_100baseT_Full;

if (val & BMSR_100HALF) features |= SUPPORTED_100baseT_Half;

if (val & BMSR_10FULL) features |= SUPPORTED_10baseT_Full;

if (val & BMSR_10HALF) features |= SUPPORTED_10baseT_Half;

if (val & BMSR_ESTATEN) { val = phy_read(phydev, MII_ESTATUS);

if (val < 0) return val; if (val & ESTATUS_1000_TFULL) features |= SUPPORTED_1000baseT_Full;

if (val & ESTATUS_1000_THALF) features |= SUPPORTED_1000baseT_Half;

}

phydev->supported = features;

phydev->advertising = features;

return 0;

}

int 8201f_config_aneg(struct phy_device *phydev)

{

int result;

if (AUTONEG_ENABLE != phydev->autoneg)

return genphy_setup_forced(phydev);

result = genphy_config_advert(phydev);

if (result < 0) /* error */ return result;

if (result == 0) { /* Advertisment hasn't changed, but maybe aneg was never on to * begin with?  Or maybe phy was isolated? */

int ctl = phy_read(phydev, MII_BMCR);

if (ctl < 0) return ctl;

if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))

result = 1; /* do restart aneg */

}

/* Only restart aneg if we are advertising something different * than we were before. */

if (result > 0)

result = genphy_restart_aneg(phydev);

return result;

}

static struct phy_driver 8201f_driver = {

.phy_id         = 0x001cc810,

.name           = "Realtack 8201f",

.phy_id_mask    = 0x0ffffff0,

.features       = PHY_BASIC_FEATURES,

.config_init    = 8201f_config_init,

.config_aneg    = 8201f_config_aneg,

.read_status    = genphy_read_status,

.driver         = { .owner = THIS_MODULE,},

};

static int __init 8201f_init(void) {

int ret;

ret = phy_driver_register(&8201f_driver);

if (ret)            phy_driver_unregister(&8201f_driver);

return ret; } static void __exit 8201f_exit(void) {

phy_driver_unregister(&8201f_driver);

}

module_init(8201f_init); module_exit(8201f_exit);

PHY自协商基本原理

自动协商模式是端口根据另一端设备的连接速度和双工模式,自动把它的速度调节到最高的公共水平,即线路两端能具有的最快速度和双工模式。

自协商功能允许一个网络设备能够将自己所支持的工作模式信息传达给网络上的对端,并接受对方可能传递过来的相应信息,从而解决双工和10M/100M速率自协商问题。自协商功能完全由物理层芯片设计实现,因此并不使用专用数据包或带来任何高层协议开销。

自协商功能的基本机制是:每个网络设备在上电、管理命令发出、或是用户干预时发出FLP(快速连接脉冲),协商信息封装在这些FLP序列中。FLT中包含有时钟/数字序列,将这些数据从中提取出来就可以得到对端设备支持的工作模式,以及一些用于协商握手机制的其他信息。当一个设备不能对FLP作出有效反应,而仅返回一个NLP(普通连接脉冲)时,它被作为一个10BASE-T兼容设备。 快速链路脉冲FLP和普通链路脉冲NLP都仅使用于非屏蔽双绞线上,而不能应用在光纤媒体。

自动协商的内容主要包括双工模式、运行速率、流控等内容,一旦协商通过,链路两端的设备就锁定在这样一种运行模式下。1000M以太网也支持自协商,在此从略。

电口和光口自协商主要区别是在OSI 中它们所处的位置不同。对于电口来说,协商发生在链路信号传输之前;对于光口来说, 自协商机制与PCS在同一层, 这意味着光口的协商必须先建立链路同步以后才可以进行协商。

协商过程

如果两端都支持自协商,则都会接收到对方的FLP,并且把FLP中的信息解码出来。得到对方的连接能力。并且把对端的自协商能力值记录在自协商对端能力寄存器中(Auto-Negotiation Link Partner Ability Register , PHY标准寄存器地址5 )。同时把状态寄存器(PHY标准寄存器地址1)的自协商完成bit(bit5)置成1。在自协商未完成的情况下,这个bit一直为0。

然后各自根据自己和对方的最大连接能力,选择最好的连接方式Link。比如,如果双方都即支持10M也支持100M,则速率按照100M连接;双方都即支持全双工也支持半双工,则按照全双工连接。

一定连接建立后,FLP就停止发送。直到链路中断,或者得到自协商Restart命令时,才会再次发送FLP。

为了保证在对端不能支持自协商的情况下也能连接,引入了被称为并行检测(Parallel Detection)的机制。在一端打开自协商,另一端关闭自协商的情况下,连接的建立就依靠并行检测功能实现。

并行检测机制是这样的:在具有自协商能力的设备端口上,如果接收不到FLP,则检测是否有10M链路的特征信号或100M链路的特征信号。

如果设备是10M设备,不支持自协商,则在链路上发送普通连接脉冲(Normal Link Pulse)简称NLP。NLP仅仅表示设备在位,不包含其它的额外信息。NLP脉冲如图:

如果是100M设备,不支持自协商,则在没有数据的情况下,在链路上一直发送4B/5B编码的Idle符号。

并行检测机制如果检测到NLP,则知道对方支持10M速率;如果检测到4B/5B编码的Idle符号,则知道对方支持100M速率。但是对方是否支持全双工、是否支持流控帧这些信息是无法得到的。因此在这种情况下,认为对方只支持半双工,不支持全双工,且不支持流控帧。

基于以上原理,在对端不打开自协商时,打开自协商的一方只能协商成半双工模式。

802.3协议规定,通过并行检测建立连接后,PHY的状态寄存器(PHY标准寄存器地址1)的自协商完成bit(bit5)依然要置位成1,尽管链路上并非使用了真正的自协商操作。同时规定在自协商完成bit为1的情况下,本地自协商能力寄存器(PHY标准寄存器地址4)和对端自协商能力寄存器(PHY标准寄存器地址5)是有意义的。所以,要把寄存器5中的数据更新。如果建立的连接为10M,则寄存器5的10M能力bit(bit5)置1,其它bit置0,表示对端只能支持10M半双工;如果建立的连接为100M,则寄存器5的100M能力bit(bit7)置1,其它bit置0,表示对端只能支持100M半双工。

千兆光口自协商

千兆光口可以工作在强制和自协商两种模式。802.3规范中千兆光口只支持1000M速率,支持全双工(Full)和半双工(Half)两种双工模式。

自协商和强制最根本的区别就是两者再建立物理链路时发送的码流不同,自协商模式发送的是/C/码,也就是配置(Configuration)码流,而强制模式发送的是/I/码,也就是idle码流。

千兆光口自协商过程:

1.两端都设置为自协商模式

双方互相发送/C/码流,如果连续接收到3个相同的/C/码且接收到的码流和本端工作方式相匹配,则返回给对方一个带有Ack应答的/C/码,对端接收到Ack信息后,认为两者可以互通,设置端口为UP状态

2.一端设置为自协商,一端设置为强制

自协商端发送/C/码流,强制端发送/I/码流,强制端无法给对端提供本端的协商信息,也无法给对端返回Ack应答,故自协商端DOWN。但是强制端本身可以识别/C/码,认为对端是与自己相匹配的端口,所以直接设置本端端口为UP状态

3.两端均设置为强制模式

双方互相发送/I/码流,一端接收到/I/码流后,认为对端是与自己相匹配的端口,直接设置本端端口为UP状态

快速链接脉冲(FLPs)和普通链接脉冲(NLPs)

自动协商的执行是通过FLPs来实现的。NLPs是周期为16ms左右的脉冲,脉冲宽度为100ns(10base-T)、10ns(100base-TX)。FLPs类似于NLPs,它是连续的17~33个的脉冲用来传输16bit的连接码(link code word)以进行自动协商,码宽为125us,在125us码宽中间有脉冲为1,无脉冲为0。link code word并不是以太网通信结点的有效数据,只被PHY接口模块识别。

自协商基本页信息

在链路初始化的时候,自协商协议向对端发送16Bit的报文,也就是所谓的脉冲信号,然后从对端接收类似的报文,这个16Bit的报文就是我们所说的基本页,不同的设备,在针对基本页做字位信息的时候,那就能识别它是属于哪一个情况.。

bit0~4:指示自协商数据帧,对于802.3标准,设置为'10000';

bit5~12:指示结点(端口)信息性能域;

bit5~9:定义端口可连接类型,按照优先级从高到低如下(SETBIT有效):

bit8:100base-TX全双工;bit9:100base-T4;bit7:100base-TX半双工;bit6:10base-T全双工;bit5:10base-T半双工;

bit10:指示流量控制信息:0:流控无效;1:流控有效,决定了端口后续通信是否有PAUSE帧;

bit11:支持全双工连接时的非对称暂停机制;

bit12:扩展下一页信息页,仅用于千兆端口;

bit13:远程故障指示;

bit14:握手信号Ack,当收到三个连续的相同FLP后,此位置1;

bit15:指示是否有下一页基本页信息。下一页信息用来传输在自协商过程中已连接节点的额外信息。

PAUSE帧(流量控制)

为什么要有流量控制呢?现在的网络有10M和100M的以太,那么当10m以太和100m以太共存的时候,那就有可能会产生这种线路速率不匹配的情况,这个时候,当通过交换机一个端口的流量过大,超出了它的处理能力时,就会发生端口拥塞,拥塞的时候那么丢包、重传、时延等都会随之而来,流量控制的作用时防止在出现拥塞的情况下丢帧。

这里的流量控制采用的是最常用的一种方式—PAUSE帧。

在半双工方式下,流量控制是通过后退压力(backpressure)技术实现的,模拟产生碰撞,使得信息源降低发送速度。

在全双工方式下流控一般遵循IEEE 802.3X标准。采用一64字节的PAUSE的帧来控制,使用一个保留的组播地址:01-80-C2-00-00-01发送给正在发送的站,发送站接到该帧后,就会暂停或停止发送。这个地址的数据不会被网桥和交换机所转发,所以PAUSE帧不会产生附加信息量。

PAUSE功能应用场合:

->一对终端(简单的两点网络)

->一个交换机和一个终端

->交换机和交换机之间的链路

PAUSE功能的增加主要是为了防止瞬时流量的过载导致的缓冲区溢出而造成以太网帧的丢弃。

PAUSE功能不能解决下列问题:

->稳定状态的网络拥塞

->端到端流量控制

->比简单“停—启”更复杂的机制

以太网端口电口工作模式简单介绍

1.以太网口的两端工作模式(10M半双工、10M全双工、100M半双工、100M全双工、自协商)必须设置一致。

2.如果一端是固定模式(无论是10M、100M),另外一端是自协商模式,即便能够协商成功,自协商的那一端也将只能工作在半双工模式。

3.如果一端工作在全双工模式,另外一端工作在半双工模式(包括自协商出来的半双工,也一样处理),Ping是没有问题的,流量小的时候也没有任何问题,流量达到约15%以上时,就会出现冲突、错包,最终影响了工作性能!

4.对于两端工作模式都是自协商,最后协商成的结果是“两端都支持的工作模式中优先级最高的那一类”。

5. 如果A端自协商,B端设置为100M全双工,A协商为100M半双工后,再强制将B改为10M全双工,A端也会马上向下协商到10M半双工;如果A端自协商,B端设置为10M全双工,A协商为10M半双工后,再强制将B改为100M全双工,会出现协商不成功,连接不上!这个时候,如果插拔一下网线,又会重新协商在100M半双工。

建议

以太网口的两端工作模式必须设置一致。 否则,就会出现流量一大速度变慢的问题。大多数设备以太网口的默认的出厂设置是自协商。如果两端都是自协商,协商成功了,但网络不通,此时请检查网线是否支持100M。如果两端都是自协商,协商成功并且运行在全双工,在没有Link Down的前提下,将其中一端“立刻”设置为固定的“10M/100M全双工”,两端仍然能够工作在全双工。但是,万一将来插拔网线或者其他原因出现重新Link,就会重新协商为“一端全双工&一端半双工”的不稳定连接。因此,这种情况一定要避免!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/470220.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Laravel框架开发规范-修订版

1.PHP编码规范 1.1 标签 PHP 程序可以使用<?php ?>或<? ?>来界定PHP代码 在HTML 页面中嵌入纯变量时&#xff0c;使用<? ?>这样的形式 纯PHP类文件&#xff0c;文件开始标签使用<?php&#xff0c;闭合标签?>必须省略 1.2 编码 PHP文件必须使用…

vue显示两位小数的方法_Vue toFixed保留两位小数的3种方式

Vue toFixed保留两位小数的3种方式第一种&#xff1a;直接写在js里面&#xff0c;这是最简单的val.toFixed(2)第二种&#xff1a;在ElementUi表格中使用第三种&#xff1a;在取值符号中使用 {{}}定义一个方法towNumber(val) {return val.toFixed(2)}使用{{ towNumber(row.equiV…

Tyvj 1176 火焰巨魔的惆怅

Tyvj 1176 火焰巨魔的惆怅 背景 TYVJ2月月赛第一道巨魔家族在某天受到了其他种族的屠杀&#xff0c;作为一个英雄&#xff0c;他主动担任了断后的任务&#xff0c;但是&#xff0c;在巨魔家族整体转移过后&#xff0c;火焰巨魔却被困住了&#xff0c;他出逃的方式也只有召唤小火…

Vue3 组件通信学习笔记

一、父子组件之间通信 父子组件之间如何进行通信呢&#xff1f; 父组件传递给子组件&#xff1a;通过props属性&#xff1b;子组件传递给父组件&#xff1a;通过$emit触发事件&#xff1b; 1.1 父组件传递给子组件 在开发中很常见的就是父子组件之间通信&#xff0c;比如父…

js调用vlc_如何使用HTML5或JavaScript查看RTSP流,而不使用Real Player插件上的VLC插件等插件?...

The idea is to develop a cross-platform, standalone application that could play a video, streamed over RTSP, using HTML5 or JavaScript or any other web technology.解决方案RTSP is a protocol on the same level as HTTP. Its impossible to do RTSP via HTTP.The …

HDU-3729 二分匹配 匈牙利算法

题目大意&#xff1a;学生给出其成绩区间&#xff0c;但可能出现矛盾情况&#xff0c;找出合理组合使没有说谎的人尽可能多&#xff0c;并按maximum lexicographic规则输出组合。 //用学生去和成绩匹配&#xff0c;成绩区间就是学生可以匹配的成绩#include <iostream> #i…

Vue3 slot插槽——(默认插槽、具名插槽、作用域插槽)

一、认识插槽Slot 在开发中&#xff0c;我们会经常封装一个个可复用的组件&#xff1a; 前面我们会通过props传递给组件一些数据&#xff0c;让组件来进行展示&#xff1b;但是为了让这个组件具备更强的通用性&#xff0c;我们不能将组件中的内容限制为固定的div、span等等这…

dbcc dbreindex server sql_DBCC DBREINDEX重建索引提高SQL Server性能

DBCC DBREINDEX重建索引提高SQL Server性能[转载]大多数SQL Server表需要索引来提高数据的访问速度&#xff0c;如果没有索引&#xff0c;SQL Server要进行表格扫描读取表中的每一个记录才能找到索要的数据。索引可以分为簇索引和非簇索引&#xff0c;簇索引通过重排表中的数据…

Vue动态组件和组件缓存

一、切换组件案例 比如我们现在想要实现了一个功能&#xff1a; 点击一个tab-bar&#xff0c;切换不同的组件显示&#xff1b; 这个案例我们可以通过两种不同的实现思路来实现&#xff1a; 方式一&#xff1a;通过v-if来判断&#xff0c;显示不同的组件&#xff1b; 方式二…

hidl 原理分析_一个 health service 不生效问题引出的一点知识

从 Android P 开始&#xff0c;Google 开始推荐厂家再定制一个 health 。前不久遇到一个定制 health 中的信息未成功反应到 Framework 的问题&#xff0c;在分析解决问题的过程中&#xff0c;学习到了一点新知识&#xff0c;所以就在这篇文章里根据解决问题的流程做一个小小的记…

比较list集合相等的方法

1. 内容相同,不管顺序! public static boolean isListContentEquals(List<String> src, List<String> des){return src.containsAll(des) && des.containsAll(src);} 2.内容和顺序都完全一样 方法1: public static boolean isListsCompletelyEqual(List<…

Webpack的代码分包Vue3中定义异步组件分包refs的使用

一、默认的打包过程&#xff1a; 默认情况下&#xff0c;在构建整个组件树的过程中&#xff0c;因为组件和组件之间是通过模块化直接依赖的&#xff0c;那么webpack在打包时就会将组件模块打包到一起&#xff08;比如一个app.js文件中&#xff09;&#xff1b; 这个时候随着项…

经典JS

用apply把document当作this传入getId函数&#xff0c;帮助“修正”this; document.getElementById (function (func) {return function () {return func.apply(document, arguments);} })(document.getElementById);//调用 var getId document.getElementById; var div getI…

组件的v-model Mixin extends

一、组件的v-model 前面我们在input中可以使用v-model来完成双向绑定&#xff1a; 这个时候往往会非常方便&#xff0c;因为v-model默认帮助我们完成了两件事&#xff1b;v-bind:value的数据绑定 和 input的事件监听&#xff1b; 如果我们现在封装了一个组件&#xff0c;其…

springmvcget中文乱码_解决SpringMVC Controller 接收页面传递的中文参数出现乱码的问题...

新配置一个spring的MVC项目&#xff0c;发现对Get请求的中文参数出现了乱码&#xff1a;查看了SpingMVC中关于编码的配置(在web.xml中)&#xff0c;如下&#xff1a;encodingFilterorg.springframework.web.filter.CharacterEncodingFilterencodingutf-8forceEncodingtrueencod…

SQL学习之SELECT子句顺序

下面来总计下之前的随笔中所说过的所有的SELECT子句的顺序。 子句            说明            是否必须使用 SELECT 要返回的列或者表达式 是 FROM 从中检索数据的表 …

Vue3过渡动画实现

一、认识动画 在开发中&#xff0c;我们想要给一个组件的显示和消失添加某种过渡动画&#xff0c;可以很好的增加用户体验&#xff1a; React框架本身并没有提供任何动画相关的API&#xff0c;所以在React中使用过渡动画我们需要使用一个第三方库react-transition-group&…

linux退出 putty_使用putty远程连接linux防止关闭putty程序就停止

如题&#xff1a;有时候我们使用putty连接linux的时候执行某个命令运行程序的时候&#xff0c;关闭putty就会出现应用程序也关闭的情况&#xff1b;这里建议就使用如下命令nohup youcommand &(&可加可不加)这个时候默认会在你当前目录创建一个nohup中创建一个nohup.out…

在Linux下不使用密码远程登陆其他Linux

有时需要再一台Linux上登陆其他Linux服务器&#xff0c;通常可以直接使用SSH命令&#xff0c;加入两台服务器一台服务器A&#xff0c;IP地址192.168.1.2&#xff0c;另一 台服务器B&#xff0c;IP地址192.168.1.3&#xff0c;如果想从A服务器使用root用户登陆B服务器只需要在A服…

Vue3 Composition API(一)——setup、reactive、ref、readonly

一、Options API的弊端 在Vue2中&#xff0c;我们编写组件的方式是Options API&#xff1a; Options API的一大特点就是在对应的属性中编写对应的功能模块&#xff1b;比如data定义数据、methods中定义方法、computed中定义计算属性、watch中监听属性改变&#xff0c;也包括生…