forked from Bananymous/banan-os
Kernel: Rewrite whole device structure
We now have DevFileSystem which is derived from RamFileSystem. All devices are RamInodes. We don't have separate DeviceManager anymore. To iterate over devices, you can loop througn every inode in devfs.
This commit is contained in:
@@ -1,13 +1,11 @@
|
||||
#include <BAN/Time.h>
|
||||
#include <kernel/Device.h>
|
||||
#include <kernel/RTC.h>
|
||||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
Device::Device()
|
||||
: m_create_time({ BAN::to_unix_time(RTC::get_current_time()), 0 })
|
||||
, m_ino_t(DeviceManager::get().get_next_ino())
|
||||
Device::Device(mode_t mode, uid_t uid, gid_t gid)
|
||||
: RamInode(DevFileSystem::get(), mode, uid, gid)
|
||||
{ }
|
||||
|
||||
}
|
||||
@@ -1,163 +0,0 @@
|
||||
#include <kernel/DeviceManager.h>
|
||||
#include <kernel/LockGuard.h>
|
||||
#include <kernel/PCI.h>
|
||||
#include <kernel/Process.h>
|
||||
#include <kernel/Storage/ATAController.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
DeviceManager& DeviceManager::get()
|
||||
{
|
||||
static DeviceManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void DeviceManager::initialize_pci_devices()
|
||||
{
|
||||
for (const auto& pci_device : PCI::get().devices())
|
||||
{
|
||||
switch (pci_device.class_code())
|
||||
{
|
||||
case 0x01:
|
||||
{
|
||||
StorageController* controller = nullptr;
|
||||
switch (pci_device.subclass())
|
||||
{
|
||||
case 0x01:
|
||||
if (auto res = ATAController::create(pci_device); res.is_error())
|
||||
dprintln("{}", res.error());
|
||||
else
|
||||
controller = res.value();
|
||||
break;
|
||||
default:
|
||||
dprintln("unsupported storage device (pci {2H}.{2H}.{2H})", pci_device.class_code(), pci_device.subclass(), pci_device.prog_if());
|
||||
break;
|
||||
}
|
||||
|
||||
if (controller)
|
||||
{
|
||||
add_device(controller);
|
||||
for (auto* device : controller->devices())
|
||||
{
|
||||
add_device(device);
|
||||
if (auto res = device->initialize_partitions(); res.is_error())
|
||||
dprintln("{}", res.error());
|
||||
else
|
||||
{
|
||||
for (auto* partition : device->partitions())
|
||||
add_device(partition);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManager::initialize_updater()
|
||||
{
|
||||
Process::create_kernel(
|
||||
[](void*)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
DeviceManager::get().update();
|
||||
PIT::sleep(1);
|
||||
}
|
||||
}, nullptr
|
||||
);
|
||||
}
|
||||
|
||||
ino_t DeviceManager::get_next_ino() const
|
||||
{
|
||||
static ino_t next_ino = 1;
|
||||
return next_ino++;
|
||||
}
|
||||
|
||||
dev_t DeviceManager::get_next_rdev() const
|
||||
{
|
||||
static dev_t next_dev = 1;
|
||||
return next_dev++;
|
||||
}
|
||||
|
||||
uint8_t DeviceManager::get_next_input_dev() const
|
||||
{
|
||||
static uint8_t next_dev = 0;
|
||||
return next_dev++;
|
||||
}
|
||||
|
||||
void DeviceManager::update()
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
for (Device* device : m_devices)
|
||||
device->update();
|
||||
}
|
||||
|
||||
void DeviceManager::add_device(Device* device)
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
MUST(m_devices.push_back(device));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<Inode>> DeviceManager::directory_find_inode(BAN::StringView name)
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
if (name == "."sv || name == ".."sv)
|
||||
return BAN::RefPtr<Inode>(this);
|
||||
for (Device* device : m_devices)
|
||||
if (device->name() == name)
|
||||
return BAN::RefPtr<Inode>(device);
|
||||
return BAN::Error::from_errno(ENOENT);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> DeviceManager::directory_read_next_entries(off_t offset, DirectoryEntryList* list, size_t list_size)
|
||||
{
|
||||
if (offset != 0)
|
||||
{
|
||||
list->entry_count = 0;
|
||||
return {};
|
||||
}
|
||||
|
||||
LockGuard _(m_lock);
|
||||
|
||||
size_t needed_size = sizeof(DirectoryEntryList);
|
||||
needed_size += sizeof(DirectoryEntry) + 2;
|
||||
needed_size += sizeof(DirectoryEntry) + 3;
|
||||
for (Device* device : m_devices)
|
||||
needed_size += sizeof(DirectoryEntry) + device->name().size() + 1;
|
||||
if (needed_size > list_size)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
DirectoryEntry* ptr = list->array;
|
||||
|
||||
ptr->dirent.d_ino = ino();
|
||||
ptr->rec_len = sizeof(DirectoryEntry) + 2;
|
||||
memcpy(ptr->dirent.d_name, ".", 2);
|
||||
ptr = ptr->next();
|
||||
|
||||
ptr->dirent.d_ino = 69; // FIXME: store parent inode number when we implement proper RAM fs
|
||||
ptr->rec_len = sizeof(DirectoryEntry) + 3;
|
||||
memcpy(ptr->dirent.d_name, "..", 3);
|
||||
ptr = ptr->next();
|
||||
|
||||
for (Device* device : m_devices)
|
||||
{
|
||||
ptr->dirent.d_ino = device->ino();
|
||||
ptr->rec_len = sizeof(DirectoryEntry) + device->name().size() + 1;
|
||||
memcpy(ptr->dirent.d_name, device->name().data(), device->name().size());
|
||||
ptr->dirent.d_name[device->name().size()] = '\0';
|
||||
|
||||
ptr = ptr->next();
|
||||
}
|
||||
|
||||
list->entry_count = m_devices.size() + 2;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
63
kernel/kernel/FS/DevFS/FileSystem.cpp
Normal file
63
kernel/kernel/FS/DevFS/FileSystem.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#include <BAN/ScopeGuard.h>
|
||||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
#include <kernel/FS/RamFS/Inode.h>
|
||||
#include <kernel/LockGuard.h>
|
||||
#include <kernel/Process.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
static DevFileSystem* s_instance = nullptr;
|
||||
|
||||
void DevFileSystem::initialize()
|
||||
{
|
||||
ASSERT(s_instance == nullptr);
|
||||
s_instance = new DevFileSystem(1024 * 1024);
|
||||
ASSERT(s_instance);
|
||||
|
||||
auto root_inode = MUST(RamDirectoryInode::create(*s_instance, 0, Inode::Mode::IFDIR | 0755, 0, 0));
|
||||
MUST(s_instance->set_root_inode(root_inode));
|
||||
}
|
||||
|
||||
DevFileSystem& DevFileSystem::get()
|
||||
{
|
||||
ASSERT(s_instance);
|
||||
return *s_instance;
|
||||
}
|
||||
|
||||
void DevFileSystem::initialize_device_updater()
|
||||
{
|
||||
Process::create_kernel(
|
||||
[](void*)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
s_instance->m_device_lock.lock();
|
||||
s_instance->for_each_inode(
|
||||
[](BAN::RefPtr<RamInode> inode)
|
||||
{
|
||||
if (inode->is_device())
|
||||
((Device*)inode.ptr())->update();
|
||||
}
|
||||
);
|
||||
s_instance->m_device_lock.unlock();
|
||||
|
||||
PIT::sleep(1);
|
||||
}
|
||||
}, nullptr
|
||||
);
|
||||
}
|
||||
|
||||
void DevFileSystem::add_device(BAN::StringView path, BAN::RefPtr<Device> device)
|
||||
{
|
||||
ASSERT(!path.contains('/'));
|
||||
MUST(reinterpret_cast<RamDirectoryInode*>(root_inode().ptr())->add_inode(path, device));
|
||||
}
|
||||
|
||||
dev_t DevFileSystem::get_next_rdev()
|
||||
{
|
||||
static dev_t next_rdev = 1;
|
||||
return next_rdev++;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,22 +9,29 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<RamFileSystem*> RamFileSystem::create(size_t size, mode_t mode, uid_t uid, gid_t gid)
|
||||
{
|
||||
auto* ramfs = new RamFileSystem;
|
||||
auto* ramfs = new RamFileSystem(size);
|
||||
if (ramfs == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
ramfs->m_size = size;
|
||||
|
||||
BAN::ScopeGuard deleter([ramfs] { delete ramfs; });
|
||||
|
||||
auto root_inode = TRY(RamDirectoryInode::create(*ramfs, 0, mode, uid, gid));
|
||||
TRY(ramfs->add_inode(root_inode));
|
||||
ramfs->m_root_inode = root_inode->ino();
|
||||
TRY(ramfs->set_root_inode(root_inode));;
|
||||
|
||||
deleter.disable();
|
||||
|
||||
return ramfs;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> RamFileSystem::set_root_inode(BAN::RefPtr<RamDirectoryInode> root_inode)
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
ASSERT(m_root_inode == 0);
|
||||
TRY(add_inode(root_inode));
|
||||
m_root_inode = root_inode->ino();
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> RamFileSystem::add_inode(BAN::RefPtr<RamInode> inode)
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
@@ -42,4 +49,11 @@ namespace Kernel
|
||||
return m_inodes[ino];
|
||||
}
|
||||
|
||||
void RamFileSystem::for_each_inode(void (*callback)(BAN::RefPtr<RamInode>))
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
for (auto& [_, inode] : m_inodes)
|
||||
callback(inode);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -180,13 +180,6 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<void> RamDirectoryInode::create_file(BAN::StringView name, mode_t mode, uid_t uid, gid_t gid)
|
||||
{
|
||||
if (name.size() > m_name_max)
|
||||
return BAN::Error::from_errno(ENAMETOOLONG);
|
||||
|
||||
for (auto& entry : m_entries)
|
||||
if (name == entry.name)
|
||||
return BAN::Error::from_errno(EEXIST);
|
||||
|
||||
BAN::RefPtr<RamInode> inode;
|
||||
if (Mode{ mode }.ifreg())
|
||||
inode = TRY(RamInode::create(m_fs, mode, uid, gid));
|
||||
@@ -195,6 +188,20 @@ namespace Kernel
|
||||
else
|
||||
ASSERT_NOT_REACHED();
|
||||
|
||||
TRY(add_inode(name, inode));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> RamDirectoryInode::add_inode(BAN::StringView name, BAN::RefPtr<RamInode> inode)
|
||||
{
|
||||
if (name.size() > m_name_max)
|
||||
return BAN::Error::from_errno(ENAMETOOLONG);
|
||||
|
||||
for (auto& entry : m_entries)
|
||||
if (name == entry.name)
|
||||
return BAN::Error::from_errno(EEXIST);
|
||||
|
||||
TRY(m_entries.push_back({ }));
|
||||
Entry& entry = m_entries.back();
|
||||
strcpy(entry.name, name.data());
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <BAN/ScopeGuard.h>
|
||||
#include <BAN/StringView.h>
|
||||
#include <kernel/DeviceManager.h>
|
||||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
#include <kernel/FS/Ext2.h>
|
||||
#include <kernel/FS/RamFS/FileSystem.h>
|
||||
#include <kernel/FS/RamFS/Inode.h>
|
||||
@@ -22,13 +22,11 @@ namespace Kernel
|
||||
ASSERT(root.size() >= 5 && root.substring(0, 5) == "/dev/"sv);;
|
||||
root = root.substring(5);
|
||||
|
||||
auto partition_inode = MUST(DeviceManager::get().directory_find_inode(root));
|
||||
auto partition_inode = MUST(DevFileSystem::get().root_inode()->directory_find_inode(root));
|
||||
s_instance->m_root_fs = MUST(Ext2FS::create(*(Partition*)partition_inode.ptr()));
|
||||
|
||||
Credentials root_creds { 0, 0, 0, 0 };
|
||||
|
||||
DeviceManager::get().set_blksize(s_instance->m_root_fs->root_inode()->blksize());
|
||||
MUST(s_instance->mount(root_creds, &DeviceManager::get(), "/dev"));
|
||||
MUST(s_instance->mount(root_creds, &DevFileSystem::get(), "/dev"));
|
||||
|
||||
mode_t tmpfs_mode = Inode::Mode::IFDIR
|
||||
| Inode::Mode::IRUSR | Inode::Mode::IWUSR | Inode::Mode::IXUSR
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <BAN/ScopeGuard.h>
|
||||
#include <kernel/ACPI.h>
|
||||
#include <kernel/DeviceManager.h>
|
||||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
#include <kernel/IDT.h>
|
||||
#include <kernel/Input/PS2Controller.h>
|
||||
#include <kernel/Input/PS2Keyboard.h>
|
||||
@@ -258,14 +258,14 @@ namespace Kernel::Input
|
||||
IDT::register_irq_handler(PS2::IRQ::DEVICE0, device0_irq);
|
||||
InterruptController::get().enable_irq(PS2::IRQ::DEVICE0);
|
||||
config |= PS2::Config::INTERRUPT_FIRST_PORT;
|
||||
DeviceManager::get().add_device(m_devices[0]);
|
||||
DevFileSystem::get().add_device("input0", m_devices[0]);
|
||||
}
|
||||
if (m_devices[1])
|
||||
{
|
||||
IDT::register_irq_handler(PS2::IRQ::DEVICE1, device1_irq);
|
||||
InterruptController::get().enable_irq(PS2::IRQ::DEVICE1);
|
||||
config |= PS2::Config::INTERRUPT_SECOND_PORT;
|
||||
DeviceManager::get().add_device(m_devices[1]);
|
||||
DevFileSystem::get().add_device("input1", m_devices[1]);
|
||||
}
|
||||
|
||||
controller_send_command(PS2::Command::WRITE_CONFIG, config);
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#include <BAN/ScopeGuard.h>
|
||||
#include <kernel/CriticalScope.h>
|
||||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
#include <kernel/Input/PS2Keyboard.h>
|
||||
|
||||
#include <sys/sysmacros.h>
|
||||
|
||||
#define SET_MASK(byte, mask, on_off) ((on_off) ? ((byte) | (mask)) : ((byte) & ~(mask)))
|
||||
#define TOGGLE_MASK(byte, mask) ((byte) ^ (mask))
|
||||
|
||||
@@ -50,8 +53,7 @@ namespace Kernel::Input
|
||||
|
||||
PS2Keyboard::PS2Keyboard(PS2Controller& controller)
|
||||
: m_controller(controller)
|
||||
, m_name(BAN::String::formatted("input{}", DeviceManager::get().get_next_input_dev()))
|
||||
, m_rdev(makedev(DeviceManager::get().get_next_rdev(), 0))
|
||||
, m_rdev(makedev(DevFileSystem::get().get_next_rdev(), 0))
|
||||
{ }
|
||||
|
||||
void PS2Keyboard::on_byte(uint8_t byte)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <kernel/IO.h>
|
||||
#include <kernel/PCI.h>
|
||||
#include <kernel/Storage/ATAController.h>
|
||||
|
||||
#define INVALID 0xFFFF
|
||||
#define MULTI_FUNCTION 0x80
|
||||
@@ -18,6 +19,7 @@ namespace Kernel
|
||||
s_instance = new PCI();
|
||||
ASSERT(s_instance);
|
||||
s_instance->check_all_buses();
|
||||
s_instance->initialize_devices();
|
||||
}
|
||||
|
||||
PCI& PCI::get()
|
||||
@@ -91,6 +93,32 @@ namespace Kernel
|
||||
}
|
||||
}
|
||||
|
||||
void PCI::initialize_devices()
|
||||
{
|
||||
for (const auto& pci_device : PCI::get().devices())
|
||||
{
|
||||
switch (pci_device.class_code())
|
||||
{
|
||||
case 0x01:
|
||||
{
|
||||
switch (pci_device.subclass())
|
||||
{
|
||||
case 0x01:
|
||||
if (auto res = ATAController::create(pci_device); res.is_error())
|
||||
dprintln("{}", res.error());
|
||||
break;
|
||||
default:
|
||||
dprintln("unsupported storage device (pci {2H}.{2H}.{2H})", pci_device.class_code(), pci_device.subclass(), pci_device.prog_if());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PCIDevice::PCIDevice(uint8_t bus, uint8_t dev, uint8_t func)
|
||||
: m_bus(bus), m_dev(dev), m_func(func)
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/sysmacros.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
@@ -749,8 +750,9 @@ namespace Kernel
|
||||
LockGuard _(m_lock);
|
||||
if (m_tty == nullptr)
|
||||
buffer[0] = '\0';
|
||||
strcpy(buffer, "/dev/");
|
||||
strcpy(buffer + 5, m_tty->name().data());
|
||||
ASSERT(minor(m_tty->rdev()) < 10);
|
||||
strcpy(buffer, "/dev/tty1");
|
||||
buffer[8] += minor(m_tty->rdev());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Kernel
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
ATABus* ATABus::create(ATAController* controller, uint16_t base, uint16_t ctrl, uint8_t irq)
|
||||
ATABus* ATABus::create(ATAController& controller, uint16_t base, uint16_t ctrl, uint8_t irq)
|
||||
{
|
||||
ATABus* bus = new ATABus(controller, base, ctrl);
|
||||
ASSERT(bus);
|
||||
@@ -62,17 +62,20 @@ namespace Kernel
|
||||
|
||||
for (uint8_t i = 0; i < 2; i++)
|
||||
{
|
||||
m_devices[i] = new ATADevice(this);
|
||||
ATADevice* device = m_devices[i];
|
||||
ASSERT(device);
|
||||
{
|
||||
auto* temp_ptr = new ATADevice(*this);
|
||||
ASSERT(temp_ptr);
|
||||
m_devices[i] = BAN::RefPtr<ATADevice>::adopt(temp_ptr);
|
||||
}
|
||||
ATADevice& device = *m_devices[i];
|
||||
|
||||
BAN::ScopeGuard guard([this, i] { m_devices[i]->unref(); m_devices[i] = nullptr; });
|
||||
BAN::ScopeGuard guard([this, i] { m_devices[i] = nullptr; });
|
||||
|
||||
auto type = identify(device, identify_buffer);
|
||||
if (type == DeviceType::None)
|
||||
continue;
|
||||
|
||||
auto res = device->initialize(type, identify_buffer);
|
||||
auto res = device.initialize(type, identify_buffer);
|
||||
if (res.is_error())
|
||||
{
|
||||
dprintln("{}", res.error());
|
||||
@@ -87,19 +90,19 @@ namespace Kernel
|
||||
{
|
||||
if (!m_devices[i])
|
||||
continue;
|
||||
select_device(m_devices[i]);
|
||||
select_device(*m_devices[i]);
|
||||
io_write(ATA_PORT_CONTROL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ATABus::select_device(const ATADevice* device)
|
||||
void ATABus::select_device(const ATADevice& device)
|
||||
{
|
||||
uint8_t device_index = this->device_index(device);
|
||||
io_write(ATA_PORT_DRIVE_SELECT, 0xA0 | (device_index << 4));
|
||||
PIT::sleep(1);
|
||||
}
|
||||
|
||||
ATABus::DeviceType ATABus::identify(const ATADevice* device, uint16_t* buffer)
|
||||
ATABus::DeviceType ATABus::identify(const ATADevice& device, uint16_t* buffer)
|
||||
{
|
||||
select_device(device);
|
||||
|
||||
@@ -242,15 +245,15 @@ namespace Kernel
|
||||
return BAN::Error::from_error_code(ErrorCode::None);
|
||||
}
|
||||
|
||||
uint8_t ATABus::device_index(const ATADevice* device) const
|
||||
uint8_t ATABus::device_index(const ATADevice& device) const
|
||||
{
|
||||
ASSERT(device == m_devices[0] || device == m_devices[1]);
|
||||
return (device == m_devices[0]) ? 0 : 1;
|
||||
ASSERT(&device == m_devices[0].ptr() || &device == m_devices[1].ptr());
|
||||
return (&device == m_devices[0].ptr()) ? 0 : 1;
|
||||
}
|
||||
|
||||
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, uint8_t sector_count, uint8_t* buffer)
|
||||
{
|
||||
if (lba + sector_count > device->m_lba_count)
|
||||
if (lba + sector_count > device.m_lba_count)
|
||||
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
||||
|
||||
LockGuard _(m_lock);
|
||||
@@ -268,7 +271,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->m_sector_words, device->m_sector_words);
|
||||
read_buffer(ATA_PORT_DATA, (uint16_t*)buffer + sector * device.m_sector_words, device.m_sector_words);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -280,9 +283,9 @@ 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, uint8_t sector_count, const uint8_t* buffer)
|
||||
{
|
||||
if (lba + sector_count > device->m_lba_count)
|
||||
if (lba + sector_count > device.m_lba_count)
|
||||
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
||||
|
||||
LockGuard _(m_lock);
|
||||
@@ -301,7 +304,7 @@ namespace Kernel
|
||||
|
||||
for (uint32_t sector = 0; sector < sector_count; sector++)
|
||||
{
|
||||
write_buffer(ATA_PORT_DATA, (uint16_t*)buffer + sector * device->m_sector_words, device->m_sector_words);
|
||||
write_buffer(ATA_PORT_DATA, (uint16_t*)buffer + sector * device.m_sector_words, device.m_sector_words);
|
||||
block_until_irq();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
#include <BAN/ScopeGuard.h>
|
||||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
#include <kernel/LockGuard.h>
|
||||
#include <kernel/Storage/ATABus.h>
|
||||
#include <kernel/Storage/ATAController.h>
|
||||
#include <kernel/Storage/ATADefinitions.h>
|
||||
#include <kernel/Storage/ATADevice.h>
|
||||
|
||||
#include <sys/sysmacros.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
BAN::ErrorOr<ATAController*> ATAController::create(const PCIDevice& device)
|
||||
BAN::ErrorOr<BAN::RefPtr<ATAController>> ATAController::create(const PCIDevice& device)
|
||||
{
|
||||
ATAController* controller = new ATAController();
|
||||
if (controller == nullptr)
|
||||
@@ -16,9 +19,42 @@ namespace Kernel
|
||||
BAN::ScopeGuard guard([controller] { controller->unref(); });
|
||||
TRY(controller->initialize(device));
|
||||
guard.disable();
|
||||
return controller;
|
||||
|
||||
auto ref_ptr = BAN::RefPtr<ATAController>::adopt(controller);
|
||||
|
||||
DevFileSystem::get().add_device("hd"sv, ref_ptr);
|
||||
|
||||
auto devices = controller->devices();
|
||||
for (size_t i = 0; i < devices.size(); i++)
|
||||
{
|
||||
char device_name[4] { 'h', 'd', 'a', '\0' };
|
||||
device_name[2] += i;
|
||||
|
||||
DevFileSystem::get().add_device(device_name, devices[i]);
|
||||
|
||||
if (auto res = devices[i]->initialize_partitions(); res.is_error())
|
||||
dprintln("{}", res.error());
|
||||
else
|
||||
{
|
||||
char partition_name[5] { 'h', 'd', 'a', '1', '\0' };
|
||||
partition_name[2] += i;
|
||||
|
||||
auto& partitions = devices[i]->partitions();
|
||||
for (size_t j = 0; j < partitions.size(); j++)
|
||||
{
|
||||
partition_name[3] += j;
|
||||
DevFileSystem::get().add_device(partition_name, partitions[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ref_ptr;
|
||||
}
|
||||
|
||||
ATAController::ATAController()
|
||||
: m_rdev(makedev(DevFileSystem::get().get_next_rdev(), 0))
|
||||
{ }
|
||||
|
||||
BAN::ErrorOr<void> ATAController::initialize(const PCIDevice& pci_device)
|
||||
{
|
||||
struct Bus
|
||||
@@ -48,21 +84,15 @@ namespace Kernel
|
||||
return BAN::Error::from_error_code(ErrorCode::ATA_UnsupportedDevice);
|
||||
}
|
||||
|
||||
m_buses[0] = ATABus::create(this, buses[0].base, buses[0].ctrl, 14);
|
||||
m_buses[1] = ATABus::create(this, buses[1].base, buses[1].ctrl, 15);
|
||||
m_buses[0] = ATABus::create(*this, buses[0].base, buses[0].ctrl, 14);
|
||||
m_buses[1] = ATABus::create(*this, buses[1].base, buses[1].ctrl, 15);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
uint8_t ATAController::next_device_index() const
|
||||
BAN::Vector<BAN::RefPtr<StorageDevice>> ATAController::devices()
|
||||
{
|
||||
static uint8_t index = 0;
|
||||
return index++;
|
||||
}
|
||||
|
||||
BAN::Vector<StorageDevice*> ATAController::devices()
|
||||
{
|
||||
BAN::Vector<StorageDevice*> devices;
|
||||
BAN::Vector<BAN::RefPtr<StorageDevice>> devices;
|
||||
if (m_buses[0]->m_devices[0])
|
||||
MUST(devices.push_back(m_buses[0]->m_devices[0]));
|
||||
if (m_buses[0]->m_devices[1])
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
#include <kernel/IO.h>
|
||||
#include <kernel/Storage/ATABus.h>
|
||||
#include <kernel/Storage/ATADefinitions.h>
|
||||
#include <kernel/Storage/ATADevice.h>
|
||||
|
||||
#include <sys/sysmacros.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
ATADevice::ATADevice(ATABus& bus)
|
||||
: m_bus(bus)
|
||||
, m_rdev(makedev(DevFileSystem::get().get_next_rdev(), 0))
|
||||
{ }
|
||||
|
||||
BAN::ErrorOr<void> ATADevice::initialize(ATABus::DeviceType type, const uint16_t* identify_buffer)
|
||||
{
|
||||
m_type = type;
|
||||
@@ -45,13 +53,7 @@ namespace Kernel
|
||||
}
|
||||
m_model[40] = 0;
|
||||
|
||||
m_index = m_bus->controller()->next_device_index();
|
||||
m_device_name[0] = 'h';
|
||||
m_device_name[1] = 'd';
|
||||
m_device_name[2] = 'a' + m_index;
|
||||
m_device_name[3] = '\0';
|
||||
|
||||
dprintln("{} {} MB", m_device_name, total_size() / 1024 / 1024);
|
||||
dprintln("ATA disk {} MB", total_size() / 1024 / 1024);
|
||||
|
||||
add_disk_cache();
|
||||
|
||||
@@ -60,13 +62,13 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<void> ATADevice::read_sectors_impl(uint64_t lba, uint8_t sector_count, uint8_t* buffer)
|
||||
{
|
||||
TRY(m_bus->read(this, lba, sector_count, buffer));
|
||||
TRY(m_bus.read(*this, lba, sector_count, buffer));
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> ATADevice::write_sectors_impl(uint64_t lba, uint8_t sector_count, const uint8_t* buffer)
|
||||
{
|
||||
TRY(m_bus->write(this, lba, sector_count, buffer));
|
||||
TRY(m_bus.write(*this, lba, sector_count, buffer));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <kernel/PCI.h>
|
||||
#include <kernel/Storage/StorageDevice.h>
|
||||
|
||||
#include <sys/sysmacros.h>
|
||||
|
||||
#define ATA_DEVICE_PRIMARY 0x1F0
|
||||
#define ATA_DEVICE_SECONDARY 0x170
|
||||
#define ATA_DEVICE_SLAVE_BIT 0x10
|
||||
@@ -199,23 +201,18 @@ namespace Kernel
|
||||
}
|
||||
|
||||
Partition::Partition(StorageDevice& device, const GUID& type, const GUID& guid, uint64_t start, uint64_t end, uint64_t attr, const char* label, uint32_t index)
|
||||
: m_device(device)
|
||||
: BlockDevice(0660, 0, 0)
|
||||
, m_device(device)
|
||||
, m_type(type)
|
||||
, m_guid(guid)
|
||||
, m_lba_start(start)
|
||||
, m_lba_end(end)
|
||||
, m_attributes(attr)
|
||||
, m_index(index)
|
||||
, m_device_name(BAN::String::formatted("{}{}", m_device.name(), index))
|
||||
, m_rdev(makedev(major(device.rdev()), index))
|
||||
{
|
||||
memcpy(m_label, label, sizeof(m_label));
|
||||
}
|
||||
|
||||
dev_t Partition::rdev() const
|
||||
{
|
||||
return makedev(major(m_device.rdev()), m_index);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Partition::read_sectors(uint64_t lba, uint8_t sector_count, uint8_t* buffer)
|
||||
{
|
||||
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
#include <BAN/ScopeGuard.h>
|
||||
#include <BAN/UTF8.h>
|
||||
#include <kernel/Debug.h>
|
||||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
#include <kernel/LockGuard.h>
|
||||
#include <kernel/Process.h>
|
||||
#include <kernel/Terminal/TTY.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/sysmacros.h>
|
||||
|
||||
#define BEL 0x07
|
||||
#define BS 0x08
|
||||
@@ -26,7 +28,7 @@ namespace Kernel
|
||||
|
||||
static dev_t next_tty_rdev()
|
||||
{
|
||||
static dev_t major = DeviceManager::get().get_next_rdev();
|
||||
static dev_t major = DevFileSystem::get().get_next_rdev();
|
||||
static dev_t minor = 1;
|
||||
return makedev(major, minor++);
|
||||
}
|
||||
@@ -34,7 +36,8 @@ namespace Kernel
|
||||
static TTY* s_tty = nullptr;
|
||||
|
||||
TTY::TTY(TerminalDriver* driver)
|
||||
: m_terminal_driver(driver)
|
||||
: CharacterDevice(0444, 0, 0)
|
||||
, m_terminal_driver(driver)
|
||||
{
|
||||
m_width = m_terminal_driver->width();
|
||||
m_height = m_terminal_driver->height();
|
||||
@@ -54,8 +57,12 @@ namespace Kernel
|
||||
void TTY::initialize_device()
|
||||
{
|
||||
m_rdev = next_tty_rdev();
|
||||
m_name = BAN::String::formatted("tty{}", minor(m_rdev));
|
||||
DeviceManager::get().add_device(this);
|
||||
|
||||
char name[5] { 't', 't', 'y', '1', '\0'};
|
||||
name[3] += minor(m_rdev);
|
||||
ASSERT(minor(m_rdev) < 10);
|
||||
|
||||
DevFileSystem::get().add_device(name, this);
|
||||
|
||||
if (s_input_process)
|
||||
return;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <kernel/ACPI.h>
|
||||
#include <kernel/Arch.h>
|
||||
#include <kernel/Debug.h>
|
||||
#include <kernel/DeviceManager.h>
|
||||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
#include <kernel/FS/VirtualFileSystem.h>
|
||||
#include <kernel/GDT.h>
|
||||
#include <kernel/IDT.h>
|
||||
@@ -140,6 +140,9 @@ extern "C" void kernel_main()
|
||||
ASSERT(terminal_driver);
|
||||
dprintln("VESA initialized");
|
||||
|
||||
DevFileSystem::initialize();
|
||||
dprintln("devfs initialized");
|
||||
|
||||
TTY* tty1 = new TTY(terminal_driver);
|
||||
ASSERT(tty1);
|
||||
dprintln("TTY initialized");
|
||||
@@ -147,9 +150,6 @@ extern "C" void kernel_main()
|
||||
parse_command_line();
|
||||
dprintln("command line parsed, root='{}'", cmdline.root);
|
||||
|
||||
PCI::initialize();
|
||||
dprintln("PCI initialized");
|
||||
|
||||
MUST(ACPI::initialize());
|
||||
dprintln("ACPI initialized");
|
||||
|
||||
@@ -160,6 +160,8 @@ extern "C" void kernel_main()
|
||||
dprintln("PIT initialized");
|
||||
|
||||
MUST(Scheduler::initialize());
|
||||
dprintln("Scheduler initialized");
|
||||
|
||||
Scheduler& scheduler = Scheduler::get();
|
||||
Process::create_kernel(init2, tty1);
|
||||
scheduler.start();
|
||||
@@ -172,9 +174,13 @@ static void init2(void* tty1)
|
||||
using namespace Kernel;
|
||||
using namespace Kernel::Input;
|
||||
|
||||
DeviceManager::get().initialize_pci_devices();
|
||||
DeviceManager::get().initialize_updater();
|
||||
dprintln("Scheduler started");
|
||||
|
||||
DevFileSystem::get().initialize_device_updater();
|
||||
|
||||
PCI::initialize();
|
||||
dprintln("PCI initialized");
|
||||
|
||||
VirtualFileSystem::initialize(cmdline.root);
|
||||
|
||||
if (auto res = PS2Controller::initialize(); res.is_error())
|
||||
|
||||
Reference in New Issue
Block a user