diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 6f6be4d6450..e834a3695ef 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -48,7 +48,6 @@ set(KERNEL_SOURCES Devices/Audio/AC97.cpp Devices/Audio/Channel.cpp Devices/Audio/Management.cpp - Devices/Audio/SB16.cpp Devices/BlockDevice.cpp Devices/CharacterDevice.cpp Devices/ConsoleDevice.cpp diff --git a/Kernel/Devices/Audio/Management.cpp b/Kernel/Devices/Audio/Management.cpp index 095b3c796bb..5e05588f9cc 100644 --- a/Kernel/Devices/Audio/Management.cpp +++ b/Kernel/Devices/Audio/Management.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include namespace Kernel { @@ -39,9 +38,6 @@ 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) diff --git a/Kernel/Devices/Audio/SB16.cpp b/Kernel/Devices/Audio/SB16.cpp deleted file mode 100644 index 65036ccebf7..00000000000 --- a/Kernel/Devices/Audio/SB16.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Kernel { - -enum class SampleFormat : u8 { - Signed = 0x10, - Stereo = 0x20, -}; - -constexpr int SB16_DEFAULT_IRQ = 5; - -constexpr u16 DSP_READ = 0x22A; -constexpr u16 DSP_WRITE = 0x22C; -constexpr u16 DSP_STATUS = 0x22E; -constexpr u16 DSP_R_ACK = 0x22F; - -/* Write a value to the DSP write register */ -void SB16::dsp_write(u8 value) -{ - while (IO::in8(DSP_WRITE) & 0x80) - ; - IO::out8(DSP_WRITE, value); -} - -/* Reads the value of the DSP read register */ -u8 SB16::dsp_read() -{ - while (!(IO::in8(DSP_STATUS) & 0x80)) - ; - return IO::in8(DSP_READ); -} - -/* Changes the sample rate of sound output */ -void SB16::set_sample_rate(uint16_t hz) -{ - dbgln("SB16: Changing sample rate to {} Hz", hz); - m_sample_rate = hz; - dsp_write(0x41); // output - dsp_write((u8)(hz >> 8)); - dsp_write((u8)hz); - dsp_write(0x42); // input - dsp_write((u8)(hz >> 8)); - dsp_write((u8)hz); -} - -UNMAP_AFTER_INIT SB16::SB16() - : IRQHandler(SB16_DEFAULT_IRQ) -{ - initialize(); -} - -UNMAP_AFTER_INIT SB16::~SB16() -{ -} - -UNMAP_AFTER_INIT ErrorOr> SB16::try_detect_and_create() -{ - IO::out8(0x226, 1); - IO::delay(32); - IO::out8(0x226, 0); - - auto data = dsp_read(); - if (data != 0xaa) - return Error::from_errno(ENODEV); - return adopt_nonnull_ref_or_enomem(new (nothrow) SB16()); -} - -UNMAP_AFTER_INIT void SB16::initialize() -{ - disable_irq(); - - IO::out8(0x226, 1); - IO::delay(32); - IO::out8(0x226, 0); - - auto data = dsp_read(); - if (data != 0xaa) { - dbgln("SB16: SoundBlaster not ready"); - return; - } - - // Get the version info - dsp_write(0xe1); - m_major_version = dsp_read(); - auto vmin = dsp_read(); - - dmesgln("SB16: Found version {}.{}", m_major_version, vmin); - set_irq_register(SB16_DEFAULT_IRQ); - dmesgln("SB16: IRQ {}", get_irq_line()); - - set_sample_rate(m_sample_rate); -} - -void SB16::set_irq_register(u8 irq_number) -{ - u8 bitmask; - switch (irq_number) { - case 2: - bitmask = 0; - break; - case 5: - bitmask = 0b10; - break; - case 7: - bitmask = 0b100; - break; - case 10: - bitmask = 0b1000; - break; - default: - VERIFY_NOT_REACHED(); - } - IO::out8(0x224, 0x80); - IO::out8(0x225, bitmask); -} - -u8 SB16::get_irq_line() -{ - IO::out8(0x224, 0x80); - u8 bitmask = IO::in8(0x225); - switch (bitmask) { - case 0: - return 2; - case 0b10: - return 5; - case 0b100: - return 7; - case 0b1000: - return 10; - } - return bitmask; -} -void SB16::set_irq_line(u8 irq_number) -{ - InterruptDisabler disabler; - if (irq_number == get_irq_line()) - return; - set_irq_register(irq_number); - change_irq_number(irq_number); -} - -void SB16::dma_start(uint32_t length) -{ - auto const addr = m_dma_region->physical_page(0)->paddr().get(); - u8 const channel = 5; // 16-bit samples use DMA channel 5 (on the master DMA controller) - u8 const mode = 0x48; - - // Disable the DMA channel - IO::out8(0xd4, 4 + (channel % 4)); - - // Clear the byte pointer flip-flop - IO::out8(0xd8, 0); - - // Write the DMA mode for the transfer - IO::out8(0xd6, (channel % 4) | mode); - - // Write the offset of the buffer - u16 offset = (addr / 2) % 65536; - IO::out8(0xc4, (u8)offset); - IO::out8(0xc4, (u8)(offset >> 8)); - - // Write the transfer length - IO::out8(0xc6, (u8)(length - 1)); - IO::out8(0xc6, (u8)((length - 1) >> 8)); - - // Write the buffer - IO::out8(0x8b, addr >> 16); - auto page_number = addr >> 16; - VERIFY(page_number <= NumericLimits::max()); - IO::out8(0x8b, page_number); - - // Enable the DMA channel - IO::out8(0xd4, (channel % 4)); -} - -bool SB16::handle_irq(RegisterState const&) -{ - // FIXME: Check if the interrupt was actually for us or not... (shared IRQs) - - // Stop sound output ready for the next block. - dsp_write(0xd5); - - IO::in8(DSP_STATUS); // 8 bit interrupt - if (m_major_version >= 4) - IO::in8(DSP_R_ACK); // 16 bit interrupt - - m_irq_queue.wake_all(); - return true; -} - -void SB16::wait_for_irq() -{ - m_irq_queue.wait_forever("SB16"); - disable_irq(); -} - -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)); - } - - dbgln_if(SB16_DEBUG, "SB16: Writing buffer of {} bytes", length); - - if (length > PAGE_SIZE) { - return ENOSPC; - } - - u8 mode = (u8)SampleFormat::Signed | (u8)SampleFormat::Stereo; - - TRY(data.read(m_dma_region->vaddr().as_ptr(), length)); - dma_start(length); - - // 16-bit single-cycle output. - // FIXME: Implement auto-initialized output. - u8 command = 0xb0; - - u16 sample_count = length / sizeof(i16); - if (mode & (u8)SampleFormat::Stereo) - sample_count /= 2; - - sample_count -= 1; - - cli(); - enable_irq(); - - dsp_write(command); - dsp_write(mode); - dsp_write((u8)sample_count); - dsp_write((u8)(sample_count >> 8)); - - wait_for_irq(); - return length; -} - -} diff --git a/Kernel/Devices/Audio/SB16.h b/Kernel/Devices/Audio/SB16.h deleted file mode 100644 index 8d6e85d467f..00000000000 --- a/Kernel/Devices/Audio/SB16.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace Kernel { - -class SB16; - -class SB16 final - : public AudioController - , public IRQHandler { - -public: - virtual ~SB16() override; - - static ErrorOr> try_detect_and_create(); - - 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; - - void initialize(); - void wait_for_irq(); - void dma_start(uint32_t length); - void set_sample_rate(uint16_t hz); - void dsp_write(u8 value); - static u8 dsp_read(); - u8 get_irq_line(); - void set_irq_register(u8 irq_number); - void set_irq_line(u8 irq_number); - - OwnPtr m_dma_region; - int m_major_version { 0 }; - u16 m_sample_rate { 44100 }; - - WaitQueue m_irq_queue; - RefPtr m_audio_channel; -}; -}