DMA: HDMA init/run must interrupt/cancel regular DMA

This commit is contained in:
Sour 2019-03-09 12:01:36 -05:00
parent f0ce0f63af
commit 2cecde26fb
2 changed files with 20 additions and 2 deletions

View file

@ -30,17 +30,21 @@ void DmaController::RunSingleTransfer(DmaChannelConfig &channel)
channel.TransferSize--; channel.TransferSize--;
transferByteCount--; transferByteCount--;
i++; i++;
} while(channel.TransferSize > 0 && transferByteCount > 0); } while(channel.TransferSize > 0 && transferByteCount > 0 && !channel.InterruptedByHdma);
} }
void DmaController::RunDma(DmaChannelConfig &channel) void DmaController::RunDma(DmaChannelConfig &channel)
{ {
if(channel.InterruptedByHdma) {
return;
}
do { do {
//Manual DMA transfers run to the end of the transfer when started //Manual DMA transfers run to the end of the transfer when started
RunSingleTransfer(channel); RunSingleTransfer(channel);
//TODO : Run HDMA when needed, between 2 DMA transfers //TODO : Run HDMA when needed, between 2 DMA transfers
} while(channel.TransferSize > 0); } while(channel.TransferSize > 0 && !channel.InterruptedByHdma);
} }
void DmaController::InitHdmaChannels() void DmaController::InitHdmaChannels()
@ -57,6 +61,7 @@ void DmaController::InitHdmaChannels()
if(_hdmaChannels & (1 << i)) { if(_hdmaChannels & (1 << i)) {
//"1. Copy AAddress into Address." //"1. Copy AAddress into Address."
ch.HdmaTableAddress = ch.SrcAddress; ch.HdmaTableAddress = ch.SrcAddress;
ch.InterruptedByHdma = true;
//"2. Load $43xA (Line Counter and Repeat) from the table. I believe $00 will terminate this channel immediately." //"2. Load $43xA (Line Counter and Repeat) from the table. I believe $00 will terminate this channel immediately."
ch.HdmaLineCounterAndRepeat = _memoryManager->ReadDma((ch.SrcBank << 16) | ch.HdmaTableAddress); ch.HdmaLineCounterAndRepeat = _memoryManager->ReadDma((ch.SrcBank << 16) | ch.HdmaTableAddress);
@ -89,6 +94,8 @@ void DmaController::RunHdmaTransfer(DmaChannelConfig &channel)
const uint8_t *transferOffsets = _transferOffset[channel.TransferMode]; const uint8_t *transferOffsets = _transferOffset[channel.TransferMode];
uint8_t transferByteCount = _transferByteCount[channel.TransferMode]; uint8_t transferByteCount = _transferByteCount[channel.TransferMode];
channel.InterruptedByHdma = true;
uint32_t srcAddress; uint32_t srcAddress;
if(channel.HdmaIndirectAddressing) { if(channel.HdmaIndirectAddressing) {
srcAddress = (channel.HdmaBank << 16) | channel.TransferSize; srcAddress = (channel.HdmaBank << 16) | channel.TransferSize;
@ -125,6 +132,12 @@ void DmaController::ProcessHdmaChannels()
if(_hdmaChannels) { if(_hdmaChannels) {
_hdmaPending = true; _hdmaPending = true;
for(int i = 0; i < 8; i++) {
if(_hdmaChannels & (1 << i)) {
_channel[i].InterruptedByHdma = true;
}
}
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
DmaChannelConfig &ch = _channel[i]; DmaChannelConfig &ch = _channel[i];
if((_hdmaChannels & (1 << i)) == 0 || ch.HdmaFinished) { if((_hdmaChannels & (1 << i)) == 0 || ch.HdmaFinished) {
@ -198,6 +211,10 @@ void DmaController::Write(uint16_t addr, uint8_t value)
//"and an extra 8 master cycles overhead for the whole thing" //"and an extra 8 master cycles overhead for the whole thing"
_memoryManager->IncrementMasterClockValue<8>(); _memoryManager->IncrementMasterClockValue<8>();
for(int i = 0; i < 8; i++) {
_channel[i].InterruptedByHdma = false;
}
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
if(value & (1 << i)) { if(value & (1 << i)) {
//"Then perform the DMA: 8 master cycles overhead and 8 master cycles per byte per channel" //"Then perform the DMA: 8 master cycles overhead and 8 master cycles per byte per channel"

View file

@ -24,6 +24,7 @@ struct DmaChannelConfig
bool DoTransfer; bool DoTransfer;
bool HdmaFinished; bool HdmaFinished;
bool InterruptedByHdma;
bool UnusedFlag; bool UnusedFlag;
}; };