forked from Bananymous/banan-os
Kernel: Rewrite all read/write functions to use BAN::ByteSpan
This allows us to not work with raw pointers and use sized containers for reading and writing.
This commit is contained in:
@@ -158,28 +158,30 @@ namespace Kernel
|
||||
__builtin_ia32_pause();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> AHCIDevice::read_sectors_impl(uint64_t lba, uint64_t sector_count, uint8_t* buffer)
|
||||
BAN::ErrorOr<void> AHCIDevice::read_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ByteSpan buffer)
|
||||
{
|
||||
ASSERT(buffer.size() >= sector_count * sector_size());
|
||||
const size_t sectors_per_page = PAGE_SIZE / sector_size();
|
||||
for (uint64_t sector_off = 0; sector_off < sector_count; sector_off += sectors_per_page)
|
||||
{
|
||||
uint64_t to_read = BAN::Math::min<uint64_t>(sector_count - sector_off, sectors_per_page);
|
||||
|
||||
TRY(send_command_and_block(lba + sector_off, to_read, Command::Read));
|
||||
memcpy(buffer + sector_off * sector_size(), (void*)m_data_dma_region->vaddr(), to_read * sector_size());
|
||||
memcpy(buffer.data() + sector_off * sector_size(), (void*)m_data_dma_region->vaddr(), to_read * sector_size());
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> AHCIDevice::write_sectors_impl(uint64_t lba, uint64_t sector_count, const uint8_t* buffer)
|
||||
BAN::ErrorOr<void> AHCIDevice::write_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan buffer)
|
||||
{
|
||||
ASSERT(buffer.size() >= sector_count * sector_size());
|
||||
const size_t sectors_per_page = PAGE_SIZE / sector_size();
|
||||
for (uint64_t sector_off = 0; sector_off < sector_count; sector_off += sectors_per_page)
|
||||
{
|
||||
uint64_t to_read = BAN::Math::min<uint64_t>(sector_count - sector_off, sectors_per_page);
|
||||
|
||||
memcpy((void*)m_data_dma_region->vaddr(), buffer + sector_off * sector_size(), to_read * sector_size());
|
||||
memcpy((void*)m_data_dma_region->vaddr(), buffer.data() + sector_off * sector_size(), to_read * sector_size());
|
||||
TRY(send_command_and_block(lba + sector_off, to_read, Command::Write));
|
||||
}
|
||||
|
||||
|
||||
@@ -228,8 +228,10 @@ namespace Kernel
|
||||
return BAN::Error::from_error_code(ErrorCode::None);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> ATABus::read(ATADevice& device, uint64_t lba, uint8_t sector_count, uint8_t* buffer)
|
||||
BAN::ErrorOr<void> ATABus::read(ATADevice& device, uint64_t lba, uint64_t sector_count, BAN::ByteSpan buffer)
|
||||
{
|
||||
ASSERT(sector_count <= 0xFF);
|
||||
ASSERT(buffer.size() >= sector_count * device.sector_size());
|
||||
if (lba + sector_count > device.sector_count())
|
||||
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
||||
|
||||
@@ -251,7 +253,7 @@ namespace Kernel
|
||||
for (uint32_t sector = 0; sector < sector_count; sector++)
|
||||
{
|
||||
block_until_irq();
|
||||
read_buffer(ATA_PORT_DATA, (uint16_t*)buffer + sector * device.words_per_sector(), device.words_per_sector());
|
||||
read_buffer(ATA_PORT_DATA, (uint16_t*)buffer.data() + sector * device.words_per_sector(), device.words_per_sector());
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -263,8 +265,10 @@ namespace Kernel
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> ATABus::write(ATADevice& device, uint64_t lba, uint8_t sector_count, const uint8_t* buffer)
|
||||
BAN::ErrorOr<void> ATABus::write(ATADevice& device, uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan buffer)
|
||||
{
|
||||
ASSERT(sector_count <= 0xFF);
|
||||
ASSERT(buffer.size() >= sector_count * device.sector_size());
|
||||
if (lba + sector_count > device.sector_count())
|
||||
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
||||
|
||||
@@ -285,7 +289,7 @@ namespace Kernel
|
||||
|
||||
for (uint32_t sector = 0; sector < sector_count; sector++)
|
||||
{
|
||||
write_buffer(ATA_PORT_DATA, (uint16_t*)buffer + sector * device.words_per_sector(), device.words_per_sector());
|
||||
write_buffer(ATA_PORT_DATA, (uint16_t*)buffer.data() + sector * device.words_per_sector(), device.words_per_sector());
|
||||
block_until_irq();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,24 +82,24 @@ namespace Kernel
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> detail::ATABaseDevice::read_impl(off_t offset, void* buffer, size_t bytes)
|
||||
BAN::ErrorOr<size_t> detail::ATABaseDevice::read_impl(off_t offset, BAN::ByteSpan buffer)
|
||||
{
|
||||
if (offset % sector_size())
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
if (bytes % sector_size())
|
||||
if (buffer.size() % sector_size())
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
TRY(read_sectors(offset / sector_size(), bytes / sector_size(), (uint8_t*)buffer));
|
||||
return bytes;
|
||||
TRY(read_sectors(offset / sector_size(), buffer.size() / sector_size(), buffer));
|
||||
return buffer.size();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> detail::ATABaseDevice::write_impl(off_t offset, const void* buffer, size_t bytes)
|
||||
BAN::ErrorOr<size_t> detail::ATABaseDevice::write_impl(off_t offset, BAN::ConstByteSpan buffer)
|
||||
{
|
||||
if (offset % sector_size())
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
if (bytes % sector_size())
|
||||
if (buffer.size() % sector_size())
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
TRY(write_sectors(offset / sector_size(), bytes / sector_size(), (const uint8_t*)buffer));
|
||||
return bytes;
|
||||
TRY(write_sectors(offset / sector_size(), buffer.size() / sector_size(), buffer));
|
||||
return buffer.size();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<ATADevice>> ATADevice::create(BAN::RefPtr<ATABus> bus, ATABus::DeviceType type, bool is_secondary, BAN::Span<const uint16_t> identify_data)
|
||||
@@ -118,14 +118,16 @@ namespace Kernel
|
||||
, m_is_secondary(is_secondary)
|
||||
{ }
|
||||
|
||||
BAN::ErrorOr<void> ATADevice::read_sectors_impl(uint64_t lba, uint64_t sector_count, uint8_t* buffer)
|
||||
BAN::ErrorOr<void> ATADevice::read_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ByteSpan buffer)
|
||||
{
|
||||
ASSERT(buffer.size() >= sector_count * sector_size());
|
||||
TRY(m_bus->read(*this, lba, sector_count, buffer));
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> ATADevice::write_sectors_impl(uint64_t lba, uint64_t sector_count, const uint8_t* buffer)
|
||||
BAN::ErrorOr<void> ATADevice::write_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan buffer)
|
||||
{
|
||||
ASSERT(buffer.size() >= sector_count * sector_size());
|
||||
TRY(m_bus->write(*this, lba, sector_count, buffer));
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -24,8 +24,10 @@ namespace Kernel
|
||||
release_all_pages();
|
||||
}
|
||||
|
||||
bool DiskCache::read_from_cache(uint64_t sector, uint8_t* buffer)
|
||||
bool DiskCache::read_from_cache(uint64_t sector, BAN::ByteSpan buffer)
|
||||
{
|
||||
ASSERT(buffer.size() >= m_sector_size);
|
||||
|
||||
uint64_t sectors_per_page = PAGE_SIZE / m_sector_size;
|
||||
uint64_t page_cache_offset = sector % sectors_per_page;
|
||||
uint64_t page_cache_start = sector - page_cache_offset;
|
||||
@@ -46,7 +48,7 @@ namespace Kernel
|
||||
|
||||
CriticalScope _;
|
||||
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::Present);
|
||||
memcpy(buffer, (void*)(page_cache_offset * m_sector_size), m_sector_size);
|
||||
memcpy(buffer.data(), (void*)(page_cache_offset * m_sector_size), m_sector_size);
|
||||
page_table.unmap_page(0);
|
||||
|
||||
return true;
|
||||
@@ -55,8 +57,9 @@ namespace Kernel
|
||||
return false;
|
||||
};
|
||||
|
||||
BAN::ErrorOr<void> DiskCache::write_to_cache(uint64_t sector, const uint8_t* buffer, bool dirty)
|
||||
BAN::ErrorOr<void> DiskCache::write_to_cache(uint64_t sector, BAN::ConstByteSpan buffer, bool dirty)
|
||||
{
|
||||
ASSERT(buffer.size() >= m_sector_size);
|
||||
uint64_t sectors_per_page = PAGE_SIZE / m_sector_size;
|
||||
uint64_t page_cache_offset = sector % sectors_per_page;
|
||||
uint64_t page_cache_start = sector - page_cache_offset;
|
||||
@@ -80,7 +83,7 @@ namespace Kernel
|
||||
{
|
||||
CriticalScope _;
|
||||
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||
memcpy((void*)(page_cache_offset * m_sector_size), buffer, m_sector_size);
|
||||
memcpy((void*)(page_cache_offset * m_sector_size), buffer.data(), m_sector_size);
|
||||
page_table.unmap_page(0);
|
||||
}
|
||||
|
||||
@@ -110,8 +113,8 @@ namespace Kernel
|
||||
|
||||
{
|
||||
CriticalScope _;
|
||||
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::Present);
|
||||
memcpy((void*)(page_cache_offset * m_sector_size), buffer, m_sector_size);
|
||||
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||
memcpy((void*)(page_cache_offset * m_sector_size), buffer.data(), m_sector_size);
|
||||
page_table.unmap_page(0);
|
||||
}
|
||||
|
||||
@@ -149,7 +152,8 @@ namespace Kernel
|
||||
else
|
||||
{
|
||||
dprintln_if(DEBUG_SYNC, "syncing {}->{}", cache.first_sector + sector_start, cache.first_sector + sector_start + sector_count);
|
||||
TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, m_sync_cache.data() + sector_start * m_sector_size));
|
||||
auto data_slice = m_sync_cache.span().slice(sector_start * m_sector_size, sector_count * m_sector_size);
|
||||
TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, data_slice));
|
||||
sector_start += sector_count + 1;
|
||||
sector_count = 0;
|
||||
}
|
||||
@@ -158,7 +162,8 @@ namespace Kernel
|
||||
if (sector_count > 0)
|
||||
{
|
||||
dprintln_if(DEBUG_SYNC, "syncing {}->{}", cache.first_sector + sector_start, cache.first_sector + sector_start + sector_count);
|
||||
TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, m_sync_cache.data() + sector_start * m_sector_size));
|
||||
auto data_slice = m_sync_cache.span().slice(sector_start * m_sector_size, sector_count * m_sector_size);
|
||||
TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, data_slice));
|
||||
}
|
||||
|
||||
cache.dirty_mask = 0;
|
||||
|
||||
@@ -153,8 +153,10 @@ namespace Kernel
|
||||
if (total_size() < sizeof(GPTHeader))
|
||||
return BAN::Error::from_error_code(ErrorCode::Storage_GPTHeader);
|
||||
|
||||
BAN::Vector<uint8_t> lba1(sector_size());
|
||||
TRY(read_sectors(1, 1, lba1.data()));
|
||||
BAN::Vector<uint8_t> lba1;
|
||||
TRY(lba1.resize(sector_size()));
|
||||
|
||||
TRY(read_sectors(1, 1, lba1.span()));
|
||||
|
||||
const GPTHeader& header = *(const GPTHeader*)lba1.data();
|
||||
if (!is_valid_gpt_header(header, sector_size()))
|
||||
@@ -169,7 +171,7 @@ namespace Kernel
|
||||
|
||||
BAN::Vector<uint8_t> entry_array;
|
||||
TRY(entry_array.resize(size));
|
||||
TRY(read_sectors(header.partition_entry_lba, size / sector_size(), entry_array.data()));
|
||||
TRY(read_sectors(header.partition_entry_lba, size / sector_size(), entry_array.span()));
|
||||
|
||||
if (!is_valid_gpt_crc32(header, lba1, entry_array))
|
||||
return BAN::Error::from_error_code(ErrorCode::Storage_GPTHeader);
|
||||
@@ -226,8 +228,9 @@ namespace Kernel
|
||||
memcpy(m_label, label, sizeof(m_label));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Partition::read_sectors(uint64_t lba, uint8_t sector_count, uint8_t* buffer)
|
||||
BAN::ErrorOr<void> Partition::read_sectors(uint64_t lba, uint8_t sector_count, BAN::ByteSpan buffer)
|
||||
{
|
||||
ASSERT(buffer.size() >= sector_count * m_device.sector_size());
|
||||
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
|
||||
if (lba + sector_count > sectors_in_partition)
|
||||
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
||||
@@ -235,8 +238,9 @@ namespace Kernel
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Partition::write_sectors(uint64_t lba, uint8_t sector_count, const uint8_t* buffer)
|
||||
BAN::ErrorOr<void> Partition::write_sectors(uint64_t lba, uint8_t sector_count, BAN::ConstByteSpan buffer)
|
||||
{
|
||||
ASSERT(buffer.size() >= sector_count * m_device.sector_size());
|
||||
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
|
||||
if (lba + sector_count > sectors_in_partition)
|
||||
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
||||
@@ -244,23 +248,23 @@ namespace Kernel
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> Partition::read_impl(off_t offset, void* buffer, size_t bytes)
|
||||
BAN::ErrorOr<size_t> Partition::read_impl(off_t offset, BAN::ByteSpan buffer)
|
||||
{
|
||||
ASSERT(offset >= 0);
|
||||
|
||||
if (offset % m_device.sector_size() || bytes % m_device.sector_size())
|
||||
if (offset % m_device.sector_size() || buffer.size() % m_device.sector_size())
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
|
||||
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
|
||||
uint32_t lba = offset / m_device.sector_size();
|
||||
uint32_t sector_count = bytes / m_device.sector_size();
|
||||
uint32_t sector_count = buffer.size() / m_device.sector_size();
|
||||
|
||||
if (lba == sectors_in_partition)
|
||||
return 0;
|
||||
if (lba + sector_count > sectors_in_partition)
|
||||
sector_count = sectors_in_partition - lba;
|
||||
|
||||
TRY(read_sectors(lba, sector_count, (uint8_t*)buffer));
|
||||
TRY(read_sectors(lba, sector_count, buffer));
|
||||
return sector_count * m_device.sector_size();
|
||||
}
|
||||
|
||||
@@ -283,36 +287,51 @@ namespace Kernel
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> StorageDevice::read_sectors(uint64_t lba, uint64_t sector_count, uint8_t* buffer)
|
||||
BAN::ErrorOr<void> StorageDevice::read_sectors(uint64_t lba, uint64_t sector_count, BAN::ByteSpan buffer)
|
||||
{
|
||||
ASSERT(buffer.size() >= sector_count * sector_size());
|
||||
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
Thread::TerminateBlocker blocker(Thread::current());
|
||||
if (!m_disk_cache.has_value())
|
||||
return read_sectors_impl(lba, sector_count, buffer);
|
||||
}
|
||||
|
||||
for (uint64_t offset = 0; offset < sector_count; offset++)
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
Thread::TerminateBlocker blocker(Thread::current());
|
||||
|
||||
uint8_t* buffer_ptr = buffer + offset * sector_size();
|
||||
if (m_disk_cache.has_value())
|
||||
if (m_disk_cache->read_from_cache(lba + offset, buffer_ptr))
|
||||
continue;
|
||||
TRY(read_sectors_impl(lba + offset, 1, buffer_ptr));
|
||||
if (m_disk_cache.has_value())
|
||||
(void)m_disk_cache->write_to_cache(lba + offset, buffer_ptr, false);
|
||||
auto sector_buffer = buffer.slice(offset * sector_size(), sector_size());
|
||||
if (m_disk_cache->read_from_cache(lba + offset, sector_buffer))
|
||||
continue;
|
||||
TRY(read_sectors_impl(lba + offset, 1, sector_buffer));
|
||||
(void)m_disk_cache->write_to_cache(lba + offset, sector_buffer, false);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> StorageDevice::write_sectors(uint64_t lba, uint64_t sector_count, const uint8_t* buffer)
|
||||
BAN::ErrorOr<void> StorageDevice::write_sectors(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan buffer)
|
||||
{
|
||||
// TODO: use disk cache for dirty pages. I don't wanna think about how to do it safely now
|
||||
ASSERT(buffer.size() >= sector_count * sector_size());
|
||||
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
Thread::TerminateBlocker blocker(Thread::current());
|
||||
if (!m_disk_cache.has_value())
|
||||
return write_sectors_impl(lba, sector_count, buffer);
|
||||
}
|
||||
|
||||
for (uint8_t offset = 0; offset < sector_count; offset++)
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
Thread::TerminateBlocker blocker(Thread::current());
|
||||
|
||||
const uint8_t* buffer_ptr = buffer + offset * sector_size();
|
||||
if (!m_disk_cache.has_value() || m_disk_cache->write_to_cache(lba + offset, buffer_ptr, true).is_error())
|
||||
TRY(write_sectors_impl(lba + offset, 1, buffer_ptr));
|
||||
auto sector_buffer = buffer.slice(offset * sector_size(), sector_size());
|
||||
if (m_disk_cache->write_to_cache(lba + offset, sector_buffer, true).is_error())
|
||||
TRY(write_sectors_impl(lba + offset, 1, sector_buffer));
|
||||
}
|
||||
|
||||
return {};
|
||||
|
||||
Reference in New Issue
Block a user