+#define DMA_ADDR_MASK ULL(0x3ffffffff)
+
+Addr
+TsunamiPChip::translatePciToDma(Addr busAddr)
+{
+ // compare the address to the window base registers
+ uint64_t tbaMask = 0;
+ uint64_t baMask = 0;
+
+ uint64_t windowMask = 0;
+ uint64_t windowBase = 0;
+
+ uint64_t pteEntry = 0;
+
+ 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] & (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
+ /** @todo
+ This currently is faked by just doing a direct
+ read from memory, however, to be realistic, this
+ needs to actually do a bus transaction. The process
+ is explained in the tsunami documentation on page
+ 10-12 and basically munges the address to look up a
+ PTE from a table in memory and then uses that mapping
+ to create an address for the SG page
+ */
+
+ 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,
+ tsunami->system->
+ physmem->dma_addr(pteAddr, sizeof(uint64_t)),
+ sizeof(uint64_t));
+
+ dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff));
+
+ } else {
+ baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff);
+ tbaMask = ~baMask;
+ dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask);
+ }
+
+ return (dmaAddr & DMA_ADDR_MASK);
+ }
+ }
+ }
+
+ // if no match was found, then return the original address
+ return busAddr;
+}
+