Fixes in translation in PCI to DMA address to fix boot problems with
authorAndrew Schultz <alschult@umich.edu>
Thu, 3 Jun 2004 21:48:05 +0000 (17:48 -0400)
committerAndrew Schultz <alschult@umich.edu>
Thu, 3 Jun 2004 21:48:05 +0000 (17:48 -0400)
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
dev/ide_disk.hh
dev/tsunami_pchip.cc
dev/tsunami_pchip.hh

index e8baa75394508c6923aad92c50920c23fb8cd6d3..dcaaf64c84b45f7a78162f4aa74d1502b3a15bf4 100644 (file)
@@ -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;
 
index eb8c8a047c7411d9027da3de064f3a2b444c8692..8f1d582c9849cf3afb2518c14506ee0ced740bfe 100644 (file)
@@ -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));
index 2ac3cae860699457c9c3005eb46f5c0414ac3823..6a9cb7931476f1aa7b5e1b62d560abcb9eb1ae75 100644 (file)
@@ -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 &section)
 {
+    UNSERIALIZE_SCALAR(pctl);
     UNSERIALIZE_ARRAY(wsba, 4);
     UNSERIALIZE_ARRAY(wsm, 4);
     UNSERIALIZE_ARRAY(tba, 4);
index 44f145a606b88e2854191cf7c1052771e54d76c8..2c8da7ecc0909f48faf456e2f27b8a21cf4e87dd 100644 (file)
@@ -56,6 +56,9 @@ class TsunamiPChip : public FunctionalMemory
      */
     Tsunami *tsunami;
 
+    /** Pchip control register */
+    uint64_t pctl;
+
     /** Window Base addresses */
     uint64_t wsba[4];