diff --git a/Kernel/Net/E1000NetworkAdapter.cpp b/Kernel/Net/E1000NetworkAdapter.cpp index b0f8ec0178..568715ecce 100644 --- a/Kernel/Net/E1000NetworkAdapter.cpp +++ b/Kernel/Net/E1000NetworkAdapter.cpp @@ -466,4 +466,29 @@ void E1000NetworkAdapter::receive() } } +i32 E1000NetworkAdapter::link_speed() +{ + if (!link_up()) + return NetworkAdapter::LINKSPEED_INVALID; + + u32 speed = in32(REG_STATUS) & STATUS_SPEED; + switch (speed) { + case STATUS_SPEED_10MB: + return 10; + case STATUS_SPEED_100MB: + return 100; + case STATUS_SPEED_1000MB1: + case STATUS_SPEED_1000MB2: + return 1000; + default: + return NetworkAdapter::LINKSPEED_INVALID; + } +} + +bool E1000NetworkAdapter::link_full_duplex() +{ + u32 status = in32(REG_STATUS); + return !!(status & STATUS_FD); +} + } diff --git a/Kernel/Net/E1000NetworkAdapter.h b/Kernel/Net/E1000NetworkAdapter.h index 157b929ffa..2475d4d144 100644 --- a/Kernel/Net/E1000NetworkAdapter.h +++ b/Kernel/Net/E1000NetworkAdapter.h @@ -27,6 +27,8 @@ public: virtual void send_raw(ReadonlyBytes) override; virtual bool link_up() override; + virtual i32 link_speed() override; + virtual bool link_full_duplex() override; virtual StringView purpose() const override { return class_name(); } diff --git a/Kernel/Net/LoopbackAdapter.h b/Kernel/Net/LoopbackAdapter.h index a30538c73e..fb75abb3c0 100644 --- a/Kernel/Net/LoopbackAdapter.h +++ b/Kernel/Net/LoopbackAdapter.h @@ -23,6 +23,8 @@ public: virtual void send_raw(ReadonlyBytes) override; virtual StringView class_name() const override { return "LoopbackAdapter"; } virtual bool link_up() override { return true; } + virtual bool link_full_duplex() override { return true; } + virtual int link_speed() override { return 1000; } }; } diff --git a/Kernel/Net/NE2000NetworkAdapter.h b/Kernel/Net/NE2000NetworkAdapter.h index 2fda43ccfc..01f7f53b09 100644 --- a/Kernel/Net/NE2000NetworkAdapter.h +++ b/Kernel/Net/NE2000NetworkAdapter.h @@ -29,6 +29,12 @@ public: // just assume that it's up. return true; } + virtual i32 link_speed() + { + // Can only do 10mbit.. + return 10; + } + virtual bool link_full_duplex() { return true; } virtual StringView purpose() const override { return class_name(); } diff --git a/Kernel/Net/NetworkAdapter.h b/Kernel/Net/NetworkAdapter.h index 2a6b192f7d..ee7c82235d 100644 --- a/Kernel/Net/NetworkAdapter.h +++ b/Kernel/Net/NetworkAdapter.h @@ -42,6 +42,8 @@ struct PacketWithTimestamp : public RefCounted { class NetworkAdapter : public RefCounted , public Weakable { public: + static constexpr i32 LINKSPEED_INVALID = -1; + virtual ~NetworkAdapter(); virtual StringView class_name() const = 0; @@ -53,6 +55,12 @@ public: IPv4Address ipv4_broadcast() const { return IPv4Address { (m_ipv4_address.to_u32() & m_ipv4_netmask.to_u32()) | ~m_ipv4_netmask.to_u32() }; } IPv4Address ipv4_gateway() const { return m_ipv4_gateway; } virtual bool link_up() { return false; } + virtual i32 link_speed() + { + // In Mbit/sec. + return LINKSPEED_INVALID; + } + virtual bool link_full_duplex() { return false; } void set_ipv4_address(const IPv4Address&); void set_ipv4_netmask(const IPv4Address&); diff --git a/Kernel/Net/RTL8139NetworkAdapter.cpp b/Kernel/Net/RTL8139NetworkAdapter.cpp index 567948d1ab..6348651333 100644 --- a/Kernel/Net/RTL8139NetworkAdapter.cpp +++ b/Kernel/Net/RTL8139NetworkAdapter.cpp @@ -29,6 +29,7 @@ namespace Kernel { #define REG_CONFIG1 0x52 #define REG_MSR 0x58 #define REG_BMCR 0x62 +#define REG_ANLPAR 0x68 #define TX_STATUS_OWN 0x2000 #define TX_STATUS_THRESHOLD_MAX 0x3F0000 @@ -84,12 +85,16 @@ namespace Kernel { #define RXCFG_FTH_NONE 0xE000 #define MSR_LINKB 0x02 +#define MSR_SPEED_10 0x08 #define MSR_RX_FLOW_CONTROL_ENABLE 0x40 #define BMCR_SPEED 0x2000 #define BMCR_AUTO_NEGOTIATE 0x1000 #define BMCR_DUPLEX 0x0100 +#define ANLPAR_10FD 0x0040 +#define ANLPAR_TXFD 0x0100 + #define RX_MULTICAST 0x8000 #define RX_PHYSICAL_MATCH 0x4000 #define RX_BROADCAST 0x2000 @@ -366,4 +371,22 @@ u32 RTL8139NetworkAdapter::in32(u16 address) return m_io_base.offset(address).in(); } +bool RTL8139NetworkAdapter::link_full_duplex() +{ + // Note: this code assumes auto-negotiation is enabled (which is now always the case) and + // bases the duplex state on the link partner advertisement. + // If non-auto-negotiation is ever implemented this should be changed. + u16 anlpar = in16(REG_ANLPAR); + return !!(anlpar & (ANLPAR_TXFD | ANLPAR_10FD)); +} + +i32 RTL8139NetworkAdapter::link_speed() +{ + if (!link_up()) + return NetworkAdapter::LINKSPEED_INVALID; + + u16 msr = in16(REG_MSR); + return msr & MSR_SPEED_10 ? 10 : 100; +} + } diff --git a/Kernel/Net/RTL8139NetworkAdapter.h b/Kernel/Net/RTL8139NetworkAdapter.h index 164fbb0c77..d42e6a505e 100644 --- a/Kernel/Net/RTL8139NetworkAdapter.h +++ b/Kernel/Net/RTL8139NetworkAdapter.h @@ -26,6 +26,8 @@ public: virtual void send_raw(ReadonlyBytes) override; virtual bool link_up() override { return m_link_up; } + virtual i32 link_speed() override; + virtual bool link_full_duplex() override; virtual StringView purpose() const override { return class_name(); } diff --git a/Kernel/Net/RTL8168NetworkAdapter.cpp b/Kernel/Net/RTL8168NetworkAdapter.cpp index a1d6c7f763..6563e6555f 100644 --- a/Kernel/Net/RTL8168NetworkAdapter.cpp +++ b/Kernel/Net/RTL8168NetworkAdapter.cpp @@ -172,6 +172,11 @@ namespace Kernel { #define MISC2_PFM_D3COLD_ENABLE 0x40 +#define PHYSTATUS_FULLDUP 0x01 +#define PHYSTATUS_1000MF 0x10 +#define PHYSTATUS_100M 0x08 +#define PHYSTATUS_10M 0x04 + #define TX_BUFFER_SIZE 0x1FF8 #define RX_BUFFER_SIZE 0x1FF8 // FIXME: this should be increased (0x3FFF) @@ -1631,4 +1636,27 @@ String RTL8168NetworkAdapter::possible_device_name() } VERIFY_NOT_REACHED(); } + +bool RTL8168NetworkAdapter::link_full_duplex() +{ + u8 phystatus = in8(REG_PHYSTATUS); + return !!(phystatus & (PHYSTATUS_FULLDUP | PHYSTATUS_1000MF)); +} + +i32 RTL8168NetworkAdapter::link_speed() +{ + if (!link_up()) + return NetworkAdapter::LINKSPEED_INVALID; + + u8 phystatus = in8(REG_PHYSTATUS); + if (phystatus & PHYSTATUS_1000MF) + return 1000; + if (phystatus & PHYSTATUS_100M) + return 100; + if (phystatus & PHYSTATUS_10M) + return 10; + + return NetworkAdapter::LINKSPEED_INVALID; +} + } diff --git a/Kernel/Net/RTL8168NetworkAdapter.h b/Kernel/Net/RTL8168NetworkAdapter.h index 0066e8d23b..ae71976fc9 100644 --- a/Kernel/Net/RTL8168NetworkAdapter.h +++ b/Kernel/Net/RTL8168NetworkAdapter.h @@ -26,6 +26,8 @@ public: virtual void send_raw(ReadonlyBytes) override; virtual bool link_up() override { return m_link_up; } + virtual bool link_full_duplex() override; + virtual i32 link_speed() override; virtual StringView purpose() const override { return class_name(); }