─────────────────────────────────────────────────────────────────────────────
INTRO TO DMA by Draeden of VLA
─────────────────────────────────────────────────────────────────────────────
DMA means Direct Memory Access. You probably already know where and
why you use it, so I'll skip right down to the dirty stuff. This all
should speak for it's self, so... Enjoy.
Draeden /VLA
─────────────────────────────────────────────────────────────────────────────
To do a DMA transfer, you need to know a few things:
1) Address of the memory to access
2) Length of data to read/write
This can all be put into a structure:
STRUC DMAInfo
Page db ?
Offset dw ?
Length dw ?
ENDS
Page is the highest 4 bits of the absolute 20 bit address of the memory
location. Note that DMA transfers CANNOT cross 64k page boundries.
The Length is actually LENGTH-1; sending in a 0 will move 1 byte,
sending a 0FFFFh will move 64k.
─────────────────────────────────────────────────────────────────────
; IN: DX:AX = segment/offset address of memory area
;
;OUT: DH = Page (0-F) (DL is destroyed)
; AX = Offset
─────────────────────────────────────────────────────────────────────
PROC MakePage
push bx
mov bl,dh
shr bl,4 ;isolate upper 4 bits of segment
shl dx,4 ;make segment into ABS address
add ax,dx ;add the offset and put it in AX
adc bl,0 ;complete the addition
mov dh,bl ;put the PAGE where it goes
pop bx ; DH:AX is now the PAGE:OFFSET address
ret
ENDP
─────────────────────────────────────────────────────────────────────────────
Programming DMA channels 0 thru 3
─────────────────────────────────────────────────────────────────────────────
There are 3 ports that are DMA channel specific:
1) The Page register
2) The DMA count (length) register
3) The memory address (offset register)
They are as follows:
DMACH PAGE ADDRESS LENGTH
0 87h 0 1
1 83h 2 3
2 81h 4 5
3 82h 6 7
And now some general registers:
DMA Mask Register: 0Ah
────────────────────────
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
USE: You must set the mask of the channel before you
can reprogram it.
DMA Mode Register: 0Bh
────────────────────────
bit 7 - 6 = 00 Demand mode
= 01 Signal mode
= 10 Block mode
= 11 Cascade mode
bit 5 - 4 = 0 Reserved
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
USE: Tell the DMAC what to do. Common modes are:
48h (Read operation, Signal mode)
Used to read data from host memory and send to whomever
polls it.
44h (Write operation, Signal mode)
Used to write data taken from a device to memory.
DMA clear byte ptr: 0Ch
────────────────────────
USE: Send a zero to reset the internal ptrs
WHAT TO DO:
────────────────────────
1) Set the Mask bit for the channel
mov al,4
add al,[DMA_Channel]
out 0ah,al
2) Clear Byte Ptr
sub al,al
out 0Ch,al
3) Set the DMA transfer mode
mov al,48h ;MODE output (read)
add al,[DMA_Channel]
out 0Bh,al
4) Set the memory ADDRESS and LENGTH
; AX = offset
; CX = Length
;[DMA_Base] = port # of memory address
mov dx,[DMA_Base]
out dx,al ;send lower byte address
mov al,ah
out dx,al ;send high byte address
inc dl ;point to Count port
mov al,cl
out dx,al ;send low byte length
mov al,ch
out dx,al ;send high byte length
5) Set the DMA page
; AL = Page
mov dx,[Dma_Page]
out dx,al ; write the Page
6) Clear DMA mask bit
mov al,[byte DMA_Channel]
out 0Ah,al ; port 0Ah, DMA-1 mask reg bit
7) Program the other device that is going to use the DMA output/input
─────────────────────────────────────────────────────────────────────
; This routine programs the DMAC for channels 0-3
;
; IN: [DMA_Channel], [DMAbaseAdd], [DMApageReg] must be setup
; [DAMBaseAdd] = Memory Address port
;
; dh = mode
; ax = address
; cx = length
; dl = page
─────────────────────────────────────────────────────────────────────
PROC Prog_DMA03 NEAR
push bx
mov bx,ax
mov al,4
add al,[DMA_Channel]
out 0Ah,al ; mask reg bit
sub al,al
out 0Ch,al ; clr byte ptr
mov al,dh
add al,[DMA_Channel]
out 0Bh,al ; set mode reg
push dx
mov dx,[DMAbaseAdd]
mov al,bl
out dx,al ; set base address low
mov al,bh
out dx,al ; set base address high
inc dx ;point to length
mov al,cl
out dx,al ; set length low
mov al,ch
out dx,al ; set length high
pop dx
mov al,dl
mov dx,[DmaPageReg]
out dx,al ; set DMA page reg
mov al,[DMA_Channel]
out 0Ah,al ; unmask (activate) dma channel
pop bx
ret
ENDP
─────────────────────────────────────────────────────────────────────────────
─────────────────────────────────────────────────────────────────────────────
Programming DMA channels 4 thru 7
─────────────────────────────────────────────────────────────────────────────
─────────────────────────────────────────────────────────────────────────────
Again, there are 3 ports that are DMA channel specific:
1) The Page register
2) The DMA count (length) register
3) The memory address (offset register
They are as follows:
DMACH PAGE ADDRESS LENGTH
4 8Fh C0h C2h
5 8Bh C4h C6h
6 89h C8h CAh
7 8Ah CCh CEh
And now some general registers:
DMA Mask Register: 0D4h
────────────────────────
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
USE: You must set the mask of the channel before you
can reprogram it.
DMA Mode Register: 0D6h
────────────────────────
bit 7 - 6 = 00 Demand mode
= 01 Signal mode
= 10 Block mode
= 11 Cascade mode
bit 5 - 4 = 0 Reserved
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
USE: Tell the DMAC what to do. Common modes are:
48h (Read operation, Signal mode)
Used to read data from host memory and send to whomever
polls it.
44h (Write operation, Signal mode)
Used to write data taken from a device to memory.
DMA clear byte ptr: 0D8h
────────────────────────
USE: Send a zero to reset the internal ptrs
WHAT TO DO: (exactly the same thing, just different io PORTs)
────────────────────────
1) Set the Mask bit for the channel
mov al,[DMA_Channel] ;because the DMA's are 4-7, bit #3
out 0D4h,al ; is already set
2) Clear Byte Ptr
sub al,al
out 0D8h,al
3) Set the DMA transfer mode
mov al,[DMA_Channel]
sub al,4
or al,48h ;MODE output (read)
out 0D6h,al
4) Set the memory ADDRESS and LENGTH
; AX = offset
; CX = Length
;[DMA_Base] = port # of memory address
mov dx,[DMA_Base]
out dx,al ;send lower byte address
mov al,ah
out dx,al ;send high byte address
add dl,2 ;point to Count port (seperated by 2)
mov al,cl
out dx,al ;send low byte length
mov al,ch
out dx,al ;send high byte length
5) Set the DMA page
; AL = Page
mov dx,[Dma_Page]
out dx,al ; write the Page
6) Clear DMA mask bit
mov al,[byte DMA_Channel]
and al,00000011b
out 0d4h,al ; port 0Ah, DMA-1 mask reg bit
7) Program the other device that is going to use the DMA output/input
─────────────────────────────────────────────────────────────────────
; This routine programs the DMAC for channels 4-7
;
; IN: [DMA_Channel], [DMAbaseAdd], [DMApageReg] must be setup
; [DAMBaseAdd] = Memory Address port
;
; dh = mode
; ax = address
; cx = length
; dl = page
─────────────────────────────────────────────────────────────────────
PROC Prog_DMA47 NEAR
push bx
mov bx,ax
mov al,[DMA_Channel]
out 0D4h,al ; mask reg bit
sub al,al
out 0D8h,al ; clr byte ptr
mov al,[DMA_Channel]
sub al,4
add al,dh
out 0D6h,al ; set mode reg
push dx
mov dx,[DMAbaseAdd]
mov al,bl
out dx,al ; set base address low
mov al,bh
out dx,al ; set base address high
add dl,2 ;point to length
mov al,cl
out dx,al ; set length low
mov al,ch
out dx,al ; set length high
pop dx
mov al,dl
mov dx,[DmaPageReg]
out dx,al ; set DMA page reg
mov al,[DMA_Channel]
and al,00000011b
out 0D4h,al ; unmask (activate) dma channel
pop bx
ret
ENDP
─────────────────────────────────────────────────────────────────────
; This routine programs the DMAC for channels 0-7
;
; IN: [DMA_Channel], [DMAbaseAdd], [DMApageReg] must be setup
; [DAMBaseAdd] = Memory Address port
;
; dh = mode
; ax = address
; cx = length
; dl = page
─────────────────────────────────────────────────────────────────────
PROC Prog_DMA NEAR
push bx
mov bx,ax
cmp [DMA_Channel],4
jb @@DoDMA03
mov al,[DMA_Channel]
out 0D4h,al ; mask reg bit
sub al,al
out 0D8h,al ; clr byte ptr
mov al,[DMA_Channel]
sub al,4
add al,dh
out 0D6h,al ; set mode reg
push dx
mov dx,[DMAbaseAdd]
mov al,bl
out dx,al ; set base address low
mov al,bh
out dx,al ; set base address high
add dl,2 ;point to length
mov al,cl
out dx,al ; set length low
mov al,ch
out dx,al ; set length high
pop dx
mov al,dl
mov dx,[DmaPageReg]
out dx,al ; set DMA page reg
mov al,[DMA_Channel]
and al,00000011b
out 0D4h,al ; unmask (activate) dma channel
pop bx
ret
@@DoDMA03:
mov al,4
add al,[DMA_Channel]
out 0Ah,al ; mask reg bit
sub al,al
out 0Ch,al ; clr byte ptr
mov al,dh
add al,[DMA_Channel]
out 0Bh,al ; set mode reg
push dx
mov dx,[DMAbaseAdd]
mov al,bl
out dx,al ; set base address low
mov al,bh
out dx,al ; set base address high
inc dx ;point to length
mov al,cl
out dx,al ; set length low
mov al,ch
out dx,al ; set length high
pop dx
mov al,dl
mov dx,[DmaPageReg]
out dx,al ; set DMA page reg
mov al,[DMA_Channel]
out 0Ah,al ; unmask (activate) dma channel
pop bx
ret
ENDP