Written by : Peter Quiring (Feb 1/97)
typedef unsigned long int dword;
dword getbuffer(dword size) { //size can not exceed 64k
dword addr,page1,page2;
addr=(dword)malloc(size*2);
if (addr==0) return 0; //0=NULL
page1=addr & 0xff0000h;
page2=(addr + size - 1) & 0xff0000h;
if (page1 != page2) {
//the 1st part of the buffer crosses a 64k thing so we shall
// start our buffer
return (page2);
} else {
return (addr);
}
}
This will always return successful (unless of course malloc() fails) but
it requires to alloc twice as much as needed. If page1 != page2 then if our
buffer were to start at addr it would cross a boundry. In this case
we simple return page2 which will still be inside of the alloc block of RAM
and will be big enough for the buffer size requested and will not cross
a boundry.
DMA Channel PAGE ADDRESS LENGTH
0 87h 0 1
1 83h 2 3
2 81h 4 5
3 82h 6 7
The rest of the ports do not depend on which channel you plan on using:MASK 0ah MODE 0bh CLEAR 0chThe MASK port is as follows:
bit 7 - 3 = 0 Reserved
bit 2 = 0 clear mask
= 1 set mask
bits 1 - 0 = 00 Select channel 0
= 01 select channel 1
= 10 select channel 2
= 11 select channel 3
This port is used to tell the DMAC which DMA channel you are going to program.
You set the mask for the channel, program the DMAC, clear the mask for
the channel.
bit 7 - 6 = 00 Demand mode
= 01 Signal mode
= 10 Block mode
= 11 Cascade mode
bit 5 = 0 Reserved
bit 4 = 0 Normal mode
= 1 Autoinitilize mode
bit 3 - 2 = 00 Verify operation
= 01 Write operation
= 10 Read operation
= 11 Reserved
bits 1 - 0 = 00 Select channel 0
= 01 select channel 1
= 10 select channel 2
= 11 select channel 3
When using sound cards (48h+DMA channel) would be for playback of a WAV, and
(44h+DMA channel) would be for recording a WAV.
byte pageport[]={0x87,0x83,0x81,0x82};
// defines for direction
#define PLAYBACK 0
#define RECORD 1
void setupDMA8(dword addr,dword size,byte dma,byte dir) {
byte page;
word offset;
byte mode;
size--; //size must be 1 less than requested
page = (addr >> 16) & 0xff;
offset = addr & 0xffff;
outp(0xa,4+dma); //mask DMA channel
outp(0xc,0); //clear DMA
outp(pageport[dma],page); //set page
outp(dma*2,offset & 0xff); //set offset (LO BYTE)
outp(dma*2,(offset & 0xff00) >> 8); //set offset (HI BYTE)
outp(dma*2+1,size & 0xff); //set size (LO BYTE)
outp(dma*2+1,(size & 0xff00) >> 8); //set size (HI BYTE)
if (dir==PLAYBACK) mode=44h; else mode==48h;
mode+=dma;
// mode+=0x10; //add this to use Auto DMA mode
outp(0xb,mode); //set mode
outp(0xa,dma); //unmask DMA
}
That's it!
DMA Channel PAGE ADDRESS LENGTH
4 8Fh C0h C2h
5 8Bh C4h C6h
6 89h C8h CAh
7 8Ah CCh CEh
MASK = 0xd4
bit 7 - 3 = 0 Reserved
bit 2 = 0 clear mask
= 1 set mask
bits 1 - 0 = 00 Select channel 4
= 01 select channel 5
= 10 select channel 6
= 11 select channel 7
MODE = 0xd6
bit 7 - 6 = 00 Demand mode
= 01 Signal mode
= 10 Block mode
= 11 Cascade mode
bit 5 = 0 Reserved
bit 4 = 0 Normal mode
= 1 Auto Init mode
bit 3 - 2 = 00 Verify operation
= 01 Write operation
= 10 Read operation
= 11 Reserved
bits 1 - 0 = 00 Select channel 4
= 01 select channel 5
= 10 select channel 6
= 11 select channel 7
CLEAR = 0xd8
These all are used the same way as in the 8bit version except the addressing
is different because 16bit words are used.
byte pageport16[]={0x8f,0x8b,0x89,0x8a};
// defines for direction (dir)
#define PLAYBACK 0
#define RECORD 1
void setupDMA16(dword addr,dword size,byte dma,byte dir) {
byte page;
word offset;
byte mode;
size--; //size must be 1 less than requested
page = (addr >> 16) & 0xff;
offset = (addr & 0xffff) >> 1;
offset += (page & 0x1) << 15; outp(0xd4,dma); //mask DMA channel outp(0xd8,0); //clear DMA outp(pageport16[dma-4],page); //set page outp(0xc0+(dma-4)*4,offset & 0xff); //set offset (LO BYTE) outp(0xc0+(dma-4)*4,(offset & 0xff00)>> 8); //set offset (HI BYTE)
outp(0xc0+(dma-4)*4+2,size & 0xff); //set size (LO BYTE)
outp(0xc0+(dma-4)*4+2,(size & 0xff00) >> 8); //set size (HI BYTE)
if (dir==PLAYBACK) mode=44h; else mode==48h;
mode+=dma;
// mode+=0x10; //add this to use Auto DMA mode
outp(0xd6,mode); //set mode
outp(0xd4,dma-4); //unmask DMA
}
Notes:| BACK |