From 5f8170548866f16c9eeb2adf3e159e4b8da1d770 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Thu, 22 Nov 2012 16:35:05 +0100 Subject: [PATCH] Atapi: limit block count in DMA request (fix #514) The block count in DMA requests is limited to 8 bit. Therefore, if a client requests more than 255 blocks in a single packet request, split the request in a loop. --- os/src/drivers/atapi/ata_device.cc | 60 +++++++++++++++++++----------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/os/src/drivers/atapi/ata_device.cc b/os/src/drivers/atapi/ata_device.cc index cc7c5972cb..f7c82fcd2d 100644 --- a/os/src/drivers/atapi/ata_device.cc +++ b/os/src/drivers/atapi/ata_device.cc @@ -123,40 +123,56 @@ void Ata::Device::read_capacity() void Ata::Device::read(unsigned long block_nr, unsigned long count, off_t offset) { - if (dma_enabled()) { + while (count > 0) { + unsigned long c = count > 255 ? 255 : count; - if (verbose) - PDBG("DMA read: block %lu, count %lu, offset: %08lx, base: %08lx", - block_nr, count, offset, _base_addr); + if (dma_enabled()) { - if (dma_pci_lba28(dev_num(), CMD_READ_DMA, 0, count, block_nr, - (unsigned char *)(_base_addr + offset), count)) - throw Io_error(); + if (verbose) + PDBG("DMA read: block %lu, c %lu, offset: %08lx, base: %08lx", + block_nr, c, offset, _base_addr); + + if (dma_pci_lba28(dev_num(), CMD_READ_DMA, 0, c, block_nr, + (unsigned char *)(_base_addr + offset), c)) + throw Io_error(); + } + else + if (reg_pio_data_in_lba28(dev_num(), CMD_READ_SECTORS, 0, c, block_nr, + (unsigned char *)(_base_addr + offset), c, 0)) + throw Io_error(); + + count -= c; + block_nr += c; + offset += c * block_size(); } - else - if (reg_pio_data_in_lba28(dev_num(), CMD_READ_SECTORS, 0, count, block_nr, - (unsigned char *)(_base_addr + offset), count, 0)) - throw Io_error(); } void Ata::Device::write(unsigned long block_nr, unsigned long count, off_t offset) { - if (dma_enabled()) { + while (count > 0) { + unsigned long c = count > 255 ? 255 : count; - if (verbose) - PDBG("DMA read: block %lu, count %lu, offset: %08lx, base: %08lx", - block_nr, count, offset, _base_addr); + if (dma_enabled()) { - if (dma_pci_lba28(dev_num(), CMD_WRITE_DMA, 0, count, block_nr, - (unsigned char *)(_base_addr + offset), count)) - throw Io_error(); + if (verbose) + PDBG("DMA read: block %lu, c %lu, offset: %08lx, base: %08lx", + block_nr, c, offset, _base_addr); + + if (dma_pci_lba28(dev_num(), CMD_WRITE_DMA, 0, c, block_nr, + (unsigned char *)(_base_addr + offset), c)) + throw Io_error(); + } + else + if (reg_pio_data_out_lba28(dev_num(), CMD_WRITE_SECTORS, 0, c, block_nr, + (unsigned char *)(_base_addr + offset), c, 0)) + throw Io_error(); + + count -= c; + block_nr += c; + offset += c * block_size(); } - else - if (reg_pio_data_out_lba28(dev_num(), CMD_WRITE_SECTORS, 0, count, block_nr, - (unsigned char *)(_base_addr + offset), count, 0)) - throw Io_error(); }