Compare commits
No commits in common. "211cad03ff1f2fa4a66950bec5b8bd28550f848b" and "bcf62c5f2e6368129d1b7f421c22ee940b69a675" have entirely different histories.
211cad03ff
...
bcf62c5f2e
Binary file not shown.
|
@ -34,7 +34,6 @@ set(KERNEL_SOURCES
|
||||||
kernel/Input/PS2Keymap.cpp
|
kernel/Input/PS2Keymap.cpp
|
||||||
kernel/InterruptController.cpp
|
kernel/InterruptController.cpp
|
||||||
kernel/kernel.cpp
|
kernel/kernel.cpp
|
||||||
kernel/Memory/DMARegion.cpp
|
|
||||||
kernel/Memory/FileBackedRegion.cpp
|
kernel/Memory/FileBackedRegion.cpp
|
||||||
kernel/Memory/GeneralAllocator.cpp
|
kernel/Memory/GeneralAllocator.cpp
|
||||||
kernel/Memory/Heap.cpp
|
kernel/Memory/Heap.cpp
|
||||||
|
@ -53,9 +52,9 @@ set(KERNEL_SOURCES
|
||||||
kernel/Semaphore.cpp
|
kernel/Semaphore.cpp
|
||||||
kernel/SpinLock.cpp
|
kernel/SpinLock.cpp
|
||||||
kernel/SSP.cpp
|
kernel/SSP.cpp
|
||||||
kernel/Storage/ATA/ATABus.cpp
|
kernel/Storage/ATABus.cpp
|
||||||
kernel/Storage/ATA/ATAController.cpp
|
kernel/Storage/ATAController.cpp
|
||||||
kernel/Storage/ATA/ATADevice.cpp
|
kernel/Storage/ATADevice.cpp
|
||||||
kernel/Storage/DiskCache.cpp
|
kernel/Storage/DiskCache.cpp
|
||||||
kernel/Storage/StorageDevice.cpp
|
kernel/Storage/StorageDevice.cpp
|
||||||
kernel/Syscall.cpp
|
kernel/Syscall.cpp
|
||||||
|
|
|
@ -17,8 +17,6 @@ namespace Kernel
|
||||||
|
|
||||||
virtual dev_t rdev() const override = 0;
|
virtual dev_t rdev() const override = 0;
|
||||||
|
|
||||||
virtual BAN::StringView name() const = 0;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Device(mode_t, uid_t, gid_t);
|
Device(mode_t, uid_t, gid_t);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <kernel/Device/Device.h>
|
#include <kernel/Device/Device.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
|
@ -12,8 +10,6 @@ namespace Kernel
|
||||||
|
|
||||||
virtual dev_t rdev() const override { return m_rdev; }
|
virtual dev_t rdev() const override { return m_rdev; }
|
||||||
|
|
||||||
virtual BAN::StringView name() const override { return "null"sv; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NullDevice(mode_t mode, uid_t uid, gid_t gid, dev_t rdev)
|
NullDevice(mode_t mode, uid_t uid, gid_t gid, dev_t rdev)
|
||||||
: CharacterDevice(mode, uid, gid)
|
: CharacterDevice(mode, uid, gid)
|
||||||
|
|
|
@ -10,8 +10,6 @@ namespace Kernel
|
||||||
|
|
||||||
virtual dev_t rdev() const override { return m_rdev; }
|
virtual dev_t rdev() const override { return m_rdev; }
|
||||||
|
|
||||||
virtual BAN::StringView name() const override { return "zero"sv; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ZeroDevice(mode_t mode, uid_t uid, gid_t gid, dev_t rdev)
|
ZeroDevice(mode_t mode, uid_t uid, gid_t gid, dev_t rdev)
|
||||||
: CharacterDevice(mode, uid, gid)
|
: CharacterDevice(mode, uid, gid)
|
||||||
|
|
|
@ -15,12 +15,10 @@ namespace Kernel
|
||||||
|
|
||||||
void initialize_device_updater();
|
void initialize_device_updater();
|
||||||
|
|
||||||
void add_device(BAN::RefPtr<Device>);
|
void add_device(BAN::StringView path, BAN::RefPtr<RamInode>);
|
||||||
void add_inode(BAN::StringView path, BAN::RefPtr<RamInode>);
|
|
||||||
void for_each_device(const BAN::Function<BAN::Iteration(Device*)>& callback);
|
void for_each_device(const BAN::Function<BAN::Iteration(Device*)>& callback);
|
||||||
|
|
||||||
dev_t get_next_dev() const;
|
dev_t get_next_dev();
|
||||||
int get_next_input_device() const;
|
|
||||||
|
|
||||||
void initiate_sync(bool should_block);
|
void initiate_sync(bool should_block);
|
||||||
|
|
||||||
|
@ -30,7 +28,7 @@ namespace Kernel
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable SpinLock m_device_lock;
|
SpinLock m_device_lock;
|
||||||
|
|
||||||
Semaphore m_sync_done;
|
Semaphore m_sync_done;
|
||||||
Semaphore m_sync_semaphore;
|
Semaphore m_sync_semaphore;
|
||||||
|
|
|
@ -9,13 +9,12 @@ namespace Kernel::Input
|
||||||
class PS2Device : public CharacterDevice, public Interruptable
|
class PS2Device : public CharacterDevice, public Interruptable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PS2Device();
|
|
||||||
virtual ~PS2Device() {}
|
virtual ~PS2Device() {}
|
||||||
|
|
||||||
virtual BAN::StringView name() const override { return m_name; }
|
public:
|
||||||
|
PS2Device()
|
||||||
private:
|
: CharacterDevice(Mode::IRUSR | Mode::IRGRP, 0, 0)
|
||||||
const BAN::String m_name;
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
class PS2Controller
|
class PS2Controller
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <kernel/Memory/MemoryRegion.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
class DMARegion
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<DMARegion>> create(size_t size);
|
|
||||||
~DMARegion();
|
|
||||||
|
|
||||||
size_t size() const { return m_size; }
|
|
||||||
vaddr_t vaddr() const { return m_vaddr; }
|
|
||||||
paddr_t paddr() const { return m_paddr; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
DMARegion(size_t size, vaddr_t vaddr, paddr_t paddr);
|
|
||||||
|
|
||||||
private:
|
|
||||||
const size_t m_size;
|
|
||||||
const vaddr_t m_vaddr;
|
|
||||||
const paddr_t m_paddr;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -21,9 +21,6 @@ namespace Kernel
|
||||||
paddr_t take_free_page();
|
paddr_t take_free_page();
|
||||||
void release_page(paddr_t);
|
void release_page(paddr_t);
|
||||||
|
|
||||||
paddr_t take_free_contiguous_pages(size_t pages);
|
|
||||||
void release_contiguous_pages(paddr_t paddr, size_t pages);
|
|
||||||
|
|
||||||
size_t used_pages() const;
|
size_t used_pages() const;
|
||||||
size_t free_pages() const;
|
size_t free_pages() const;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <kernel/Memory/Types.h>
|
#include <kernel/Memory/Types.h>
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
@ -11,40 +12,42 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PhysicalRange(paddr_t, size_t);
|
PhysicalRange(paddr_t, size_t);
|
||||||
|
|
||||||
paddr_t reserve_page();
|
paddr_t reserve_page();
|
||||||
void release_page(paddr_t);
|
void release_page(paddr_t);
|
||||||
|
|
||||||
paddr_t reserve_contiguous_pages(size_t pages);
|
|
||||||
void release_contiguous_pages(paddr_t paddr, size_t pages);
|
|
||||||
|
|
||||||
paddr_t start() const { return m_paddr; }
|
paddr_t start() const { return m_paddr; }
|
||||||
paddr_t end() const { return m_paddr + m_size; }
|
paddr_t end() const { return m_paddr + m_size; }
|
||||||
bool contains(paddr_t addr) const { return m_paddr <= addr && addr < m_paddr + m_size; }
|
bool contains(paddr_t addr) const { return m_paddr <= addr && addr < m_paddr + m_size; }
|
||||||
|
|
||||||
size_t usable_memory() const { return m_data_pages * PAGE_SIZE; }
|
size_t usable_memory() const { return m_reservable_pages * PAGE_SIZE; }
|
||||||
|
|
||||||
size_t used_pages() const { return m_data_pages - m_free_pages; }
|
size_t used_pages() const { return m_used_pages; }
|
||||||
size_t free_pages() const { return m_free_pages; }
|
size_t free_pages() const { return m_free_pages; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned long long* ull_bitmap_ptr() { return (unsigned long long*)m_vaddr; }
|
struct node
|
||||||
const unsigned long long* ull_bitmap_ptr() const { return (const unsigned long long*)m_vaddr; }
|
{
|
||||||
|
node* next;
|
||||||
|
node* prev;
|
||||||
|
};
|
||||||
|
|
||||||
paddr_t paddr_for_bit(unsigned long long) const;
|
paddr_t page_address(const node*) const;
|
||||||
unsigned long long bit_for_paddr(paddr_t paddr) const;
|
node* node_address(paddr_t) const;
|
||||||
|
|
||||||
unsigned long long contiguous_bits_set(unsigned long long start, unsigned long long count) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const paddr_t m_paddr { 0 };
|
paddr_t m_paddr { 0 };
|
||||||
const size_t m_size { 0 };
|
|
||||||
|
|
||||||
vaddr_t m_vaddr { 0 };
|
vaddr_t m_vaddr { 0 };
|
||||||
|
size_t m_size { 0 };
|
||||||
|
|
||||||
const size_t m_bitmap_pages { 0 };
|
uint64_t m_total_pages { 0 };
|
||||||
const size_t m_data_pages { 0 };
|
uint64_t m_reservable_pages { 0 };
|
||||||
|
uint64_t m_list_pages { 0 };
|
||||||
|
|
||||||
|
size_t m_used_pages { 0 };
|
||||||
size_t m_free_pages { 0 };
|
size_t m_free_pages { 0 };
|
||||||
|
|
||||||
|
node* m_free_list { nullptr };
|
||||||
|
node* m_used_list { nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -3,9 +3,6 @@
|
||||||
#include <BAN/UniqPtr.h>
|
#include <BAN/UniqPtr.h>
|
||||||
#include <BAN/Vector.h>
|
#include <BAN/Vector.h>
|
||||||
#include <kernel/Memory/Types.h>
|
#include <kernel/Memory/Types.h>
|
||||||
#include <kernel/Storage/StorageController.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
namespace Kernel::PCI
|
namespace Kernel::PCI
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <BAN/UniqPtr.h>
|
|
||||||
#include <kernel/PCI.h>
|
|
||||||
#include <kernel/Storage/StorageController.h>
|
|
||||||
#include <kernel/Storage/ATA/ATABus.h>
|
|
||||||
#include <kernel/Storage/ATA/ATADevice.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
class ATAController : public StorageController
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<StorageController>> create(PCI::Device&);
|
|
||||||
virtual BAN::ErrorOr<void> initialize() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
ATAController(PCI::Device& pci_device)
|
|
||||||
: m_pci_device(pci_device)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
private:
|
|
||||||
PCI::Device& m_pci_device;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,46 +1,48 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <BAN/RefPtr.h>
|
#include <BAN/Errors.h>
|
||||||
#include <BAN/Vector.h>
|
|
||||||
#include <kernel/InterruptController.h>
|
#include <kernel/InterruptController.h>
|
||||||
#include <kernel/SpinLock.h>
|
#include <kernel/SpinLock.h>
|
||||||
|
#include <kernel/Storage/ATAController.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
class ATADevice;
|
class ATADevice;
|
||||||
|
|
||||||
class ATABus : public BAN::RefCounted<ATABus>, public Interruptable
|
class ATABus : public Interruptable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class DeviceType
|
enum class DeviceType
|
||||||
{
|
{
|
||||||
|
None,
|
||||||
ATA,
|
ATA,
|
||||||
ATAPI,
|
ATAPI,
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<ATABus>> create(uint16_t base, uint16_t ctrl, uint8_t irq);
|
static ATABus* create(ATAController&, uint16_t base, uint16_t ctrl, uint8_t irq);
|
||||||
|
|
||||||
BAN::ErrorOr<void> read(ATADevice&, uint64_t, uint8_t, uint8_t*);
|
BAN::ErrorOr<void> read(ATADevice&, uint64_t, uint8_t, uint8_t*);
|
||||||
BAN::ErrorOr<void> write(ATADevice&, uint64_t, uint8_t, const uint8_t*);
|
BAN::ErrorOr<void> write(ATADevice&, uint64_t, uint8_t, const uint8_t*);
|
||||||
|
|
||||||
|
ATAController& controller() { return m_controller; }
|
||||||
|
|
||||||
virtual void handle_irq() override;
|
virtual void handle_irq() override;
|
||||||
|
|
||||||
void initialize_devfs();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ATABus(uint16_t base, uint16_t ctrl)
|
ATABus(ATAController& controller, uint16_t base, uint16_t ctrl)
|
||||||
: m_base(base)
|
: m_controller(controller)
|
||||||
|
, m_base(base)
|
||||||
, m_ctrl(ctrl)
|
, m_ctrl(ctrl)
|
||||||
{}
|
{}
|
||||||
BAN::ErrorOr<void> initialize();
|
void initialize(uint8_t irq);
|
||||||
|
|
||||||
void select_device(bool secondary);
|
void select_device(const ATADevice&);
|
||||||
BAN::ErrorOr<DeviceType> identify(bool secondary, BAN::Span<uint16_t> buffer);
|
DeviceType identify(const ATADevice&, uint16_t*);
|
||||||
|
|
||||||
void block_until_irq();
|
void block_until_irq();
|
||||||
//uint8_t device_index(const ATADevice&) const;
|
uint8_t device_index(const ATADevice&) const;
|
||||||
|
|
||||||
uint8_t io_read(uint16_t);
|
uint8_t io_read(uint16_t);
|
||||||
void io_write(uint16_t, uint8_t);
|
void io_write(uint16_t, uint8_t);
|
||||||
|
@ -50,14 +52,14 @@ namespace Kernel
|
||||||
BAN::Error error();
|
BAN::Error error();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ATAController& m_controller;
|
||||||
const uint16_t m_base;
|
const uint16_t m_base;
|
||||||
const uint16_t m_ctrl;
|
const uint16_t m_ctrl;
|
||||||
SpinLock m_lock;
|
SpinLock m_lock;
|
||||||
|
|
||||||
bool m_has_got_irq { false };
|
bool m_has_got_irq { false };
|
||||||
|
|
||||||
// Non-owning pointers
|
BAN::RefPtr<ATADevice> m_devices[2] {};
|
||||||
BAN::Vector<ATADevice*> m_devices;
|
|
||||||
|
|
||||||
friend class ATAController;
|
friend class ATAController;
|
||||||
};
|
};
|
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <kernel/PCI.h>
|
||||||
|
#include <kernel/Storage/StorageController.h>
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
|
||||||
|
class ATABus;
|
||||||
|
|
||||||
|
class ATAController final : public StorageController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static BAN::ErrorOr<BAN::RefPtr<ATAController>> create(const PCI::Device&);
|
||||||
|
|
||||||
|
virtual BAN::Vector<BAN::RefPtr<StorageDevice>> devices() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ATAController();
|
||||||
|
BAN::ErrorOr<void> initialize(const PCI::Device& device);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ATABus* m_buses[2] { nullptr, nullptr };
|
||||||
|
friend class ATABus;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual Mode mode() const override { return { Mode::IFCHR }; }
|
||||||
|
virtual uid_t uid() const override { return 0; }
|
||||||
|
virtual gid_t gid() const override { return 0; }
|
||||||
|
virtual dev_t rdev() const override { return m_rdev; }
|
||||||
|
|
||||||
|
virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const dev_t m_rdev;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -1,8 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define ATA_PROGIF_PRIMARY_NATIVE (1 << 0)
|
|
||||||
#define ATA_PROGIF_SECONDARY_NATIVE (1 << 2)
|
|
||||||
|
|
||||||
#define ATA_PORT_DATA 0x00
|
#define ATA_PORT_DATA 0x00
|
||||||
#define ATA_PORT_ERROR 0x00
|
#define ATA_PORT_ERROR 0x00
|
||||||
#define ATA_PORT_SECTOR_COUNT 0x02
|
#define ATA_PORT_SECTOR_COUNT 0x02
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <kernel/Storage/ATA/ATABus.h>
|
#include <kernel/Storage/ATABus.h>
|
||||||
#include <kernel/Storage/StorageDevice.h>
|
#include <kernel/Storage/StorageDevice.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
|
@ -9,31 +9,23 @@ namespace Kernel
|
||||||
class ATADevice final : public StorageDevice
|
class ATADevice final : public StorageDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<ATADevice>> create(BAN::RefPtr<ATABus>, ATABus::DeviceType, bool is_secondary, BAN::Span<const uint16_t> identify_data);
|
ATADevice(ATABus&);
|
||||||
|
BAN::ErrorOr<void> initialize(ATABus::DeviceType, const uint16_t*);
|
||||||
|
|
||||||
virtual uint32_t sector_size() const override { return m_sector_words * 2; }
|
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(); }
|
virtual uint64_t total_size() const override { return m_lba_count * sector_size(); }
|
||||||
|
|
||||||
bool is_secondary() const { return m_is_secondary; }
|
|
||||||
uint32_t words_per_sector() const { return m_sector_words; }
|
|
||||||
uint64_t sector_count() const { return m_lba_count; }
|
|
||||||
|
|
||||||
BAN::StringView model() const { return m_model; }
|
BAN::StringView model() const { return m_model; }
|
||||||
BAN::StringView name() const;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual BAN::ErrorOr<void> read_sectors_impl(uint64_t, uint8_t, uint8_t*) override;
|
virtual BAN::ErrorOr<void> read_sectors_impl(uint64_t, uint8_t, uint8_t*) override;
|
||||||
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t, uint8_t, const uint8_t*) override;
|
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t, uint8_t, const uint8_t*) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ATADevice(BAN::RefPtr<ATABus>, ATABus::DeviceType, bool is_secodary);
|
ATABus& m_bus;
|
||||||
BAN::ErrorOr<void> initialize(BAN::Span<const uint16_t> identify_data);
|
uint8_t m_index;
|
||||||
|
|
||||||
private:
|
ATABus::DeviceType m_type;
|
||||||
BAN::RefPtr<ATABus> m_bus;
|
|
||||||
const ATABus::DeviceType m_type;
|
|
||||||
const bool m_is_secondary;
|
|
||||||
|
|
||||||
uint16_t m_signature;
|
uint16_t m_signature;
|
||||||
uint16_t m_capabilities;
|
uint16_t m_capabilities;
|
||||||
uint32_t m_command_set;
|
uint32_t m_command_set;
|
||||||
|
@ -41,6 +33,8 @@ namespace Kernel
|
||||||
uint64_t m_lba_count;
|
uint64_t m_lba_count;
|
||||||
char m_model[41];
|
char m_model[41];
|
||||||
|
|
||||||
|
friend class ATABus;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Mode mode() const override { return { Mode::IFBLK | Mode::IRUSR | Mode::IRGRP }; }
|
virtual Mode mode() const override { return { Mode::IFBLK | Mode::IRUSR | Mode::IRGRP }; }
|
||||||
virtual uid_t uid() const override { return 0; }
|
virtual uid_t uid() const override { return 0; }
|
|
@ -1,13 +1,17 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <kernel/Storage/StorageDevice.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
class StorageController
|
class StorageController : public CharacterDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~StorageController() {}
|
StorageController()
|
||||||
virtual BAN::ErrorOr<void> initialize() = 0;
|
: CharacterDevice(0660, 0, 0)
|
||||||
|
{ }
|
||||||
|
virtual BAN::Vector<BAN::RefPtr<StorageDevice>> devices() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -20,7 +20,7 @@ namespace Kernel
|
||||||
class Partition final : public BlockDevice
|
class Partition final : public BlockDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<Partition>> create(StorageDevice&, const GUID& type, const GUID& guid, uint64_t start, uint64_t end, uint64_t attr, const char* label, uint32_t index);
|
Partition(StorageDevice&, const GUID&, const GUID&, uint64_t, uint64_t, uint64_t, const char*, uint32_t);
|
||||||
|
|
||||||
const GUID& partition_type() const { return m_type; }
|
const GUID& partition_type() const { return m_type; }
|
||||||
const GUID& partition_guid() const { return m_guid; }
|
const GUID& partition_guid() const { return m_guid; }
|
||||||
|
@ -32,11 +32,6 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<void> read_sectors(uint64_t lba, uint8_t sector_count, uint8_t* buffer);
|
BAN::ErrorOr<void> read_sectors(uint64_t lba, uint8_t sector_count, uint8_t* buffer);
|
||||||
BAN::ErrorOr<void> write_sectors(uint64_t lba, uint8_t sector_count, const uint8_t* buffer);
|
BAN::ErrorOr<void> write_sectors(uint64_t lba, uint8_t sector_count, const uint8_t* buffer);
|
||||||
|
|
||||||
virtual BAN::StringView name() const override { return m_name; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Partition(StorageDevice&, const GUID&, const GUID&, uint64_t, uint64_t, uint64_t, const char*, uint32_t);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StorageDevice& m_device;
|
StorageDevice& m_device;
|
||||||
|
@ -46,7 +41,6 @@ namespace Kernel
|
||||||
const uint64_t m_lba_end;
|
const uint64_t m_lba_end;
|
||||||
const uint64_t m_attributes;
|
const uint64_t m_attributes;
|
||||||
char m_label[36 * 4 + 1];
|
char m_label[36 * 4 + 1];
|
||||||
const BAN::String m_name;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual bool is_partition() const override { return true; }
|
virtual bool is_partition() const override { return true; }
|
||||||
|
@ -79,8 +73,8 @@ namespace Kernel
|
||||||
virtual uint32_t sector_size() const = 0;
|
virtual uint32_t sector_size() const = 0;
|
||||||
virtual uint64_t total_size() const = 0;
|
virtual uint64_t total_size() const = 0;
|
||||||
|
|
||||||
BAN::Vector<BAN::RefPtr<Partition>>& partitions() { return m_partitions; }
|
BAN::Vector<Partition*>& partitions() { return m_partitions; }
|
||||||
const BAN::Vector<BAN::RefPtr<Partition>>& partitions() const { return m_partitions; }
|
const BAN::Vector<Partition*>& partitions() const { return m_partitions; }
|
||||||
|
|
||||||
BAN::ErrorOr<void> sync_disk_cache();
|
BAN::ErrorOr<void> sync_disk_cache();
|
||||||
virtual bool is_storage_device() const override { return true; }
|
virtual bool is_storage_device() const override { return true; }
|
||||||
|
@ -91,9 +85,9 @@ namespace Kernel
|
||||||
void add_disk_cache();
|
void add_disk_cache();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SpinLock m_lock;
|
SpinLock m_lock;
|
||||||
BAN::Optional<DiskCache> m_disk_cache;
|
BAN::Optional<DiskCache> m_disk_cache;
|
||||||
BAN::Vector<BAN::RefPtr<Partition>> m_partitions;
|
BAN::Vector<Partition*> m_partitions;
|
||||||
|
|
||||||
friend class DiskCache;
|
friend class DiskCache;
|
||||||
};
|
};
|
||||||
|
|
|
@ -50,6 +50,8 @@ namespace Kernel
|
||||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override;
|
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override;
|
||||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override;
|
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override;
|
||||||
|
|
||||||
|
virtual BAN::StringView name() const = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void do_backspace();
|
void do_backspace();
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@ namespace Kernel
|
||||||
auto root_inode = MUST(RamDirectoryInode::create(*s_instance, 0, 0755, 0, 0));
|
auto root_inode = MUST(RamDirectoryInode::create(*s_instance, 0, 0755, 0, 0));
|
||||||
MUST(s_instance->set_root_inode(root_inode));
|
MUST(s_instance->set_root_inode(root_inode));
|
||||||
|
|
||||||
s_instance->add_device(MUST(NullDevice::create(0666, 0, 0)));
|
s_instance->add_device("null", MUST(NullDevice::create(0666, 0, 0)));
|
||||||
s_instance->add_device(MUST(ZeroDevice::create(0666, 0, 0)));
|
s_instance->add_device("zero", MUST(ZeroDevice::create(0666, 0, 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
DevFileSystem& DevFileSystem::get()
|
DevFileSystem& DevFileSystem::get()
|
||||||
|
@ -117,16 +117,10 @@ namespace Kernel
|
||||||
m_sync_done.block();
|
m_sync_done.block();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DevFileSystem::add_device(BAN::RefPtr<Device> device)
|
void DevFileSystem::add_device(BAN::StringView path, BAN::RefPtr<RamInode> device)
|
||||||
{
|
|
||||||
ASSERT(!device->name().contains('/'));
|
|
||||||
MUST(reinterpret_cast<RamDirectoryInode*>(root_inode().ptr())->add_inode(device->name(), device));
|
|
||||||
}
|
|
||||||
|
|
||||||
void DevFileSystem::add_inode(BAN::StringView path, BAN::RefPtr<RamInode> inode)
|
|
||||||
{
|
{
|
||||||
ASSERT(!path.contains('/'));
|
ASSERT(!path.contains('/'));
|
||||||
MUST(reinterpret_cast<RamDirectoryInode*>(root_inode().ptr())->add_inode(path, inode));
|
MUST(reinterpret_cast<RamDirectoryInode*>(root_inode().ptr())->add_inode(path, device));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DevFileSystem::for_each_device(const BAN::Function<BAN::Iteration(Device*)>& callback)
|
void DevFileSystem::for_each_device(const BAN::Function<BAN::Iteration(Device*)>& callback)
|
||||||
|
@ -142,18 +136,11 @@ namespace Kernel
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_t DevFileSystem::get_next_dev() const
|
dev_t DevFileSystem::get_next_dev()
|
||||||
{
|
{
|
||||||
LockGuard _(m_device_lock);
|
LockGuard _(m_device_lock);
|
||||||
static dev_t next_dev = 1;
|
static dev_t next_dev = 1;
|
||||||
return next_dev++;
|
return next_dev++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DevFileSystem::get_next_input_device() const
|
|
||||||
{
|
|
||||||
LockGuard _(m_device_lock);
|
|
||||||
static dev_t next_dev = 0;
|
|
||||||
return next_dev++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -68,11 +68,6 @@ namespace Kernel::Input
|
||||||
|
|
||||||
static PS2Controller* s_instance = nullptr;
|
static PS2Controller* s_instance = nullptr;
|
||||||
|
|
||||||
PS2Device::PS2Device()
|
|
||||||
: CharacterDevice(0440, 0, 0)
|
|
||||||
, m_name(BAN::String::formatted("input{}", DevFileSystem::get().get_next_input_device()))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> PS2Controller::initialize()
|
BAN::ErrorOr<void> PS2Controller::initialize()
|
||||||
{
|
{
|
||||||
ASSERT(s_instance == nullptr);
|
ASSERT(s_instance == nullptr);
|
||||||
|
@ -180,14 +175,14 @@ namespace Kernel::Input
|
||||||
m_devices[0]->set_irq(PS2::IRQ::DEVICE0);
|
m_devices[0]->set_irq(PS2::IRQ::DEVICE0);
|
||||||
m_devices[0]->enable_interrupt();
|
m_devices[0]->enable_interrupt();
|
||||||
config |= PS2::Config::INTERRUPT_FIRST_PORT;
|
config |= PS2::Config::INTERRUPT_FIRST_PORT;
|
||||||
DevFileSystem::get().add_device(m_devices[0]);
|
DevFileSystem::get().add_device("input0", m_devices[0]);
|
||||||
}
|
}
|
||||||
if (m_devices[1])
|
if (m_devices[1])
|
||||||
{
|
{
|
||||||
m_devices[1]->set_irq(PS2::IRQ::DEVICE1);
|
m_devices[1]->set_irq(PS2::IRQ::DEVICE1);
|
||||||
m_devices[1]->enable_interrupt();
|
m_devices[1]->enable_interrupt();
|
||||||
config |= PS2::Config::INTERRUPT_SECOND_PORT;
|
config |= PS2::Config::INTERRUPT_SECOND_PORT;
|
||||||
DevFileSystem::get().add_device(m_devices[1]);
|
DevFileSystem::get().add_device("input1", m_devices[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
controller_send_command(PS2::Command::WRITE_CONFIG, config);
|
controller_send_command(PS2::Command::WRITE_CONFIG, config);
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
#include <BAN/ScopeGuard.h>
|
|
||||||
#include <kernel/Memory/DMARegion.h>
|
|
||||||
#include <kernel/Memory/Heap.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<DMARegion>> DMARegion::create(size_t size)
|
|
||||||
{
|
|
||||||
size_t needed_pages = BAN::Math::div_round_up<size_t>(size, PAGE_SIZE);
|
|
||||||
|
|
||||||
vaddr_t vaddr = PageTable::kernel().reserve_free_contiguous_pages(needed_pages, KERNEL_OFFSET);
|
|
||||||
if (vaddr == 0)
|
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
|
||||||
BAN::ScopeGuard vaddr_guard([vaddr, size] { PageTable::kernel().unmap_range(vaddr, size); });
|
|
||||||
|
|
||||||
paddr_t paddr = Heap::get().take_free_contiguous_pages(needed_pages);
|
|
||||||
if (paddr == 0)
|
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
|
||||||
BAN::ScopeGuard paddr_guard([paddr, needed_pages] { Heap::get().release_contiguous_pages(paddr, needed_pages); });
|
|
||||||
|
|
||||||
auto* region_ptr = new DMARegion(size, vaddr, paddr);
|
|
||||||
if (region_ptr == nullptr)
|
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
|
||||||
|
|
||||||
vaddr_guard.disable();
|
|
||||||
paddr_guard.disable();
|
|
||||||
|
|
||||||
PageTable::kernel().map_range_at(paddr, vaddr, size, PageTable::Flags::CacheDisable | PageTable::Flags::ReadWrite | PageTable::Flags::Reserved);
|
|
||||||
|
|
||||||
return BAN::UniqPtr<DMARegion>::adopt(region_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
DMARegion::DMARegion(size_t size, vaddr_t vaddr, paddr_t paddr)
|
|
||||||
: m_size(size)
|
|
||||||
, m_vaddr(vaddr)
|
|
||||||
, m_paddr(paddr)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
DMARegion::~DMARegion()
|
|
||||||
{
|
|
||||||
PageTable::kernel().unmap_range(m_vaddr, m_size);
|
|
||||||
Heap::get().release_contiguous_pages(m_vaddr, BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -3,8 +3,6 @@
|
||||||
#include <kernel/Memory/PageTable.h>
|
#include <kernel/Memory/PageTable.h>
|
||||||
#include <kernel/multiboot.h>
|
#include <kernel/multiboot.h>
|
||||||
|
|
||||||
extern uint8_t g_kernel_end[];
|
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -32,22 +30,14 @@ namespace Kernel
|
||||||
for (size_t i = 0; i < g_multiboot_info->mmap_length;)
|
for (size_t i = 0; i < g_multiboot_info->mmap_length;)
|
||||||
{
|
{
|
||||||
multiboot_memory_map_t* mmmt = (multiboot_memory_map_t*)P2V(g_multiboot_info->mmap_addr + i);
|
multiboot_memory_map_t* mmmt = (multiboot_memory_map_t*)P2V(g_multiboot_info->mmap_addr + i);
|
||||||
|
|
||||||
if (mmmt->type == 1)
|
if (mmmt->type == 1)
|
||||||
{
|
{
|
||||||
paddr_t start = mmmt->base_addr;
|
PhysicalRange range(mmmt->base_addr, mmmt->length);
|
||||||
if (start < V2P(g_kernel_end))
|
if (range.usable_memory() > 0)
|
||||||
start = V2P(g_kernel_end);
|
MUST(m_physical_ranges.push_back(range));
|
||||||
if (auto rem = start % PAGE_SIZE)
|
|
||||||
start += PAGE_SIZE - rem;
|
|
||||||
|
|
||||||
paddr_t end = mmmt->base_addr + mmmt->length;
|
|
||||||
if (auto rem = end % PAGE_SIZE)
|
|
||||||
end -= rem;
|
|
||||||
|
|
||||||
// Physical pages needs atleast 2 pages
|
|
||||||
if (end > start + PAGE_SIZE)
|
|
||||||
MUST(m_physical_ranges.emplace_back(start, end - start));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i += mmmt->size + sizeof(uint32_t);
|
i += mmmt->size + sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,36 +55,22 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
for (auto& range : m_physical_ranges)
|
for (auto& range : m_physical_ranges)
|
||||||
if (range.free_pages() >= 1)
|
if (paddr_t page = range.reserve_page())
|
||||||
return range.reserve_page();
|
return page;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Heap::release_page(paddr_t paddr)
|
void Heap::release_page(paddr_t addr)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
for (auto& range : m_physical_ranges)
|
for (auto& range : m_physical_ranges)
|
||||||
if (range.contains(paddr))
|
{
|
||||||
return range.release_page(paddr);
|
if (range.contains(addr))
|
||||||
ASSERT_NOT_REACHED();
|
{
|
||||||
}
|
range.release_page(addr);
|
||||||
|
return;
|
||||||
paddr_t Heap::take_free_contiguous_pages(size_t pages)
|
}
|
||||||
{
|
}
|
||||||
LockGuard _(m_lock);
|
|
||||||
for (auto& range : m_physical_ranges)
|
|
||||||
if (range.free_pages() >= pages)
|
|
||||||
if (paddr_t paddr = range.reserve_contiguous_pages(pages))
|
|
||||||
return paddr;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Heap::release_contiguous_pages(paddr_t paddr, size_t pages)
|
|
||||||
{
|
|
||||||
LockGuard _(m_lock);
|
|
||||||
for (auto& range : m_physical_ranges)
|
|
||||||
if (range.contains(paddr))
|
|
||||||
return range.release_contiguous_pages(paddr, pages);
|
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,150 +3,123 @@
|
||||||
#include <kernel/Memory/PageTable.h>
|
#include <kernel/Memory/PageTable.h>
|
||||||
#include <kernel/Memory/PhysicalRange.h>
|
#include <kernel/Memory/PhysicalRange.h>
|
||||||
|
|
||||||
|
extern uint8_t g_kernel_end[];
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
using ull = unsigned long long;
|
PhysicalRange::PhysicalRange(paddr_t start, size_t size)
|
||||||
|
|
||||||
static constexpr ull ull_bits = sizeof(ull) * 8;
|
|
||||||
|
|
||||||
PhysicalRange::PhysicalRange(paddr_t paddr, size_t size)
|
|
||||||
: m_paddr(paddr)
|
|
||||||
, m_size(size)
|
|
||||||
, m_bitmap_pages(BAN::Math::div_round_up<size_t>(size / PAGE_SIZE, 8))
|
|
||||||
, m_data_pages((size / PAGE_SIZE) - m_bitmap_pages)
|
|
||||||
, m_free_pages(m_data_pages)
|
|
||||||
{
|
{
|
||||||
ASSERT(paddr % PAGE_SIZE == 0);
|
// We can't use the memory ovelapping with kernel
|
||||||
ASSERT(size % PAGE_SIZE == 0);
|
if (start + size <= V2P(g_kernel_end))
|
||||||
ASSERT(m_bitmap_pages < size / PAGE_SIZE);
|
return;
|
||||||
|
|
||||||
m_vaddr = PageTable::kernel().reserve_free_contiguous_pages(m_bitmap_pages, KERNEL_OFFSET);
|
// Align start to page boundary and after the kernel memory
|
||||||
|
m_paddr = BAN::Math::max(start, V2P(g_kernel_end));
|
||||||
|
if (auto rem = m_paddr % PAGE_SIZE)
|
||||||
|
m_paddr += PAGE_SIZE - rem;
|
||||||
|
|
||||||
|
if (size <= m_paddr - start)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Align size to page boundary
|
||||||
|
m_size = size - (m_paddr - start);
|
||||||
|
if (auto rem = m_size % PAGE_SIZE)
|
||||||
|
m_size -= rem;
|
||||||
|
|
||||||
|
// We need atleast 2 pages
|
||||||
|
m_total_pages = m_size / PAGE_SIZE;
|
||||||
|
if (m_total_pages <= 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// FIXME: if total pages is just over multiple of (PAGE_SIZE / sizeof(node)) we might make
|
||||||
|
// couple of pages unallocatable
|
||||||
|
m_list_pages = BAN::Math::div_round_up<uint64_t>(m_total_pages * sizeof(node), PAGE_SIZE);
|
||||||
|
m_reservable_pages = m_total_pages - m_list_pages;
|
||||||
|
|
||||||
|
m_used_pages = 0;
|
||||||
|
m_free_pages = m_reservable_pages;
|
||||||
|
|
||||||
|
m_vaddr = PageTable::kernel().reserve_free_contiguous_pages(m_list_pages, KERNEL_OFFSET);
|
||||||
ASSERT(m_vaddr);
|
ASSERT(m_vaddr);
|
||||||
PageTable::kernel().map_range_at(m_paddr, m_vaddr, size, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
|
||||||
|
PageTable::kernel().map_range_at(m_paddr, m_vaddr, m_list_pages * PAGE_SIZE, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||||
|
|
||||||
memset((void*)m_vaddr, 0x00, m_bitmap_pages * PAGE_SIZE);
|
// Initialize page list so that every page points to the next one
|
||||||
memset((void*)m_vaddr, 0xFF, m_data_pages / 8);
|
node* page_list = (node*)m_vaddr;
|
||||||
for (ull i = 0; i < m_data_pages % 8; i++)
|
|
||||||
((uint8_t*)m_vaddr)[m_data_pages / 8] |= 1 << i;
|
|
||||||
|
|
||||||
dprintln("physical range needs {} pages for bitmap", m_bitmap_pages);
|
for (uint64_t i = 0; i < m_reservable_pages; i++)
|
||||||
}
|
page_list[i] = { page_list + i - 1, page_list + i + 1 };
|
||||||
|
page_list[ 0 ].next = nullptr;
|
||||||
|
page_list[m_reservable_pages - 1].prev = nullptr;
|
||||||
|
|
||||||
paddr_t PhysicalRange::paddr_for_bit(ull bit) const
|
m_free_list = page_list;
|
||||||
{
|
m_used_list = nullptr;
|
||||||
return m_paddr + (m_bitmap_pages + bit) * PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ull PhysicalRange::bit_for_paddr(paddr_t paddr) const
|
|
||||||
{
|
|
||||||
return (paddr - m_paddr) / PAGE_SIZE - m_bitmap_pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
ull PhysicalRange::contiguous_bits_set(ull start, ull count) const
|
|
||||||
{
|
|
||||||
for (ull i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
ull off = (start + i) / ull_bits;
|
|
||||||
ull bit = (start + i) % ull_bits;
|
|
||||||
if (!(ull_bitmap_ptr()[off] & (1ull << bit)))
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
paddr_t PhysicalRange::reserve_page()
|
paddr_t PhysicalRange::reserve_page()
|
||||||
{
|
{
|
||||||
ASSERT(free_pages() > 0);
|
if (m_free_list == nullptr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
ull ull_count = BAN::Math::div_round_up<ull>(m_data_pages, ull_bits);
|
node* page = m_free_list;
|
||||||
|
ASSERT(page->next == nullptr);
|
||||||
|
|
||||||
for (ull i = 0; i < ull_count; i++)
|
// Detatch page from top of the free list
|
||||||
{
|
m_free_list = m_free_list->prev;
|
||||||
if (ull_bitmap_ptr()[i] == 0)
|
if (m_free_list)
|
||||||
continue;
|
m_free_list->next = nullptr;
|
||||||
|
|
||||||
int lsb = __builtin_ctzll(ull_bitmap_ptr()[i]);
|
// Add page to used list
|
||||||
|
if (m_used_list)
|
||||||
|
m_used_list->next = page;
|
||||||
|
page->prev = m_used_list;
|
||||||
|
m_used_list = page;
|
||||||
|
|
||||||
ull_bitmap_ptr()[i] &= ~(1ull << lsb);
|
m_used_pages++;
|
||||||
m_free_pages--;
|
m_free_pages--;
|
||||||
return paddr_for_bit(i * ull_bits + lsb);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT_NOT_REACHED();
|
return page_address(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicalRange::release_page(paddr_t paddr)
|
void PhysicalRange::release_page(paddr_t page_address)
|
||||||
{
|
{
|
||||||
ASSERT(paddr % PAGE_SIZE == 0);
|
ASSERT(m_used_list);
|
||||||
ASSERT(paddr - m_paddr <= m_size);
|
|
||||||
|
|
||||||
ull full_bit = bit_for_paddr(paddr);
|
node* page = node_address(page_address);
|
||||||
ull off = full_bit / ull_bits;
|
|
||||||
ull bit = full_bit % ull_bits;
|
// Detach page from used list
|
||||||
ull mask = 1ull << bit;
|
if (page->prev)
|
||||||
|
page->prev->next = page->next;
|
||||||
|
if (page->next)
|
||||||
|
page->next->prev = page->prev;
|
||||||
|
if (m_used_list == page)
|
||||||
|
m_used_list = page->prev;
|
||||||
|
|
||||||
ASSERT(!(ull_bitmap_ptr()[off] & mask));
|
// Add page to the top of free list
|
||||||
ull_bitmap_ptr()[off] |= mask;
|
page->prev = m_free_list;
|
||||||
|
page->next = nullptr;
|
||||||
|
if (m_free_list)
|
||||||
|
m_free_list->next = page;
|
||||||
|
m_free_list = page;
|
||||||
|
|
||||||
|
m_used_pages--;
|
||||||
m_free_pages++;
|
m_free_pages++;
|
||||||
}
|
}
|
||||||
|
|
||||||
paddr_t PhysicalRange::reserve_contiguous_pages(size_t pages)
|
paddr_t PhysicalRange::page_address(const node* page) const
|
||||||
{
|
{
|
||||||
ASSERT(pages > 0);
|
ASSERT((vaddr_t)page <= m_vaddr + m_reservable_pages * sizeof(node));
|
||||||
ASSERT(free_pages() > 0);
|
uint64_t page_index = page - (node*)m_vaddr;
|
||||||
|
return m_paddr + (page_index + m_list_pages) * PAGE_SIZE;
|
||||||
if (pages == 1)
|
|
||||||
return reserve_page();
|
|
||||||
|
|
||||||
ull ull_count = BAN::Math::div_round_up<ull>(m_data_pages, ull_bits);
|
|
||||||
|
|
||||||
// NOTE: This feels kinda slow, but I don't want to be
|
|
||||||
// doing premature optimization. This will be only
|
|
||||||
// used when creating DMA regions.
|
|
||||||
|
|
||||||
for (ull i = 0; i < ull_count; i++)
|
|
||||||
{
|
|
||||||
if (ull_bitmap_ptr()[i] == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (ull bit = 0; bit < ull_bits;)
|
|
||||||
{
|
|
||||||
ull start = i * ull_bits + bit;
|
|
||||||
ull set_cnt = contiguous_bits_set(start, pages);
|
|
||||||
if (set_cnt == pages)
|
|
||||||
{
|
|
||||||
for (ull j = 0; j < pages; j++)
|
|
||||||
ull_bitmap_ptr()[(start + j) / ull_bits] &= ~(1ull << ((start + j) % ull_bits));
|
|
||||||
m_free_pages -= pages;
|
|
||||||
return paddr_for_bit(start);
|
|
||||||
}
|
|
||||||
bit += set_cnt + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicalRange::release_contiguous_pages(paddr_t paddr, size_t pages)
|
PhysicalRange::node* PhysicalRange::node_address(paddr_t page_address) const
|
||||||
{
|
{
|
||||||
ASSERT(paddr % PAGE_SIZE == 0);
|
ASSERT(page_address % PAGE_SIZE == 0);
|
||||||
ASSERT(paddr - m_paddr <= m_size);
|
ASSERT(m_paddr + m_list_pages * PAGE_SIZE <= page_address && page_address < m_paddr + m_size);
|
||||||
ASSERT(pages > 0);
|
uint64_t page_offset = page_address - (m_paddr + m_list_pages * PAGE_SIZE);
|
||||||
|
return (node*)m_vaddr + page_offset / PAGE_SIZE;
|
||||||
ull start_bit = bit_for_paddr(paddr);
|
}
|
||||||
for (size_t i = 0; i < pages; i++)
|
|
||||||
{
|
|
||||||
ull off = (start_bit + i) / ull_bits;
|
|
||||||
ull bit = (start_bit + i) % ull_bits;
|
|
||||||
ull mask = 1ull << bit;
|
|
||||||
|
|
||||||
ASSERT(!(ull_bitmap_ptr()[off] & mask));
|
|
||||||
ull_bitmap_ptr()[off] |= mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_free_pages += pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
#include <kernel/MMIO.h>
|
#include <kernel/MMIO.h>
|
||||||
#include <kernel/Networking/E1000.h>
|
#include <kernel/Networking/E1000.h>
|
||||||
#include <kernel/PCI.h>
|
#include <kernel/PCI.h>
|
||||||
#include <kernel/Storage/ATA/AHCI/Controller.h>
|
#include <kernel/Storage/ATAController.h>
|
||||||
#include <kernel/Storage/ATA/ATAController.h>
|
|
||||||
|
|
||||||
#define INVALID_VENDOR 0xFFFF
|
#define INVALID_VENDOR 0xFFFF
|
||||||
#define MULTI_FUNCTION 0x80
|
#define MULTI_FUNCTION 0x80
|
||||||
|
@ -144,8 +143,6 @@ namespace Kernel::PCI
|
||||||
switch (pci_device.subclass())
|
switch (pci_device.subclass())
|
||||||
{
|
{
|
||||||
case 0x01:
|
case 0x01:
|
||||||
case 0x05:
|
|
||||||
case 0x06:
|
|
||||||
if (auto res = ATAController::create(pci_device); res.is_error())
|
if (auto res = ATAController::create(pci_device); res.is_error())
|
||||||
dprintln("ATA: {}", res.error());
|
dprintln("ATA: {}", res.error());
|
||||||
break;
|
break;
|
||||||
|
@ -184,12 +181,12 @@ namespace Kernel::PCI
|
||||||
// disable io/mem space while reading bar
|
// disable io/mem space while reading bar
|
||||||
device.write_dword(0x04, command_status & ~3);
|
device.write_dword(0x04, command_status & ~3);
|
||||||
|
|
||||||
uint8_t offset = 0x10 + bar_num * 4;
|
uint8_t offset = 0x10 + bar_num * 8;
|
||||||
|
|
||||||
uint64_t addr = device.read_dword(offset);
|
uint64_t addr = device.read_dword(offset);
|
||||||
|
|
||||||
device.write_dword(offset, 0xFFFFFFFF);
|
device.write_dword(offset, 0xFFFFFFFF);
|
||||||
uint32_t size = device.read_dword(offset);
|
uint32_t size = device.read_dword(0x10 + bar_num * 8);
|
||||||
size = ~size + 1;
|
size = ~size + 1;
|
||||||
device.write_dword(offset, addr);
|
device.write_dword(offset, addr);
|
||||||
|
|
||||||
|
@ -209,7 +206,7 @@ namespace Kernel::PCI
|
||||||
{
|
{
|
||||||
type = BarType::MEM;
|
type = BarType::MEM;
|
||||||
addr &= 0xFFFFFFF0;
|
addr &= 0xFFFFFFF0;
|
||||||
addr |= (uint64_t)device.read_dword(offset + 4) << 32;
|
addr |= (uint64_t)device.read_dword(offset + 8) << 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == BarType::INVALID)
|
if (type == BarType::INVALID)
|
||||||
|
|
|
@ -1,76 +0,0 @@
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
|
||||||
#include <kernel/Storage/ATA/ATABus.h>
|
|
||||||
#include <kernel/Storage/ATA/ATAController.h>
|
|
||||||
#include <kernel/Storage/ATA/ATADefinitions.h>
|
|
||||||
#include <kernel/Storage/ATA/ATADevice.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<StorageController>> ATAController::create(PCI::Device& pci_device)
|
|
||||||
{
|
|
||||||
StorageController* controller_ptr = nullptr;
|
|
||||||
|
|
||||||
switch (pci_device.subclass())
|
|
||||||
{
|
|
||||||
case 0x01:
|
|
||||||
controller_ptr = new ATAController(pci_device);
|
|
||||||
break;
|
|
||||||
case 0x05:
|
|
||||||
dwarnln("unsupported DMA ATA Controller");
|
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
|
||||||
case 0x06:
|
|
||||||
dwarnln("unsupported SATA Controller");
|
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
|
||||||
default:
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (controller_ptr == nullptr)
|
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
|
||||||
|
|
||||||
auto controller = BAN::UniqPtr<StorageController>::adopt(controller_ptr);
|
|
||||||
TRY(controller->initialize());
|
|
||||||
return controller;
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> ATAController::initialize()
|
|
||||||
{
|
|
||||||
BAN::Vector<BAN::RefPtr<ATABus>> buses;
|
|
||||||
|
|
||||||
uint8_t prog_if = m_pci_device.read_byte(0x09);
|
|
||||||
|
|
||||||
if (!(prog_if & ATA_PROGIF_PRIMARY_NATIVE))
|
|
||||||
{
|
|
||||||
auto bus_or_error = ATABus::create(0x1F0, 0x3F6, 14);
|
|
||||||
if (bus_or_error.is_error())
|
|
||||||
dprintln("IDE ATABus: {}", bus_or_error.error());
|
|
||||||
else
|
|
||||||
TRY(buses.push_back(bus_or_error.release_value()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dprintln("unsupported IDE ATABus in native mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
// BUS 2
|
|
||||||
if (!(prog_if & ATA_PROGIF_SECONDARY_NATIVE))
|
|
||||||
{
|
|
||||||
auto bus_or_error = ATABus::create(0x170, 0x376, 15);
|
|
||||||
if (bus_or_error.is_error())
|
|
||||||
dprintln("IDE ATABus: {}", bus_or_error.error());
|
|
||||||
else
|
|
||||||
TRY(buses.push_back(bus_or_error.release_value()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dprintln("unsupported IDE ATABus in native mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& bus : buses)
|
|
||||||
bus->initialize_devfs();
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,117 +0,0 @@
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
|
||||||
#include <kernel/IO.h>
|
|
||||||
#include <kernel/Storage/ATA/ATABus.h>
|
|
||||||
#include <kernel/Storage/ATA/ATADefinitions.h>
|
|
||||||
#include <kernel/Storage/ATA/ATADevice.h>
|
|
||||||
|
|
||||||
#include <sys/sysmacros.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
static dev_t get_ata_dev_major()
|
|
||||||
{
|
|
||||||
static dev_t major = DevFileSystem::get().get_next_dev();
|
|
||||||
return major;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dev_t get_ata_dev_minor()
|
|
||||||
{
|
|
||||||
static dev_t minor = 0;
|
|
||||||
return minor++;
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<ATADevice>> ATADevice::create(BAN::RefPtr<ATABus> bus, ATABus::DeviceType type, bool is_secondary, BAN::Span<const uint16_t> identify_data)
|
|
||||||
{
|
|
||||||
auto* device_ptr = new ATADevice(bus, type, is_secondary);
|
|
||||||
if (device_ptr == nullptr)
|
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
|
||||||
auto device = BAN::RefPtr<ATADevice>::adopt(device_ptr);
|
|
||||||
TRY(device->initialize(identify_data));
|
|
||||||
return device;
|
|
||||||
}
|
|
||||||
|
|
||||||
ATADevice::ATADevice(BAN::RefPtr<ATABus> bus, ATABus::DeviceType type, bool is_secondary)
|
|
||||||
: m_bus(bus)
|
|
||||||
, m_type(type)
|
|
||||||
, m_is_secondary(is_secondary)
|
|
||||||
, m_rdev(makedev(get_ata_dev_major(), get_ata_dev_minor()))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> ATADevice::initialize(BAN::Span<const uint16_t> identify_data)
|
|
||||||
{
|
|
||||||
ASSERT(identify_data.size() >= 256);
|
|
||||||
|
|
||||||
m_signature = identify_data[ATA_IDENTIFY_SIGNATURE];
|
|
||||||
m_capabilities = identify_data[ATA_IDENTIFY_CAPABILITIES];
|
|
||||||
|
|
||||||
m_command_set = 0;
|
|
||||||
m_command_set |= (uint32_t)(identify_data[ATA_IDENTIFY_COMMAND_SET + 0] << 0);
|
|
||||||
m_command_set |= (uint32_t)(identify_data[ATA_IDENTIFY_COMMAND_SET + 1] << 16);
|
|
||||||
|
|
||||||
if (!(m_capabilities & ATA_CAPABILITIES_LBA))
|
|
||||||
return BAN::Error::from_error_code(ErrorCode::ATA_NoLBA);
|
|
||||||
|
|
||||||
if ((identify_data[ATA_IDENTIFY_SECTOR_INFO] & (1 << 15)) == 0 &&
|
|
||||||
(identify_data[ATA_IDENTIFY_SECTOR_INFO] & (1 << 14)) != 0 &&
|
|
||||||
(identify_data[ATA_IDENTIFY_SECTOR_INFO] & (1 << 12)) != 0)
|
|
||||||
{
|
|
||||||
m_sector_words = *(uint32_t*)(identify_data.data() + ATA_IDENTIFY_SECTOR_WORDS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_sector_words = 256;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_lba_count = 0;
|
|
||||||
if (m_command_set & ATA_COMMANDSET_LBA48_SUPPORTED)
|
|
||||||
m_lba_count = *(uint64_t*)(identify_data.data() + ATA_IDENTIFY_LBA_COUNT_EXT);
|
|
||||||
if (m_lba_count < (1 << 28))
|
|
||||||
m_lba_count = *(uint32_t*)(identify_data.data() + ATA_IDENTIFY_LBA_COUNT);
|
|
||||||
|
|
||||||
for (int i = 0; i < 20; i++)
|
|
||||||
{
|
|
||||||
uint16_t word = identify_data[ATA_IDENTIFY_MODEL + i];
|
|
||||||
m_model[2 * i + 0] = word >> 8;
|
|
||||||
m_model[2 * i + 1] = word & 0xFF;
|
|
||||||
}
|
|
||||||
m_model[40] = 0;
|
|
||||||
|
|
||||||
dprintln("ATA disk {} MB", total_size() / 1024 / 1024);
|
|
||||||
|
|
||||||
add_disk_cache();
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
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));
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> ATADevice::read_impl(off_t offset, void* buffer, size_t bytes)
|
|
||||||
{
|
|
||||||
ASSERT(offset >= 0);
|
|
||||||
if (offset % sector_size() || bytes % sector_size())
|
|
||||||
return BAN::Error::from_errno(EINVAL);
|
|
||||||
if ((size_t)offset == total_size())
|
|
||||||
return 0;
|
|
||||||
TRY(read_sectors(offset / sector_size(), bytes / sector_size(), (uint8_t*)buffer));
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::StringView ATADevice::name() const
|
|
||||||
{
|
|
||||||
static char device_name[] = "sda";
|
|
||||||
device_name[2] += minor(m_rdev);
|
|
||||||
return device_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,31 +1,27 @@
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
#include <BAN/ScopeGuard.h>
|
||||||
#include <kernel/IDT.h>
|
#include <kernel/IDT.h>
|
||||||
#include <kernel/InterruptController.h>
|
#include <kernel/InterruptController.h>
|
||||||
#include <kernel/IO.h>
|
#include <kernel/IO.h>
|
||||||
#include <kernel/LockGuard.h>
|
#include <kernel/LockGuard.h>
|
||||||
#include <kernel/Storage/ATA/ATABus.h>
|
#include <kernel/Storage/ATADevice.h>
|
||||||
#include <kernel/Storage/ATA/ATADefinitions.h>
|
#include <kernel/Storage/ATABus.h>
|
||||||
#include <kernel/Storage/ATA/ATADevice.h>
|
#include <kernel/Storage/ATADefinitions.h>
|
||||||
#include <kernel/Timer/Timer.h>
|
#include <kernel/Timer/Timer.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<ATABus>> ATABus::create(uint16_t base, uint16_t ctrl, uint8_t irq)
|
ATABus* ATABus::create(ATAController& controller, uint16_t base, uint16_t ctrl, uint8_t irq)
|
||||||
{
|
{
|
||||||
auto* bus_ptr = new ATABus(base, ctrl);
|
ATABus* bus = new ATABus(controller, base, ctrl);
|
||||||
if (bus_ptr == nullptr)
|
ASSERT(bus);
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
bus->initialize(irq);
|
||||||
auto bus = BAN::RefPtr<ATABus>::adopt(bus_ptr);
|
|
||||||
bus->set_irq(irq);
|
|
||||||
TRY(bus->initialize());
|
|
||||||
if (bus->m_devices.empty())
|
|
||||||
return BAN::Error::from_errno(ENODEV);
|
|
||||||
return bus;
|
return bus;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> ATABus::initialize()
|
void ATABus::initialize(uint8_t irq)
|
||||||
{
|
{
|
||||||
|
set_irq(irq);
|
||||||
enable_interrupt();
|
enable_interrupt();
|
||||||
|
|
||||||
BAN::Vector<uint16_t> identify_buffer;
|
BAN::Vector<uint16_t> identify_buffer;
|
||||||
|
@ -33,57 +29,49 @@ namespace Kernel
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 2; i++)
|
for (uint8_t i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
bool is_secondary = (i == 1);
|
|
||||||
|
|
||||||
DeviceType device_type;
|
|
||||||
if (auto res = identify(is_secondary, identify_buffer.span()); res.is_error())
|
|
||||||
continue;
|
|
||||||
else
|
|
||||||
device_type = res.value();
|
|
||||||
|
|
||||||
auto device_or_error = ATADevice::create(this, device_type, is_secondary, identify_buffer.span());
|
|
||||||
|
|
||||||
if (device_or_error.is_error())
|
|
||||||
{
|
{
|
||||||
dprintln("{}", device_or_error.error());
|
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] = nullptr; });
|
||||||
|
|
||||||
|
auto type = identify(device, identify_buffer.data());
|
||||||
|
if (type == DeviceType::None)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto res = device.initialize(type, identify_buffer.data());
|
||||||
|
if (res.is_error())
|
||||||
|
{
|
||||||
|
dprintln("{}", res.error());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto device = device_or_error.release_value();
|
guard.disable();
|
||||||
device->ref();
|
|
||||||
TRY(m_devices.push_back(device.ptr()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable disk interrupts
|
// Enable disk interrupts
|
||||||
for (auto& device : m_devices)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
select_device(device->is_secondary());
|
if (!m_devices[i])
|
||||||
|
continue;
|
||||||
|
select_device(*m_devices[i]);
|
||||||
io_write(ATA_PORT_CONTROL, 0);
|
io_write(ATA_PORT_CONTROL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ATABus::initialize_devfs()
|
void ATABus::select_device(const ATADevice& device)
|
||||||
{
|
{
|
||||||
for (auto& device : m_devices)
|
uint8_t device_index = this->device_index(device);
|
||||||
{
|
io_write(ATA_PORT_DRIVE_SELECT, 0xA0 | (device_index << 4));
|
||||||
DevFileSystem::get().add_device(device);
|
|
||||||
if (auto res = device->initialize_partitions(); res.is_error())
|
|
||||||
dprintln("{}", res.error());
|
|
||||||
device->unref();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ATABus::select_device(bool secondary)
|
|
||||||
{
|
|
||||||
io_write(ATA_PORT_DRIVE_SELECT, 0xA0 | ((uint8_t)secondary << 4));
|
|
||||||
SystemTimer::get().sleep(1);
|
SystemTimer::get().sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<ATABus::DeviceType> ATABus::identify(bool secondary, BAN::Span<uint16_t> buffer)
|
ATABus::DeviceType ATABus::identify(const ATADevice& device, uint16_t* buffer)
|
||||||
{
|
{
|
||||||
select_device(secondary);
|
select_device(device);
|
||||||
|
|
||||||
// Disable interrupts
|
// Disable interrupts
|
||||||
io_write(ATA_PORT_CONTROL, ATA_CONTROL_nIEN);
|
io_write(ATA_PORT_CONTROL, ATA_CONTROL_nIEN);
|
||||||
|
@ -93,7 +81,7 @@ namespace Kernel
|
||||||
|
|
||||||
// No device on port
|
// No device on port
|
||||||
if (io_read(ATA_PORT_STATUS) == 0)
|
if (io_read(ATA_PORT_STATUS) == 0)
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return DeviceType::None;
|
||||||
|
|
||||||
DeviceType type = DeviceType::ATA;
|
DeviceType type = DeviceType::ATA;
|
||||||
|
|
||||||
|
@ -109,7 +97,7 @@ namespace Kernel
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dprintln("Unsupported device type");
|
dprintln("Unsupported device type");
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return DeviceType::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY_PACKET);
|
io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY_PACKET);
|
||||||
|
@ -118,12 +106,11 @@ namespace Kernel
|
||||||
if (auto res = wait(true); res.is_error())
|
if (auto res = wait(true); res.is_error())
|
||||||
{
|
{
|
||||||
dprintln("Fatal error: {}", res.error());
|
dprintln("Fatal error: {}", res.error());
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return DeviceType::None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(buffer.size() >= 256);
|
read_buffer(ATA_PORT_DATA, buffer, 256);
|
||||||
read_buffer(ATA_PORT_DATA, buffer.data(), 256);
|
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
@ -225,9 +212,18 @@ namespace Kernel
|
||||||
return BAN::Error::from_error_code(ErrorCode::None);
|
return BAN::Error::from_error_code(ErrorCode::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t ATABus::device_index(const ATADevice& device) const
|
||||||
|
{
|
||||||
|
if (m_devices[0] && m_devices[0].ptr() == &device)
|
||||||
|
return 0;
|
||||||
|
if (m_devices[1] && m_devices[1].ptr() == &device)
|
||||||
|
return 1;
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
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.sector_count())
|
if (lba + sector_count > device.m_lba_count)
|
||||||
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
@ -235,7 +231,7 @@ namespace Kernel
|
||||||
if (lba < (1 << 28))
|
if (lba < (1 << 28))
|
||||||
{
|
{
|
||||||
// LBA28
|
// LBA28
|
||||||
io_write(ATA_PORT_DRIVE_SELECT, 0xE0 | ((uint8_t)device.is_secondary() << 4) | ((lba >> 24) & 0x0F));
|
io_write(ATA_PORT_DRIVE_SELECT, 0xE0 | (device_index(device) << 4) | ((lba >> 24) & 0x0F));
|
||||||
io_write(ATA_PORT_SECTOR_COUNT, sector_count);
|
io_write(ATA_PORT_SECTOR_COUNT, sector_count);
|
||||||
io_write(ATA_PORT_LBA0, (uint8_t)(lba >> 0));
|
io_write(ATA_PORT_LBA0, (uint8_t)(lba >> 0));
|
||||||
io_write(ATA_PORT_LBA1, (uint8_t)(lba >> 8));
|
io_write(ATA_PORT_LBA1, (uint8_t)(lba >> 8));
|
||||||
|
@ -245,7 +241,7 @@ namespace Kernel
|
||||||
for (uint32_t sector = 0; sector < sector_count; sector++)
|
for (uint32_t sector = 0; sector < sector_count; sector++)
|
||||||
{
|
{
|
||||||
block_until_irq();
|
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 + sector * device.m_sector_words, device.m_sector_words);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -259,7 +255,7 @@ namespace Kernel
|
||||||
|
|
||||||
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.sector_count())
|
if (lba + sector_count > device.m_lba_count)
|
||||||
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
@ -267,7 +263,7 @@ namespace Kernel
|
||||||
if (lba < (1 << 28))
|
if (lba < (1 << 28))
|
||||||
{
|
{
|
||||||
// LBA28
|
// LBA28
|
||||||
io_write(ATA_PORT_DRIVE_SELECT, 0xE0 | ((uint8_t)device.is_secondary() << 4) | ((lba >> 24) & 0x0F));
|
io_write(ATA_PORT_DRIVE_SELECT, 0xE0 | (device_index(device) << 4) | ((lba >> 24) & 0x0F));
|
||||||
io_write(ATA_PORT_SECTOR_COUNT, sector_count);
|
io_write(ATA_PORT_SECTOR_COUNT, sector_count);
|
||||||
io_write(ATA_PORT_LBA0, (uint8_t)(lba >> 0));
|
io_write(ATA_PORT_LBA0, (uint8_t)(lba >> 0));
|
||||||
io_write(ATA_PORT_LBA1, (uint8_t)(lba >> 8));
|
io_write(ATA_PORT_LBA1, (uint8_t)(lba >> 8));
|
||||||
|
@ -278,7 +274,7 @@ namespace Kernel
|
||||||
|
|
||||||
for (uint32_t sector = 0; sector < sector_count; sector++)
|
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 + sector * device.m_sector_words, device.m_sector_words);
|
||||||
block_until_irq();
|
block_until_irq();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
#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<BAN::RefPtr<ATAController>> ATAController::create(const PCI::Device& device)
|
||||||
|
{
|
||||||
|
ATAController* controller = new ATAController();
|
||||||
|
if (controller == nullptr)
|
||||||
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
BAN::ScopeGuard guard([controller] { controller->unref(); });
|
||||||
|
TRY(controller->initialize(device));
|
||||||
|
guard.disable();
|
||||||
|
|
||||||
|
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', (char)('a' + i), '\0' };
|
||||||
|
DevFileSystem::get().add_device(device_name, devices[i]);
|
||||||
|
|
||||||
|
if (auto res = devices[i]->initialize_partitions(); res.is_error())
|
||||||
|
dprintln("{}", res.error());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto& partitions = devices[i]->partitions();
|
||||||
|
for (size_t j = 0; j < partitions.size(); j++)
|
||||||
|
{
|
||||||
|
char partition_name[5] { 'h', 'd', (char)('a' + i), (char)('1' + j), '\0' };
|
||||||
|
DevFileSystem::get().add_device(partition_name, partitions[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ref_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ATAController::ATAController()
|
||||||
|
: m_rdev(makedev(DevFileSystem::get().get_next_dev(), 0))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> ATAController::initialize(const PCI::Device& pci_device)
|
||||||
|
{
|
||||||
|
struct Bus
|
||||||
|
{
|
||||||
|
uint16_t base;
|
||||||
|
uint16_t ctrl;
|
||||||
|
};
|
||||||
|
|
||||||
|
Bus buses[2];
|
||||||
|
buses[0].base = 0x1F0;
|
||||||
|
buses[0].ctrl = 0x3F6;
|
||||||
|
|
||||||
|
buses[1].base = 0x170;
|
||||||
|
buses[1].ctrl = 0x376;
|
||||||
|
|
||||||
|
uint8_t prog_if = pci_device.read_byte(0x09);
|
||||||
|
if (prog_if & 0x01)
|
||||||
|
{
|
||||||
|
buses[0].base = pci_device.read_dword(0x10) & 0xFFFFFFFC;
|
||||||
|
buses[0].ctrl = pci_device.read_dword(0x14) & 0xFFFFFFFC;
|
||||||
|
return BAN::Error::from_error_code(ErrorCode::ATA_UnsupportedDevice);
|
||||||
|
}
|
||||||
|
if (prog_if & 0x04)
|
||||||
|
{
|
||||||
|
buses[1].base = pci_device.read_dword(0x18) & 0xFFFFFFFC;
|
||||||
|
buses[1].ctrl = pci_device.read_dword(0x1C) & 0xFFFFFFFC;
|
||||||
|
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);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::Vector<BAN::RefPtr<StorageDevice>> ATAController::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])
|
||||||
|
MUST(devices.push_back(m_buses[0]->m_devices[1]));
|
||||||
|
if (m_buses[1]->m_devices[0])
|
||||||
|
MUST(devices.push_back(m_buses[1]->m_devices[0]));
|
||||||
|
if (m_buses[1]->m_devices[1])
|
||||||
|
MUST(devices.push_back(m_buses[1]->m_devices[1]));
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
#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_dev(), 0))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> ATADevice::initialize(ATABus::DeviceType type, const uint16_t* identify_buffer)
|
||||||
|
{
|
||||||
|
m_type = type;
|
||||||
|
|
||||||
|
m_signature = identify_buffer[ATA_IDENTIFY_SIGNATURE];
|
||||||
|
m_capabilities = identify_buffer[ATA_IDENTIFY_CAPABILITIES];
|
||||||
|
|
||||||
|
m_command_set = 0;
|
||||||
|
m_command_set |= (uint32_t)(identify_buffer[ATA_IDENTIFY_COMMAND_SET + 0] << 0);
|
||||||
|
m_command_set |= (uint32_t)(identify_buffer[ATA_IDENTIFY_COMMAND_SET + 1] << 16);
|
||||||
|
|
||||||
|
if (!(m_capabilities & ATA_CAPABILITIES_LBA))
|
||||||
|
return BAN::Error::from_error_code(ErrorCode::ATA_NoLBA);
|
||||||
|
|
||||||
|
if ((identify_buffer[ATA_IDENTIFY_SECTOR_INFO] & (1 << 15)) == 0 &&
|
||||||
|
(identify_buffer[ATA_IDENTIFY_SECTOR_INFO] & (1 << 14)) != 0 &&
|
||||||
|
(identify_buffer[ATA_IDENTIFY_SECTOR_INFO] & (1 << 12)) != 0)
|
||||||
|
{
|
||||||
|
m_sector_words = *(uint32_t*)(identify_buffer + ATA_IDENTIFY_SECTOR_WORDS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_sector_words = 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lba_count = 0;
|
||||||
|
if (m_command_set & ATA_COMMANDSET_LBA48_SUPPORTED)
|
||||||
|
m_lba_count = *(uint64_t*)(identify_buffer + ATA_IDENTIFY_LBA_COUNT_EXT);
|
||||||
|
if (m_lba_count < (1 << 28))
|
||||||
|
m_lba_count = *(uint32_t*)(identify_buffer + ATA_IDENTIFY_LBA_COUNT);
|
||||||
|
|
||||||
|
for (int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
uint16_t word = identify_buffer[ATA_IDENTIFY_MODEL + i];
|
||||||
|
m_model[2 * i + 0] = word >> 8;
|
||||||
|
m_model[2 * i + 1] = word & 0xFF;
|
||||||
|
}
|
||||||
|
m_model[40] = 0;
|
||||||
|
|
||||||
|
dprintln("ATA disk {} MB", total_size() / 1024 / 1024);
|
||||||
|
|
||||||
|
add_disk_cache();
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
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));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<size_t> ATADevice::read_impl(off_t offset, void* buffer, size_t bytes)
|
||||||
|
{
|
||||||
|
ASSERT(offset >= 0);
|
||||||
|
if (offset % sector_size() || bytes % sector_size())
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
if ((size_t)offset == total_size())
|
||||||
|
return 0;
|
||||||
|
TRY(read_sectors(offset / sector_size(), bytes / sector_size(), (uint8_t*)buffer));
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,7 +2,6 @@
|
||||||
#include <BAN/ScopeGuard.h>
|
#include <BAN/ScopeGuard.h>
|
||||||
#include <BAN/StringView.h>
|
#include <BAN/StringView.h>
|
||||||
#include <BAN/UTF8.h>
|
#include <BAN/UTF8.h>
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
|
||||||
#include <kernel/FS/VirtualFileSystem.h>
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
#include <kernel/LockGuard.h>
|
#include <kernel/LockGuard.h>
|
||||||
#include <kernel/PCI.h>
|
#include <kernel/PCI.h>
|
||||||
|
@ -185,7 +184,7 @@ namespace Kernel
|
||||||
char utf8_name[36 * 4 + 1];
|
char utf8_name[36 * 4 + 1];
|
||||||
BAN::UTF8::from_codepoints(entry.partition_name, 36, utf8_name);
|
BAN::UTF8::from_codepoints(entry.partition_name, 36, utf8_name);
|
||||||
|
|
||||||
auto partition = TRY(Partition::create(
|
Partition* partition = new Partition(
|
||||||
*this,
|
*this,
|
||||||
entry.partition_type_guid,
|
entry.partition_type_guid,
|
||||||
entry.unique_partition_guid,
|
entry.unique_partition_guid,
|
||||||
|
@ -194,24 +193,14 @@ namespace Kernel
|
||||||
entry.attributes,
|
entry.attributes,
|
||||||
utf8_name,
|
utf8_name,
|
||||||
i + 1
|
i + 1
|
||||||
));
|
);
|
||||||
TRY(m_partitions.push_back(BAN::move(partition)));
|
ASSERT(partition != nullptr);
|
||||||
|
MUST(m_partitions.push_back(partition));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto partition : m_partitions)
|
|
||||||
DevFileSystem::get().add_device(partition);
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<Partition>> Partition::create(StorageDevice& device, const GUID& type, const GUID& guid, uint64_t start, uint64_t end, uint64_t attr, const char* label, uint32_t index)
|
|
||||||
{
|
|
||||||
auto partition_ptr = new Partition(device, type, guid, start, end, attr, label, index);
|
|
||||||
if (partition_ptr == nullptr)
|
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
|
||||||
return BAN::RefPtr<Partition>::adopt(partition_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
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)
|
||||||
: BlockDevice(0660, 0, 0)
|
: BlockDevice(0660, 0, 0)
|
||||||
, m_device(device)
|
, m_device(device)
|
||||||
|
@ -220,7 +209,6 @@ namespace Kernel
|
||||||
, m_lba_start(start)
|
, m_lba_start(start)
|
||||||
, m_lba_end(end)
|
, m_lba_end(end)
|
||||||
, m_attributes(attr)
|
, m_attributes(attr)
|
||||||
, m_name(BAN::String::formatted("{}{}", device.name(), index))
|
|
||||||
, m_rdev(makedev(major(device.rdev()), index))
|
, m_rdev(makedev(major(device.rdev()), index))
|
||||||
{
|
{
|
||||||
memcpy(m_label, label, sizeof(m_label));
|
memcpy(m_label, label, sizeof(m_label));
|
||||||
|
|
|
@ -202,7 +202,7 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ref_ptr = BAN::RefPtr<SerialTTY>::adopt(tty);
|
auto ref_ptr = BAN::RefPtr<SerialTTY>::adopt(tty);
|
||||||
DevFileSystem::get().add_device(ref_ptr);
|
DevFileSystem::get().add_device(ref_ptr->name(), ref_ptr);
|
||||||
if (serial.port() == COM1_PORT)
|
if (serial.port() == COM1_PORT)
|
||||||
s_com1 = ref_ptr;
|
s_com1 = ref_ptr;
|
||||||
if (serial.port() == COM2_PORT)
|
if (serial.port() == COM2_PORT)
|
||||||
|
|
|
@ -28,11 +28,11 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
s_tty = this;
|
s_tty = this;
|
||||||
|
|
||||||
auto inode_or_error = DevFileSystem::get().root_inode()->find_inode("tty"sv);
|
auto inode_or_error = DevFileSystem::get().root_inode()->find_inode("tty");
|
||||||
if (inode_or_error.is_error())
|
if (inode_or_error.is_error())
|
||||||
{
|
{
|
||||||
if (inode_or_error.error().get_error_code() == ENOENT)
|
if (inode_or_error.error().get_error_code() == ENOENT)
|
||||||
DevFileSystem::get().add_inode("tty"sv, MUST(RamSymlinkInode::create(DevFileSystem::get(), s_tty->name(), 0666, 0, 0)));
|
DevFileSystem::get().add_device("tty"sv, MUST(RamSymlinkInode::create(DevFileSystem::get(), s_tty->name(), 0666, 0, 0)));
|
||||||
else
|
else
|
||||||
dwarnln("{}", inode_or_error.error());
|
dwarnln("{}", inode_or_error.error());
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -33,12 +33,12 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<VirtualTTY>> VirtualTTY::create(TerminalDriver* driver)
|
BAN::ErrorOr<BAN::RefPtr<VirtualTTY>> VirtualTTY::create(TerminalDriver* driver)
|
||||||
{
|
{
|
||||||
auto* tty_ptr = new VirtualTTY(driver);
|
auto* tty = new VirtualTTY(driver);
|
||||||
ASSERT(tty_ptr);
|
ASSERT(tty);
|
||||||
|
|
||||||
auto tty = BAN::RefPtr<VirtualTTY>::adopt(tty_ptr);
|
auto ref_ptr = BAN::RefPtr<VirtualTTY>::adopt(tty);
|
||||||
DevFileSystem::get().add_device(tty);
|
DevFileSystem::get().add_device(ref_ptr->name(), ref_ptr);
|
||||||
return tty;
|
return ref_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualTTY::VirtualTTY(TerminalDriver* driver)
|
VirtualTTY::VirtualTTY(TerminalDriver* driver)
|
||||||
|
|
|
@ -177,7 +177,6 @@ static void init2(void*)
|
||||||
dprintln("PCI initialized");
|
dprintln("PCI initialized");
|
||||||
|
|
||||||
VirtualFileSystem::initialize(cmdline.root);
|
VirtualFileSystem::initialize(cmdline.root);
|
||||||
dprintln("VFS initialized");
|
|
||||||
|
|
||||||
if (auto res = PS2Controller::initialize(); res.is_error())
|
if (auto res = PS2Controller::initialize(); res.is_error())
|
||||||
dprintln("{}", res.error());
|
dprintln("{}", res.error());
|
||||||
|
|
Loading…
Reference in New Issue