kernel+init: Create a device node in /dev to access the CDROM from userspace!
Some checks failed
continuous-integration/drone/pr Build is failing

Still using PIO, though.
This commit is contained in:
apio 2023-05-17 18:15:01 +02:00
parent e18bca8c32
commit 0d1c01fd62
Signed by: apio
GPG Key ID: B8A7D06E42258954
3 changed files with 117 additions and 10 deletions

View File

@ -4,6 +4,7 @@
#include "arch/Timer.h" #include "arch/Timer.h"
#include "arch/x86_64/IO.h" #include "arch/x86_64/IO.h"
#include "memory/MemoryManager.h" #include "memory/MemoryManager.h"
#include <luna/Alignment.h>
#include <luna/CType.h> #include <luna/CType.h>
#include <luna/SafeArithmetic.h> #include <luna/SafeArithmetic.h>
#include <luna/Vector.h> #include <luna/Vector.h>
@ -329,6 +330,12 @@ namespace ATA
m_drives[drive] = {}; m_drives[drive] = {};
return false; return false;
} }
if (ATADevice::create(m_drives[drive]).has_error())
{
kwarnln("ata: Failed to register ATA drive %d:%d in DeviceRegistry", m_channel_index, drive);
continue;
}
} }
} }
@ -675,6 +682,25 @@ namespace ATA
return send_packet_atapi_pio(&read_packet, out, (u16)size); return send_packet_atapi_pio(&read_packet, out, (u16)size);
} }
Result<void> Drive::read_lba(u64 lba, void* out, usize nblocks)
{
const usize blocks_per_page = ARCH_PAGE_SIZE / m_block_size;
if (m_is_atapi)
{
kdbgln("ata: Reading %zu blocks from ATAPI drive using PIO, at LBA %ld", nblocks, lba);
while (nblocks > blocks_per_page)
{
TRY(atapi_read_pio(lba, out, ARCH_PAGE_SIZE));
lba += blocks_per_page;
nblocks -= blocks_per_page;
out = offset_ptr(out, ARCH_PAGE_SIZE);
}
return atapi_read_pio(lba, out, nblocks * m_block_size);
}
else
todo();
}
void Drive::irq_handler() void Drive::irq_handler()
{ {
// Clear the IRQ flag. // Clear the IRQ flag.
@ -694,3 +720,61 @@ namespace ATA
} }
} }
} }
static u32 next_minor = 0;
Result<void> ATADevice::create(SharedPtr<ATA::Drive> drive)
{
auto device = TRY(adopt_shared_if_nonnull(new (std::nothrow) ATADevice()));
device->m_drive = drive;
return DeviceRegistry::register_special_device(DeviceRegistry::Disk, next_minor++, device);
}
Result<u64> ATADevice::read(u8* buf, usize offset, usize size) const
{
if (size == 0) return 0;
if (offset > m_drive->capacity()) return 0;
if (offset + size > m_drive->capacity()) size = m_drive->capacity() - offset;
usize length = size;
auto block_size = m_drive->block_size();
auto* temp = TRY(make_array<u8>(block_size));
auto guard = make_scope_guard([temp] { delete[] temp; });
if (offset % block_size)
{
usize extra_size = block_size - (offset % block_size);
TRY(m_drive->read_lba(offset / block_size, temp, 1));
memcpy(buf, temp + (offset % block_size), extra_size);
offset += extra_size;
size -= extra_size;
buf += extra_size;
}
while (size >= ARCH_PAGE_SIZE)
{
TRY(m_drive->read_lba(offset / block_size, buf, ARCH_PAGE_SIZE / block_size));
offset += ARCH_PAGE_SIZE;
size -= ARCH_PAGE_SIZE;
buf += ARCH_PAGE_SIZE;
}
while (size >= block_size)
{
TRY(m_drive->read_lba(offset / block_size, buf, 1));
offset += block_size;
size -= block_size;
buf += block_size;
}
if (size)
{
TRY(m_drive->read_lba(offset / block_size, temp, 1));
memcpy(buf, temp, size);
}
return length;
}

View File

@ -142,6 +142,23 @@ namespace ATA
void irq_handler(); void irq_handler();
usize block_size() const
{
return m_block_size;
}
usize block_count() const
{
return m_block_count;
}
usize capacity() const
{
return m_block_count * m_block_size;
}
Result<void> read_lba(u64 lba, void* out, usize nblocks);
private: private:
bool identify_ata(); bool identify_ata();
@ -265,23 +282,28 @@ class ATADevice : public Device
{ {
public: public:
// Initializer for DeviceRegistry. // Initializer for DeviceRegistry.
static Result<void> create(SharedPtr<ATA::Controller> controller, int channel, int drive); static Result<void> create(SharedPtr<ATA::Drive> drive);
Result<usize> read(u8*, usize, usize) const override; Result<usize> read(u8*, usize, usize) const override;
Result<usize> write(const u8*, usize, usize) override; Result<usize> write(const u8*, usize, usize) override
{
return err(ENOTSUP);
}
bool blocking() const override; bool blocking() const override
{
return false;
}
Result<u64> ioctl(int request, void* arg) override; usize size() const override
{
usize size() const override; return m_drive->capacity();
}
virtual ~ATADevice() = default; virtual ~ATADevice() = default;
private: private:
ATADevice(SharedPtr<ATA::Controller> controller); ATADevice() = default;
SharedPtr<ATA::Controller> m_controller; SharedPtr<ATA::Drive> m_drive;
int m_channel;
int m_drive;
}; };

View File

@ -12,6 +12,7 @@ namespace DeviceRegistry
Console = 1, Console = 1,
Memory = 2, Memory = 2,
Framebuffer = 3, Framebuffer = 3,
Disk = 4,
}; };
Result<SharedPtr<Device>> fetch_special_device(u32 major, u32 minor); Result<SharedPtr<Device>> fetch_special_device(u32 major, u32 minor);