1
0
Fork 0

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:
Sjoerd van der Berg 2003-08-29 08:38:59 +00:00
parent 9c53a50c70
commit 942bef0e09

View file

@ -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");
}