Kernel: Add driver for RTL8168 & RTL8111 NICs
These are pretty common on older LGA1366 & LGA1150 motherboards. NOTE: Since the registers datasheets for all versions of the chip besides versions 1 - 3 are still under NDAs i had to collect several "magical vendor constants" from the *BSD driver and the linux driver that i was not able to name verbosely, and as such these are labeled with the comment "vendor magic values".
This commit is contained in:
parent
de6d032273
commit
a898e01d4d
Notes:
sideshowbarker
2024-07-18 12:29:02 +09:00
Author: https://github.com/IdanHo Commit: https://github.com/SerenityOS/serenity/commit/a898e01d4dc Pull-request: https://github.com/SerenityOS/serenity/pull/6076 Reviewed-by: https://github.com/Lubrsi
8 changed files with 1683 additions and 1 deletions
|
@ -12,6 +12,7 @@ Serenity boots to a graphical desktop on all machines unless otherwise noted.
|
|||
| Intel 82545XX | Also known as e1000 |
|
||||
| NE2000 compatible cards | |
|
||||
| Intel 82574L | Also known as e1000e |
|
||||
| RTL8168/8111 (Variants B & E-VL) | Other variants are WIP |
|
||||
|
||||
### Desktop machines
|
||||
|
||||
|
|
|
@ -125,6 +125,7 @@ set(KERNEL_SOURCES
|
|||
Net/NetworkingManagement.cpp
|
||||
Net/NetworkTask.cpp
|
||||
Net/RTL8139NetworkAdapter.cpp
|
||||
Net/RTL8168NetworkAdapter.cpp
|
||||
Net/Routing.cpp
|
||||
Net/Socket.cpp
|
||||
Net/TCPSocket.cpp
|
||||
|
|
|
@ -238,6 +238,10 @@
|
|||
#cmakedefine01 RTL8139_DEBUG
|
||||
#endif
|
||||
|
||||
#ifndef RTL8168_DEBUG
|
||||
#cmakedefine01 RTL8168_DEBUG
|
||||
#endif
|
||||
|
||||
#ifndef SB16_DEBUG
|
||||
#cmakedefine01 SB16_DEBUG
|
||||
#endif
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <Kernel/Net/NE2000NetworkAdapter.h>
|
||||
#include <Kernel/Net/NetworkingManagement.h>
|
||||
#include <Kernel/Net/RTL8139NetworkAdapter.h>
|
||||
#include <Kernel/Net/RTL8168NetworkAdapter.h>
|
||||
#include <Kernel/Panic.h>
|
||||
#include <Kernel/VM/AnonymousVMObject.h>
|
||||
|
||||
|
@ -81,6 +82,8 @@ UNMAP_AFTER_INIT RefPtr<NetworkAdapter> NetworkingManagement::determine_network_
|
|||
return candidate;
|
||||
if (auto candidate = RTL8139NetworkAdapter::try_to_initialize(address); !candidate.is_null())
|
||||
return candidate;
|
||||
if (auto candidate = RTL8168NetworkAdapter::try_to_initialize(address); !candidate.is_null())
|
||||
return candidate;
|
||||
if (auto candidate = NE2000NetworkAdapter::try_to_initialize(address); !candidate.is_null())
|
||||
return candidate;
|
||||
return {};
|
||||
|
|
1473
Kernel/Net/RTL8168NetworkAdapter.cpp
Normal file
1473
Kernel/Net/RTL8168NetworkAdapter.cpp
Normal file
File diff suppressed because it is too large
Load diff
198
Kernel/Net/RTL8168NetworkAdapter.h
Normal file
198
Kernel/Net/RTL8168NetworkAdapter.h
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/NonnullOwnPtrVector.h>
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <Kernel/IO.h>
|
||||
#include <Kernel/Net/NetworkAdapter.h>
|
||||
#include <Kernel/PCI/Access.h>
|
||||
#include <Kernel/PCI/Device.h>
|
||||
#include <Kernel/Random.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
// RTL8618 / RTL8111 Driver based on https://people.freebsd.org/~wpaul/RealTek/RTL8111B_8168B_Registers_DataSheet_1.0.pdf
|
||||
class RTL8168NetworkAdapter final : public NetworkAdapter
|
||||
, public PCI::Device {
|
||||
public:
|
||||
static RefPtr<RTL8168NetworkAdapter> try_to_initialize(PCI::Address);
|
||||
|
||||
virtual ~RTL8168NetworkAdapter() override;
|
||||
|
||||
virtual void send_raw(ReadonlyBytes) override;
|
||||
virtual bool link_up() override { return m_link_up; }
|
||||
|
||||
virtual const char* purpose() const override { return class_name(); }
|
||||
|
||||
private:
|
||||
// FIXME: should this be increased? (maximum allowed here is 1024) - memory usage vs packet loss chance tradeoff
|
||||
static const size_t number_of_rx_descriptors = 64;
|
||||
static const size_t number_of_tx_descriptors = 16;
|
||||
|
||||
RTL8168NetworkAdapter(PCI::Address, u8 irq);
|
||||
|
||||
virtual void handle_irq(const RegisterState&) override;
|
||||
virtual const char* class_name() const override { return "RTL8168NetworkAdapter"; }
|
||||
|
||||
struct [[gnu::packed]] TXDescriptor {
|
||||
volatile u16 frame_length; // top 2 bits are reserved
|
||||
volatile u16 flags;
|
||||
volatile u16 vlan_tag;
|
||||
volatile u16 vlan_flags;
|
||||
volatile u32 buffer_address_low;
|
||||
volatile u32 buffer_address_high;
|
||||
|
||||
// flags bit field
|
||||
static constexpr u16 Ownership = 0x8000u;
|
||||
static constexpr u16 EndOfRing = 0x4000u;
|
||||
static constexpr u16 FirstSegment = 0x2000u;
|
||||
static constexpr u16 LastSegment = 0x1000u;
|
||||
static constexpr u16 LargeSend = 0x800u;
|
||||
};
|
||||
|
||||
static_assert(sizeof(TXDescriptor) == 16u);
|
||||
|
||||
struct [[gnu::packed]] RXDescriptor {
|
||||
volatile u16 buffer_size; // top 2 bits are reserved
|
||||
volatile u16 flags;
|
||||
volatile u16 vlan_tag;
|
||||
volatile u16 vlan_flags;
|
||||
volatile u32 buffer_address_low;
|
||||
volatile u32 buffer_address_high;
|
||||
|
||||
// flags bit field
|
||||
static constexpr u16 Ownership = 0x8000u;
|
||||
static constexpr u16 EndOfRing = 0x4000u;
|
||||
static constexpr u16 FirstSegment = 0x2000u;
|
||||
static constexpr u16 LastSegment = 0x1000u;
|
||||
static constexpr u16 MulticastPacket = 0x800u;
|
||||
static constexpr u16 PhysicalPacket = 0x400u;
|
||||
static constexpr u16 BroadcastPacket = 0x200u;
|
||||
static constexpr u16 WatchdogTimerExpired = 0x40;
|
||||
static constexpr u16 ErrorSummary = 0x20;
|
||||
static constexpr u16 RuntPacket = 0x10;
|
||||
static constexpr u16 CRCError = 0x8;
|
||||
};
|
||||
|
||||
static_assert(sizeof(RXDescriptor) == 16u);
|
||||
|
||||
enum class ChipVersion : u8 {
|
||||
Unknown = 0,
|
||||
Version1 = 1,
|
||||
Version2 = 2,
|
||||
Version3 = 3,
|
||||
Version4 = 4,
|
||||
Version5 = 5,
|
||||
Version6 = 6,
|
||||
Version7 = 7,
|
||||
Version8 = 8,
|
||||
Version9 = 9,
|
||||
Version10 = 10,
|
||||
Version11 = 11,
|
||||
Version12 = 12,
|
||||
Version13 = 13,
|
||||
Version14 = 14,
|
||||
Version15 = 15,
|
||||
Version16 = 16,
|
||||
Version17 = 17,
|
||||
Version18 = 18,
|
||||
Version19 = 19,
|
||||
Version20 = 20,
|
||||
Version21 = 21,
|
||||
Version22 = 22,
|
||||
Version23 = 23,
|
||||
Version24 = 24,
|
||||
Version25 = 25,
|
||||
Version26 = 26,
|
||||
Version27 = 27,
|
||||
Version28 = 28,
|
||||
Version29 = 29,
|
||||
Version30 = 30
|
||||
};
|
||||
|
||||
void identify_chip_version();
|
||||
String possible_device_name();
|
||||
|
||||
void reset();
|
||||
void read_mac_address();
|
||||
void set_phy_speed();
|
||||
void start_hardware();
|
||||
void initialize();
|
||||
void startup();
|
||||
|
||||
void configure_phy();
|
||||
void configure_phy_b_1();
|
||||
void configure_phy_b_2();
|
||||
void configure_phy_h_1();
|
||||
void configure_phy_h_2();
|
||||
|
||||
void hardware_quirks();
|
||||
void hardware_quirks_b_1();
|
||||
void hardware_quirks_b_2();
|
||||
void hardware_quirks_h();
|
||||
|
||||
void initialize_rx_descriptors();
|
||||
void initialize_tx_descriptors();
|
||||
|
||||
void receive();
|
||||
|
||||
void out8(u16 address, u8 data);
|
||||
void out16(u16 address, u16 data);
|
||||
void out32(u16 address, u32 data);
|
||||
void out64(u16 address, u64 data);
|
||||
u8 in8(u16 address);
|
||||
u16 in16(u16 address);
|
||||
u32 in32(u16 address);
|
||||
|
||||
void phy_out(u8 address, u16 data);
|
||||
u16 phy_in(u8 address);
|
||||
void phy_update(u32 address, u32 set, u32 clear);
|
||||
struct PhyRegister {
|
||||
u16 address;
|
||||
u16 data;
|
||||
};
|
||||
void phy_out_batch(const PhyRegister[], size_t length);
|
||||
|
||||
void extended_phy_out(u8 address, u16 data);
|
||||
u16 extended_phy_in(u8 address);
|
||||
struct EPhyUpdate {
|
||||
u32 offset;
|
||||
u16 clear;
|
||||
u16 set;
|
||||
};
|
||||
void extended_phy_initialize(const EPhyUpdate[], size_t length);
|
||||
|
||||
void eri_out(u32 address, u32 mask, u32 data, u32 type);
|
||||
u32 eri_in(u32 address, u32 type);
|
||||
void eri_update(u32 address, u32 mask, u32 set, u32 clear, u32 type);
|
||||
|
||||
void csi_out(u32 address, u32 data);
|
||||
u32 csi_in(u32 address);
|
||||
void csi_enable(u32 bits);
|
||||
|
||||
void ocp_out(u32 address, u32 data);
|
||||
u32 ocp_in(u32 address);
|
||||
|
||||
void ocp_phy_out(u32 address, u32 data);
|
||||
u16 ocp_phy_in(u32 address);
|
||||
|
||||
ChipVersion m_version { ChipVersion::Unknown };
|
||||
bool m_version_uncertain { true };
|
||||
IOAddress m_io_base;
|
||||
u32 m_ocp_base_address { 0 };
|
||||
OwnPtr<Region> m_rx_descriptors_region;
|
||||
NonnullOwnPtrVector<Region> m_rx_buffers_regions;
|
||||
u16 m_rx_free_index { 0 };
|
||||
OwnPtr<Region> m_tx_descriptors_region;
|
||||
NonnullOwnPtrVector<Region> m_tx_buffers_regions;
|
||||
u16 m_tx_free_index { 0 };
|
||||
bool m_link_up { false };
|
||||
EntropySource m_entropy_source;
|
||||
WaitQueue m_wait_queue;
|
||||
};
|
||||
}
|
|
@ -12,7 +12,8 @@ enum class PCIVendorID {
|
|||
VirtIO = 0x1af4,
|
||||
Intel = 0x8086,
|
||||
WCH = 0x1c00,
|
||||
RedHat = 0x1b36
|
||||
RedHat = 0x1b36,
|
||||
Realtek = 0x10ec
|
||||
};
|
||||
|
||||
enum class PCIDeviceID {
|
||||
|
|
|
@ -142,6 +142,7 @@ set(RESOURCE_DEBUG ON)
|
|||
set(ROUTING_DEBUG ON)
|
||||
set(RSA_PARSE_DEBUG ON)
|
||||
set(RTL8139_DEBUG ON)
|
||||
set(RTL8168_DEBUG ON)
|
||||
set(SAFE_SYSCALL_DEBUG ON)
|
||||
set(SB16_DEBUG ON)
|
||||
set(SCHEDULER_DEBUG ON)
|
||||
|
|
Loading…
Add table
Reference in a new issue