mirror of https://github.com/PCSX2/pcsx2.git
DEV9: Don't fake the FIFO
This commit is contained in:
parent
1f2d9ab4e5
commit
1bdd53a6c5
|
@ -167,8 +167,8 @@ public:
|
||||||
|
|
||||||
void Async(u32 cycles);
|
void Async(u32 cycles);
|
||||||
|
|
||||||
void ATAreadDMA8Mem(u8* pMem, int size);
|
int ReadDMAToFIFO(u8* buffer, int space);
|
||||||
void ATAwriteDMA8Mem(u8* pMem, int size);
|
int WriteDMAFromFIFO(u8* buffer, int available);
|
||||||
|
|
||||||
u16 ATAreadPIO();
|
u16 ATAreadPIO();
|
||||||
//ATAwritePIO;
|
//ATAwritePIO;
|
||||||
|
|
|
@ -10,7 +10,7 @@ void ATA::DRQCmdDMADataToHost()
|
||||||
regStatus &= ~ATA_STAT_BUSY;
|
regStatus &= ~ATA_STAT_BUSY;
|
||||||
regStatus |= ATA_STAT_DRQ;
|
regStatus |= ATA_STAT_DRQ;
|
||||||
dmaReady = true;
|
dmaReady = true;
|
||||||
_DEV9irq(SPD_INTR_ATA_FIFO_DATA, 1);
|
DEV9runFIFO();
|
||||||
//PCSX2 will Start DMA
|
//PCSX2 will Start DMA
|
||||||
}
|
}
|
||||||
void ATA::PostCmdDMADataToHost()
|
void ATA::PostCmdDMADataToHost()
|
||||||
|
@ -22,11 +22,9 @@ void ATA::PostCmdDMADataToHost()
|
||||||
regStatus &= ~ATA_STAT_BUSY;
|
regStatus &= ~ATA_STAT_BUSY;
|
||||||
dmaReady = false;
|
dmaReady = false;
|
||||||
|
|
||||||
dev9.irqcause &= ~SPD_INTR_ATA_FIFO_DATA;
|
|
||||||
pendingInterrupt = true;
|
pendingInterrupt = true;
|
||||||
if (regControlEnableIRQ)
|
if (regControlEnableIRQ)
|
||||||
_DEV9irq(ATA_INTR_INTRQ, 1);
|
_DEV9irq(ATA_INTR_INTRQ, 1);
|
||||||
//PCSX2 Will Start DMA
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ATA::DRQCmdDMADataFromHost()
|
void ATA::DRQCmdDMADataFromHost()
|
||||||
|
@ -44,7 +42,7 @@ void ATA::DRQCmdDMADataFromHost()
|
||||||
regStatus &= ~ATA_STAT_BUSY;
|
regStatus &= ~ATA_STAT_BUSY;
|
||||||
regStatus |= ATA_STAT_DRQ;
|
regStatus |= ATA_STAT_DRQ;
|
||||||
dmaReady = true;
|
dmaReady = true;
|
||||||
_DEV9irq(SPD_INTR_ATA_FIFO_DATA, 1);
|
DEV9runFIFO();
|
||||||
//PCSX2 will Start DMA
|
//PCSX2 will Start DMA
|
||||||
}
|
}
|
||||||
void ATA::PostCmdDMADataFromHost()
|
void ATA::PostCmdDMADataFromHost()
|
||||||
|
@ -62,8 +60,6 @@ void ATA::PostCmdDMADataFromHost()
|
||||||
regStatus &= ~ATA_STAT_DRQ;
|
regStatus &= ~ATA_STAT_DRQ;
|
||||||
dmaReady = false;
|
dmaReady = false;
|
||||||
|
|
||||||
dev9.irqcause &= ~SPD_INTR_ATA_FIFO_DATA;
|
|
||||||
|
|
||||||
if (fetWriteCacheEnabled)
|
if (fetWriteCacheEnabled)
|
||||||
{
|
{
|
||||||
regStatus &= ~ATA_STAT_BUSY;
|
regStatus &= ~ATA_STAT_BUSY;
|
||||||
|
@ -77,18 +73,16 @@ void ATA::PostCmdDMADataFromHost()
|
||||||
Async(-1);
|
Async(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ATA::ATAreadDMA8Mem(u8* pMem, int size)
|
int ATA::ReadDMAToFIFO(u8* buffer, int space)
|
||||||
{
|
{
|
||||||
if ((udmaMode >= 0 || mdmaMode >= 0) &&
|
if (udmaMode >= 0 || mdmaMode >= 0)
|
||||||
(dev9.if_ctrl & SPD_IF_ATA_DMAEN) != 0)
|
|
||||||
{
|
{
|
||||||
if (size == 0 || nsector == -1)
|
if (space == 0 || nsector == -1)
|
||||||
return;
|
return 0;
|
||||||
DevCon.WriteLn("DEV9: DMA read, size %i, transferred %i, total size %i", size, rdTransferred, nsector * 512);
|
|
||||||
|
|
||||||
//read
|
// Read to FIFO
|
||||||
size = std::min(size, nsector * 512 - rdTransferred);
|
const int size = std::min(space, nsector * 512 - rdTransferred);
|
||||||
memcpy(pMem, &readBuffer[rdTransferred], size);
|
memcpy(buffer, &readBuffer[rdTransferred], size);
|
||||||
|
|
||||||
rdTransferred += size;
|
rdTransferred += size;
|
||||||
|
|
||||||
|
@ -100,21 +94,22 @@ void ATA::ATAreadDMA8Mem(u8* pMem, int size)
|
||||||
rdTransferred = 0;
|
rdTransferred = 0;
|
||||||
PostCmdDMADataToHost();
|
PostCmdDMADataToHost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ATA::ATAwriteDMA8Mem(u8* pMem, int size)
|
int ATA::WriteDMAFromFIFO(u8* buffer, int available)
|
||||||
{
|
{
|
||||||
if ((udmaMode >= 0 || mdmaMode >= 0) &&
|
if (udmaMode >= 0 || mdmaMode >= 0)
|
||||||
(dev9.if_ctrl & SPD_IF_ATA_DMAEN) != 0)
|
|
||||||
{
|
{
|
||||||
if (nsector == -1)
|
if (available == 0 || nsector == -1)
|
||||||
return;
|
return 0;
|
||||||
DevCon.WriteLn("DEV9: DMA write, size %i, transferred %i, total size %i", size, wrTransferred, nsector * 512);
|
|
||||||
|
|
||||||
//write
|
// Write to FIFO
|
||||||
size = std::min(size, nsector * 512 - wrTransferred);
|
const int size = std::min(available, nsector * 512 - wrTransferred);
|
||||||
memcpy(¤tWrite[wrTransferred], pMem, size);
|
memcpy(¤tWrite[wrTransferred], buffer, size);
|
||||||
|
|
||||||
wrTransferred += size;
|
wrTransferred += size;
|
||||||
|
|
||||||
|
@ -126,7 +121,10 @@ void ATA::ATAwriteDMA8Mem(u8* pMem, int size)
|
||||||
wrTransferred = 0;
|
wrTransferred = 0;
|
||||||
PostCmdDMADataFromHost();
|
PostCmdDMADataFromHost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//GENRAL FEATURE SET
|
//GENRAL FEATURE SET
|
||||||
|
|
|
@ -202,6 +202,7 @@ void DEV9close()
|
||||||
{
|
{
|
||||||
DevCon.WriteLn("DEV9: DEV9close");
|
DevCon.WriteLn("DEV9: DEV9close");
|
||||||
|
|
||||||
|
dev9.dma_iop_ptr = nullptr;
|
||||||
dev9.ata->Close();
|
dev9.ata->Close();
|
||||||
TermNet();
|
TermNet();
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
|
@ -228,49 +229,124 @@ void _DEV9irq(int cause, int cycles)
|
||||||
dev9Irq(cycles);
|
dev9Irq(cycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Fakes SPEED FIFO
|
// SPEED <-> HDD FIFO
|
||||||
void HDDWriteFIFO()
|
void HDDWriteFIFO()
|
||||||
{
|
{
|
||||||
if (dev9.ata->dmaReady && (dev9.if_ctrl & SPD_IF_ATA_DMAEN))
|
pxAssert(dev9.ata->dmaReady && (dev9.if_ctrl & SPD_IF_ATA_DMAEN));
|
||||||
{
|
pxAssert((dev9.if_ctrl & SPD_IF_READ));
|
||||||
const int unread = (dev9.fifo_bytes_write - dev9.fifo_bytes_read);
|
|
||||||
const int spaceSectors = (SPD_DBUF_AVAIL_MAX * 512 - unread) / 512;
|
|
||||||
if (spaceSectors < 0)
|
|
||||||
{
|
|
||||||
Console.Error("DEV9: No Space on SPEED FIFO");
|
|
||||||
pxAssert(false);
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
const int readSectors = dev9.ata->nsectorLeft < spaceSectors ? dev9.ata->nsectorLeft : spaceSectors;
|
const int unread = (dev9.fifo_bytes_write - dev9.fifo_bytes_read);
|
||||||
dev9.fifo_bytes_write += readSectors * 512;
|
const int space = (SPD_DBUF_AVAIL_MAX * 512 - unread);
|
||||||
dev9.ata->nsectorLeft -= readSectors;
|
const int base = dev9.fifo_bytes_write % (SPD_DBUF_AVAIL_MAX * 512);
|
||||||
|
|
||||||
|
pxAssert(unread <= SPD_DBUF_AVAIL_MAX * 512);
|
||||||
|
|
||||||
|
int read;
|
||||||
|
if (base + space > SPD_DBUF_AVAIL_MAX * 512)
|
||||||
|
{
|
||||||
|
const int was = SPD_DBUF_AVAIL_MAX * 512 - base;
|
||||||
|
read = dev9.ata->ReadDMAToFIFO(dev9.fifo + base, was);
|
||||||
|
if (read == was)
|
||||||
|
read += dev9.ata->ReadDMAToFIFO(dev9.fifo, space - was);
|
||||||
}
|
}
|
||||||
//FIFOIntr();
|
else
|
||||||
|
{
|
||||||
|
read = dev9.ata->ReadDMAToFIFO(dev9.fifo + base, space);
|
||||||
|
}
|
||||||
|
|
||||||
|
dev9.fifo_bytes_write += read;
|
||||||
}
|
}
|
||||||
void HDDReadFIFO()
|
void HDDReadFIFO()
|
||||||
{
|
{
|
||||||
if (dev9.ata->dmaReady && (dev9.if_ctrl & SPD_IF_ATA_DMAEN))
|
pxAssert(dev9.ata->dmaReady && (dev9.if_ctrl & SPD_IF_ATA_DMAEN));
|
||||||
|
pxAssert((dev9.if_ctrl & SPD_IF_READ) == 0);
|
||||||
|
|
||||||
|
const int unread = (dev9.fifo_bytes_write - dev9.fifo_bytes_read);
|
||||||
|
const int base = dev9.fifo_bytes_read % (SPD_DBUF_AVAIL_MAX * 512);
|
||||||
|
|
||||||
|
pxAssert(unread <= SPD_DBUF_AVAIL_MAX * 512);
|
||||||
|
|
||||||
|
int write;
|
||||||
|
if (base + unread > SPD_DBUF_AVAIL_MAX * 512)
|
||||||
{
|
{
|
||||||
const int writeSectors = (dev9.fifo_bytes_write - dev9.fifo_bytes_read) / 512;
|
const int was = SPD_DBUF_AVAIL_MAX * 512 - base;
|
||||||
dev9.fifo_bytes_read += writeSectors * 512;
|
write = dev9.ata->WriteDMAFromFIFO(dev9.fifo + base, was);
|
||||||
dev9.ata->nsectorLeft -= writeSectors;
|
if (write == was)
|
||||||
|
write += dev9.ata->WriteDMAFromFIFO(dev9.fifo, unread - was);
|
||||||
}
|
}
|
||||||
//FIFOIntr();
|
else
|
||||||
|
{
|
||||||
|
write = dev9.ata->WriteDMAFromFIFO(dev9.fifo + base, unread);
|
||||||
|
}
|
||||||
|
|
||||||
|
dev9.fifo_bytes_read += write;
|
||||||
}
|
}
|
||||||
void IOPReadFIFO(int bytes)
|
void IOPReadFIFO()
|
||||||
{
|
{
|
||||||
dev9.fifo_bytes_read += bytes;
|
pxAssert((dev9.dma_iop_ptr != nullptr) && (dev9.xfr_ctrl & SPD_XFR_DMAEN));
|
||||||
|
pxAssert((dev9.xfr_ctrl & SPD_XFR_WRITE) == 0);
|
||||||
|
|
||||||
|
const int unread = (dev9.fifo_bytes_write - dev9.fifo_bytes_read);
|
||||||
|
const int base = dev9.fifo_bytes_read % (SPD_DBUF_AVAIL_MAX * 512);
|
||||||
|
|
||||||
|
const int remain = dev9.dma_iop_size - dev9.dma_iop_transfered;
|
||||||
|
const int read = std::min(remain, unread);
|
||||||
|
|
||||||
|
pxAssert(unread <= SPD_DBUF_AVAIL_MAX * 512);
|
||||||
|
|
||||||
|
if (read == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (base + read > SPD_DBUF_AVAIL_MAX * 512)
|
||||||
|
{
|
||||||
|
const int was = SPD_DBUF_AVAIL_MAX * 512 - base;
|
||||||
|
|
||||||
|
std::memcpy(dev9.dma_iop_ptr + dev9.dma_iop_transfered, dev9.fifo + base, was);
|
||||||
|
std::memcpy(dev9.dma_iop_ptr + dev9.dma_iop_transfered + was, dev9.fifo, read - was);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::memcpy(dev9.dma_iop_ptr + dev9.dma_iop_transfered, dev9.fifo + base, read);
|
||||||
|
}
|
||||||
|
|
||||||
|
dev9.dma_iop_transfered += read;
|
||||||
|
dev9.fifo_bytes_read += read;
|
||||||
if (dev9.fifo_bytes_read > dev9.fifo_bytes_write)
|
if (dev9.fifo_bytes_read > dev9.fifo_bytes_write)
|
||||||
Console.Error("DEV9: UNDERFLOW BY IOP");
|
Console.Error("DEV9: UNDERFLOW BY IOP");
|
||||||
//FIFOIntr();
|
|
||||||
}
|
}
|
||||||
void IOPWriteFIFO(int bytes)
|
void IOPWriteFIFO()
|
||||||
{
|
{
|
||||||
dev9.fifo_bytes_write += bytes;
|
pxAssert((dev9.dma_iop_ptr != nullptr) && (dev9.xfr_ctrl & SPD_XFR_DMAEN));
|
||||||
if (dev9.fifo_bytes_write - SPD_DBUF_AVAIL_MAX * 512 > dev9.fifo_bytes_read)
|
pxAssert(dev9.xfr_ctrl & SPD_XFR_WRITE);
|
||||||
|
|
||||||
|
const int unread = (dev9.fifo_bytes_write - dev9.fifo_bytes_read);
|
||||||
|
const int space = (SPD_DBUF_AVAIL_MAX * 512 - unread);
|
||||||
|
const int base = dev9.fifo_bytes_write % (SPD_DBUF_AVAIL_MAX * 512);
|
||||||
|
|
||||||
|
const int remain = dev9.dma_iop_size - dev9.dma_iop_transfered;
|
||||||
|
const int write = std::min(remain, space);
|
||||||
|
|
||||||
|
pxAssert(unread <= SPD_DBUF_AVAIL_MAX * 512);
|
||||||
|
|
||||||
|
if (write == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (base + write > SPD_DBUF_AVAIL_MAX * 512)
|
||||||
|
{
|
||||||
|
const int was = SPD_DBUF_AVAIL_MAX * 512 - base;
|
||||||
|
|
||||||
|
std::memcpy(dev9.fifo + base, dev9.dma_iop_ptr + dev9.dma_iop_transfered, was);
|
||||||
|
std::memcpy(dev9.fifo + base, dev9.dma_iop_ptr + dev9.dma_iop_transfered + was, write - was);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::memcpy(dev9.fifo + base, dev9.dma_iop_ptr + dev9.dma_iop_transfered, write);
|
||||||
|
}
|
||||||
|
|
||||||
|
dev9.dma_iop_transfered += write;
|
||||||
|
dev9.fifo_bytes_write += write;
|
||||||
|
if ((dev9.fifo_bytes_write - dev9.fifo_bytes_read) > SPD_DBUF_AVAIL_MAX * 512)
|
||||||
Console.Error("DEV9: OVERFLOW BY IOP");
|
Console.Error("DEV9: OVERFLOW BY IOP");
|
||||||
//FIFOIntr();
|
|
||||||
}
|
}
|
||||||
void FIFOIntr()
|
void FIFOIntr()
|
||||||
{
|
{
|
||||||
|
@ -279,14 +355,83 @@ void FIFOIntr()
|
||||||
|
|
||||||
if (unread == 0)
|
if (unread == 0)
|
||||||
{
|
{
|
||||||
|
dev9.irqcause &= ~SPD_INTR_ATA_FIFO_DATA;
|
||||||
if ((dev9.irqcause & SPD_INTR_ATA_FIFO_EMPTY) == 0)
|
if ((dev9.irqcause & SPD_INTR_ATA_FIFO_EMPTY) == 0)
|
||||||
_DEV9irq(SPD_INTR_ATA_FIFO_EMPTY, 1);
|
_DEV9irq(SPD_INTR_ATA_FIFO_EMPTY, 1);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dev9.irqcause &= ~SPD_INTR_ATA_FIFO_EMPTY;
|
||||||
|
if ((dev9.irqcause & SPD_INTR_ATA_FIFO_DATA) == 0)
|
||||||
|
_DEV9irq(SPD_INTR_ATA_FIFO_DATA, 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (unread == SPD_DBUF_AVAIL_MAX * 512)
|
if (unread == SPD_DBUF_AVAIL_MAX * 512)
|
||||||
{
|
{
|
||||||
//Log_Error("FIFO Full");
|
if ((dev9.irqcause & SPD_INTR_ATA_FIFO_FULL) == 0)
|
||||||
//INTR Full?
|
_DEV9irq(SPD_INTR_ATA_FIFO_FULL, 1);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dev9.irqcause &= ~SPD_INTR_ATA_FIFO_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is DMA finished
|
||||||
|
if ((dev9.dma_iop_ptr != nullptr) &&
|
||||||
|
(dev9.dma_iop_transfered == dev9.dma_iop_size))
|
||||||
|
{
|
||||||
|
dev9.dma_iop_ptr = nullptr;
|
||||||
|
psxDMA8Interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIFO counters operate based on the direction set in SPD_R_XFR_CTRL
|
||||||
|
// Both might have to set to the same direction for (SPEED <-> HDD) to work
|
||||||
|
void DEV9runFIFO()
|
||||||
|
{
|
||||||
|
const bool iopWrite = dev9.xfr_ctrl & SPD_XFR_WRITE; // IOP writes to FIFO
|
||||||
|
const bool hddRead = dev9.if_ctrl & SPD_IF_READ; // HDD writes to FIFO
|
||||||
|
|
||||||
|
const bool iopXfer = (dev9.dma_iop_ptr != nullptr) && (dev9.xfr_ctrl & SPD_XFR_DMAEN);
|
||||||
|
const bool hddXfer = dev9.ata->dmaReady && (dev9.if_ctrl & SPD_IF_ATA_DMAEN);
|
||||||
|
|
||||||
|
// Order operations based on iopWrite to ensure DMA has data/space to work with.
|
||||||
|
if (iopWrite)
|
||||||
|
{
|
||||||
|
// Perform DMA from IOP.
|
||||||
|
if (iopXfer)
|
||||||
|
IOPWriteFIFO();
|
||||||
|
|
||||||
|
// Drain the FIFO
|
||||||
|
if (hddXfer && !hddRead)
|
||||||
|
{
|
||||||
|
HDDReadFIFO();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Ensure FIFO has data.
|
||||||
|
if (hddXfer && hddRead)
|
||||||
|
{
|
||||||
|
HDDWriteFIFO();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iopXfer)
|
||||||
|
{
|
||||||
|
// Perform DMA to IOP.
|
||||||
|
IOPReadFIFO();
|
||||||
|
|
||||||
|
// Refill FIFO after DMA.
|
||||||
|
// Need to recheck dmaReady incase prior
|
||||||
|
// HDDWriteFIFO competed the transfer from HDD
|
||||||
|
if (hddXfer && hddRead && dev9.ata->dmaReady)
|
||||||
|
{
|
||||||
|
HDDWriteFIFO();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FIFOIntr();
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 SpeedRead(u32 addr, int width)
|
u16 SpeedRead(u32 addr, int width)
|
||||||
|
@ -359,18 +504,8 @@ u16 SpeedRead(u32 addr, int width)
|
||||||
return dev9.xfr_ctrl;
|
return dev9.xfr_ctrl;
|
||||||
case SPD_R_DBUF_STAT:
|
case SPD_R_DBUF_STAT:
|
||||||
{
|
{
|
||||||
if (dev9.if_ctrl & SPD_IF_READ) // Semi async
|
|
||||||
{
|
|
||||||
HDDWriteFIFO(); // Yes this is not a typo
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HDDReadFIFO();
|
|
||||||
}
|
|
||||||
FIFOIntr();
|
|
||||||
|
|
||||||
const u8 count = static_cast<u8>((dev9.fifo_bytes_write - dev9.fifo_bytes_read) / 512);
|
const u8 count = static_cast<u8>((dev9.fifo_bytes_write - dev9.fifo_bytes_read) / 512);
|
||||||
if (dev9.xfr_ctrl & SPD_XFR_WRITE) // or ifRead?
|
if (dev9.xfr_ctrl & SPD_XFR_WRITE)
|
||||||
{
|
{
|
||||||
hard = static_cast<u8>(SPD_DBUF_AVAIL_MAX - count);
|
hard = static_cast<u8>(SPD_DBUF_AVAIL_MAX - count);
|
||||||
hard |= (count == 0) ? SPD_DBUF_STAT_1 : static_cast<u16>(0);
|
hard |= (count == 0) ? SPD_DBUF_STAT_1 : static_cast<u16>(0);
|
||||||
|
@ -518,9 +653,14 @@ void SpeedWrite(u32 addr, u16 value, int width)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case SPD_R_XFR_CTRL:
|
case SPD_R_XFR_CTRL:
|
||||||
|
{
|
||||||
//DevCon.WriteLn("DEV9: SPD_R_XFR_CTRL %dbit write %x", width, value);
|
//DevCon.WriteLn("DEV9: SPD_R_XFR_CTRL %dbit write %x", width, value);
|
||||||
|
const u16 oldValue = dev9.xfr_ctrl;
|
||||||
dev9.xfr_ctrl = value;
|
dev9.xfr_ctrl = value;
|
||||||
|
|
||||||
|
if ((value & SPD_XFR_WRITE) != (oldValue & SPD_XFR_WRITE))
|
||||||
|
DEV9runFIFO();
|
||||||
|
|
||||||
//if (value & SPD_XFR_WRITE)
|
//if (value & SPD_XFR_WRITE)
|
||||||
// DevCon.WriteLn("DEV9: SPD_R_XFR_CTRL Set Write");
|
// DevCon.WriteLn("DEV9: SPD_R_XFR_CTRL Set Write");
|
||||||
//else
|
//else
|
||||||
|
@ -532,8 +672,11 @@ void SpeedWrite(u32 addr, u16 value, int width)
|
||||||
//if ((value & (1 << 2)) != 0)
|
//if ((value & (1 << 2)) != 0)
|
||||||
// DevCon.WriteLn("DEV9: SPD_R_XFR_CTRL Unknown Bit 2");
|
// DevCon.WriteLn("DEV9: SPD_R_XFR_CTRL Unknown Bit 2");
|
||||||
|
|
||||||
//if (value & SPD_XFR_DMAEN)
|
if (value & SPD_XFR_DMAEN)
|
||||||
// DevCon.WriteLn("DEV9: SPD_R_XFR_CTRL For DMA Enabled");
|
{
|
||||||
|
//DevCon.WriteLn("DEV9: SPD_R_XFR_CTRL For DMA Enabled");
|
||||||
|
DEV9runFIFO();
|
||||||
|
}
|
||||||
//else
|
//else
|
||||||
// DevCon.WriteLn("DEV9: SPD_R_XFR_CTRL For DMA Disabled");
|
// DevCon.WriteLn("DEV9: SPD_R_XFR_CTRL For DMA Disabled");
|
||||||
|
|
||||||
|
@ -541,6 +684,7 @@ void SpeedWrite(u32 addr, u16 value, int width)
|
||||||
Console.Error("DEV9: SPD_R_XFR_CTRL Unknown value written %x", value);
|
Console.Error("DEV9: SPD_R_XFR_CTRL Unknown value written %x", value);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SPD_R_DBUF_STAT:
|
case SPD_R_DBUF_STAT:
|
||||||
//DevCon.WriteLn("DEV9: SPD_R_DBUF_STAT %dbit write %x", width, value);
|
//DevCon.WriteLn("DEV9: SPD_R_DBUF_STAT %dbit write %x", width, value);
|
||||||
|
|
||||||
|
@ -560,13 +704,19 @@ void SpeedWrite(u32 addr, u16 value, int width)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPD_R_IF_CTRL:
|
case SPD_R_IF_CTRL:
|
||||||
|
{
|
||||||
//DevCon.WriteLn("DEV9: SPD_R_IF_CTRL %dbit write %x", width, value);
|
//DevCon.WriteLn("DEV9: SPD_R_IF_CTRL %dbit write %x", width, value);
|
||||||
|
const u16 oldValue = dev9.if_ctrl;
|
||||||
dev9.if_ctrl = value;
|
dev9.if_ctrl = value;
|
||||||
|
|
||||||
//if (value & SPD_IF_UDMA)
|
//if (value & SPD_IF_UDMA)
|
||||||
// DevCon.WriteLn("DEV9: IF_CTRL UDMA Enabled");
|
// DevCon.WriteLn("DEV9: IF_CTRL UDMA Enabled");
|
||||||
//else
|
//else
|
||||||
// DevCon.WriteLn("DEV9: IF_CTRL UDMA Disabled");
|
// DevCon.WriteLn("DEV9: IF_CTRL UDMA Disabled");
|
||||||
|
|
||||||
|
if ((value & SPD_IF_READ) != (oldValue & SPD_IF_READ))
|
||||||
|
DEV9runFIFO();
|
||||||
|
|
||||||
//if (value & SPD_IF_READ)
|
//if (value & SPD_IF_READ)
|
||||||
// DevCon.WriteLn("DEV9: IF_CTRL DMA Is ATA Read");
|
// DevCon.WriteLn("DEV9: IF_CTRL DMA Is ATA Read");
|
||||||
//else
|
//else
|
||||||
|
@ -575,15 +725,7 @@ void SpeedWrite(u32 addr, u16 value, int width)
|
||||||
if (value & SPD_IF_ATA_DMAEN)
|
if (value & SPD_IF_ATA_DMAEN)
|
||||||
{
|
{
|
||||||
//DevCon.WriteLn("DEV9: IF_CTRL ATA DMA Enabled");
|
//DevCon.WriteLn("DEV9: IF_CTRL ATA DMA Enabled");
|
||||||
if (value & SPD_IF_READ) //Semi async
|
DEV9runFIFO();
|
||||||
{
|
|
||||||
HDDWriteFIFO(); //Yes this is not a typo
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HDDReadFIFO();
|
|
||||||
}
|
|
||||||
FIFOIntr();
|
|
||||||
}
|
}
|
||||||
//else
|
//else
|
||||||
// DevCon.WriteLn("DEV9: IF_CTRL ATA DMA Disabled");
|
// DevCon.WriteLn("DEV9: IF_CTRL ATA DMA Disabled");
|
||||||
|
@ -617,6 +759,7 @@ void SpeedWrite(u32 addr, u16 value, int width)
|
||||||
Console.Error("DEV9: IF_CTRL Unknown Bit(s) %x", (value & 0xFF00));
|
Console.Error("DEV9: IF_CTRL Unknown Bit(s) %x", (value & 0xFF00));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SPD_R_PIO_MODE: //ATA only? or includes EEPROM?
|
case SPD_R_PIO_MODE: //ATA only? or includes EEPROM?
|
||||||
//DevCon.WriteLn("DEV9: SPD_R_PIO_MODE 16bit %dbit write %x", width, value);
|
//DevCon.WriteLn("DEV9: SPD_R_PIO_MODE 16bit %dbit write %x", width, value);
|
||||||
dev9.pio_mode = value;
|
dev9.pio_mode = value;
|
||||||
|
@ -924,14 +1067,14 @@ void DEV9readDMA8Mem(u32* pMem, int size)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (dev9.xfr_ctrl & SPD_XFR_DMAEN &&
|
if (!(dev9.xfr_ctrl & SPD_XFR_WRITE))
|
||||||
!(dev9.xfr_ctrl & SPD_XFR_WRITE))
|
|
||||||
{
|
{
|
||||||
HDDWriteFIFO();
|
pxAssert(size <= SPD_DBUF_AVAIL_MAX * 512);
|
||||||
IOPReadFIFO(size);
|
dev9.dma_iop_ptr = reinterpret_cast<u8*>(pMem);
|
||||||
dev9.ata->ATAreadDMA8Mem((u8*)pMem, size);
|
dev9.dma_iop_size = size;
|
||||||
FIFOIntr();
|
dev9.dma_iop_transfered = 0;
|
||||||
psxDMA8Interrupt();
|
|
||||||
|
DEV9runFIFO();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -954,18 +1097,16 @@ void DEV9writeDMA8Mem(u32* pMem, int size)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (dev9.xfr_ctrl & SPD_XFR_DMAEN &&
|
if (dev9.xfr_ctrl & SPD_XFR_WRITE)
|
||||||
dev9.xfr_ctrl & SPD_XFR_WRITE)
|
|
||||||
{
|
{
|
||||||
IOPWriteFIFO(size);
|
pxAssert(size <= SPD_DBUF_AVAIL_MAX * 512);
|
||||||
HDDReadFIFO();
|
dev9.dma_iop_ptr = reinterpret_cast<u8*>(pMem);
|
||||||
dev9.ata->ATAwriteDMA8Mem((u8*)pMem, size);
|
dev9.dma_iop_size = size;
|
||||||
FIFOIntr();
|
dev9.dma_iop_transfered = 0;
|
||||||
psxDMA8Interrupt();
|
|
||||||
|
DEV9runFIFO();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO, track if write was successful
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DEV9async(u32 cycles)
|
void DEV9async(u32 cycles)
|
||||||
|
|
|
@ -69,9 +69,15 @@ typedef struct
|
||||||
u16 mdma_mode;
|
u16 mdma_mode;
|
||||||
u16 udma_mode;
|
u16 udma_mode;
|
||||||
|
|
||||||
//Non-Regs
|
// FIFO
|
||||||
int fifo_bytes_read;
|
int fifo_bytes_read;
|
||||||
int fifo_bytes_write;
|
int fifo_bytes_write;
|
||||||
|
u8 fifo[16 * 512];
|
||||||
|
|
||||||
|
// DMA
|
||||||
|
u8* dma_iop_ptr;
|
||||||
|
int dma_iop_transfered;
|
||||||
|
int dma_iop_size;
|
||||||
} dev9Struct;
|
} dev9Struct;
|
||||||
|
|
||||||
//EEPROM states
|
//EEPROM states
|
||||||
|
@ -672,6 +678,7 @@ void FLASHwrite32(u32 addr, u32 value, int size);
|
||||||
void _DEV9irq(int cause, int cycles);
|
void _DEV9irq(int cause, int cycles);
|
||||||
int DEV9irqHandler(void);
|
int DEV9irqHandler(void);
|
||||||
void DEV9async(u32 cycles);
|
void DEV9async(u32 cycles);
|
||||||
|
void DEV9runFIFO();
|
||||||
void DEV9writeDMA8Mem(u32* pMem, int size);
|
void DEV9writeDMA8Mem(u32* pMem, int size);
|
||||||
void DEV9readDMA8Mem(u32* pMem, int size);
|
void DEV9readDMA8Mem(u32* pMem, int size);
|
||||||
u8 DEV9read8(u32 addr);
|
u8 DEV9read8(u32 addr);
|
||||||
|
|
Loading…
Reference in New Issue