Some updates to DMA to allow better handling of masked bit and reaching terminal count.
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1208
This commit is contained in:
parent
9c53a50c70
commit
942bef0e09
1 changed files with 50 additions and 29 deletions
|
@ -32,12 +32,6 @@
|
|||
#include "dma.h"
|
||||
#include "pic.h"
|
||||
|
||||
#if DEBUG_DMA
|
||||
#define DMA_DEBUG LOG_DEBUG
|
||||
#else
|
||||
#define DMA_DEBUG
|
||||
#endif
|
||||
|
||||
#define DMA_MODE_DEMAND 0
|
||||
#define DMA_MODE_SINGLE 1
|
||||
#define DMA_MODE_BLOCK 2
|
||||
|
@ -71,7 +65,9 @@ struct DMA_CONTROLLER {
|
|||
};
|
||||
|
||||
static DMA_CONTROLLER dma[2];
|
||||
void DMA_TestChannel(DMA_CHANNEL * chan);
|
||||
|
||||
void DMA_CheckEnabled(DMA_CHANNEL * chan);
|
||||
void DMA_SetEnabled(DMA_CHANNEL * chan,bool enabled);
|
||||
|
||||
static Bit8u read_dma(Bit32u port) {
|
||||
/* only use first dma for now */
|
||||
|
@ -107,10 +103,10 @@ static Bit8u read_dma(Bit32u port) {
|
|||
default:
|
||||
LOG(LOG_DMA,LOG_ERROR)("DMA:Unhandled read from %X",port);
|
||||
}
|
||||
// LOG_MSG("DMA Read port %x result %x",port,ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void write_dma(Bit32u port,Bit8u val) {
|
||||
/* only use first dma for now */
|
||||
DMA_CONTROLLER * cont=&dma[0];
|
||||
|
@ -123,7 +119,6 @@ static void write_dma(Bit32u port,Bit8u val) {
|
|||
} else {
|
||||
chan->base_address=(chan->base_address & 0x00ff) | (val<<8);
|
||||
}
|
||||
// LOG_MSG("DMA:Address %X",chan->base_address);
|
||||
cont->flipflop=!cont->flipflop;
|
||||
chan->addr_changed=true;
|
||||
break;
|
||||
|
@ -134,10 +129,9 @@ static void write_dma(Bit32u port,Bit8u val) {
|
|||
} else {
|
||||
chan->base_count=(chan->base_count & 0x00ff) | (val<<8);
|
||||
}
|
||||
// LOG_MSG("DMA:count %X",chan->base_count);
|
||||
cont->flipflop=!cont->flipflop;
|
||||
chan->addr_changed=true;
|
||||
DMA_TestChannel(chan);
|
||||
DMA_CheckEnabled(chan);
|
||||
break;
|
||||
case 0x08: /* Command Register */
|
||||
if (val != 4) LOG(LOG_DMA,LOG_ERROR)("DMA1:Illegal command %2X",val);
|
||||
|
@ -155,8 +149,13 @@ static void write_dma(Bit32u port,Bit8u val) {
|
|||
break;
|
||||
case 0x0a: /* single mask bit register */
|
||||
chan=&cont->chan[val & 0x3];
|
||||
chan->masked=(val & 4)>0;
|
||||
DMA_TestChannel(chan);
|
||||
if ((val & 4)>0) {
|
||||
DMA_SetEnabled(chan,false);
|
||||
chan->masked=(val & 4)>0; //Set it later
|
||||
} else {
|
||||
chan->masked=(val & 4)>0;
|
||||
DMA_CheckEnabled(chan);
|
||||
}
|
||||
break;
|
||||
case 0x0b: /* mode register */
|
||||
chan=&cont->chan[val & 0x3];
|
||||
|
@ -167,7 +166,7 @@ static void write_dma(Bit32u port,Bit8u val) {
|
|||
if (chan->mode.address_decrement) {
|
||||
LOG(LOG_DMA,LOG_ERROR)("DMA:Address Decrease not supported yet");
|
||||
}
|
||||
DMA_TestChannel(chan);
|
||||
DMA_CheckEnabled(chan);
|
||||
break;
|
||||
case 0x0c: /* Clear Flip/Flip */
|
||||
cont->flipflop=true;
|
||||
|
@ -177,7 +176,6 @@ static void write_dma(Bit32u port,Bit8u val) {
|
|||
};
|
||||
};
|
||||
|
||||
|
||||
void write_dma_page(Bit32u port,Bit8u val) {
|
||||
Bitu channel;
|
||||
switch (port) {
|
||||
|
@ -194,20 +192,33 @@ void write_dma_page(Bit32u port,Bit8u val) {
|
|||
dma[0].chan[channel].addr_changed=true;
|
||||
}
|
||||
|
||||
Bit8u read_dma_page(Bit32u port) {
|
||||
Bitu channel;
|
||||
switch (port) {
|
||||
case 0x81: /* dma0 page register, channel 2 */
|
||||
channel=2;break;
|
||||
case 0x82: /* dma0 page register, channel 3 */
|
||||
channel=3;break;
|
||||
case 0x83: /* dma0 page register, channel 1 */
|
||||
channel=1;break;
|
||||
case 0x87: /* dma0 page register, channel 0 */
|
||||
channel=0;break;
|
||||
}
|
||||
return dma[0].chan[channel].page;
|
||||
}
|
||||
|
||||
INLINE void ResetDMA8(DMA_CHANNEL * chan) {
|
||||
chan->addr_changed=false;
|
||||
chan->address=(chan->page << 16)+chan->base_address;
|
||||
chan->current_count=chan->base_count+1;
|
||||
chan->current_address=chan->base_address;
|
||||
// LOG_MSG("DMA8:Setup at address %X:%X count %X",chan->page<<12,chan->base_address,chan->current_count);
|
||||
LOG(LOG_DMA,LOG_NORMAL)("Setup at address %X:%X count %X",chan->page<<12,chan->base_address,chan->current_count);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Bitu DMA_8_Read(Bitu dmachan,Bit8u * buffer,Bitu count) {
|
||||
DMA_CHANNEL * chan=&dma[0].chan[dmachan];
|
||||
if (chan->masked || !count) return 0;
|
||||
if (chan->masked) return 0;
|
||||
if (!count) return 0;
|
||||
if (chan->addr_changed) ResetDMA8(chan);
|
||||
if (chan->current_count>count) {
|
||||
MEM_BlockRead(chan->address,buffer,count);
|
||||
|
@ -222,10 +233,10 @@ Bitu DMA_8_Read(Bitu dmachan,Bit8u * buffer,Bitu count) {
|
|||
/* Set the end of counter bit */
|
||||
dma[0].status_reg|=(1 << dmachan);
|
||||
count=chan->current_count;
|
||||
chan->current_address+=count;;
|
||||
chan->address+=count;
|
||||
chan->current_count=0;
|
||||
if (chan->enable_callback) chan->enable_callback(false);
|
||||
chan->enabled=false;
|
||||
LOG(LOG_DMA,LOG_NORMAL)("8-bit Channel %d reached terminal count");
|
||||
return count;
|
||||
} else {
|
||||
buffer+=chan->current_count;
|
||||
|
@ -244,7 +255,8 @@ Bitu DMA_8_Read(Bitu dmachan,Bit8u * buffer,Bitu count) {
|
|||
|
||||
Bitu DMA_8_Write(Bitu dmachan,Bit8u * buffer,Bitu count) {
|
||||
DMA_CHANNEL * chan=&dma[0].chan[dmachan];
|
||||
if (chan->masked || !count) return 0;
|
||||
if (chan->masked) return 0;
|
||||
if (!count) return 0;
|
||||
if (chan->addr_changed) ResetDMA8(chan);
|
||||
if (chan->current_count>count) {
|
||||
MEM_BlockWrite(chan->address,buffer,count);
|
||||
|
@ -261,6 +273,7 @@ Bitu DMA_8_Write(Bitu dmachan,Bit8u * buffer,Bitu count) {
|
|||
count=chan->current_count;
|
||||
chan->current_address+=count;;
|
||||
chan->current_count=0;
|
||||
chan->enabled=false;
|
||||
return count;
|
||||
} else {
|
||||
buffer+=chan->current_count;
|
||||
|
@ -289,8 +302,13 @@ Bitu DMA_16_Write(Bitu dmachan,Bit8u * buffer,Bitu count) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void DMA_TestChannel(DMA_CHANNEL * chan) {
|
||||
if (!chan->enable_callback) return;
|
||||
void DMA_SetEnabled(DMA_CHANNEL * chan,bool enabled) {
|
||||
if (chan->enabled == enabled) return;
|
||||
chan->enabled=enabled;
|
||||
if (chan->enable_callback) (*chan->enable_callback)(enabled);
|
||||
}
|
||||
|
||||
void DMA_CheckEnabled(DMA_CHANNEL * chan) {
|
||||
bool enabled;
|
||||
if (chan->masked) enabled=false;
|
||||
else {
|
||||
|
@ -298,10 +316,7 @@ void DMA_TestChannel(DMA_CHANNEL * chan) {
|
|||
else if (chan->current_count || chan->addr_changed) enabled=true;
|
||||
else enabled=false;
|
||||
}
|
||||
if (enabled == chan->enabled) return;
|
||||
chan->enabled=enabled;
|
||||
chan->enable_callback(enabled);
|
||||
|
||||
DMA_SetEnabled(chan,enabled);
|
||||
}
|
||||
|
||||
|
||||
|
@ -314,7 +329,7 @@ void DMA_SetEnableCallBack(Bitu channel,DMA_EnableCallBack callback) {
|
|||
} else return;
|
||||
chan->enabled=false;
|
||||
chan->enable_callback=callback;
|
||||
DMA_TestChannel(chan);
|
||||
DMA_CheckEnabled(chan);
|
||||
}
|
||||
|
||||
void DMA_Init(Section* sec) {
|
||||
|
@ -327,4 +342,10 @@ void DMA_Init(Section* sec) {
|
|||
IO_RegisterWriteHandler(0x82,write_dma_page,"DMA Pages");
|
||||
IO_RegisterWriteHandler(0x83,write_dma_page,"DMA Pages");
|
||||
IO_RegisterWriteHandler(0x87,write_dma_page,"DMA Pages");
|
||||
|
||||
IO_RegisterReadHandler(0x81,read_dma_page,"DMA Pages");
|
||||
IO_RegisterReadHandler(0x82,read_dma_page,"DMA Pages");
|
||||
IO_RegisterReadHandler(0x83,read_dma_page,"DMA Pages");
|
||||
IO_RegisterReadHandler(0x87,read_dma_page,"DMA Pages");
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue