1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 21:08:12 +00:00

Kernel/IntelGraphics: Move pipe management to the Transcoder class

It became apparent to me that future generations of the Intel graphics
chipset utilize the same register set as part of the Transcoder register
set. Therefore, it should be included now in the Transcoder class.
This commit is contained in:
Liav A 2022-04-01 12:52:49 +03:00 committed by Andrew Kaster
parent 2def16a3d2
commit 8042ae43c3
7 changed files with 95 additions and 122 deletions

View file

@ -10,11 +10,6 @@
namespace Kernel::IntelGraphics { namespace Kernel::IntelGraphics {
enum class GlobalGenerationRegister {
PipeAConf = 0x70008,
PipeBConf = 0x71008,
};
struct PLLSettings; struct PLLSettings;
struct PLLParameterLimit { struct PLLParameterLimit {

View file

@ -147,12 +147,14 @@ ErrorOr<void> IntelDisplayConnectorGroup::initialize_gen4_connectors()
// NOTE: Just assume we will need one Gen4 "transcoder" // NOTE: Just assume we will need one Gen4 "transcoder"
// NOTE: Main block of registers starting at HorizontalTotalA register (0x60000) // NOTE: Main block of registers starting at HorizontalTotalA register (0x60000)
auto transcoder_registers_paddr = m_mmio_first_region.pci_bar_paddr.offset(0x60000); auto transcoder_registers_paddr = m_mmio_first_region.pci_bar_paddr.offset(0x60000);
// NOTE: Main block of Pipe registers starting at PipeA_DSL register (0x70000)
auto pipe_registers_paddr = m_mmio_first_region.pci_bar_paddr.offset(0x70000);
// NOTE: DPLL registers starting at DPLLDivisorA0 register (0x6040) // NOTE: DPLL registers starting at DPLLDivisorA0 register (0x6040)
auto dpll_registers_paddr = m_mmio_first_region.pci_bar_paddr.offset(0x6040); auto dpll_registers_paddr = m_mmio_first_region.pci_bar_paddr.offset(0x6040);
// NOTE: DPLL A control registers starting at 0x6014 (DPLL A Control register), // NOTE: DPLL A control registers starting at 0x6014 (DPLL A Control register),
// DPLL A Multiplier is at 0x601C, between them (at 0x6018) there is the DPLL B Control register. // DPLL A Multiplier is at 0x601C, between them (at 0x6018) there is the DPLL B Control register.
auto dpll_control_registers_paddr = m_mmio_first_region.pci_bar_paddr.offset(0x6014); auto dpll_control_registers_paddr = m_mmio_first_region.pci_bar_paddr.offset(0x6014);
m_transcoders[0] = TRY(IntelAnalogDisplayTranscoder::create_with_physical_addresses(transcoder_registers_paddr, dpll_registers_paddr, dpll_control_registers_paddr)); m_transcoders[0] = TRY(IntelAnalogDisplayTranscoder::create_with_physical_addresses(transcoder_registers_paddr, pipe_registers_paddr, dpll_registers_paddr, dpll_control_registers_paddr));
m_planes[0] = TRY(IntelG33DisplayPlane::create_with_physical_address(m_mmio_first_region.pci_bar_paddr.offset(0x70180))); m_planes[0] = TRY(IntelG33DisplayPlane::create_with_physical_address(m_mmio_first_region.pci_bar_paddr.offset(0x70180)));
Array<u8, 128> crt_edid_bytes {}; Array<u8, 128> crt_edid_bytes {};
{ {
@ -299,29 +301,6 @@ u32 IntelDisplayConnectorGroup::read_from_analog_output_register(AnalogOutputReg
return value; return value;
} }
void IntelDisplayConnectorGroup::write_to_global_generation_register(IntelGraphics::GlobalGenerationRegister index, u32 value)
{
write_to_general_register(to_underlying(index), value);
}
u32 IntelDisplayConnectorGroup::read_from_global_generation_register(IntelGraphics::GlobalGenerationRegister index) const
{
u32 value = read_from_general_register(to_underlying(index));
return value;
}
bool IntelDisplayConnectorGroup::pipe_a_enabled() const
{
VERIFY(m_control_lock.is_locked());
return read_from_global_generation_register(IntelGraphics::GlobalGenerationRegister::PipeAConf) & (1 << 30);
}
bool IntelDisplayConnectorGroup::pipe_b_enabled() const
{
VERIFY(m_control_lock.is_locked());
return read_from_global_generation_register(IntelGraphics::GlobalGenerationRegister::PipeBConf) & (1 << 30);
}
static size_t compute_dac_multiplier(size_t pixel_clock_in_khz) static size_t compute_dac_multiplier(size_t pixel_clock_in_khz)
{ {
dbgln_if(INTEL_GRAPHICS_DEBUG, "Intel native graphics: Pixel clock is {} KHz", pixel_clock_in_khz); dbgln_if(INTEL_GRAPHICS_DEBUG, "Intel native graphics: Pixel clock is {} KHz", pixel_clock_in_khz);
@ -351,8 +330,7 @@ bool IntelDisplayConnectorGroup::set_crt_resolution(DisplayConnector::ModeSettin
disable_dac_output(); disable_dac_output();
MUST(m_planes[0]->disable({})); MUST(m_planes[0]->disable({}));
disable_pipe_a(); MUST(m_transcoders[0]->disable_pipe({}));
disable_pipe_b();
MUST(m_transcoders[0]->disable_dpll({})); MUST(m_transcoders[0]->disable_dpll({}));
disable_vga_emulation(); disable_vga_emulation();
@ -362,8 +340,8 @@ bool IntelDisplayConnectorGroup::set_crt_resolution(DisplayConnector::ModeSettin
MUST(m_transcoders[0]->enable_dpll_without_vga({})); MUST(m_transcoders[0]->enable_dpll_without_vga({}));
MUST(m_transcoders[0]->set_mode_setting_timings({}, mode_setting)); MUST(m_transcoders[0]->set_mode_setting_timings({}, mode_setting));
VERIFY(!pipe_a_enabled()); VERIFY(!m_transcoders[0]->pipe_enabled({}));
enable_pipe_a(); MUST(m_transcoders[0]->enable_pipe({}));
MUST(m_planes[0]->set_plane_settings({}, m_mmio_second_region.pci_bar_paddr, IntelDisplayPlane::PipeSelect::PipeA, mode_setting.horizontal_active)); MUST(m_planes[0]->set_plane_settings({}, m_mmio_second_region.pci_bar_paddr, IntelDisplayPlane::PipeSelect::PipeA, mode_setting.horizontal_active));
MUST(m_planes[0]->enable({})); MUST(m_planes[0]->enable({}));
enable_dac_output(); enable_dac_output();
@ -371,74 +349,6 @@ bool IntelDisplayConnectorGroup::set_crt_resolution(DisplayConnector::ModeSettin
return true; return true;
} }
bool IntelDisplayConnectorGroup::wait_for_enabled_pipe_a(size_t milliseconds_timeout) const
{
size_t current_time = 0;
while (current_time < milliseconds_timeout) {
if (pipe_a_enabled())
return true;
microseconds_delay(1000);
current_time++;
}
return false;
}
bool IntelDisplayConnectorGroup::wait_for_disabled_pipe_a(size_t milliseconds_timeout) const
{
size_t current_time = 0;
while (current_time < milliseconds_timeout) {
if (!pipe_a_enabled())
return true;
microseconds_delay(1000);
current_time++;
}
return false;
}
bool IntelDisplayConnectorGroup::wait_for_disabled_pipe_b(size_t milliseconds_timeout) const
{
size_t current_time = 0;
while (current_time < milliseconds_timeout) {
if (!pipe_b_enabled())
return true;
microseconds_delay(1000);
current_time++;
}
return false;
}
void IntelDisplayConnectorGroup::disable_pipe_a()
{
VERIFY(m_control_lock.is_locked());
VERIFY(m_modeset_lock.is_locked());
write_to_global_generation_register(IntelGraphics::GlobalGenerationRegister::PipeAConf, 0);
dbgln_if(INTEL_GRAPHICS_DEBUG, "Disabling Pipe A");
wait_for_disabled_pipe_a(100);
dbgln_if(INTEL_GRAPHICS_DEBUG, "Disabling Pipe A - done.");
}
void IntelDisplayConnectorGroup::disable_pipe_b()
{
VERIFY(m_control_lock.is_locked());
VERIFY(m_modeset_lock.is_locked());
write_to_global_generation_register(IntelGraphics::GlobalGenerationRegister::PipeAConf, 0);
dbgln_if(INTEL_GRAPHICS_DEBUG, "Disabling Pipe B");
wait_for_disabled_pipe_b(100);
dbgln_if(INTEL_GRAPHICS_DEBUG, "Disabling Pipe B - done.");
}
void IntelDisplayConnectorGroup::enable_pipe_a()
{
VERIFY(m_control_lock.is_locked());
VERIFY(m_modeset_lock.is_locked());
VERIFY(!(read_from_global_generation_register(IntelGraphics::GlobalGenerationRegister::PipeAConf) & (1 << 31)));
VERIFY(!(read_from_global_generation_register(IntelGraphics::GlobalGenerationRegister::PipeAConf) & (1 << 30)));
write_to_global_generation_register(IntelGraphics::GlobalGenerationRegister::PipeAConf, (1 << 31) | (1 << 24));
dbgln_if(INTEL_GRAPHICS_DEBUG, "enabling Pipe A");
// FIXME: Seems like my video card is buggy and doesn't set the enabled bit (bit 30)!!
wait_for_enabled_pipe_a(100);
dbgln_if(INTEL_GRAPHICS_DEBUG, "enabling Pipe A - done.");
}
void IntelDisplayConnectorGroup::disable_dac_output() void IntelDisplayConnectorGroup::disable_dac_output()
{ {
VERIFY(m_control_lock.is_locked()); VERIFY(m_control_lock.is_locked());

View file

@ -60,8 +60,6 @@ private:
StringView convert_analog_output_register_to_string(AnalogOutputRegisterOffset index) const; StringView convert_analog_output_register_to_string(AnalogOutputRegisterOffset index) const;
void write_to_analog_output_register(AnalogOutputRegisterOffset, u32 value); void write_to_analog_output_register(AnalogOutputRegisterOffset, u32 value);
u32 read_from_analog_output_register(AnalogOutputRegisterOffset) const; u32 read_from_analog_output_register(AnalogOutputRegisterOffset) const;
u32 read_from_global_generation_register(IntelGraphics::GlobalGenerationRegister index) const;
void write_to_global_generation_register(IntelGraphics::GlobalGenerationRegister index, u32 value);
void write_to_general_register(RegisterOffset offset, u32 value); void write_to_general_register(RegisterOffset offset, u32 value);
u32 read_from_general_register(RegisterOffset offset) const; u32 read_from_general_register(RegisterOffset offset) const;
@ -71,8 +69,6 @@ private:
// General Modesetting methods // General Modesetting methods
ErrorOr<void> set_gen4_mode_setting(IntelNativeDisplayConnector&, DisplayConnector::ModeSetting const&); ErrorOr<void> set_gen4_mode_setting(IntelNativeDisplayConnector&, DisplayConnector::ModeSetting const&);
bool pipe_a_enabled() const;
bool pipe_b_enabled() const;
bool set_crt_resolution(DisplayConnector::ModeSetting const&); bool set_crt_resolution(DisplayConnector::ModeSetting const&);
@ -82,15 +78,6 @@ private:
void disable_dac_output(); void disable_dac_output();
void enable_dac_output(); void enable_dac_output();
void disable_pipe_a();
void disable_pipe_b();
void enable_pipe_a();
bool wait_for_enabled_pipe_a(size_t milliseconds_timeout) const;
bool wait_for_disabled_pipe_a(size_t milliseconds_timeout) const;
bool wait_for_disabled_pipe_b(size_t milliseconds_timeout) const;
Optional<IntelGraphics::PLLSettings> create_pll_settings(u64 target_frequency, u64 reference_clock, IntelGraphics::PLLMaxSettings const&); Optional<IntelGraphics::PLLSettings> create_pll_settings(u64 target_frequency, u64 reference_clock, IntelGraphics::PLLMaxSettings const&);
Spinlock<LockRank::None> m_control_lock; Spinlock<LockRank::None> m_control_lock;

View file

@ -11,17 +11,18 @@
namespace Kernel { namespace Kernel {
ErrorOr<NonnullOwnPtr<IntelAnalogDisplayTranscoder>> IntelAnalogDisplayTranscoder::create_with_physical_addresses(PhysicalAddress transcoder_registers_start_address, ErrorOr<NonnullOwnPtr<IntelAnalogDisplayTranscoder>> IntelAnalogDisplayTranscoder::create_with_physical_addresses(PhysicalAddress transcoder_registers_start_address,
PhysicalAddress dpll_registers_start_address, PhysicalAddress dpll_multiplier_register_start_address) PhysicalAddress pipe_registers_start_address, PhysicalAddress dpll_registers_start_address, PhysicalAddress dpll_multiplier_register_start_address)
{ {
auto transcoder_registers_mapping = TRY(Memory::map_typed<TranscoderRegisters volatile>(transcoder_registers_start_address, sizeof(IntelDisplayTranscoder::TranscoderRegisters), Memory::Region::Access::ReadWrite)); auto transcoder_registers_mapping = TRY(Memory::map_typed<TranscoderRegisters volatile>(transcoder_registers_start_address, sizeof(IntelDisplayTranscoder::TranscoderRegisters), Memory::Region::Access::ReadWrite));
auto pipe_registers_mapping = TRY(Memory::map_typed<PipeRegisters volatile>(pipe_registers_start_address, sizeof(IntelDisplayTranscoder::PipeRegisters), Memory::Region::Access::ReadWrite));
auto dpll_registers_mapping = TRY(Memory::map_typed<DPLLRegisters volatile>(dpll_registers_start_address, sizeof(DPLLRegisters), Memory::Region::Access::ReadWrite)); auto dpll_registers_mapping = TRY(Memory::map_typed<DPLLRegisters volatile>(dpll_registers_start_address, sizeof(DPLLRegisters), Memory::Region::Access::ReadWrite));
auto dpll_control_mapping = TRY(Memory::map_typed<DPLLControlRegisters volatile>(dpll_multiplier_register_start_address, sizeof(DPLLControlRegisters), Memory::Region::Access::ReadWrite)); auto dpll_control_mapping = TRY(Memory::map_typed<DPLLControlRegisters volatile>(dpll_multiplier_register_start_address, sizeof(DPLLControlRegisters), Memory::Region::Access::ReadWrite));
return adopt_nonnull_own_or_enomem(new (nothrow) IntelAnalogDisplayTranscoder(move(transcoder_registers_mapping), move(dpll_registers_mapping), move(dpll_control_mapping))); return adopt_nonnull_own_or_enomem(new (nothrow) IntelAnalogDisplayTranscoder(move(transcoder_registers_mapping), move(pipe_registers_mapping), move(dpll_registers_mapping), move(dpll_control_mapping)));
} }
IntelAnalogDisplayTranscoder::IntelAnalogDisplayTranscoder(Memory::TypedMapping<TranscoderRegisters volatile> transcoder_registers_mapping, IntelAnalogDisplayTranscoder::IntelAnalogDisplayTranscoder(Memory::TypedMapping<TranscoderRegisters volatile> transcoder_registers_mapping,
Memory::TypedMapping<DPLLRegisters volatile> dpll_registers_mapping, Memory::TypedMapping<DPLLControlRegisters volatile> dpll_control_registers) Memory::TypedMapping<PipeRegisters volatile> pipe_registers_mapping, Memory::TypedMapping<DPLLRegisters volatile> dpll_registers_mapping, Memory::TypedMapping<DPLLControlRegisters volatile> dpll_control_registers)
: IntelDisplayTranscoder(move(transcoder_registers_mapping)) : IntelDisplayTranscoder(move(transcoder_registers_mapping), move(pipe_registers_mapping))
, m_dpll_registers(move(dpll_registers_mapping)) , m_dpll_registers(move(dpll_registers_mapping))
, m_dpll_control_registers(move(dpll_control_registers)) , m_dpll_control_registers(move(dpll_control_registers))
{ {

View file

@ -17,7 +17,7 @@ class IntelDisplayConnectorGroup;
class IntelAnalogDisplayTranscoder final : public IntelDisplayTranscoder { class IntelAnalogDisplayTranscoder final : public IntelDisplayTranscoder {
public: public:
static ErrorOr<NonnullOwnPtr<IntelAnalogDisplayTranscoder>> create_with_physical_addresses(PhysicalAddress transcoder_registers_start_address, static ErrorOr<NonnullOwnPtr<IntelAnalogDisplayTranscoder>> create_with_physical_addresses(PhysicalAddress transcoder_registers_start_address,
PhysicalAddress dpll_registers_start_address, PhysicalAddress dpll_control_registers_start_address); PhysicalAddress pipe_registers_start_address, PhysicalAddress dpll_registers_start_address, PhysicalAddress dpll_control_registers_start_address);
virtual ErrorOr<void> set_dpll_settings(Badge<IntelDisplayConnectorGroup>, IntelGraphics::PLLSettings const& settings, size_t dac_multiplier) override; virtual ErrorOr<void> set_dpll_settings(Badge<IntelDisplayConnectorGroup>, IntelGraphics::PLLSettings const& settings, size_t dac_multiplier) override;
virtual ErrorOr<void> enable_dpll_without_vga(Badge<IntelDisplayConnectorGroup>) override; virtual ErrorOr<void> enable_dpll_without_vga(Badge<IntelDisplayConnectorGroup>) override;
@ -35,7 +35,7 @@ private:
u32 multiplier; u32 multiplier;
}; };
IntelAnalogDisplayTranscoder(Memory::TypedMapping<TranscoderRegisters volatile>, Memory::TypedMapping<DPLLRegisters volatile>, Memory::TypedMapping<DPLLControlRegisters volatile>); IntelAnalogDisplayTranscoder(Memory::TypedMapping<TranscoderRegisters volatile>, Memory::TypedMapping<PipeRegisters volatile>, Memory::TypedMapping<DPLLRegisters volatile>, Memory::TypedMapping<DPLLControlRegisters volatile>);
Memory::TypedMapping<DPLLRegisters volatile> m_dpll_registers; Memory::TypedMapping<DPLLRegisters volatile> m_dpll_registers;
Memory::TypedMapping<DPLLControlRegisters volatile> m_dpll_control_registers; Memory::TypedMapping<DPLLControlRegisters volatile> m_dpll_control_registers;
}; };

View file

@ -4,13 +4,15 @@
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <Kernel/Arch/Delay.h>
#include <Kernel/Graphics/Intel/Transcoder/DisplayTranscoder.h> #include <Kernel/Graphics/Intel/Transcoder/DisplayTranscoder.h>
#include <Kernel/PhysicalAddress.h> #include <Kernel/PhysicalAddress.h>
namespace Kernel { namespace Kernel {
IntelDisplayTranscoder::IntelDisplayTranscoder(Memory::TypedMapping<TranscoderRegisters volatile> registers_mapping) IntelDisplayTranscoder::IntelDisplayTranscoder(Memory::TypedMapping<TranscoderRegisters volatile> registers_mapping, Memory::TypedMapping<PipeRegisters volatile> pipe_registers_mapping)
: m_transcoder_registers(move(registers_mapping)) : m_transcoder_registers(move(registers_mapping))
, m_pipe_registers(move(pipe_registers_mapping))
{ {
} }
@ -54,4 +56,55 @@ ErrorOr<void> IntelDisplayTranscoder::set_mode_setting_timings(Badge<IntelDispla
return {}; return {};
} }
ErrorOr<void> IntelDisplayTranscoder::disable_pipe(Badge<IntelDisplayConnectorGroup>)
{
SpinlockLocker locker(m_access_lock);
m_pipe_registers->pipe_configuration = 0;
m_shadow_registers.pipe_conf = 0;
dbgln_if(INTEL_GRAPHICS_DEBUG, "Disabling Pipe");
size_t milliseconds_elapsed = 0;
while (milliseconds_elapsed < 100) {
u32 value = m_pipe_registers->pipe_configuration;
if (!(value & (1 << 30)))
return {};
microseconds_delay(1000);
milliseconds_elapsed++;
}
return Error::from_errno(EBUSY);
}
ErrorOr<void> IntelDisplayTranscoder::enable_pipe(Badge<IntelDisplayConnectorGroup>)
{
SpinlockLocker locker(m_access_lock);
u32 value = m_pipe_registers->pipe_configuration;
// Note: Just verify these are not already enabled...
if ((value & (1 << 30)) && (value & (1 << 31)))
return {};
// Note: Set the pipe configuration register with these bits:
// 1. Bit 31 - to enable the Pipe
// 2. Bit 24 - to enable Gamma Unit Mode to 10 bit Gamma mode.
// 3. Bits 21-23 are set to zero to indicate Progressive mode (non Interlaced mode)
// 4. Bits 18 and 19 are set to zero to indicate Normal operations of assigned
// Cursor and Display planes.
m_pipe_registers->pipe_configuration = (1 << 31) | (1 << 24);
m_shadow_registers.pipe_conf = (1 << 31) | (1 << 24);
dbgln_if(INTEL_GRAPHICS_DEBUG, "Enabling Pipe");
size_t milliseconds_elapsed = 0;
while (milliseconds_elapsed < 100) {
u32 value = m_pipe_registers->pipe_configuration;
if ((value & (1 << 30)))
return {};
microseconds_delay(1000);
milliseconds_elapsed++;
}
// FIXME: Seems like my video card is buggy and doesn't set the enabled bit (bit 30)!!
return {};
}
bool IntelDisplayTranscoder::pipe_enabled(Badge<IntelDisplayConnectorGroup>) const
{
SpinlockLocker locker(m_access_lock);
u32 value = m_pipe_registers->pipe_configuration;
return (value & (1 << 30));
}
} }

View file

@ -48,6 +48,7 @@ public:
u32 n1_link; u32 n1_link;
u32 m2_link; u32 m2_link;
u32 n2_link; u32 n2_link;
u32 pipe_conf;
}; };
ErrorOr<void> set_mode_setting_timings(Badge<IntelDisplayConnectorGroup>, DisplayConnector::ModeSetting const&); ErrorOr<void> set_mode_setting_timings(Badge<IntelDisplayConnectorGroup>, DisplayConnector::ModeSetting const&);
@ -55,6 +56,10 @@ public:
virtual ErrorOr<void> enable_dpll_without_vga(Badge<IntelDisplayConnectorGroup>) = 0; virtual ErrorOr<void> enable_dpll_without_vga(Badge<IntelDisplayConnectorGroup>) = 0;
virtual ErrorOr<void> disable_dpll(Badge<IntelDisplayConnectorGroup>) = 0; virtual ErrorOr<void> disable_dpll(Badge<IntelDisplayConnectorGroup>) = 0;
ErrorOr<void> disable_pipe(Badge<IntelDisplayConnectorGroup>);
ErrorOr<void> enable_pipe(Badge<IntelDisplayConnectorGroup>);
bool pipe_enabled(Badge<IntelDisplayConnectorGroup>) const;
ShadowRegisters current_registers_state() const; ShadowRegisters current_registers_state() const;
virtual ~IntelDisplayTranscoder() = default; virtual ~IntelDisplayTranscoder() = default;
@ -83,9 +88,31 @@ protected:
u32 n2_link; u32 n2_link;
}; };
explicit IntelDisplayTranscoder(Memory::TypedMapping<TranscoderRegisters volatile>); struct [[gnu::packed]] PipeRegisters {
u32 pipe_display_scan_line;
u32 pipe_display_scan_line_count_range_compare;
u32 pipe_configuration;
u32 reserved;
u32 pipe_gamma_correction_max_red;
u32 pipe_gamma_correction_max_green;
u32 pipe_gamma_correction_max_blue;
u32 reserved2[2];
u32 pipe_display_status;
u32 reserved3[2];
u32 display_arbitration_control;
u32 display_fifo_watermark_control1;
u32 display_fifo_watermark_control2;
u32 display_fifo_watermark_control3;
u32 pipe_frame_count_high;
// Note: The specification calls this "Pipe Frame Count Low and Pixel Count"
u32 pipe_frame_count_low;
};
IntelDisplayTranscoder(Memory::TypedMapping<TranscoderRegisters volatile>, Memory::TypedMapping<PipeRegisters volatile>);
mutable Spinlock<LockRank::None> m_access_lock; mutable Spinlock<LockRank::None> m_access_lock;
ShadowRegisters m_shadow_registers {}; ShadowRegisters m_shadow_registers {};
Memory::TypedMapping<TranscoderRegisters volatile> m_transcoder_registers; Memory::TypedMapping<TranscoderRegisters volatile> m_transcoder_registers;
Memory::TypedMapping<PipeRegisters volatile> m_pipe_registers;
}; };
} }