diff options
author | Andrew Schultz <alschult@umich.edu> | 2004-05-11 18:06:50 -0400 |
---|---|---|
committer | Andrew Schultz <alschult@umich.edu> | 2004-05-11 18:06:50 -0400 |
commit | 3bfb59f70d4bf8ca7b9e6a0bdbcacdbbebf41403 (patch) | |
tree | 38265703cdce2674d31de1dcb18c6effb1ae901b /dev/ide_disk.cc | |
parent | 4a5dcc37bfb26c152c195061fa70c7aa246b5ca6 (diff) | |
download | gem5-3bfb59f70d4bf8ca7b9e6a0bdbcacdbbebf41403.tar.xz |
Changes to fix bad DMA handling by disk when using scatter gather page
mappings (writes still unverified, and read could probably be looked over
a bit more too)
dev/ide_disk.cc:
dev/ide_disk.hh:
Major changes to fix bogus handling of dma transfers. The read seems to
work pretty well, but the write is unverfied until we can get a disk
image that actually tries to write.
dev/tsunami_pchip.cc:
Change mask to properly mask 13 bits not 12
--HG--
extra : convert_revision : 08fe9bc32970e449cd045de479553a96a4e389d6
Diffstat (limited to 'dev/ide_disk.cc')
-rw-r--r-- | dev/ide_disk.cc | 94 |
1 files changed, 91 insertions, 3 deletions
diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc index f4e73c833..38d6a919b 100644 --- a/dev/ide_disk.cc +++ b/dev/ide_disk.cc @@ -35,6 +35,7 @@ #include <deque> #include <string> +#include "arch/alpha/pmap.h" #include "base/cprintf.hh" // csprintf #include "base/trace.hh" #include "dev/disk_image.hh" @@ -60,7 +61,7 @@ IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys, dmaWriteWaitEvent(this), dmaPrdReadEvent(this), dmaReadEvent(this), dmaWriteEvent(this) { - diskDelay = (delay * ticksPerSecond / 1000) / image->size(); + diskDelay = (delay * ticksPerSecond / 100000); // initialize the data buffer and shadow registers dataBuffer = new uint8_t[MAX_DMA_SIZE]; @@ -153,6 +154,15 @@ IdeDisk::~IdeDisk() delete [] dataBuffer; } +Addr +IdeDisk::pciToDma(Addr &pciAddr) +{ + if (ctrl) + return ctrl->tsunami->pchip->translatePciToDma(pciAddr); + else + panic("Access to unset controller!\n"); +} + //// // Device registers read/write //// @@ -309,6 +319,51 @@ IdeDisk::doDmaRead() void IdeDisk::dmaReadDone() { + + Addr curAddr = 0, dmaAddr = 0; + uint32_t bytesWritten = 0, bytesInPage = 0, bytesLeft = 0; + + // set initial address + curAddr = curPrd.getBaseAddr(); + + // clear out the data buffer + memset(dataBuffer, 0, MAX_DMA_SIZE); + + // read the data from memory via DMA into a data buffer + while (bytesWritten < curPrd.getByteCount()) { + if (cmdBytesLeft <= 0) + panic("DMA data is larger than # of sectors specified\n"); + + dmaAddr = pciToDma(curAddr); + + // calculate how many bytes are in the current page + bytesLeft = curPrd.getByteCount() - bytesWritten; + bytesInPage = (bytesLeft > ALPHA_PGBYTES) ? ALPHA_PGBYTES : bytesLeft; + // check to make sure we don't cross a page boundary + if ((curAddr + bytesInPage) > + (alpha_trunc_page(curAddr) + ALPHA_PGBYTES)) + + bytesInPage = alpha_round_page(curAddr) - curAddr; + + // copy the data from memory into the data buffer + /** @todo Use real DMA with interfaces here */ + memcpy((void *)(dataBuffer + bytesWritten), + physmem->dma_addr(dmaAddr, bytesInPage), + bytesInPage); + + curAddr += bytesInPage; + bytesWritten += bytesInPage; + cmdBytesLeft -= bytesInPage; + } + + // write the data to the disk image + for (bytesWritten = 0; + bytesWritten < curPrd.getByteCount(); + bytesWritten += SectorSize) + + writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten)); + +#if 0 // actually copy the data from memory to data buffer Addr dmaAddr = ctrl->tsunami->pchip->translatePciToDma(curPrd.getBaseAddr()); @@ -327,6 +382,7 @@ IdeDisk::dmaReadDone() bytesWritten += SectorSize; cmdBytesLeft -= SectorSize; } +#endif // check for the EOT if (curPrd.getEOT()){ @@ -364,27 +420,59 @@ IdeDisk::doDmaWrite() void IdeDisk::dmaWriteDone() { - uint32_t bytesRead = 0; + Addr curAddr = 0, pageAddr = 0, dmaAddr = 0; + uint32_t bytesRead = 0, bytesInPage = 0; + + // setup the initial page and DMA address + curAddr = curPrd.getBaseAddr(); + pageAddr = alpha_trunc_page(curAddr); + dmaAddr = pciToDma(curAddr); // clear out the data buffer memset(dataBuffer, 0, MAX_DMA_SIZE); while (bytesRead < curPrd.getByteCount()) { + // see if we have crossed into a new page + if (pageAddr != alpha_trunc_page(curAddr)) { + // write the data to memory + /** @todo Do real DMA using interfaces here */ + memcpy(physmem->dma_addr(dmaAddr, bytesInPage), + (void *)(dataBuffer + (bytesRead - bytesInPage)), + bytesInPage); + + // update the DMA address and page address + pageAddr = alpha_trunc_page(curAddr); + dmaAddr = pciToDma(curAddr); + + bytesInPage = 0; + } + if (cmdBytesLeft <= 0) panic("DMA requested data is larger than # sectors specified\n"); readDisk(curSector++, (uint8_t *)(dataBuffer + bytesRead)); + curAddr += SectorSize; bytesRead += SectorSize; + bytesInPage += SectorSize; cmdBytesLeft -= SectorSize; } - // copy the data to memory + // write the last page worth read to memory + /** @todo Do real DMA using interfaces here */ + if (bytesInPage != 0) { + memcpy(physmem->dma_addr(dmaAddr, bytesInPage), + (void *)(dataBuffer + (bytesRead - bytesInPage)), + bytesInPage); + } + +#if 0 Addr dmaAddr = ctrl->tsunami->pchip-> translatePciToDma(curPrd.getBaseAddr()); memcpy(physmem->dma_addr(dmaAddr, curPrd.getByteCount()), (void *)dataBuffer, curPrd.getByteCount()); +#endif // check for the EOT if (curPrd.getEOT()) { |