From 6efa27537a108ddb19e5f112c2d4d86e72ed647b Mon Sep 17 00:00:00 2001 From: Liav A Date: Fri, 11 Feb 2022 21:47:45 +0200 Subject: [PATCH] Kernel/Audio: Introduce a new design architecture for the subsystem We have 3 new components: 1. The AudioManagement singleton. This class like in other subsystems, is responsible to find hardware audio controllers and keep a reference to them. 2. AudioController class - this class is the parent class for hardware controllers like the Sound Blaster 16 or Intel 82801AA (AC97). For now, this class has simple interface for getting and controlling sample rate of audio channels, as well a write interface for specific audio channel but not reading from it. One AudioController object might have multiple AudioChannel "child" objects to hold with reference counting. 3. AudioChannel class - this is based on the CharacterDevice class, and represents hardware PCM audio channel. It facilitates an ioctl interface which should be consistent across all supported hardware currently. It has a weak reference to a parent AudioController, and when trying to write to a channel, it redirects the data to the parent AudioController. Each audio channel device should be added into a new directory under the /dev filesystem called "audio". --- Kernel/CMakeLists.txt | 2 + Kernel/Devices/Audio/AC97.cpp | 71 +++++++++++-------------- Kernel/Devices/Audio/AC97.h | 31 ++++++----- Kernel/Devices/Audio/Channel.cpp | 73 +++++++++++++++++++++++++ Kernel/Devices/Audio/Channel.h | 43 +++++++++++++++ Kernel/Devices/Audio/Controller.h | 45 ++++++++++++++++ Kernel/Devices/Audio/Management.cpp | 82 +++++++++++++++++++++++++++++ Kernel/Devices/Audio/Management.h | 38 +++++++++++++ Kernel/Devices/Audio/SB16.cpp | 79 +++++++++++++-------------- Kernel/Devices/Audio/SB16.h | 30 +++++------ Kernel/Devices/DeviceManagement.cpp | 5 -- Kernel/Devices/DeviceManagement.h | 4 -- Kernel/init.cpp | 6 +-- 13 files changed, 382 insertions(+), 127 deletions(-) create mode 100644 Kernel/Devices/Audio/Channel.cpp create mode 100644 Kernel/Devices/Audio/Channel.h create mode 100644 Kernel/Devices/Audio/Controller.h create mode 100644 Kernel/Devices/Audio/Management.cpp create mode 100644 Kernel/Devices/Audio/Management.h diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index cdf1dca325..d32357bd25 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -46,6 +46,8 @@ set(KERNEL_SOURCES Coredump.cpp Devices/AsyncDeviceRequest.cpp Devices/Audio/AC97.cpp + Devices/Audio/Channel.cpp + Devices/Audio/Management.cpp Devices/Audio/SB16.cpp Devices/BlockDevice.cpp Devices/CharacterDevice.cpp diff --git a/Kernel/Devices/Audio/AC97.cpp b/Kernel/Devices/Audio/AC97.cpp index b19ab3b00b..d603313f9b 100644 --- a/Kernel/Devices/Audio/AC97.cpp +++ b/Kernel/Devices/Audio/AC97.cpp @@ -7,7 +7,6 @@ #include #include #include -#include namespace Kernel { @@ -20,28 +19,14 @@ static constexpr u16 pcm_fixed_sample_rate = 48000; static constexpr u16 pcm_sample_rate_minimum = 8000; static constexpr u16 pcm_sample_rate_maximum = 48000; -UNMAP_AFTER_INIT void AC97::detect() +UNMAP_AFTER_INIT ErrorOr> AC97::try_create(PCI::DeviceIdentifier const& pci_device_identifier) { - PCI::enumerate([&](PCI::DeviceIdentifier const& device_identifier) { - // Only consider PCI audio controllers - if (device_identifier.class_code().value() != to_underlying(PCI::ClassID::Multimedia) - || device_identifier.subclass_code().value() != to_underlying(PCI::Multimedia::SubclassID::AudioController)) - return; - - dbgln("AC97: found audio controller at {}", device_identifier.address()); - auto device_or_error = DeviceManagement::try_create_device(device_identifier); - if (device_or_error.is_error()) { - dbgln("AC97: failed to initialize device {}", device_identifier.address()); - return; - } - DeviceManagement::the().attach_audio_device(device_or_error.release_value()); - }); + return adopt_nonnull_ref_or_enomem(new (nothrow) AC97(pci_device_identifier)); } UNMAP_AFTER_INIT AC97::AC97(PCI::DeviceIdentifier const& pci_device_identifier) : PCI::Device(pci_device_identifier.address()) , IRQHandler(pci_device_identifier.interrupt_line().value()) - , CharacterDevice(42, 42) , m_io_mixer_base(PCI::get_BAR0(pci_address()) & ~1) , m_io_bus_base(PCI::get_BAR1(pci_address()) & ~1) , m_pcm_out_channel(channel("PCMOut"sv, NativeAudioBusChannel::PCMOutChannel)) @@ -129,28 +114,6 @@ UNMAP_AFTER_INIT void AC97::initialize() enable_irq(); } -ErrorOr AC97::ioctl(OpenFileDescription&, unsigned request, Userspace arg) -{ - switch (request) { - case SOUNDCARD_IOCTL_GET_SAMPLE_RATE: { - auto output = static_ptr_cast(arg); - return copy_to_user(output, &m_sample_rate); - } - case SOUNDCARD_IOCTL_SET_SAMPLE_RATE: { - auto sample_rate = static_cast(arg.ptr()); - TRY(set_pcm_output_sample_rate(sample_rate)); - return {}; - } - default: - return EINVAL; - } -} - -ErrorOr AC97::read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) -{ - return 0; -} - void AC97::reset_pcm_out() { m_pcm_out_channel.reset(); @@ -194,8 +157,36 @@ void AC97::set_pcm_output_volume(u8 left_channel, u8 right_channel, Muted mute) m_io_mixer_base.offset(NativeAudioMixerRegister::SetPCMOutputVolume).out(volume_value); } -ErrorOr AC97::write(OpenFileDescription&, u64, UserOrKernelBuffer const& data, size_t length) +RefPtr AC97::audio_channel(u32 index) const { + if (index == 0) + return m_audio_channel; + return {}; +} +void AC97::detect_hardware_audio_channels(Badge) +{ + m_audio_channel = AudioChannel::must_create(*this, 0); +} + +ErrorOr AC97::set_pcm_output_sample_rate(size_t channel_index, u32 samples_per_second_rate) +{ + if (channel_index != 0) + return Error::from_errno(ENODEV); + TRY(set_pcm_output_sample_rate(samples_per_second_rate)); + return {}; +} +ErrorOr AC97::get_pcm_output_sample_rate(size_t channel_index) +{ + if (channel_index != 0) + return Error::from_errno(ENODEV); + return m_sample_rate; +} + +ErrorOr AC97::write(size_t channel_index, UserOrKernelBuffer const& data, size_t length) +{ + if (channel_index != 0) + return Error::from_errno(ENODEV); + if (!m_output_buffer) { m_output_buffer = TRY(MM.allocate_dma_buffer_pages(m_output_buffer_page_count * PAGE_SIZE, "AC97 Output buffer"sv, Memory::Region::Access::Write)); } diff --git a/Kernel/Devices/Audio/AC97.h b/Kernel/Devices/Audio/AC97.h index 56c31acd9e..a20fb9d2ec 100644 --- a/Kernel/Devices/Audio/AC97.h +++ b/Kernel/Devices/Audio/AC97.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -17,25 +18,18 @@ namespace Kernel { // See: https://www-inst.eecs.berkeley.edu/~cs150/Documents/ac97_r23.pdf // And: https://www.intel.com/content/dam/doc/manual/io-controller-hub-7-hd-audio-ac97-manual.pdf -class AC97 final : public PCI::Device - , public IRQHandler - , public CharacterDevice { - friend class DeviceManagement; +class AC97 final + : public AudioController + , public PCI::Device + , public IRQHandler { public: - static void detect(); + static ErrorOr> try_create(PCI::DeviceIdentifier const&); virtual ~AC97() override; // ^IRQHandler - virtual StringView purpose() const override { return class_name(); } - - // ^CharacterDevice - virtual bool can_read(const OpenFileDescription&, u64) const override { return false; } - virtual bool can_write(const OpenFileDescription&, u64) const override { return true; } - virtual ErrorOr ioctl(OpenFileDescription&, unsigned, Userspace) override; - virtual ErrorOr read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override; - virtual ErrorOr write(OpenFileDescription&, u64, const UserOrKernelBuffer&, size_t) override; + virtual StringView purpose() const override { return "AC97"sv; } private: enum NativeAudioMixerRegister : u8 { @@ -150,9 +144,6 @@ private: // ^IRQHandler virtual bool handle_irq(const RegisterState&) override; - // ^CharacterDevice - virtual StringView class_name() const override { return "AC97"sv; } - AC97Channel channel(StringView name, NativeAudioBusChannel channel) { return AC97Channel(*this, name, m_io_bus_base.offset(channel)); } void initialize(); void reset_pcm_out(); @@ -161,6 +152,13 @@ private: void set_pcm_output_volume(u8, u8, Muted); ErrorOr write_single_buffer(UserOrKernelBuffer const&, size_t, size_t); + // ^AudioController + virtual RefPtr audio_channel(u32 index) const override; + virtual ErrorOr write(size_t channel_index, UserOrKernelBuffer const& data, size_t length) override; + virtual void detect_hardware_audio_channels(Badge) override; + virtual ErrorOr set_pcm_output_sample_rate(size_t channel_index, u32 samples_per_second_rate) override; + virtual ErrorOr get_pcm_output_sample_rate(size_t channel_index) override; + OwnPtr m_buffer_descriptor_list; u8 m_buffer_descriptor_list_index = 0; bool m_double_rate_pcm_enabled = false; @@ -173,6 +171,7 @@ private: AC97Channel m_pcm_out_channel; u32 m_sample_rate = 0; bool m_variable_rate_pcm_supported = false; + RefPtr m_audio_channel; }; } diff --git a/Kernel/Devices/Audio/Channel.cpp b/Kernel/Devices/Audio/Channel.cpp new file mode 100644 index 0000000000..ac390d7aed --- /dev/null +++ b/Kernel/Devices/Audio/Channel.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include + +namespace Kernel { + +UNMAP_AFTER_INIT NonnullRefPtr AudioChannel::must_create(AudioController const& controller, size_t channel_index) +{ + auto audio_device_or_error = DeviceManagement::try_create_device(controller, channel_index); + // FIXME: Find a way to propagate errors + VERIFY(!audio_device_or_error.is_error()); + return audio_device_or_error.release_value(); +} + +AudioChannel::AudioChannel(AudioController const& controller, size_t channel_index) + : CharacterDevice(AudioManagement::the().audio_type_major_number(), AudioManagement::the().generate_storage_minor_number()) + , m_controller(controller) + , m_channel_index(channel_index) +{ +} + +ErrorOr AudioChannel::ioctl(OpenFileDescription&, unsigned request, Userspace arg) +{ + auto controller = m_controller.strong_ref(); + if (!controller) + return Error::from_errno(EIO); + switch (request) { + case SOUNDCARD_IOCTL_GET_SAMPLE_RATE: { + auto output = static_ptr_cast(arg); + u32 sample_rate = 0; + sample_rate = TRY(controller->get_pcm_output_sample_rate(m_channel_index)); + return copy_to_user(output, &sample_rate); + } + case SOUNDCARD_IOCTL_SET_SAMPLE_RATE: { + auto sample_rate = static_cast(arg.ptr()); + TRY(controller->set_pcm_output_sample_rate(m_channel_index, sample_rate)); + return {}; + } + default: + return EINVAL; + } +} + +bool AudioChannel::can_read(const OpenFileDescription&, u64) const +{ + // FIXME: Implement input from device + return false; +} + +ErrorOr AudioChannel::read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) +{ + // FIXME: Implement input from device + return Error::from_errno(ENOTIMPL); +} + +ErrorOr AudioChannel::write(OpenFileDescription&, u64, UserOrKernelBuffer const& buffer, size_t size) +{ + auto controller = m_controller.strong_ref(); + if (!controller) + return Error::from_errno(EIO); + return controller->write(m_channel_index, buffer, size); +} + +} diff --git a/Kernel/Devices/Audio/Channel.h b/Kernel/Devices/Audio/Channel.h new file mode 100644 index 0000000000..08da059352 --- /dev/null +++ b/Kernel/Devices/Audio/Channel.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace Kernel { + +class AudioController; +class AudioChannel final + : public CharacterDevice { + friend class DeviceManagement; + +public: + static NonnullRefPtr must_create(AudioController const&, size_t channel_index); + virtual ~AudioChannel() override { } + + // ^CharacterDevice + virtual bool can_read(const OpenFileDescription&, u64) const override; + virtual ErrorOr read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override; + virtual ErrorOr write(OpenFileDescription&, u64, const UserOrKernelBuffer&, size_t) override; + virtual bool can_write(const OpenFileDescription&, u64) const override { return true; } + + virtual ErrorOr ioctl(OpenFileDescription&, unsigned, Userspace) override; + +private: + AudioChannel(AudioController const&, size_t channel_index); + + // ^CharacterDevice + virtual StringView class_name() const override { return "AudioChannel"sv; } + + WeakPtr m_controller; + const size_t m_channel_index; +}; +} diff --git a/Kernel/Devices/Audio/Controller.h b/Kernel/Devices/Audio/Controller.h new file mode 100644 index 0000000000..0b63c50eb6 --- /dev/null +++ b/Kernel/Devices/Audio/Controller.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Kernel { + +class AudioManagement; +class AudioController + : public RefCounted + , public Weakable { + friend class AudioManagement; + +public: + virtual ~AudioController() = default; + + virtual RefPtr audio_channel(u32 index) const = 0; + virtual ErrorOr write(size_t channel_index, UserOrKernelBuffer const& data, size_t length) = 0; + + virtual void detect_hardware_audio_channels(Badge) = 0; + + virtual ErrorOr set_pcm_output_sample_rate(size_t channel_index, u32 samples_per_second_rate) = 0; + // Note: The return value is rate of samples per second + virtual ErrorOr get_pcm_output_sample_rate(size_t channel_index) = 0; + +private: + IntrusiveListNode> m_node; +}; +} diff --git a/Kernel/Devices/Audio/Management.cpp b/Kernel/Devices/Audio/Management.cpp new file mode 100644 index 0000000000..095b3c796b --- /dev/null +++ b/Kernel/Devices/Audio/Management.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace Kernel { + +static Singleton s_the; +static Atomic s_device_minor_number; + +MajorNumber AudioManagement::audio_type_major_number() +{ + return 116; +} +MinorNumber AudioManagement::generate_storage_minor_number() +{ + auto minor_number = s_device_minor_number.load(); + s_device_minor_number++; + return minor_number; +} + +AudioManagement& AudioManagement::the() +{ + return *s_the; +} + +UNMAP_AFTER_INIT AudioManagement::AudioManagement() +{ +} + +UNMAP_AFTER_INIT void AudioManagement::enumerate_hardware_controllers() +{ + if (auto controller = SB16::try_detect_and_create(); !controller.is_error()) + m_controllers_list.append(controller.release_value()); + + PCI::enumerate([&](PCI::DeviceIdentifier const& device_identifier) { + // Note: Only consider PCI audio controllers + if (device_identifier.class_code().value() != to_underlying(PCI::ClassID::Multimedia) + || device_identifier.subclass_code().value() != to_underlying(PCI::Multimedia::SubclassID::AudioController)) + return; + + dbgln("AC97: found audio controller at {}", device_identifier.address()); + // FIXME: Propagate errors properly + m_controllers_list.append(AC97::try_create(device_identifier).release_value()); + }); +} + +UNMAP_AFTER_INIT void AudioManagement::enumerate_hardware_audio_channels() +{ + for (auto& controller : m_controllers_list) + controller.detect_hardware_audio_channels({}); +} + +UNMAP_AFTER_INIT bool AudioManagement::initialize() +{ + + /* Explanation on the flow: + * 1. Enumerate all audio controllers connected to the system: + * a. Try to find the SB16 ISA-based controller. + * b. Enumerate the PCI bus and try to find audio controllers there too + * 2. Ask each controller to detect the audio channels and instantiate AudioChannel objects. + */ + enumerate_hardware_controllers(); + enumerate_hardware_audio_channels(); + + if (m_controllers_list.is_empty()) { + dbgln("No audio controller was initialized."); + return false; + } + return true; +} + +} diff --git a/Kernel/Devices/Audio/Management.h b/Kernel/Devices/Audio/Management.h new file mode 100644 index 0000000000..9294fa881c --- /dev/null +++ b/Kernel/Devices/Audio/Management.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Kernel { + +class AudioManagement { + +public: + AudioManagement(); + static AudioManagement& the(); + + static MajorNumber audio_type_major_number(); + static MinorNumber generate_storage_minor_number(); + + bool initialize(); + +private: + void enumerate_hardware_controllers(); + void enumerate_hardware_audio_channels(); + + IntrusiveList<&AudioController::m_node> m_controllers_list; +}; + +} diff --git a/Kernel/Devices/Audio/SB16.cpp b/Kernel/Devices/Audio/SB16.cpp index b654060ba1..2d23118538 100644 --- a/Kernel/Devices/Audio/SB16.cpp +++ b/Kernel/Devices/Audio/SB16.cpp @@ -62,8 +62,6 @@ void SB16::set_sample_rate(uint16_t hz) UNMAP_AFTER_INIT SB16::SB16() : IRQHandler(SB16_DEFAULT_IRQ) - // FIXME: We can't change version numbers later, i.e. after the sound card is initialized. - , CharacterDevice(42, 42) { initialize(); } @@ -72,7 +70,7 @@ UNMAP_AFTER_INIT SB16::~SB16() { } -UNMAP_AFTER_INIT RefPtr SB16::try_detect_and_create() +UNMAP_AFTER_INIT ErrorOr> SB16::try_detect_and_create() { IO::out8(0x226, 1); IO::delay(32); @@ -80,13 +78,8 @@ UNMAP_AFTER_INIT RefPtr SB16::try_detect_and_create() auto data = dsp_read(); if (data != 0xaa) - return {}; - auto device_or_error = DeviceManagement::try_create_device(); - if (device_or_error.is_error()) - return {}; - auto device = device_or_error.release_value(); - DeviceManagement::the().attach_audio_device(device); - return device; + return Error::from_errno(ENODEV); + return adopt_nonnull_ref_or_enomem(new (nothrow) SB16()); } UNMAP_AFTER_INIT void SB16::initialize() @@ -115,27 +108,6 @@ UNMAP_AFTER_INIT void SB16::initialize() set_sample_rate(m_sample_rate); } -ErrorOr SB16::ioctl(OpenFileDescription&, unsigned request, Userspace arg) -{ - switch (request) { - case SOUNDCARD_IOCTL_GET_SAMPLE_RATE: { - auto output = static_ptr_cast(arg); - return copy_to_user(output, &m_sample_rate); - } - case SOUNDCARD_IOCTL_SET_SAMPLE_RATE: { - auto sample_rate_input = static_cast(arg.ptr()); - if (sample_rate_input == 0 || sample_rate_input > 44100) - return ENOTSUP; - auto sample_rate_value = static_cast(sample_rate_input); - if (m_sample_rate != sample_rate_value) - set_sample_rate(sample_rate_value); - return {}; - } - default: - return EINVAL; - } -} - void SB16::set_irq_register(u8 irq_number) { u8 bitmask; @@ -184,16 +156,6 @@ void SB16::set_irq_line(u8 irq_number) change_irq_number(irq_number); } -bool SB16::can_read(OpenFileDescription const&, u64) const -{ - return false; -} - -ErrorOr SB16::read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) -{ - return 0; -} - void SB16::dma_start(uint32_t length) { auto const addr = m_dma_region->physical_page(0)->paddr().get(); @@ -249,8 +211,41 @@ void SB16::wait_for_irq() disable_irq(); } -ErrorOr SB16::write(OpenFileDescription&, u64, UserOrKernelBuffer const& data, size_t length) +RefPtr SB16::audio_channel(u32 index) const { + if (index == 0) + return m_audio_channel; + return {}; +} +void SB16::detect_hardware_audio_channels(Badge) +{ + m_audio_channel = AudioChannel::must_create(*this, 0); +} + +ErrorOr SB16::set_pcm_output_sample_rate(size_t channel_index, u32 samples_per_second_rate) +{ + if (channel_index != 0) + return Error::from_errno(ENODEV); + if (samples_per_second_rate == 0 || samples_per_second_rate > 44100) + return Error::from_errno(ENOTSUP); + auto sample_rate_value = static_cast(samples_per_second_rate); + if (m_sample_rate != sample_rate_value) + set_sample_rate(sample_rate_value); + return {}; +} + +ErrorOr SB16::get_pcm_output_sample_rate(size_t channel_index) +{ + if (channel_index != 0) + return Error::from_errno(ENODEV); + return m_sample_rate; +} + +ErrorOr SB16::write(size_t channel_index, UserOrKernelBuffer const& data, size_t length) +{ + if (channel_index != 0) + return Error::from_errno(ENODEV); + if (!m_dma_region) { m_dma_region = TRY(MM.allocate_dma_buffer_page("SB16 DMA buffer", Memory::Region::Access::Write)); } diff --git a/Kernel/Devices/Audio/SB16.h b/Kernel/Devices/Audio/SB16.h index a5b77dc76b..8d6e85d467 100644 --- a/Kernel/Devices/Audio/SB16.h +++ b/Kernel/Devices/Audio/SB16.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include #include @@ -16,34 +17,30 @@ namespace Kernel { class SB16; -class SB16 final : public IRQHandler - , public CharacterDevice { - friend class DeviceManagement; +class SB16 final + : public AudioController + , public IRQHandler { public: virtual ~SB16() override; - static RefPtr try_detect_and_create(); + static ErrorOr> try_detect_and_create(); - // ^CharacterDevice - virtual bool can_read(const OpenFileDescription&, u64) const override; - virtual ErrorOr read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override; - virtual ErrorOr write(OpenFileDescription&, u64, const UserOrKernelBuffer&, size_t) override; - virtual bool can_write(const OpenFileDescription&, u64) const override { return true; } - - virtual StringView purpose() const override { return class_name(); } - - virtual ErrorOr ioctl(OpenFileDescription&, unsigned, Userspace) override; + virtual StringView purpose() const override { return "SB16"sv; } private: + // ^AudioController + virtual RefPtr audio_channel(u32 index) const override; + virtual ErrorOr write(size_t channel_index, UserOrKernelBuffer const& data, size_t length) override; + virtual void detect_hardware_audio_channels(Badge) override; + virtual ErrorOr set_pcm_output_sample_rate(size_t channel_index, u32 samples_per_second_rate) override; + virtual ErrorOr get_pcm_output_sample_rate(size_t channel_index) override; + SB16(); // ^IRQHandler virtual bool handle_irq(const RegisterState&) override; - // ^CharacterDevice - virtual StringView class_name() const override { return "SB16"sv; } - void initialize(); void wait_for_irq(); void dma_start(uint32_t length); @@ -59,5 +56,6 @@ private: u16 m_sample_rate { 44100 }; WaitQueue m_irq_queue; + RefPtr m_audio_channel; }; } diff --git a/Kernel/Devices/DeviceManagement.cpp b/Kernel/Devices/DeviceManagement.cpp index cf107a0f68..af82467454 100644 --- a/Kernel/Devices/DeviceManagement.cpp +++ b/Kernel/Devices/DeviceManagement.cpp @@ -22,11 +22,6 @@ UNMAP_AFTER_INIT void DeviceManagement::initialize() s_the.ensure_instance(); } -UNMAP_AFTER_INIT void DeviceManagement::attach_audio_device(CharacterDevice const& device) -{ - m_audio_devices.append(device); -} - UNMAP_AFTER_INIT void DeviceManagement::attach_console_device(ConsoleDevice const& device) { m_console_device = device; diff --git a/Kernel/Devices/DeviceManagement.h b/Kernel/Devices/DeviceManagement.h index 0e849d72bd..e23f86ce92 100644 --- a/Kernel/Devices/DeviceManagement.h +++ b/Kernel/Devices/DeviceManagement.h @@ -38,9 +38,6 @@ public: bool is_console_device_attached() const { return !m_console_device.is_null(); } void attach_console_device(ConsoleDevice const&); - // FIXME: Once we have a singleton for managing many sound cards, remove this from here - void attach_audio_device(CharacterDevice const&); - Optional dequeue_top_device_event(Badge); void after_inserting_device(Badge, Device&); @@ -76,7 +73,6 @@ private: RefPtr m_console_device; RefPtr m_device_control_device; // FIXME: Once we have a singleton for managing many sound cards, remove this from here - NonnullRefPtrVector m_audio_devices; SpinlockProtected> m_devices; mutable Spinlock m_event_queue_lock; diff --git a/Kernel/init.cpp b/Kernel/init.cpp index bdac48bfd3..9a7da70dfa 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -13,8 +13,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -339,8 +338,7 @@ void init_stage2(void*) (void)RandomDevice::must_create().leak_ref(); PTYMultiplexer::initialize(); - (void)SB16::try_detect_and_create(); - AC97::detect(); + AudioManagement::the().initialize(); StorageManagement::the().initialize(kernel_command_line().root_device(), kernel_command_line().is_force_pio(), kernel_command_line().is_nvme_polling_enabled()); if (VirtualFileSystem::the().mount_root(StorageManagement::the().root_filesystem()).is_error()) {