From 0408051f201cb5b19c4f8d5ec1d6e96de4a9aa3f Mon Sep 17 00:00:00 2001 From: Andrew Schultz Date: Thu, 3 Jun 2004 17:48:05 -0400 Subject: [PATCH] Fixes in translation in PCI to DMA address to fix boot problems with Linux 2.6 with DMA support dev/ide_disk.cc: Add debug infomation for DMA transfers and fix handling of PRD pointer values dev/ide_disk.hh: Reduce buffer (MAX_DMA) size to 64K dev/tsunami_pchip.cc: dev/tsunami_pchip.hh: Add handling of PCTL register and also fix the translate from PCI to DMA addresses which was incorrect --HG-- extra : convert_revision : 562f55fa1c7099ad0f5a23f59dec2c8ec7601d43 --- dev/ide_disk.cc | 11 +++++++++-- dev/ide_disk.hh | 6 +++--- dev/tsunami_pchip.cc | 41 +++++++++++++++++++++++++++++++---------- dev/tsunami_pchip.hh | 3 +++ 4 files changed, 46 insertions(+), 15 deletions(-) diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc index e8baa7539..dcaaf64c8 100644 --- a/dev/ide_disk.cc +++ b/dev/ide_disk.cc @@ -330,7 +330,13 @@ IdeDisk::dmaPrdReadDone() physmem->dma_addr(curPrdAddr, sizeof(PrdEntry_t)), sizeof(PrdEntry_t)); - curPrdAddr += sizeof(PrdEntry_t); + DPRINTF(IdeDisk, "PRD: baseAddr:%#x (%#x) byteCount:%d (%d) eot:%#x sector:%d\n", + curPrd.getBaseAddr(), pciToDma(curPrd.getBaseAddr()), + curPrd.getByteCount(), (cmdBytesLeft/SectorSize), + curPrd.getEOT(), curSector); + + // make sure the new curPrdAddr is properly translated from PCI to system + curPrdAddr = pciToDma(curPrdAddr + sizeof(PrdEntry_t)); if (dmaRead) doDmaRead(); @@ -613,7 +619,8 @@ IdeDisk::startDma(const uint32_t &prdTableBase) if (devState != Transfer_Data_Dma) panic("Inconsistent device state for DMA start!\n"); - curPrdAddr = pciToDma((Addr)prdTableBase); + // PRD base address is given by bits 31:2 + curPrdAddr = pciToDma((Addr)(prdTableBase & ~ULL(0x3))); dmaState = Dma_Transfer; diff --git a/dev/ide_disk.hh b/dev/ide_disk.hh index eb8c8a047..8f1d582c9 100644 --- a/dev/ide_disk.hh +++ b/dev/ide_disk.hh @@ -40,8 +40,8 @@ #define DMA_BACKOFF_PERIOD 200 -#define MAX_DMA_SIZE (131072) // 256 * SectorSize (512) -#define MAX_MULTSECT (128) +#define MAX_DMA_SIZE (65536) // 64K +#define MAX_MULTSECT (128) #define PRD_BASE_MASK 0xfffffffe #define PRD_COUNT_MASK 0xfffe @@ -62,7 +62,7 @@ class PrdTableEntry { return (entry.baseAddr & PRD_BASE_MASK); } - uint16_t getByteCount() + uint32_t getByteCount() { return ((entry.byteCount == 0) ? MAX_DMA_SIZE : (entry.byteCount & PRD_COUNT_MASK)); diff --git a/dev/tsunami_pchip.cc b/dev/tsunami_pchip.cc index 2ac3cae86..6a9cb7931 100644 --- a/dev/tsunami_pchip.cc +++ b/dev/tsunami_pchip.cc @@ -36,6 +36,9 @@ TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, tba[i] = 0; } + // initialize pchip control register + pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36); + //Set back pointer in tsunami tsunami->pchip = this; } @@ -89,8 +92,7 @@ TsunamiPChip::read(MemReqPtr &req, uint8_t *data) *(uint64_t*)data = tba[3]; return No_Fault; case TSDEV_PC_PCTL: - // might want to change the clock?? - *(uint64_t*)data = 0x00; // try this + *(uint64_t*)data = pctl; return No_Fault; case TSDEV_PC_PLAT: panic("PC_PLAT not implemented\n"); @@ -177,8 +179,7 @@ TsunamiPChip::write(MemReqPtr &req, const uint8_t *data) tba[3] = *(uint64_t*)data; return No_Fault; case TSDEV_PC_PCTL: - // might want to change the clock?? - //*(uint64_t*)data; // try this + pctl = *(uint64_t*)data; return No_Fault; case TSDEV_PC_PLAT: panic("PC_PLAT not implemented\n"); @@ -233,12 +234,29 @@ TsunamiPChip::translatePciToDma(Addr busAddr) Addr pteAddr; Addr dmaAddr; +#if 0 + DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr); for (int i = 0; i < 4; i++) { + DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n", + i, wsba[i], wsm[i]); + windowBase = wsba[i]; - windowMask = ~wsm[i] & (0x7ff << 20); + windowMask = ~wsm[i] & (ULL(0xfff) << 20); if ((busAddr & windowMask) == (windowBase & windowMask)) { + DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n", + i, windowBase, windowMask, (busAddr & windowMask), + (windowBase & windowMask)); + } + } +#endif + for (int i = 0; i < 4; i++) { + + windowBase = wsba[i]; + windowMask = ~wsm[i] & (ULL(0xfff) << 20); + + if ((busAddr & windowMask) == (windowBase & windowMask)) { if (wsba[i] & 0x1) { // see if enabled if (wsba[i] & 0x2) { // see if SG bit is set @@ -252,8 +270,8 @@ TsunamiPChip::translatePciToDma(Addr busAddr) to create an address for the SG page */ - tbaMask = ~(((wsm[i] & (0x7ff << 20)) >> 10) | 0x3ff); - baMask = (wsm[i] & (0x7ff << 20)) | (0x7f << 13); + tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff)); + baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13); pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); memcpy((void *)&pteEntry, @@ -261,10 +279,10 @@ TsunamiPChip::translatePciToDma(Addr busAddr) physmem->dma_addr(pteAddr, sizeof(uint64_t)), sizeof(uint64_t)); - dmaAddr = ((pteEntry & ~0x1) << 12) | (busAddr & 0x1fff); + dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff)); } else { - baMask = (wsm[i] & (0x7ff << 20)) | 0xfffff; + baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff); tbaMask = ~baMask; dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask); } @@ -274,12 +292,14 @@ TsunamiPChip::translatePciToDma(Addr busAddr) } } - return 0; + // if no match was found, then return the original address + return busAddr; } void TsunamiPChip::serialize(std::ostream &os) { + SERIALIZE_SCALAR(pctl); SERIALIZE_ARRAY(wsba, 4); SERIALIZE_ARRAY(wsm, 4); SERIALIZE_ARRAY(tba, 4); @@ -288,6 +308,7 @@ TsunamiPChip::serialize(std::ostream &os) void TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) { + UNSERIALIZE_SCALAR(pctl); UNSERIALIZE_ARRAY(wsba, 4); UNSERIALIZE_ARRAY(wsm, 4); UNSERIALIZE_ARRAY(tba, 4); diff --git a/dev/tsunami_pchip.hh b/dev/tsunami_pchip.hh index 44f145a60..2c8da7ecc 100644 --- a/dev/tsunami_pchip.hh +++ b/dev/tsunami_pchip.hh @@ -56,6 +56,9 @@ class TsunamiPChip : public FunctionalMemory */ Tsunami *tsunami; + /** Pchip control register */ + uint64_t pctl; + /** Window Base addresses */ uint64_t wsba[4]; -- 2.30.2