Kernel: Fix wrong I/O ports for the ATA alternate status registers

The alternate status register is not part of the same set of registers
as all the other stuff.

Also rename wait_400ns() to io_delay() since we had no guarantee that
it was waiting for 400ns..
This commit is contained in:
Andreas Kling 2019-09-04 11:10:07 +02:00
parent 8cbb38a237
commit e5500e2a22
2 changed files with 15 additions and 17 deletions

View file

@ -71,13 +71,9 @@
#define ATA_REG_HDDEVSEL 0x06 #define ATA_REG_HDDEVSEL 0x06
#define ATA_REG_COMMAND 0x07 #define ATA_REG_COMMAND 0x07
#define ATA_REG_STATUS 0x07 #define ATA_REG_STATUS 0x07
#define ATA_REG_SECCOUNT1 0x08 #define ATA_CTL_CONTROL 0x00
#define ATA_REG_LBA3 0x09 #define ATA_CTL_ALTSTATUS 0x00
#define ATA_REG_LBA4 0x0A #define ATA_CTL_DEVADDRESS 0x01
#define ATA_REG_LBA5 0x0B
#define ATA_REG_CONTROL 0x0C
#define ATA_REG_ALTSTATUS 0x0C
#define ATA_REG_DEVADDRESS 0x0D
static Lock& s_lock() static Lock& s_lock()
{ {
@ -97,6 +93,7 @@ PATAChannel::PATAChannel(ChannelType type)
: IRQHandler((type == ChannelType::Primary ? PATA_PRIMARY_IRQ : PATA_SECONDARY_IRQ)) : IRQHandler((type == ChannelType::Primary ? PATA_PRIMARY_IRQ : PATA_SECONDARY_IRQ))
, m_channel_number((type == ChannelType::Primary ? 0 : 1)) , m_channel_number((type == ChannelType::Primary ? 0 : 1))
, m_io_base((type == ChannelType::Primary ? 0x1F0 : 0x170)) , m_io_base((type == ChannelType::Primary ? 0x1F0 : 0x170))
, m_control_base((type == ChannelType::Primary ? 0x3f6 : 0x376))
{ {
m_dma_enabled.resource() = true; m_dma_enabled.resource() = true;
ProcFS::add_sys_bool("ide_dma", m_dma_enabled); ProcFS::add_sys_bool("ide_dma", m_dma_enabled);
@ -175,10 +172,10 @@ void PATAChannel::handle_irq()
m_interrupted = true; m_interrupted = true;
} }
static void wait_400ns(u16 io_base) static void io_delay()
{ {
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
IO::in8(io_base + ATA_REG_ALTSTATUS); IO::in8(0x3f6);
} }
void PATAChannel::detect_disks() void PATAChannel::detect_disks()
@ -285,9 +282,9 @@ bool PATAChannel::ata_read_sectors_with_dma(u32 lba, u16 count, u8* outbuf, bool
if (slave_request) if (slave_request)
devsel |= 0x10; devsel |= 0x10;
IO::out8(m_io_base + ATA_REG_CONTROL, 0); IO::out8(m_control_base + ATA_CTL_CONTROL, 0);
IO::out8(m_io_base + ATA_REG_HDDEVSEL, devsel | (static_cast<u8>(slave_request) << 4)); IO::out8(m_io_base + ATA_REG_HDDEVSEL, devsel | (static_cast<u8>(slave_request) << 4));
wait_400ns(m_io_base); io_delay();
IO::out8(m_io_base + ATA_REG_FEATURES, 0); IO::out8(m_io_base + ATA_REG_FEATURES, 0);
@ -308,7 +305,7 @@ bool PATAChannel::ata_read_sectors_with_dma(u32 lba, u16 count, u8* outbuf, bool
} }
IO::out8(m_io_base + ATA_REG_COMMAND, ATA_CMD_READ_DMA_EXT); IO::out8(m_io_base + ATA_REG_COMMAND, ATA_CMD_READ_DMA_EXT);
wait_400ns(m_io_base); io_delay();
// Start bus master // Start bus master
IO::out8(m_bus_master_base, 0x9); IO::out8(m_bus_master_base, 0x9);
@ -363,9 +360,9 @@ bool PATAChannel::ata_write_sectors_with_dma(u32 lba, u16 count, const u8* inbuf
if (slave_request) if (slave_request)
devsel |= 0x10; devsel |= 0x10;
IO::out8(m_io_base + ATA_REG_CONTROL, 0); IO::out8(m_control_base + ATA_CTL_CONTROL, 0);
IO::out8(m_io_base + ATA_REG_HDDEVSEL, devsel | (static_cast<u8>(slave_request) << 4)); IO::out8(m_io_base + ATA_REG_HDDEVSEL, devsel | (static_cast<u8>(slave_request) << 4));
wait_400ns(m_io_base); io_delay();
IO::out8(m_io_base + ATA_REG_FEATURES, 0); IO::out8(m_io_base + ATA_REG_FEATURES, 0);
@ -386,7 +383,7 @@ bool PATAChannel::ata_write_sectors_with_dma(u32 lba, u16 count, const u8* inbuf
} }
IO::out8(m_io_base + ATA_REG_COMMAND, ATA_CMD_WRITE_DMA_EXT); IO::out8(m_io_base + ATA_REG_COMMAND, ATA_CMD_WRITE_DMA_EXT);
wait_400ns(m_io_base); io_delay();
// Start bus master // Start bus master
IO::out8(m_bus_master_base, 0x1); IO::out8(m_bus_master_base, 0x1);
@ -446,7 +443,7 @@ bool PATAChannel::ata_read_sectors(u32 start_sector, u16 count, u8* outbuf, bool
return false; return false;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
wait_400ns(m_io_base); io_delay();
while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY) while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY)
; ;
@ -500,7 +497,7 @@ bool PATAChannel::ata_write_sectors(u32 start_sector, u16 count, const u8* inbuf
IO::out8(m_io_base + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO); IO::out8(m_io_base + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
wait_400ns(m_io_base); io_delay();
while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY) while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY)
; ;

View file

@ -58,6 +58,7 @@ private:
// Data members // Data members
u8 m_channel_number { 0 }; // Channel number. 0 = master, 1 = slave u8 m_channel_number { 0 }; // Channel number. 0 = master, 1 = slave
u16 m_io_base { 0x1F0 }; u16 m_io_base { 0x1F0 };
u16 m_control_base { 0 };
volatile u8 m_device_error { 0 }; volatile u8 m_device_error { 0 };
volatile bool m_interrupted { false }; volatile bool m_interrupted { false };