ladybird/Kernel/Net/RTL8168NetworkAdapter.h

209 lines
6.0 KiB
C++

/*
* 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/Bus/PCI/Access.h>
#include <Kernel/Bus/PCI/Device.h>
#include <Kernel/IO.h>
#include <Kernel/Net/NetworkAdapter.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 StringView 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 bool handle_irq(const RegisterState&) override;
virtual StringView class_name() const override { return "RTL8168NetworkAdapter"sv; }
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_e_2();
void configure_phy_h_1();
void configure_phy_h_2();
void rar_exgmac_set();
void hardware_quirks();
void hardware_quirks_b_1();
void hardware_quirks_b_2();
void hardware_quirks_e_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);
struct ExgMacRegister {
u16 address;
u16 mask;
u32 value;
};
void exgmac_out_batch(const ExgMacRegister[], size_t length);
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;
};
}