mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 11:57:35 +00:00
Kernel: Enable IRQs before sending commands to devices
Without this fix, a very fast IRQ can preempt the enable_irq() call, leaving that IRQ being unhandled.
This commit is contained in:
parent
f33fb151b4
commit
a3fa40fc07
3 changed files with 19 additions and 8 deletions
|
@ -140,15 +140,21 @@ PATAChannel::PATAChannel(PCI::Address address, ChannelType type, bool force_pio)
|
||||||
ProcFS::add_sys_bool("ide_dma", m_dma_enabled);
|
ProcFS::add_sys_bool("ide_dma", m_dma_enabled);
|
||||||
|
|
||||||
m_prdt_page = MM.allocate_supervisor_physical_page();
|
m_prdt_page = MM.allocate_supervisor_physical_page();
|
||||||
|
|
||||||
initialize(force_pio);
|
initialize(force_pio);
|
||||||
detect_disks();
|
detect_disks();
|
||||||
|
disable_irq();
|
||||||
}
|
}
|
||||||
|
|
||||||
PATAChannel::~PATAChannel()
|
PATAChannel::~PATAChannel()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PATAChannel::prepare_for_irq()
|
||||||
|
{
|
||||||
|
cli();
|
||||||
|
enable_irq();
|
||||||
|
}
|
||||||
|
|
||||||
void PATAChannel::initialize(bool force_pio)
|
void PATAChannel::initialize(bool force_pio)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -158,6 +164,7 @@ void PATAChannel::initialize(bool force_pio)
|
||||||
}
|
}
|
||||||
// Let's try to set up DMA transfers.
|
// Let's try to set up DMA transfers.
|
||||||
PCI::enable_bus_mastering(pci_address());
|
PCI::enable_bus_mastering(pci_address());
|
||||||
|
PCI::enable_interrupt_line(pci_address());
|
||||||
prdt().end_of_table = 0x8000;
|
prdt().end_of_table = 0x8000;
|
||||||
m_dma_buffer_page = MM.allocate_supervisor_physical_page();
|
m_dma_buffer_page = MM.allocate_supervisor_physical_page();
|
||||||
klog() << "PATAChannel: Bus master IDE: " << m_bus_master_base;
|
klog() << "PATAChannel: Bus master IDE: " << m_bus_master_base;
|
||||||
|
@ -170,8 +177,6 @@ static void print_ide_status(u8 status)
|
||||||
|
|
||||||
void PATAChannel::wait_for_irq()
|
void PATAChannel::wait_for_irq()
|
||||||
{
|
{
|
||||||
cli();
|
|
||||||
enable_irq();
|
|
||||||
Thread::current->wait_on(m_irq_queue);
|
Thread::current->wait_on(m_irq_queue);
|
||||||
disable_irq();
|
disable_irq();
|
||||||
}
|
}
|
||||||
|
@ -313,6 +318,7 @@ bool PATAChannel::ata_read_sectors_with_dma(u32 lba, u16 count, u8* outbuf, bool
|
||||||
m_io_base.offset(ATA_REG_COMMAND).out<u8>(ATA_CMD_READ_DMA_EXT);
|
m_io_base.offset(ATA_REG_COMMAND).out<u8>(ATA_CMD_READ_DMA_EXT);
|
||||||
io_delay();
|
io_delay();
|
||||||
|
|
||||||
|
prepare_for_irq();
|
||||||
// Start bus master
|
// Start bus master
|
||||||
m_bus_master_base.out<u8>(0x9);
|
m_bus_master_base.out<u8>(0x9);
|
||||||
|
|
||||||
|
@ -383,9 +389,9 @@ bool PATAChannel::ata_write_sectors_with_dma(u32 lba, u16 count, const u8* inbuf
|
||||||
m_io_base.offset(ATA_REG_COMMAND).out<u8>(ATA_CMD_WRITE_DMA_EXT);
|
m_io_base.offset(ATA_REG_COMMAND).out<u8>(ATA_CMD_WRITE_DMA_EXT);
|
||||||
io_delay();
|
io_delay();
|
||||||
|
|
||||||
|
prepare_for_irq();
|
||||||
// Start bus master
|
// Start bus master
|
||||||
m_bus_master_base.out<u8>(0x1);
|
m_bus_master_base.out<u8>(0x1);
|
||||||
|
|
||||||
wait_for_irq();
|
wait_for_irq();
|
||||||
|
|
||||||
if (m_device_error)
|
if (m_device_error)
|
||||||
|
@ -425,6 +431,7 @@ bool PATAChannel::ata_read_sectors(u32 start_sector, u16 count, u8* outbuf, bool
|
||||||
while (!(m_io_base.offset(ATA_REG_STATUS).in<u8>() & ATA_SR_DRDY))
|
while (!(m_io_base.offset(ATA_REG_STATUS).in<u8>() & ATA_SR_DRDY))
|
||||||
;
|
;
|
||||||
|
|
||||||
|
prepare_for_irq();
|
||||||
m_io_base.offset(ATA_REG_COMMAND).out<u8>(ATA_CMD_READ_PIO);
|
m_io_base.offset(ATA_REG_COMMAND).out<u8>(ATA_CMD_READ_PIO);
|
||||||
wait_for_irq();
|
wait_for_irq();
|
||||||
|
|
||||||
|
@ -440,7 +447,7 @@ bool PATAChannel::ata_read_sectors(u32 start_sector, u16 count, u8* outbuf, bool
|
||||||
u8 status = m_io_base.offset(ATA_REG_STATUS).in<u8>();
|
u8 status = m_io_base.offset(ATA_REG_STATUS).in<u8>();
|
||||||
ASSERT(status & ATA_SR_DRQ);
|
ASSERT(status & ATA_SR_DRQ);
|
||||||
#ifdef PATA_DEBUG
|
#ifdef PATA_DEBUG
|
||||||
dbg() << "PATAChannel: Retrieving 512 bytes (part " << i << ") (status=" << String::format("%b", status) << "), outbuf=(" << (inbuf + (512 * i)) << ")...";
|
dbg() << "PATAChannel: Retrieving 512 bytes (part " << i << ") (status=" << String::format("%b", status) << "), outbuf=(" << (outbuf + (512 * i)) << ")...";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
IO::repeated_in16(m_io_base.offset(ATA_REG_DATA).get(), outbuf + (512 * i), 256);
|
IO::repeated_in16(m_io_base.offset(ATA_REG_DATA).get(), outbuf + (512 * i), 256);
|
||||||
|
@ -493,11 +500,12 @@ bool PATAChannel::ata_write_sectors(u32 start_sector, u16 count, const u8* inbuf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
IO::repeated_out16(m_io_base.offset(ATA_REG_DATA).get(), inbuf + (512 * i), 256);
|
IO::repeated_out16(m_io_base.offset(ATA_REG_DATA).get(), inbuf + (512 * i), 256);
|
||||||
|
prepare_for_irq();
|
||||||
wait_for_irq();
|
wait_for_irq();
|
||||||
status = m_io_base.offset(ATA_REG_STATUS).in<u8>();
|
status = m_io_base.offset(ATA_REG_STATUS).in<u8>();
|
||||||
ASSERT(!(status & ATA_SR_BSY));
|
ASSERT(!(status & ATA_SR_BSY));
|
||||||
}
|
}
|
||||||
|
prepare_for_irq();
|
||||||
m_io_base.offset(ATA_REG_COMMAND).out<u8>(ATA_CMD_CACHE_FLUSH);
|
m_io_base.offset(ATA_REG_COMMAND).out<u8>(ATA_CMD_CACHE_FLUSH);
|
||||||
wait_for_irq();
|
wait_for_irq();
|
||||||
u8 status = m_io_base.offset(ATA_REG_STATUS).in<u8>();
|
u8 status = m_io_base.offset(ATA_REG_STATUS).in<u8>();
|
||||||
|
|
|
@ -85,6 +85,8 @@ private:
|
||||||
bool ata_read_sectors(u32, u16, u8*, bool);
|
bool ata_read_sectors(u32, u16, u8*, bool);
|
||||||
bool ata_write_sectors(u32, u16, const u8*, bool);
|
bool ata_write_sectors(u32, u16, const u8*, bool);
|
||||||
|
|
||||||
|
inline void prepare_for_irq();
|
||||||
|
|
||||||
// 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
|
||||||
IOAddress m_io_base;
|
IOAddress m_io_base;
|
||||||
|
|
|
@ -220,8 +220,6 @@ void SB16::handle_irq(RegisterState&)
|
||||||
|
|
||||||
void SB16::wait_for_irq()
|
void SB16::wait_for_irq()
|
||||||
{
|
{
|
||||||
cli();
|
|
||||||
enable_irq();
|
|
||||||
Thread::current->wait_on(m_irq_queue);
|
Thread::current->wait_on(m_irq_queue);
|
||||||
disable_irq();
|
disable_irq();
|
||||||
}
|
}
|
||||||
|
@ -260,6 +258,9 @@ ssize_t SB16::write(FileDescription&, const u8* data, ssize_t length)
|
||||||
|
|
||||||
sample_count -= 1;
|
sample_count -= 1;
|
||||||
|
|
||||||
|
cli();
|
||||||
|
enable_irq();
|
||||||
|
|
||||||
dsp_write(command);
|
dsp_write(command);
|
||||||
dsp_write(mode);
|
dsp_write(mode);
|
||||||
dsp_write((u8)sample_count);
|
dsp_write((u8)sample_count);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue