diff options
Diffstat (limited to 'Kernel/Devices')
-rw-r--r-- | Kernel/Devices/Audio/AC97.cpp | 71 | ||||
-rw-r--r-- | Kernel/Devices/Audio/AC97.h | 31 | ||||
-rw-r--r-- | Kernel/Devices/Audio/Channel.cpp | 73 | ||||
-rw-r--r-- | Kernel/Devices/Audio/Channel.h | 43 | ||||
-rw-r--r-- | Kernel/Devices/Audio/Controller.h | 45 | ||||
-rw-r--r-- | Kernel/Devices/Audio/Management.cpp | 82 | ||||
-rw-r--r-- | Kernel/Devices/Audio/Management.h | 38 | ||||
-rw-r--r-- | Kernel/Devices/Audio/SB16.cpp | 79 | ||||
-rw-r--r-- | Kernel/Devices/Audio/SB16.h | 30 | ||||
-rw-r--r-- | Kernel/Devices/DeviceManagement.cpp | 5 | ||||
-rw-r--r-- | Kernel/Devices/DeviceManagement.h | 4 |
11 files changed, 378 insertions, 123 deletions
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 <Kernel/Devices/Audio/AC97.h> #include <Kernel/Devices/DeviceManagement.h> #include <Kernel/Memory/AnonymousVMObject.h> -#include <LibC/sys/ioctl_numbers.h> 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<NonnullRefPtr<AC97>> 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<AC97>(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<void> AC97::ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg) -{ - switch (request) { - case SOUNDCARD_IOCTL_GET_SAMPLE_RATE: { - auto output = static_ptr_cast<u32*>(arg); - return copy_to_user(output, &m_sample_rate); - } - case SOUNDCARD_IOCTL_SET_SAMPLE_RATE: { - auto sample_rate = static_cast<u32>(arg.ptr()); - TRY(set_pcm_output_sample_rate(sample_rate)); - return {}; - } - default: - return EINVAL; - } -} - -ErrorOr<size_t> 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<size_t> AC97::write(OpenFileDescription&, u64, UserOrKernelBuffer const& data, size_t length) +RefPtr<AudioChannel> AC97::audio_channel(u32 index) const { + if (index == 0) + return m_audio_channel; + return {}; +} +void AC97::detect_hardware_audio_channels(Badge<AudioManagement>) +{ + m_audio_channel = AudioChannel::must_create(*this, 0); +} + +ErrorOr<void> 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<u32> AC97::get_pcm_output_sample_rate(size_t channel_index) +{ + if (channel_index != 0) + return Error::from_errno(ENODEV); + return m_sample_rate; +} + +ErrorOr<size_t> 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 <Kernel/Arch/x86/IO.h> #include <Kernel/Bus/PCI/API.h> #include <Kernel/Bus/PCI/Device.h> +#include <Kernel/Devices/Audio/Controller.h> #include <Kernel/Devices/CharacterDevice.h> #include <Kernel/Interrupts/IRQHandler.h> @@ -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<NonnullRefPtr<AC97>> 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<void> ioctl(OpenFileDescription&, unsigned, Userspace<void*>) override; - virtual ErrorOr<size_t> read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override; - virtual ErrorOr<size_t> 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<void> write_single_buffer(UserOrKernelBuffer const&, size_t, size_t); + // ^AudioController + virtual RefPtr<AudioChannel> audio_channel(u32 index) const override; + virtual ErrorOr<size_t> write(size_t channel_index, UserOrKernelBuffer const& data, size_t length) override; + virtual void detect_hardware_audio_channels(Badge<AudioManagement>) override; + virtual ErrorOr<void> set_pcm_output_sample_rate(size_t channel_index, u32 samples_per_second_rate) override; + virtual ErrorOr<u32> get_pcm_output_sample_rate(size_t channel_index) override; + OwnPtr<Memory::Region> 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<AudioChannel> 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. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <Kernel/Devices/Audio/Management.h> +#include <Kernel/Devices/DeviceManagement.h> +#include <Kernel/Devices/RandomDevice.h> +#include <Kernel/Random.h> +#include <Kernel/Sections.h> +#include <LibC/sys/ioctl_numbers.h> + +namespace Kernel { + +UNMAP_AFTER_INIT NonnullRefPtr<AudioChannel> AudioChannel::must_create(AudioController const& controller, size_t channel_index) +{ + auto audio_device_or_error = DeviceManagement::try_create_device<AudioChannel>(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<void> AudioChannel::ioctl(OpenFileDescription&, unsigned request, Userspace<void*> 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<u32*>(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<u32>(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<size_t> AudioChannel::read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) +{ + // FIXME: Implement input from device + return Error::from_errno(ENOTIMPL); +} + +ErrorOr<size_t> 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. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <Kernel/Devices/CharacterDevice.h> +#include <Kernel/Interrupts/IRQHandler.h> +#include <Kernel/Memory/PhysicalPage.h> +#include <Kernel/PhysicalAddress.h> +#include <Kernel/WaitQueue.h> + +namespace Kernel { + +class AudioController; +class AudioChannel final + : public CharacterDevice { + friend class DeviceManagement; + +public: + static NonnullRefPtr<AudioChannel> must_create(AudioController const&, size_t channel_index); + virtual ~AudioChannel() override { } + + // ^CharacterDevice + virtual bool can_read(const OpenFileDescription&, u64) const override; + virtual ErrorOr<size_t> read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override; + virtual ErrorOr<size_t> write(OpenFileDescription&, u64, const UserOrKernelBuffer&, size_t) override; + virtual bool can_write(const OpenFileDescription&, u64) const override { return true; } + + virtual ErrorOr<void> ioctl(OpenFileDescription&, unsigned, Userspace<void*>) override; + +private: + AudioChannel(AudioController const&, size_t channel_index); + + // ^CharacterDevice + virtual StringView class_name() const override { return "AudioChannel"sv; } + + WeakPtr<AudioController> 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. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/IntrusiveList.h> +#include <AK/OwnPtr.h> +#include <AK/RefPtr.h> +#include <AK/Weakable.h> +#include <Kernel/Bus/PCI/Access.h> +#include <Kernel/Bus/PCI/Device.h> +#include <Kernel/Devices/Audio/Channel.h> +#include <Kernel/Devices/Device.h> +#include <Kernel/Locking/Mutex.h> +#include <Kernel/Memory/PhysicalPage.h> +#include <Kernel/PhysicalAddress.h> +#include <Kernel/Random.h> + +namespace Kernel { + +class AudioManagement; +class AudioController + : public RefCounted<AudioController> + , public Weakable<AudioController> { + friend class AudioManagement; + +public: + virtual ~AudioController() = default; + + virtual RefPtr<AudioChannel> audio_channel(u32 index) const = 0; + virtual ErrorOr<size_t> write(size_t channel_index, UserOrKernelBuffer const& data, size_t length) = 0; + + virtual void detect_hardware_audio_channels(Badge<AudioManagement>) = 0; + + virtual ErrorOr<void> 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<u32> get_pcm_output_sample_rate(size_t channel_index) = 0; + +private: + IntrusiveListNode<AudioController, RefPtr<AudioController>> 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. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <AK/Singleton.h> +#include <Kernel/Bus/PCI/API.h> +#include <Kernel/Bus/PCI/IDs.h> +#include <Kernel/Devices/Audio/AC97.h> +#include <Kernel/Devices/Audio/Management.h> +#include <Kernel/Devices/Audio/SB16.h> +#include <Kernel/Sections.h> + +namespace Kernel { + +static Singleton<AudioManagement> s_the; +static Atomic<u32> 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. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/Badge.h> +#include <AK/Error.h> +#include <AK/IntrusiveList.h> +#include <AK/OwnPtr.h> +#include <AK/RefPtr.h> +#include <AK/Time.h> +#include <AK/Types.h> +#include <Kernel/Devices/Audio/Controller.h> + +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> SB16::try_detect_and_create() +UNMAP_AFTER_INIT ErrorOr<NonnullRefPtr<SB16>> SB16::try_detect_and_create() { IO::out8(0x226, 1); IO::delay(32); @@ -80,13 +78,8 @@ UNMAP_AFTER_INIT RefPtr<SB16> SB16::try_detect_and_create() auto data = dsp_read(); if (data != 0xaa) - return {}; - auto device_or_error = DeviceManagement::try_create_device<SB16>(); - 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<void> SB16::ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg) -{ - switch (request) { - case SOUNDCARD_IOCTL_GET_SAMPLE_RATE: { - auto output = static_ptr_cast<u16*>(arg); - return copy_to_user(output, &m_sample_rate); - } - case SOUNDCARD_IOCTL_SET_SAMPLE_RATE: { - auto sample_rate_input = static_cast<u32>(arg.ptr()); - if (sample_rate_input == 0 || sample_rate_input > 44100) - return ENOTSUP; - auto sample_rate_value = static_cast<u16>(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<size_t> 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<size_t> SB16::write(OpenFileDescription&, u64, UserOrKernelBuffer const& data, size_t length) +RefPtr<AudioChannel> SB16::audio_channel(u32 index) const { + if (index == 0) + return m_audio_channel; + return {}; +} +void SB16::detect_hardware_audio_channels(Badge<AudioManagement>) +{ + m_audio_channel = AudioChannel::must_create(*this, 0); +} + +ErrorOr<void> 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<u16>(samples_per_second_rate); + if (m_sample_rate != sample_rate_value) + set_sample_rate(sample_rate_value); + return {}; +} + +ErrorOr<u32> SB16::get_pcm_output_sample_rate(size_t channel_index) +{ + if (channel_index != 0) + return Error::from_errno(ENODEV); + return m_sample_rate; +} + +ErrorOr<size_t> 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 <Kernel/Devices/Audio/Controller.h> #include <Kernel/Devices/CharacterDevice.h> #include <Kernel/Interrupts/IRQHandler.h> #include <Kernel/Memory/PhysicalPage.h> @@ -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<SB16> try_detect_and_create(); + static ErrorOr<NonnullRefPtr<SB16>> try_detect_and_create(); - // ^CharacterDevice - virtual bool can_read(const OpenFileDescription&, u64) const override; - virtual ErrorOr<size_t> read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override; - virtual ErrorOr<size_t> 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<void> ioctl(OpenFileDescription&, unsigned, Userspace<void*>) override; + virtual StringView purpose() const override { return "SB16"sv; } private: + // ^AudioController + virtual RefPtr<AudioChannel> audio_channel(u32 index) const override; + virtual ErrorOr<size_t> write(size_t channel_index, UserOrKernelBuffer const& data, size_t length) override; + virtual void detect_hardware_audio_channels(Badge<AudioManagement>) override; + virtual ErrorOr<void> set_pcm_output_sample_rate(size_t channel_index, u32 samples_per_second_rate) override; + virtual ErrorOr<u32> 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<AudioChannel> 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<DeviceEvent> dequeue_top_device_event(Badge<DeviceControlDevice>); void after_inserting_device(Badge<Device>, Device&); @@ -76,7 +73,6 @@ private: RefPtr<ConsoleDevice> m_console_device; RefPtr<DeviceControlDevice> m_device_control_device; // FIXME: Once we have a singleton for managing many sound cards, remove this from here - NonnullRefPtrVector<CharacterDevice, 1> m_audio_devices; SpinlockProtected<HashMap<u64, Device*>> m_devices; mutable Spinlock m_event_queue_lock; |