kernel/ATA: Start reading/writing registers and detecting drives
This commit is contained in:
parent
6f02dde85e
commit
e22c9a9659
@ -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()
|
bool Channel::initialize()
|
||||||
{
|
{
|
||||||
int offset = m_channel_index ? 2 : 0;
|
int offset = m_channel_index ? 2 : 0;
|
||||||
m_is_pci_native_mode = m_controller->device().type.prog_if & (1 << offset);
|
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)
|
if (m_is_pci_native_mode)
|
||||||
{
|
{
|
||||||
m_base_address = PCI::read32(m_controller->device().address, m_channel_index ? PCI::BAR2 : PCI::BAR0);
|
// FIXME: Properly decode BARs.
|
||||||
m_control_port_base_address =
|
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);
|
PCI::read32(m_controller->device().address, m_channel_index ? PCI::BAR3 : PCI::BAR1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_base_address = m_channel_index ? 0x170 : 0x1f0;
|
io_base_address = m_channel_index ? 0x170 : 0x1f0;
|
||||||
m_control_port_base_address = m_channel_index ? 0x376 : 0x3f6;
|
control_port_base_address = m_channel_index ? 0x376 : 0x3f6;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 interrupt_line;
|
m_io_base = (u16)io_base_address;
|
||||||
if (m_is_pci_native_mode) interrupt_line = PCI::read8(m_controller->device().address, PCI::InterruptLine);
|
m_control_base = (u16)control_port_base_address + 2;
|
||||||
else
|
|
||||||
interrupt_line = m_channel_index ? 15 : 14;
|
|
||||||
|
|
||||||
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,53 @@
|
|||||||
|
|
||||||
namespace ATA
|
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 Controller;
|
||||||
|
class Channel;
|
||||||
|
|
||||||
|
class Drive
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Channel* m_channel;
|
||||||
|
};
|
||||||
|
|
||||||
class Channel
|
class Channel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Channel(Controller* controller, u8 channel_index, Badge<Controller>);
|
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();
|
bool initialize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -20,8 +61,14 @@ namespace ATA
|
|||||||
u8 m_channel_index;
|
u8 m_channel_index;
|
||||||
bool m_is_pci_native_mode;
|
bool m_is_pci_native_mode;
|
||||||
|
|
||||||
u32 m_base_address;
|
u8 m_interrupt_line;
|
||||||
u32 m_control_port_base_address;
|
|
||||||
|
KMutex<100> m_lock {};
|
||||||
|
|
||||||
|
u16 m_io_base;
|
||||||
|
u16 m_control_base;
|
||||||
|
|
||||||
|
u8 m_current_drive = (u8)-1;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Controller
|
class Controller
|
||||||
@ -41,8 +88,6 @@ namespace ATA
|
|||||||
PCI::Device m_device;
|
PCI::Device m_device;
|
||||||
Channel m_primary_channel;
|
Channel m_primary_channel;
|
||||||
Channel m_secondary_channel;
|
Channel m_secondary_channel;
|
||||||
|
|
||||||
KMutex<100> m_lock;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -52,9 +52,8 @@ template <usize ConcurrentThreads> class KMutex
|
|||||||
template <usize ConcurrentThreads> class ScopedKMutexLock
|
template <usize ConcurrentThreads> class ScopedKMutexLock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ScopedKMutexLock(KMutex<ConcurrentThreads>& lock)
|
ScopedKMutexLock(KMutex<ConcurrentThreads>& lock) : m_lock(lock)
|
||||||
{
|
{
|
||||||
m_lock = lock;
|
|
||||||
m_lock.lock();
|
m_lock.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user