diff --git a/Kernel/Net/Realtek/RTL8168NetworkAdapter.cpp b/Kernel/Net/Realtek/RTL8168NetworkAdapter.cpp index d20d345b23..c8cd5af705 100644 --- a/Kernel/Net/Realtek/RTL8168NetworkAdapter.cpp +++ b/Kernel/Net/Realtek/RTL8168NetworkAdapter.cpp @@ -38,6 +38,8 @@ namespace Kernel { #define REG_CSI_DATA 0x64 #define REG_CSI_ADDR 0x68 #define REG_PHYSTATUS 0x6C +#define REG_MACDBG 0x6D +#define REG_GPIO 0x6E #define REG_PMCH 0x6F #define REG_ERI_DATA 0x70 #define REG_ERI_ADDR 0x74 @@ -46,6 +48,7 @@ namespace Kernel { #define REG_OCP_ADDR 0xB4 #define REG_GPHY_OCP 0xB8 #define REG_DLLPR 0xD0 +#define REG_DBG 0xD1 #define REG_MCU 0xD3 #define REG_RMS 0xDA #define REG_CPLUS_COMMAND 0xE0 @@ -61,6 +64,7 @@ namespace Kernel { #define COMMAND_TX_ENABLE 0x4 #define COMMAND_RX_ENABLE 0x8 #define COMMAND_RESET 0x10 +#define COMMAND_STOP 0x80 #define CPLUS_COMMAND_VERIFY_CHECKSUM 0x20 #define CPLUS_COMMAND_VLAN_STRIP 0x40 @@ -104,6 +108,8 @@ namespace Kernel { #define RXCFG_MULTI_ENABLE 0x4000 #define RXCFG_128INT_ENABLE 0x8000 +#define CFG1_SPEED_DOWN 0x10 + #define CFG2_CLOCK_REQUEST_ENABLE 0x80 #define CFG3_BEACON_ENABLE 0x1 @@ -180,6 +186,11 @@ namespace Kernel { #define PHYSTATUS_100M 0x08 #define PHYSTATUS_10M 0x04 +#define GPIO_ENABLE 0x1 + +#define DBG_FIX_NAK_2 0x8 +#define DBG_FIX_NAK_1 0x10 + #define TX_BUFFER_SIZE 0x1FF8 #define RX_BUFFER_SIZE 0x1FF8 // FIXME: this should be increased (0x3FFF) @@ -206,10 +217,10 @@ bool RTL8168NetworkAdapter::determine_supported_version() const case ChipVersion::Version1: case ChipVersion::Version2: case ChipVersion::Version3: - return true; case ChipVersion::Version4: case ChipVersion::Version5: case ChipVersion::Version6: + return true; case ChipVersion::Version7: case ChipVersion::Version8: case ChipVersion::Version9: @@ -325,12 +336,14 @@ UNMAP_AFTER_INIT ErrorOr RTL8168NetworkAdapter::initialize(Badge= ChipVersion::Version9 && m_version <= ChipVersion::Version15) { out8(REG_PMCH, in8(REG_PMCH) | 0x80); @@ -393,6 +424,7 @@ void RTL8168NetworkAdapter::startup() } phy_out(PHY_REG_BMCR, BMCR_AUTO_NEGOTIATE); // send known good phy write (acts as a phy barrier) start_hardware(); + pci_commit(); // re-enable interrupts auto enabled_interrupts = INT_RXOK | INT_RXERR | INT_TXOK | INT_TXERR | INT_RX_OVERFLOW | INT_LINK_CHANGE | INT_SYS_ERR; @@ -401,6 +433,7 @@ void RTL8168NetworkAdapter::startup() enabled_interrupts &= ~INT_RX_OVERFLOW; } out16(REG_IMR, enabled_interrupts); + pci_commit(); // update link status m_link_up = (in8(REG_PHYSTATUS) & PHY_LINK_STATUS) != 0; @@ -420,11 +453,14 @@ void RTL8168NetworkAdapter::configure_phy() return; } case ChipVersion::Version4: - TODO(); + configure_phy_c_1(); + return; case ChipVersion::Version5: - TODO(); + configure_phy_c_2(); + return; case ChipVersion::Version6: - TODO(); + configure_phy_c_3(); + return; case ChipVersion::Version7: TODO(); case ChipVersion::Version8: @@ -510,6 +546,79 @@ void RTL8168NetworkAdapter::configure_phy_b_2() phy_out_batch(phy_registers); } +void RTL8168NetworkAdapter::configure_phy_c_1() +{ + static constexpr auto phy_registers = to_array({ + { 0x1f, 0x0001 }, + { 0x12, 0x2300 }, + { 0x1f, 0x0002 }, + { 0x00, 0x88d4 }, + { 0x01, 0x82b1 }, + { 0x03, 0x7002 }, + { 0x08, 0x9e30 }, + { 0x09, 0x01f0 }, + { 0x0a, 0x5500 }, + { 0x0c, 0x00c8 }, + { 0x1f, 0x0003 }, + { 0x12, 0xc096 }, + { 0x16, 0x000a }, + { 0x1f, 0x0000 }, + { 0x1f, 0x0000 }, + { 0x09, 0x2000 }, + { 0x09, 0x0000 }, + }); + phy_out_batch(phy_registers); + + phy_update(0x14, 1 << 5, 0); + phy_update(0x0d, 1 << 5, 0); +} + +void RTL8168NetworkAdapter::configure_phy_c_2() +{ + static constexpr auto phy_registers = to_array({ + { 0x1f, 0x0001 }, + { 0x12, 0x2300 }, + { 0x03, 0x802f }, + { 0x02, 0x4f02 }, + { 0x01, 0x0409 }, + { 0x00, 0xf099 }, + { 0x04, 0x9800 }, + { 0x04, 0x9000 }, + { 0x1d, 0x3d98 }, + { 0x1f, 0x0002 }, + { 0x0c, 0x7eb8 }, + { 0x06, 0x0761 }, + { 0x1f, 0x0003 }, + { 0x16, 0x0f0a }, + { 0x1f, 0x0000 }, + }); + phy_out_batch(phy_registers); + + phy_update(0x16, 0x1, 0); + phy_update(0x14, 1 << 5, 0); + phy_update(0x0d, 1 << 5, 0); +} + +void RTL8168NetworkAdapter::configure_phy_c_3() +{ + static constexpr auto phy_registers = to_array({ + { 0x1f, 0x0001 }, + { 0x12, 0x2300 }, + { 0x1d, 0x3d98 }, + { 0x1f, 0x0002 }, + { 0x0c, 0x7eb8 }, + { 0x06, 0x5461 }, + { 0x1f, 0x0003 }, + { 0x16, 0x0f0a }, + { 0x1f, 0x0000 }, + }); + phy_out_batch(phy_registers); + + phy_update(0x16, 0x1, 0); + phy_update(0x14, 1 << 5, 0); + phy_update(0x0d, 1 << 5, 0); +} + void RTL8168NetworkAdapter::configure_phy_e_2() { // FIXME: linux's driver writes a firmware blob to the device at this point, is this needed? @@ -794,7 +903,6 @@ void RTL8168NetworkAdapter::rar_exgmac_set() void RTL8168NetworkAdapter::start_hardware() { - // unlock config registers out8(REG_CFG9346, CFG9346_UNLOCK); @@ -832,6 +940,7 @@ void RTL8168NetworkAdapter::start_hardware() // enable rx/tx out8(REG_COMMAND, COMMAND_RX_ENABLE | COMMAND_TX_ENABLE); + pci_commit(); // turn on all multicast out32(REG_MAR0, 0xFFFFFFFF); @@ -855,11 +964,14 @@ void RTL8168NetworkAdapter::hardware_quirks() hardware_quirks_b_2(); return; case ChipVersion::Version4: - TODO(); + hardware_quirks_c_1(); + return; case ChipVersion::Version5: - TODO(); + hardware_quirks_c_2(); + return; case ChipVersion::Version6: - TODO(); + hardware_quirks_c_3(); + return; case ChipVersion::Version7: TODO(); case ChipVersion::Version8: @@ -933,6 +1045,49 @@ void RTL8168NetworkAdapter::hardware_quirks_b_2() out8(REG_CONFIG4, in8(REG_CONFIG4) & ~1); } +void RTL8168NetworkAdapter::hardware_quirks_c_1() +{ + csi_enable(CSI_ACCESS_2); + + out8(REG_DBG, 0x06 | DBG_FIX_NAK_1 | DBG_FIX_NAK_2); + + static constexpr auto ephy_info = to_array({ + { 0x02, 0x0800, 0x1000 }, + { 0x03, 0, 0x0002 }, + { 0x06, 0x0080, 0x0000 }, + }); + extended_phy_initialize(ephy_info); + + out8(REG_CONFIG1, in8(REG_CONFIG1) | CFG1_SPEED_DOWN); + out8(REG_CONFIG3, in8(REG_CONFIG3) & ~CFG3_BEACON_ENABLE); +} + +void RTL8168NetworkAdapter::hardware_quirks_c_2() +{ + csi_enable(CSI_ACCESS_2); + + static constexpr auto ephy_info = to_array({ + { 0x01, 0, 0x1 }, + { 0x03, 0x0400, 0x0020 }, + }); + extended_phy_initialize(ephy_info); + + out8(REG_CONFIG1, in8(REG_CONFIG1) | CFG1_SPEED_DOWN); + out8(REG_CONFIG3, in8(REG_CONFIG3) | CFG3_BEACON_ENABLE); + + // FIXME: Disable PCIe clock request +} + +void RTL8168NetworkAdapter::hardware_quirks_c_3() +{ + csi_enable(CSI_ACCESS_2); + + out8(REG_CONFIG1, in8(REG_CONFIG1) | CFG1_SPEED_DOWN); + out8(REG_CONFIG3, in8(REG_CONFIG3) & ~CFG3_BEACON_ENABLE); + + // FIXME: Disable PCIe clock request +} + void RTL8168NetworkAdapter::hardware_quirks_e_2() { static constexpr auto ephy_info = to_array({ @@ -1186,6 +1341,12 @@ void RTL8168NetworkAdapter::reset() Processor::wait_check(); } +void RTL8168NetworkAdapter::pci_commit() +{ + // read any register to commit previous PCI write + in8(REG_COMMAND); +} + UNMAP_AFTER_INIT void RTL8168NetworkAdapter::read_mac_address() { MACAddress mac {}; diff --git a/Kernel/Net/Realtek/RTL8168NetworkAdapter.h b/Kernel/Net/Realtek/RTL8168NetworkAdapter.h index afda1c91db..cfb501739a 100644 --- a/Kernel/Net/Realtek/RTL8168NetworkAdapter.h +++ b/Kernel/Net/Realtek/RTL8168NetworkAdapter.h @@ -129,6 +129,7 @@ private: StringView possible_device_name(); void reset(); + void pci_commit(); void read_mac_address(); void set_phy_speed(); void start_hardware(); @@ -137,6 +138,9 @@ private: void configure_phy(); void configure_phy_b_1(); void configure_phy_b_2(); + void configure_phy_c_1(); + void configure_phy_c_2(); + void configure_phy_c_3(); void configure_phy_e_2(); void configure_phy_h_1(); void configure_phy_h_2(); @@ -146,6 +150,9 @@ private: void hardware_quirks(); void hardware_quirks_b_1(); void hardware_quirks_b_2(); + void hardware_quirks_c_1(); + void hardware_quirks_c_2(); + void hardware_quirks_c_3(); void hardware_quirks_e_2(); void hardware_quirks_h();