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
This commit is contained in:
Andrew Schultz 2004-05-11 18:06:50 -04:00
parent 4a5dcc37bf
commit 3bfb59f70d
3 changed files with 94 additions and 4 deletions

View file

@ -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()) {

View file

@ -313,6 +313,8 @@ class IdeDisk : public SimObject
(cmdReg.cyl_low << 8) | (cmdReg.sec_num));
}
inline Addr pciToDma(Addr &pciAddr);
/**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.

View file

@ -263,7 +263,7 @@ TsunamiPChip::translatePciToDma(Addr busAddr)
physmem->dma_addr(pteAddr, sizeof(uint64_t)),
sizeof(uint64_t));
dmaAddr = ((pteEntry & ~0x1) << 12) | (busAddr & 0xfff);
dmaAddr = ((pteEntry & ~0x1) << 12) | (busAddr & 0x1fff);
} else {
baMask = (wsm[i] & (0x7ff << 20)) | 0xfffff;