kernel/ATA: Start reading/writing registers and detecting drives
This commit is contained in:
parent
e8507d23ee
commit
3a84127fd6
@ -45,30 +45,88 @@ namespace ATA
|
||||
{
|
||||
}
|
||||
|
||||
u8 Channel::read_register(Register reg)
|
||||
{
|
||||
return IO::inb(m_io_base + (u16)reg);
|
||||
}
|
||||
|
||||
void Channel::write_register(Register reg, u8 value)
|
||||
{
|
||||
IO::outb(m_io_base + (u16)reg, value);
|
||||
}
|
||||
|
||||
u8 Channel::read_control(ControlRegister reg)
|
||||
{
|
||||
return IO::inb(m_control_base + (u16)reg);
|
||||
}
|
||||
|
||||
void Channel::write_control(ControlRegister reg, u8 value)
|
||||
{
|
||||
IO::outb(m_control_base + (u16)reg, value);
|
||||
}
|
||||
|
||||
void Channel::delay_400ns()
|
||||
{
|
||||
read_control(ControlRegister::AltStatus);
|
||||
read_control(ControlRegister::AltStatus);
|
||||
read_control(ControlRegister::AltStatus);
|
||||
read_control(ControlRegister::AltStatus);
|
||||
}
|
||||
|
||||
void Channel::select(u8 drive)
|
||||
{
|
||||
if (drive == m_current_drive) return;
|
||||
|
||||
u8 value = (drive << 4) | 0xa0;
|
||||
write_register(Register::DriveSelect, value);
|
||||
|
||||
delay_400ns();
|
||||
|
||||
m_current_drive = drive;
|
||||
}
|
||||
|
||||
bool Channel::initialize()
|
||||
{
|
||||
int offset = m_channel_index ? 2 : 0;
|
||||
m_is_pci_native_mode = m_controller->device().type.prog_if & (1 << offset);
|
||||
kinfoln("ata: Channel %d is %sin PCI native mode", m_channel_index, m_is_pci_native_mode ? "" : "not ");
|
||||
|
||||
u32 control_port_base_address;
|
||||
u32 io_base_address;
|
||||
|
||||
if (m_is_pci_native_mode)
|
||||
{
|
||||
m_base_address = PCI::read32(m_controller->device().address, m_channel_index ? PCI::BAR2 : PCI::BAR0);
|
||||
m_control_port_base_address =
|
||||
// FIXME: Properly decode BARs.
|
||||
io_base_address = PCI::read32(m_controller->device().address, m_channel_index ? PCI::BAR2 : PCI::BAR0);
|
||||
control_port_base_address =
|
||||
PCI::read32(m_controller->device().address, m_channel_index ? PCI::BAR3 : PCI::BAR1);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_base_address = m_channel_index ? 0x170 : 0x1f0;
|
||||
m_control_port_base_address = m_channel_index ? 0x376 : 0x3f6;
|
||||
io_base_address = m_channel_index ? 0x170 : 0x1f0;
|
||||
control_port_base_address = m_channel_index ? 0x376 : 0x3f6;
|
||||
}
|
||||
|
||||
u8 interrupt_line;
|
||||
if (m_is_pci_native_mode) interrupt_line = PCI::read8(m_controller->device().address, PCI::InterruptLine);
|
||||
else
|
||||
interrupt_line = m_channel_index ? 15 : 14;
|
||||
m_io_base = (u16)io_base_address;
|
||||
m_control_base = (u16)control_port_base_address + 2;
|
||||
|
||||
kinfoln("ata: Channel %d uses IRQ %hhu", m_channel_index, interrupt_line);
|
||||
if (m_is_pci_native_mode) m_interrupt_line = PCI::read8(m_controller->device().address, PCI::InterruptLine);
|
||||
else
|
||||
m_interrupt_line = m_channel_index ? 15 : 14;
|
||||
|
||||
for (u8 drive = 0; drive < 2; drive++)
|
||||
{
|
||||
ScopedKMutexLock<100> lock(m_lock);
|
||||
|
||||
select(drive);
|
||||
|
||||
if (read_register(Register::Status) == 0)
|
||||
{
|
||||
// No drive on this slot.
|
||||
continue;
|
||||
}
|
||||
|
||||
kinfoln("ata: Channel %d has a drive on slot %d!", m_channel_index, drive);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -7,12 +7,53 @@
|
||||
|
||||
namespace ATA
|
||||
{
|
||||
enum class Register : u16
|
||||
{
|
||||
Data = 0,
|
||||
Error = 1,
|
||||
Features = 1,
|
||||
SectorCount = 2,
|
||||
SectorNumber = 3,
|
||||
LBALow = 3,
|
||||
CylinderLow = 4,
|
||||
LBAMiddle = 4,
|
||||
CylinderHigh = 5,
|
||||
LBAHigh = 5,
|
||||
DriveSelect = 6,
|
||||
Status = 7,
|
||||
Command = 8,
|
||||
};
|
||||
|
||||
enum class ControlRegister : u16
|
||||
{
|
||||
AltStatus = 0,
|
||||
DeviceControl = 0,
|
||||
DriveAddress = 1,
|
||||
};
|
||||
|
||||
class Controller;
|
||||
class Channel;
|
||||
|
||||
class Drive
|
||||
{
|
||||
private:
|
||||
Channel* m_channel;
|
||||
};
|
||||
|
||||
class Channel
|
||||
{
|
||||
public:
|
||||
Channel(Controller* controller, u8 channel_index, Badge<Controller>);
|
||||
|
||||
u8 read_register(Register reg);
|
||||
void write_register(Register reg, u8 value);
|
||||
u8 read_control(ControlRegister reg);
|
||||
void write_control(ControlRegister reg, u8 value);
|
||||
|
||||
void delay_400ns();
|
||||
|
||||
void select(u8 drive);
|
||||
|
||||
bool initialize();
|
||||
|
||||
private:
|
||||
@ -20,8 +61,14 @@ namespace ATA
|
||||
u8 m_channel_index;
|
||||
bool m_is_pci_native_mode;
|
||||
|
||||
u32 m_base_address;
|
||||
u32 m_control_port_base_address;
|
||||
u8 m_interrupt_line;
|
||||
|
||||
KMutex<100> m_lock {};
|
||||
|
||||
u16 m_io_base;
|
||||
u16 m_control_base;
|
||||
|
||||
u8 m_current_drive = (u8)-1;
|
||||
};
|
||||
|
||||
class Controller
|
||||
@ -41,8 +88,6 @@ namespace ATA
|
||||
PCI::Device m_device;
|
||||
Channel m_primary_channel;
|
||||
Channel m_secondary_channel;
|
||||
|
||||
KMutex<100> m_lock;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -52,9 +52,8 @@ template <usize ConcurrentThreads> class KMutex
|
||||
template <usize ConcurrentThreads> class ScopedKMutexLock
|
||||
{
|
||||
public:
|
||||
ScopedKMutexLock(KMutex<ConcurrentThreads>& lock)
|
||||
ScopedKMutexLock(KMutex<ConcurrentThreads>& lock) : m_lock(lock)
|
||||
{
|
||||
m_lock = lock;
|
||||
m_lock.lock();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user