kernel+init: Create a device node in /dev to access the CDROM from userspace!
Still using PIO, though.
This commit is contained in:
parent
dceb6be559
commit
c477f85c19
@ -4,6 +4,7 @@
|
||||
#include "arch/Timer.h"
|
||||
#include "arch/x86_64/IO.h"
|
||||
#include "memory/MemoryManager.h"
|
||||
#include <luna/Alignment.h>
|
||||
#include <luna/CType.h>
|
||||
#include <luna/SafeArithmetic.h>
|
||||
#include <luna/Vector.h>
|
||||
@ -329,6 +330,12 @@ namespace ATA
|
||||
m_drives[drive] = {};
|
||||
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);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
@ -142,6 +142,23 @@ namespace ATA
|
||||
|
||||
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:
|
||||
bool identify_ata();
|
||||
|
||||
@ -265,23 +282,28 @@ class ATADevice : public Device
|
||||
{
|
||||
public:
|
||||
// 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> 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;
|
||||
|
||||
private:
|
||||
ATADevice(SharedPtr<ATA::Controller> controller);
|
||||
SharedPtr<ATA::Controller> m_controller;
|
||||
int m_channel;
|
||||
int m_drive;
|
||||
ATADevice() = default;
|
||||
SharedPtr<ATA::Drive> m_drive;
|
||||
};
|
||||
|
@ -12,6 +12,7 @@ namespace DeviceRegistry
|
||||
Console = 1,
|
||||
Memory = 2,
|
||||
Framebuffer = 3,
|
||||
Disk = 4,
|
||||
};
|
||||
|
||||
Result<SharedPtr<Device>> fetch_special_device(u32 major, u32 minor);
|
||||
|
Loading…
Reference in New Issue
Block a user