summaryrefslogtreecommitdiff
path: root/dev/ide_disk.cc
diff options
context:
space:
mode:
authorAndrew Schultz <alschult@umich.edu>2004-05-11 18:06:50 -0400
committerAndrew Schultz <alschult@umich.edu>2004-05-11 18:06:50 -0400
commit3bfb59f70d4bf8ca7b9e6a0bdbcacdbbebf41403 (patch)
tree38265703cdce2674d31de1dcb18c6effb1ae901b /dev/ide_disk.cc
parent4a5dcc37bfb26c152c195061fa70c7aa246b5ca6 (diff)
downloadgem5-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.cc94
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()) {