diff --git a/include/dma.h b/include/dma.h index 58f78c69..02819e0c 100644 --- a/include/dma.h +++ b/include/dma.h @@ -16,14 +16,347 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef __DMA_H +#define __DMA_H + +#include "mem.h" + +#define DMA_MODE_DEMAND 0 +#define DMA_MODE_SINGLE 1 +#define DMA_MODE_BLOCK 2 +#define DMA_MODE_CASCADE 3 + +#define DMA_BASEADDR 0 +#define DMA_TRANSCOUNT 1 +#define DMA_PAGEREG 2 + +#define DMA_CMDREG 0 +#define DMA_MODEREG 1 +#define DMA_CLEARREG 2 +#define DMA_DMACREG 3 +#define DMA_CLRMASKREG 4 +#define DMA_SINGLEREG 5 +#define DMA_WRITEALLREG 6 + +static Bit8u ChannelPorts [3][8] = { 0x00, 0x02, 0x04, 0x06, 0xff, 0xc4, 0xc8, 0xcc, + 0x01, 0x03, 0x05, 0x07, 0xff, 0xc6, 0xca, 0xce, + 0x87, 0x83, 0x81, 0x82, 0xff, 0x8b, 0x89, 0x8a }; + +static Bit8u ControllerPorts [2][7] = { 0x08, 0x0b, 0x0c, 0x0d, 0x0e, 0x0a, 0xf, + 0xd0, 0xd6, 0xd8, 0xda, 0xdc, 0xd4, 0xde }; + + typedef void (* DMA_EnableCallBack)(bool enable); +typedef void (* DMA_NewCallBack)(void *useChannel, bool tc); void DMA_SetEnableCallBack(Bitu channel,DMA_EnableCallBack callback); +void DMA_CheckEnabled(void * usechan); + Bitu DMA_8_Read(Bitu channel,Bit8u * buffer,Bitu count); Bitu DMA_8_Write(Bitu dmachan,Bit8u * buffer,Bitu count); Bitu DMA_16_Read(Bitu channel,Bit8u * buffer,Bitu count); Bitu DMA_16_Write(Bitu dmachan,Bit8u * buffer,Bitu count); +extern Bit8u read_dmaB(Bit32u port); +extern Bit16u read_dmaW(Bit32u port); + +extern void write_dmaB(Bit32u port,Bit8u val); +extern void write_dmaW(Bit32u port,Bit16u val); + +class DmaController { +public: + bool flipflop; + Bit8u ctrlnum; +public: + + DmaController(Bit8u num) { + int i; + for(i=0;i<7;i++) { + IO_RegisterReadBHandler(ControllerPorts[num][i],read_dmaB); + IO_RegisterReadWHandler(ControllerPorts[num][i],read_dmaW); + + IO_RegisterWriteBHandler(ControllerPorts[num][i],write_dmaB); + IO_RegisterWriteWHandler(ControllerPorts[num][i],write_dmaW); + } + flipflop = true; + ctrlnum = num; + } + + Bit16u portRead(Bit32u port, bool eightbit); + void portWrite(Bit32u port, Bit16u val, bool eightbit); + +}; + + +#define ff myController->flipflop + +class DmaChannel { +public: + + Bit8u channum; + Bit16u baseaddr; + Bit16u current_addr; + Bit16u pageaddr; + PhysPt physaddr; + PhysPt curraddr; + Bit32s transcnt; + Bit32s currcnt; + DmaController *myController; + bool DMA16; +public: + Bit8u dmamode; + bool dir; + bool autoinit; + Bit8u trantype; + bool masked; + bool enabled; + DMA_EnableCallBack enable_callback; + DMA_NewCallBack newcallback; + + DmaChannel(Bit8u num, DmaController *useController, bool sb) { + int i; + masked = true; + enabled = false; + enable_callback = NULL; + newcallback = NULL; + if(num == 4) return; + + for(i=0;i<3;i++) { + IO_RegisterReadBHandler(ChannelPorts[i][num],read_dmaB); + IO_RegisterReadWHandler(ChannelPorts[i][num],read_dmaW); + + IO_RegisterWriteBHandler(ChannelPorts[i][num],write_dmaB); + IO_RegisterWriteWHandler(ChannelPorts[i][num],write_dmaW); + } + myController = useController; + channum = num; + DMA16 = sb; + baseaddr = 0; + pageaddr = 0; + physaddr = 0; + curraddr = 0; + transcnt = 0; + currcnt = 0; + dir = false; + autoinit = false; + } + + void RegisterCallback(DMA_NewCallBack useCallBack) { newcallback = useCallBack; } + + void reset(void) { + curraddr = physaddr; + currcnt = transcnt+1; + current_addr = baseaddr; + //LOG(LOG_DMA,LOG_NORMAL)("Setup at address %X:%X count %X",pageaddr,baseaddr,currcnt); + } + + void MakeCallback(bool tc) { + if (newcallback != NULL) { + if(tc) { + (*newcallback)(this, true); + } else { + if ((enabled) && (!masked) && (transcnt!=0)) { + (*newcallback)(this, false); + } + } + + } + } + + Bit32u Read(Bit32s requestsize, Bit8u * buffer) { + Bit32s bytesread; + bytesread = 0; + if(autoinit) { + while(requestsize>0) { + if(currcnt>=requestsize) { + MEM_BlockRead(curraddr,buffer,requestsize); + curraddr+=requestsize; + buffer+=requestsize; + currcnt-=requestsize; + bytesread+=requestsize; + requestsize=0; + break; + } else { + MEM_BlockRead(curraddr,buffer,currcnt); + bytesread+=currcnt; + buffer+=currcnt; + requestsize-=currcnt; + reset(); + MakeCallback(true); + } + } + if(currcnt==0) { + reset(); + MakeCallback(true); + } + return bytesread; + + } else { + if(currcnt>=requestsize) { + MEM_BlockRead(curraddr,buffer,requestsize); + curraddr+=requestsize; + buffer+=requestsize; + currcnt-=requestsize; + bytesread+=requestsize; + } else { + MEM_BlockRead(curraddr,buffer,currcnt); + buffer+=currcnt; + requestsize-=currcnt; + bytesread+=currcnt; + currcnt=0; + } + } + if(currcnt==0) MakeCallback(true); + return bytesread; + } + + Bit32u Write(Bit32s requestsize, Bit8u * buffer) { + Bit32s byteswrite; + byteswrite = 0; + if(autoinit) { + while(requestsize>0) { + if(currcnt>=requestsize) { + MEM_BlockWrite(curraddr,buffer,requestsize); + curraddr+=requestsize; + buffer+=requestsize; + currcnt-=requestsize; + byteswrite+=requestsize; + requestsize=0; + break; + } else { + MEM_BlockWrite(curraddr,buffer,currcnt); + byteswrite+=currcnt; + buffer+=currcnt; + requestsize-=currcnt; + reset(); + MakeCallback(true); + } + } + if(currcnt==0) { + reset(); + MakeCallback(true); + } + return byteswrite; + + } else { + if(currcnt>=requestsize) { + MEM_BlockWrite(curraddr,buffer,requestsize); + curraddr+=requestsize; + buffer+=requestsize; + currcnt-=requestsize; + byteswrite+=requestsize; + } else { + MEM_BlockWrite(curraddr,buffer,currcnt); + buffer+=currcnt; + requestsize-=currcnt; + byteswrite+=currcnt; + currcnt=0; + } + } + if(currcnt==0) MakeCallback(true); + return byteswrite; + } + + + void calcPhys(void) { + if (DMA16) { + physaddr = (baseaddr << 1) | ((pageaddr >> 1) << 17); + } else { + physaddr = (baseaddr) | (pageaddr << 16); + } + curraddr = physaddr; + current_addr = baseaddr; + } + + Bit16u portRead(Bit32u port, bool eightbit) { + if (port == ChannelPorts[DMA_BASEADDR][channum]) { + if(eightbit) { + if(ff) { + ff = !ff; + return current_addr & 0xff; + } else { + ff = !ff; + return current_addr >> 8; + } + } else { + return current_addr; + } + } + if (port == ChannelPorts[DMA_TRANSCOUNT][channum]) { + if(eightbit) { + if(ff) { + ff = !ff; + return (Bit8u)(currcnt & 0xff); + } else { + ff = !ff; + return (Bit8u)(currcnt >> 8); + } + } else { + return (Bit16u)currcnt; + } + } + if (port == ChannelPorts[DMA_PAGEREG][channum]) return pageaddr; + return 0xffff; + } + + void portWrite(Bit32u port, Bit16u val, bool eightbit) { + if (port == ChannelPorts[DMA_BASEADDR][channum]) { + if(eightbit) { + if(ff) { + baseaddr = (baseaddr & 0xff00) | (Bit8u)val; + } else { + baseaddr = (baseaddr & 0xff) | (val << 8); + } + ff = !ff; + } else { + baseaddr = val; + } + calcPhys(); + reset(); + } + if (port == ChannelPorts[DMA_TRANSCOUNT][channum]) { + if(eightbit) { + if(ff) { + transcnt = (transcnt & 0xff00) | (Bit8u)val; + } else { + transcnt = (transcnt & 0xff) | (val << 8); + } + ff = !ff; + } else { + transcnt = val; + } + currcnt = transcnt+1; + reset(); + DMA_CheckEnabled(this); + MakeCallback(false); + + } + if (port == ChannelPorts[DMA_PAGEREG][channum]) { + pageaddr = val; + calcPhys(); + reset(); + } + + } + + // Notify channel when mask changes + void Notify(void) { + if(!masked) { + DMA_CheckEnabled(this); + MakeCallback(false); + } + } + +}; + +#undef ff + +extern DmaChannel *DmaChannels[8]; +extern DmaController *DmaControllers[2]; + + + +#endif \ No newline at end of file diff --git a/src/hardware/dma.cpp b/src/hardware/dma.cpp index 7a35d16d..d165ac2a 100644 --- a/src/hardware/dma.cpp +++ b/src/hardware/dma.cpp @@ -20,11 +20,6 @@ Based the port handling from the bochs dma code. */ -/* - TODO - Implement 16-bit dma -*/ - #include #include "dosbox.h" #include "mem.h" @@ -32,259 +27,193 @@ #include "dma.h" #include "pic.h" -#define DMA_MODE_DEMAND 0 -#define DMA_MODE_SINGLE 1 -#define DMA_MODE_BLOCK 2 -#define DMA_MODE_CASCADE 3 - -struct DMA_CHANNEL { - struct { - Bit8u mode_type; - bool address_decrement; - bool autoinit_enable; - Bit8u transfer_type; - } mode; - Bit16u base_address; - Bit16u base_count; - Bit16u current_address; - Bitu current_count; - Bit8u page; - bool masked; - PhysPt address; - bool addr_changed; - bool enabled; - DMA_EnableCallBack enable_callback; -}; +DmaChannel *DmaChannels[8]; +DmaController *DmaControllers[2]; -struct DMA_CONTROLLER { - bool flipflop; - Bit8u status_reg; - Bit8u command_reg; - DMA_CHANNEL chan[4]; -}; +Bit16u DmaController::portRead(Bit32u port, bool eightbit) { + LOG_MSG("Reading DMA controller at %x", port); + return 0xffff; +} -static DMA_CONTROLLER dma[2]; - -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 */ - DMA_CONTROLLER * cont=&dma[0]; - DMA_CHANNEL * chan=&cont->chan[port>>1]; - Bit8u ret; - switch (port) { - case 0x00:case 0x02:case 0x04:case 0x06: - if (cont->flipflop) { - ret=chan->current_address & 0xff; - } else { - ret=(chan->current_address>>8)&0xff; - } - cont->flipflop=!cont->flipflop; - break; - case 0x01:case 0x03:case 0x05:case 0x07: - if (cont->flipflop) { - ret=(Bit8u)((chan->current_count-1) & 0xff); - } else { - ret=(Bit8u)(((chan->current_count-1)>>8)&0xff); - } - cont->flipflop=!cont->flipflop; - break; - case 0x08: /* Read Status */ - ret=cont->status_reg; - cont->status_reg&=~0xf; /* Clear lower 4 bits on read */ - break; - case 0x0a: - case 0x0e: - /* Seem to return 0 on a real controller */ - ret=0x0; - break; - default: - LOG(LOG_DMA,LOG_ERROR)("DMA:Unhandled read from %X",port); +void DmaController::portWrite(Bit32u port, Bit16u val, bool eightbit) { + bool found; + found = false; + if(port == ControllerPorts[ctrlnum][DMA_CLRMASKREG]) { + found = true; + flipflop = true; + // Disable DMA requests + // Clear command and status registers } -// 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]; - DMA_CHANNEL * chan; - switch (port) { - case 0x00:case 0x02:case 0x04:case 0x06: - chan=&cont->chan[port>>1]; - if (cont->flipflop) { - chan->base_address=(chan->base_address & 0xff00) | val; - } else { - chan->base_address=(chan->base_address & 0x00ff) | (val<<8); - } - cont->flipflop=!cont->flipflop; - chan->addr_changed=true; - break; - case 0x01:case 0x03:case 0x05:case 0x07: - chan=&cont->chan[port>>1]; - if (cont->flipflop) { - chan->base_count=(chan->base_count & 0xff00) | val; - } else { - chan->base_count=(chan->base_count & 0x00ff) | (val<<8); - } - cont->flipflop=!cont->flipflop; - chan->addr_changed=true; - DMA_CheckEnabled(chan); - break; - case 0x08: /* Command Register */ - if (val != 4) LOG(LOG_DMA,LOG_ERROR)("DMA1:Illegal command %2X",val); - cont->command_reg=val; - break; - case 0x09: /* Request Register */ - if (val&4) { - /* Set Request bit */ - Bitu channel = val & 0x03; - cont->status_reg |= (1 << (channel+4)); - } else { - Bitu channel = val & 0x03; - cont->status_reg &= ~(1 << (channel+4)); - } - break; - case 0x0a: /* single mask bit register */ - chan=&cont->chan[val & 0x3]; - 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]; - chan->mode.mode_type = (val >> 6) & 0x03; - chan->mode.address_decrement = (val & 0x20) > 0; - chan->mode.autoinit_enable = (val & 0x10) > 0; - chan->mode.transfer_type = (val >> 2) & 0x03; - if (chan->mode.address_decrement) { - LOG(LOG_DMA,LOG_ERROR)("DMA:Address Decrease not supported yet"); - } - DMA_CheckEnabled(chan); - break; - case 0x0c: /* Clear Flip/Flip */ - cont->flipflop=true; - break; - default: - LOG(LOG_DMA,LOG_ERROR)("DMA:Unhandled write %X to %X",static_cast(val),port); - }; -}; - -void write_dma_page(Bit32u port,Bit8u val) { - 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; + if(port == ControllerPorts[ctrlnum][DMA_SINGLEREG]) { + found = true; + int dmachan; + dmachan = (ctrlnum * 2) + (val & 0x3); + DmaChannels[dmachan]->masked = ((val & 0x4) == 0x4); + DmaChannels[dmachan]->Notify(); } - dma[0].chan[channel].page=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; + if(port == ControllerPorts[ctrlnum][DMA_WRITEALLREG]) { + found = true; + int dmachan,i,r; + dmachan = (ctrlnum * 2); + r = 0; + for(i=dmachan;imasked = (((val >> r) & 0x1) == 0x1); + DmaChannels[i]->Notify(); + r++; + } } - return dma[0].chan[channel].page; + if(port == ControllerPorts[ctrlnum][DMA_CLEARREG]) { + found = true; + flipflop = true; + } + if(port == ControllerPorts[ctrlnum][DMA_MODEREG]) { + found = true; + int dmachan; + dmachan = (ctrlnum * 2) + (val & 0x3); + DmaChannels[dmachan]->trantype = (val >> 2) & 0x3; + DmaChannels[dmachan]->autoinit = ((val & 0x10) == 0x10); + DmaChannels[dmachan]->dir = ((val & 0x20) == 0x20); + DmaChannels[dmachan]->dmamode = (val >> 6) & 0x3; + DMA_CheckEnabled(DmaChannels[dmachan]); + } + if(!found) LOG_MSG("Write to DMA port %x with %x", port, val); + } -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(LOG_DMA,LOG_NORMAL)("Setup at address %X:%X count %X",chan->page<<12,chan->base_address,chan->current_count); + +static Bit16u readDMAPorts(Bit32u port, bool eightbit) { + int i,j; + + // Check for controller access + for(i=0;i<2;i++) { + for(j=0;j<7;j++) { + if(ControllerPorts[i][j] == port) { + return DmaControllers[i]->portRead(port, eightbit); + } + } + } + + // Check for DMA access + for(i=0;i<8;i++) { + for(j=0;j<3;j++) { + if(ChannelPorts[j][i] == port) { + return DmaChannels[i]->portRead(port, eightbit); + } + } + } + + LOG_MSG("Unmatched read port %x", port); + + return 0xffff; + } +static void writeDMAPorts(Bit32u port, Bit16u val, bool eightbit) { + int i,j; + + // Check for controller access + for(i=0;i<2;i++) { + for(j=0;j<7;j++) { + if(ControllerPorts[i][j] == port) { + DmaControllers[i]->portWrite(port,val,eightbit); + return; + } + } + } + + // Check for DMA access + for(i=0;i<8;i++) { + for(j=0;j<3;j++) { + if(ChannelPorts[j][i] == port) { + DmaChannels[i]->portWrite(port,val,eightbit); + return; + } + } + } + + LOG_MSG("Unmatched write port %x - val %x", port, val); + +} + +Bit8u read_dmaB(Bit32u port) { return (Bit8u)readDMAPorts(port,true); } + +Bit16u read_dmaW(Bit32u port) { return readDMAPorts(port,false); } + +void write_dmaB(Bit32u port,Bit8u val) { writeDMAPorts(port,val,true); } + +void write_dmaW(Bit32u port,Bit16u val) { writeDMAPorts(port,val,false); } + + +// Deprecated DMA read/write routines -- Keep compatibility with Sound Blaster Bitu DMA_8_Read(Bitu dmachan,Bit8u * buffer,Bitu count) { - DMA_CHANNEL * chan=&dma[0].chan[dmachan]; + DmaChannel *chan=DmaChannels[dmachan]; + 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); - chan->address+=count; - chan->current_address+=count; - chan->current_count-=count; + if (chan->currcnt>count) { + MEM_BlockRead(chan->curraddr,buffer,count); + chan->curraddr+=count; + chan->current_addr+=count; + chan->currcnt-=count; return count; } else { - /* Copy remaining piece of first buffer */ - MEM_BlockRead(chan->address,buffer,chan->current_count); - if (!chan->mode.autoinit_enable) { - /* Set the end of counter bit */ - dma[0].status_reg|=(1 << dmachan); - count=chan->current_count; - chan->address+=count; - chan->current_count=0; + // Copy remaining piece of first buffer + MEM_BlockRead(chan->curraddr,buffer,chan->currcnt); + if (!chan->autoinit) { + // Set the end of counter bit + //dma[0].status_reg|=(1 << dmachan); + count=chan->currcnt; + chan->curraddr+=count; + chan->current_addr+=count; + chan->currcnt=0; chan->enabled=false; LOG(LOG_DMA,LOG_NORMAL)("8-bit Channel %d reached terminal count"); return count; } else { - buffer+=chan->current_count; - Bitu left=count-(Bit16u)chan->current_count; - /* Autoinit reset the dma channel */ - ResetDMA8(chan); - /* Copy the rest of the buffer */ - MEM_BlockRead(chan->address,buffer,left); - chan->address+=left; - chan->current_address+=left; - chan->current_count-=left; + buffer+=chan->currcnt; + Bitu left=count-(Bit16u)chan->currcnt; + // Autoinit reset the dma channel + chan->reset(); + // Copy the rest of the buffer + MEM_BlockRead(chan->curraddr,buffer,left); + chan->curraddr+=left; + chan->current_addr+=left; + chan->currcnt-=left; return count; } } } Bitu DMA_8_Write(Bitu dmachan,Bit8u * buffer,Bitu count) { - DMA_CHANNEL * chan=&dma[0].chan[dmachan]; + DmaChannel *chan=DmaChannels[dmachan]; + 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); - chan->address+=count; - chan->current_address+=count; - chan->current_count-=count; + if (chan->currcnt>count) { + MEM_BlockWrite(chan->curraddr,buffer,count); + chan->curraddr+=count; + chan->currcnt-=count; return count; } else { - /* Copy remaining piece of first buffer */ - MEM_BlockWrite(chan->address,buffer,chan->current_count); - if (!chan->mode.autoinit_enable) { - /* Set the end of counter bit */ - dma[0].status_reg|=(1 << dmachan); - count=chan->current_count; - chan->current_address+=count;; - chan->current_count=0; - chan->enabled=false; + // Copy remaining piece of first buffer + MEM_BlockWrite(chan->curraddr,buffer,chan->currcnt); + if (!chan->autoinit) { + // Set the end of counter bit + //dma[0].status_reg|=(1 << dmachan); + count=chan->currcnt; + chan->curraddr+=count;; + chan->currcnt=0; return count; } else { - buffer+=chan->current_count; - Bitu left=count-(Bit16u)chan->current_count; - /* Autoinit reset the dma channel */ - ResetDMA8(chan); - /* Copy the rest of the buffer */ - MEM_BlockWrite(chan->address,buffer,left); - chan->address+=left; - chan->current_address+=left; - chan->current_count-=left; + buffer+=chan->currcnt; + Bitu left=count-(Bit16u)chan->currcnt; + // Autoinit reset the dma channel + chan->reset(); + // Copy the rest of the buffer + MEM_BlockWrite(chan->curraddr,buffer,left); + chan->curraddr+=left; + chan->currcnt-=left; return count; } } @@ -302,18 +231,21 @@ Bitu DMA_16_Write(Bitu dmachan,Bit8u * buffer,Bitu count) { return 0; } -void DMA_SetEnabled(DMA_CHANNEL * chan,bool enabled) { +void DMA_SetEnabled(DmaChannel * 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) { +void DMA_CheckEnabled(void * usechan) { + DmaChannel * chan; + chan = (DmaChannel *)usechan; + bool enabled; if (chan->masked) enabled=false; else { - if (chan->mode.autoinit_enable) enabled=true; - else if (chan->current_count || chan->addr_changed) enabled=true; + if (chan->autoinit) enabled=true; + else if (chan->currcnt) enabled=true; else enabled=false; } DMA_SetEnabled(chan,enabled); @@ -321,31 +253,28 @@ void DMA_CheckEnabled(DMA_CHANNEL * chan) { void DMA_SetEnableCallBack(Bitu channel,DMA_EnableCallBack callback) { - DMA_CHANNEL * chan; - if (channel<4) { - chan=&dma[0].chan[channel]; - } else if (channel<8) { - chan=&dma[1].chan[channel-4]; - } else return; + DmaChannel * chan; + chan = DmaChannels[channel]; chan->enabled=false; chan->enable_callback=callback; DMA_CheckEnabled(chan); } -void DMA_Init(Section* sec) { - Bitu i; - for (i=0;i<0x10;i++) { - IO_RegisterWriteHandler(i,write_dma,"DMA1"); - IO_RegisterReadHandler(i,read_dma,"DMA1"); - } - IO_RegisterWriteHandler(0x81,write_dma_page,"DMA Pages"); - 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"); +void DMA_Init(Section* sec) { + + Bitu i; + + DmaControllers[0] = new DmaController(0); + DmaControllers[1] = new DmaController(1); + + for(i=0;i<4;i++) { + DmaChannels[i] = new DmaChannel(i,DmaControllers[0],false); + } + for(i=4;i<8;i++) { + DmaChannels[i] = new DmaChannel(i,DmaControllers[1],true); + } } + +