diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 718a8527..e92fbe0d 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -89,6 +89,7 @@ set(KERNEL_SOURCES kernel/Storage/NVMe/Namespace.cpp kernel/Storage/NVMe/Queue.cpp kernel/Storage/Partition.cpp + kernel/Storage/SCSI.cpp kernel/Storage/StorageDevice.cpp kernel/Syscall.cpp kernel/Terminal/FramebufferTerminal.cpp diff --git a/kernel/include/kernel/Storage/ATA/ATADevice.h b/kernel/include/kernel/Storage/ATA/ATADevice.h index 63d79b57..524f9c47 100644 --- a/kernel/include/kernel/Storage/ATA/ATADevice.h +++ b/kernel/include/kernel/Storage/ATA/ATADevice.h @@ -19,7 +19,7 @@ namespace Kernel }; public: - virtual ~ATABaseDevice() {}; + virtual ~ATABaseDevice(); virtual uint32_t sector_size() const override { return m_sector_words * 2; } virtual uint64_t total_size() const override { return m_lba_count * sector_size(); } diff --git a/kernel/include/kernel/Storage/SCSI.h b/kernel/include/kernel/Storage/SCSI.h new file mode 100644 index 00000000..86a4d8d1 --- /dev/null +++ b/kernel/include/kernel/Storage/SCSI.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +namespace Kernel +{ + + dev_t scsi_get_rdev(); + void scsi_free_rdev(dev_t); + +} diff --git a/kernel/kernel/Storage/ATA/ATADevice.cpp b/kernel/kernel/Storage/ATA/ATADevice.cpp index 29e9c349..42fadf8a 100644 --- a/kernel/kernel/Storage/ATA/ATADevice.cpp +++ b/kernel/kernel/Storage/ATA/ATADevice.cpp @@ -4,25 +4,25 @@ #include #include #include +#include #include namespace Kernel { - static dev_t get_ata_dev_minor() - { - static dev_t minor = 0; - return minor++; - } - detail::ATABaseDevice::ATABaseDevice() - : m_rdev(makedev(DeviceNumber::SCSI, get_ata_dev_minor())) + : m_rdev(scsi_get_rdev()) { strcpy(m_name, "sda"); m_name[2] += minor(m_rdev); } + detail::ATABaseDevice::~ATABaseDevice() + { + scsi_free_rdev(m_rdev); + } + BAN::ErrorOr detail::ATABaseDevice::initialize(BAN::Span identify_data) { ASSERT(identify_data.size() >= 256); diff --git a/kernel/kernel/Storage/SCSI.cpp b/kernel/kernel/Storage/SCSI.cpp new file mode 100644 index 00000000..4cecc009 --- /dev/null +++ b/kernel/kernel/Storage/SCSI.cpp @@ -0,0 +1,44 @@ +#include +#include +#include + +#include + +namespace Kernel +{ + + static uint64_t s_scsi_bitmap { 0 }; + static SpinLock s_scsi_spinlock; + + static constexpr size_t s_scsi_bitmap_bits = sizeof(s_scsi_bitmap) * 8; + + dev_t scsi_get_rdev() + { + SpinLockGuard _(s_scsi_spinlock); + + uint64_t mask = 1; + for (uint8_t minor = 0; minor < s_scsi_bitmap_bits; minor++, mask <<= 1) + { + if (s_scsi_bitmap & mask) + continue; + s_scsi_bitmap |= mask; + + return makedev(DeviceNumber::SCSI, minor); + } + + ASSERT_NOT_REACHED(); + } + + void scsi_free_rdev(dev_t rdev) + { + ASSERT(major(rdev) == static_cast(DeviceNumber::SCSI)); + + SpinLockGuard _(s_scsi_spinlock); + + const uint64_t mask = static_cast(1) << minor(rdev); + ASSERT(s_scsi_bitmap & mask); + + s_scsi_bitmap &= ~mask; + } + +}