mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-05-07 18:36:09 +08:00
DMA: Help other emulation code by offering a way to determine what triggered DMA_MASKED and DMA_UNMASKED events. It is not always the DOS guest that does it, internal functions of the DMA controller can cause it too
This commit is contained in:
parent
62e1c4fa38
commit
b718ad45a8
@ -34,6 +34,15 @@ enum DMATransfer {
|
||||
DMAT_READ=2
|
||||
};
|
||||
|
||||
enum DMAActor { /* i.e. who masked/unmasked the register */
|
||||
DMAA_NONE=0,
|
||||
DMAA_CONTROLLER=1,
|
||||
DMAA_GUEST=2,
|
||||
DMAA_REISSUE=3
|
||||
};
|
||||
|
||||
const char *DMAActorStr(const DMAActor a);
|
||||
|
||||
class DmaChannel;
|
||||
typedef void (* DMA_CallBack)(DmaChannel * chan,DMAEvent event);
|
||||
|
||||
@ -46,10 +55,11 @@ public:
|
||||
uint16_t currcnt;
|
||||
uint8_t channum;
|
||||
uint8_t pagenum;
|
||||
uint8_t DMA16_PAGESHIFT;
|
||||
uint32_t DMA16_ADDRMASK;
|
||||
uint8_t DMA16_PAGESHIFT;
|
||||
uint32_t DMA16_ADDRMASK;
|
||||
uint8_t DMA16;
|
||||
uint8_t transfer_mode;
|
||||
uint8_t transfer_mode;
|
||||
DMAActor masked_by;
|
||||
bool increment;
|
||||
bool autoinit;
|
||||
bool masked;
|
||||
@ -99,18 +109,19 @@ public:
|
||||
masked=_mask;
|
||||
DoCallBack(masked ? DMA_MASKED : DMA_UNMASKED);
|
||||
}
|
||||
void Set128KMode(bool en) {
|
||||
// 128KB mode (legacy ISA) (en=true):
|
||||
// page shift = 1 (discard bit 0 of page register)
|
||||
// addr mask = 0x1FFFF (all bits 0-15 become bits 1-16, bit 15 of addr takes the place of page register bit 0)
|
||||
// 64KB mode (modern PCI including Intel chipsets) (en=false):
|
||||
// page shift = 0 (all 8 bits of page register are used)
|
||||
// addr mask = 0xFFFF (discard bit 15, bits 0-14 become bits 1-15 on ISA bus)
|
||||
DMA16_PAGESHIFT = (en && DMA16) ? 0x1 : 0x0; // nonzero if we're to discard bit 0 of page register
|
||||
DMA16_ADDRMASK = (1UL << ((en && DMA16) ? 17UL : 16UL)) - 1UL; // nonzero if (addrreg << 1) to cover 128KB, zero if (addrreg << 1) to discard MSB, limit to 64KB
|
||||
}
|
||||
void Set128KMode(bool en) {
|
||||
// 128KB mode (legacy ISA) (en=true):
|
||||
// page shift = 1 (discard bit 0 of page register)
|
||||
// addr mask = 0x1FFFF (all bits 0-15 become bits 1-16, bit 15 of addr takes the place of page register bit 0)
|
||||
// 64KB mode (modern PCI including Intel chipsets) (en=false):
|
||||
// page shift = 0 (all 8 bits of page register are used)
|
||||
// addr mask = 0xFFFF (discard bit 15, bits 0-14 become bits 1-15 on ISA bus)
|
||||
DMA16_PAGESHIFT = (en && DMA16) ? 0x1 : 0x0; // nonzero if we're to discard bit 0 of page register
|
||||
DMA16_ADDRMASK = (1UL << ((en && DMA16) ? 17UL : 16UL)) - 1UL; // nonzero if (addrreg << 1) to cover 128KB, zero if (addrreg << 1) to discard MSB, limit to 64KB
|
||||
}
|
||||
void Register_Callback(DMA_CallBack _cb) {
|
||||
callback = _cb;
|
||||
masked_by = DMAA_REISSUE;
|
||||
SetMask(masked);
|
||||
if (callback) Raise_Request();
|
||||
else Clear_Request();
|
||||
|
@ -36,6 +36,18 @@
|
||||
# define MAX(a,b) std::max(a,b)
|
||||
#endif
|
||||
|
||||
const char *DMAActorStr(const DMAActor a) {
|
||||
switch (a) {
|
||||
case DMAA_NONE: return "none";
|
||||
case DMAA_CONTROLLER: return "DMA controller";
|
||||
case DMAA_GUEST: return "DOS guest";
|
||||
case DMAA_REISSUE: return "Reissue";
|
||||
default: break;
|
||||
}
|
||||
|
||||
return "?";
|
||||
}
|
||||
|
||||
bool has_pcibus_enable(void);
|
||||
|
||||
DmaController *DmaControllers[2]={NULL};
|
||||
@ -307,6 +319,7 @@ void DmaController::WriteControllerReg(Bitu reg,Bitu val,Bitu /*len*/) {
|
||||
case 0xa: /* Mask Register */
|
||||
if ((val & 0x4)==0) UpdateEMSMapping();
|
||||
chan=GetChannel(val & 3);
|
||||
chan->masked_by = DMAA_GUEST;
|
||||
chan->SetMask((val & 0x4)>0);
|
||||
break;
|
||||
case 0xb: /* Mode Register */
|
||||
@ -323,6 +336,7 @@ void DmaController::WriteControllerReg(Bitu reg,Bitu val,Bitu /*len*/) {
|
||||
case 0xd: /* Master Clear/Reset */
|
||||
for (uint8_t ct=0;ct<4;ct++) {
|
||||
chan=GetChannel(ct);
|
||||
chan->masked_by = DMAA_GUEST;
|
||||
chan->SetMask(true);
|
||||
chan->tcount=false;
|
||||
}
|
||||
@ -332,6 +346,7 @@ void DmaController::WriteControllerReg(Bitu reg,Bitu val,Bitu /*len*/) {
|
||||
UpdateEMSMapping();
|
||||
for (uint8_t ct=0;ct<4;ct++) {
|
||||
chan=GetChannel(ct);
|
||||
chan->masked_by = DMAA_GUEST;
|
||||
chan->SetMask(false);
|
||||
}
|
||||
break;
|
||||
@ -339,6 +354,7 @@ void DmaController::WriteControllerReg(Bitu reg,Bitu val,Bitu /*len*/) {
|
||||
UpdateEMSMapping();
|
||||
for (uint8_t ct=0;ct<4;ct++) {
|
||||
chan=GetChannel(ct);
|
||||
chan->masked_by = DMAA_GUEST;
|
||||
chan->SetMask(val & 1);
|
||||
val>>=1;
|
||||
}
|
||||
@ -391,19 +407,20 @@ Bitu DmaController::ReadControllerReg(Bitu reg,Bitu /*len*/) {
|
||||
|
||||
DmaChannel::DmaChannel(uint8_t num, bool dma16) {
|
||||
masked = true;
|
||||
masked_by = DMAA_CONTROLLER;
|
||||
callback = NULL;
|
||||
channum = num;
|
||||
DMA16 = dma16 ? 0x1 : 0x0;
|
||||
transfer_mode = 0;
|
||||
transfer_mode = 0;
|
||||
|
||||
if (isadma128k >= 0)
|
||||
Set128KMode(isadma128k > 0); // user's choice
|
||||
else
|
||||
Set128KMode(true); // most hardware seems to implement the 128K case
|
||||
if (isadma128k >= 0)
|
||||
Set128KMode(isadma128k > 0); // user's choice
|
||||
else
|
||||
Set128KMode(true); // most hardware seems to implement the 128K case
|
||||
|
||||
LOG(LOG_DMACONTROL,LOG_DEBUG)("DMA channel %u. DMA16_PAGESHIFT=%u DMA16_ADDRMASK=0x%lx",
|
||||
(unsigned int)channum,(unsigned int)DMA16_PAGESHIFT,(unsigned long)DMA16_ADDRMASK);
|
||||
pagenum = 0;
|
||||
LOG(LOG_DMACONTROL,LOG_DEBUG)("DMA channel %u. DMA16_PAGESHIFT=%u DMA16_ADDRMASK=0x%lx",
|
||||
(unsigned int)channum,(unsigned int)DMA16_PAGESHIFT,(unsigned long)DMA16_ADDRMASK);
|
||||
pagenum = 0;
|
||||
pagebase = 0;
|
||||
baseaddr = 0;
|
||||
curraddr = 0;
|
||||
@ -520,6 +537,7 @@ Bitu DmaChannel::Read(Bitu want, uint8_t * buffer) {
|
||||
* [http://hackipedia.org/browse.cgi/Computer/Platform/PC%2c%20IBM%20compatible/DMA%20controller/8237/8237A%20HIGH%20PERFORMANCE%20PROGRAMMABLE%20DMA%20CONTROLLER%20%288237A%2d5%29%20%281993%2d09%29%2epdf]
|
||||
*/
|
||||
masked = true;
|
||||
masked_by = DMAA_CONTROLLER;
|
||||
UpdateEMSMapping();
|
||||
DoCallBack(DMA_MASKED);
|
||||
break;
|
||||
@ -631,6 +649,7 @@ Bitu DmaChannel::Write(Bitu want, uint8_t * buffer) {
|
||||
* [http://hackipedia.org/browse.cgi/Computer/Platform/PC%2c%20IBM%20compatible/DMA%20controller/8237/8237A%20HIGH%20PERFORMANCE%20PROGRAMMABLE%20DMA%20CONTROLLER%20%288237A%2d5%29%20%281993%2d09%29%2epdf]
|
||||
*/
|
||||
masked = true;
|
||||
masked_by = DMAA_CONTROLLER;
|
||||
UpdateEMSMapping();
|
||||
DoCallBack(DMA_MASKED);
|
||||
break;
|
||||
|
@ -507,13 +507,13 @@ static void DSP_DMA_CallBack(DmaChannel * chan, DMAEvent event) {
|
||||
if (s) GenerateDMASound(s);
|
||||
}
|
||||
sb.mode = MODE_DMA_MASKED;
|
||||
LOG(LOG_SB,LOG_NORMAL)("DMA masked, stopping %s, left %d",sb.dma.recording?"input":"output",chan->currcnt);
|
||||
LOG(LOG_SB,LOG_NORMAL)("DMA masked, stopping %s, dsp left %d, dma left %d, by %s",sb.dma.recording?"input":"output",(unsigned int)sb.dma.left,chan->currcnt+1,DMAActorStr(chan->masked_by));
|
||||
}
|
||||
} else if (event==DMA_UNMASKED) {
|
||||
if (sb.mode==MODE_DMA_MASKED && sb.dma.mode!=DSP_DMA_NONE) {
|
||||
DSP_ChangeMode(MODE_DMA);
|
||||
CheckDMAEnd();
|
||||
LOG(LOG_SB,LOG_NORMAL)("DMA unmasked, starting %s, auto %d block %d",sb.dma.recording?"input":"output",chan->autoinit,chan->basecnt);
|
||||
LOG(LOG_SB,LOG_NORMAL)("DMA unmasked, starting %s, auto %d block %d, by %s",sb.dma.recording?"input":"output",chan->autoinit,chan->basecnt,DMAActorStr(chan->masked_by));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user