📄 dma_code.asm
字号:
jmp @@AddrOk
@@BadAddr:
mov [_dma_errno],13 ;Word-alignment error message
mov ax,-1
jmp @@ExitPt
@@AddrOk:
cli ;Disable interrupts while mucking with DMA
;The "byte pointer" is also known as the LSB/MSB flip flop.
;By writing any value to it, the DMA controller registers are prepared
;to accept the address and length values LSB first.
mov dx,byte_ptr ;Reset byte pointer Flip/flop
adjust dx
out dx,al ;All we have to do is write to it
mov ax,di ;ax=LSW of 20-bit address
mov dx,bx ;dx=DMAC Base Address port
adjust dx
out dx,al ;Store LSB
mov al,ah
out dx,al ;Store next byte
;Write length to port (Channel*2 + 1)
mov ax,[Len]
mov dx,bx
inc dx ;dx=DMAC Count port
adjust dx
out dx,al ;Write LSB of Length
mov al,ah
out dx,al ;Write MSB
mov bx,[Channel]
shl bx,1
mov dx,[bx + OFFSET page_table] ;dx=page register port
mov al,ch ;al=Page number
out dx,al ;Store the page
mov dx,Mode ;dx=DMAC mode register
adjust dx
mov ax,si ;Load pre-calculated mode
out dx,al ;Write it to the DSP
IFNDEF NO_START
mov dx,DMA_Mask ;dx=DMAX DMA_Mask register
adjust dx
mov al,cl ;al=pre-calulated DMA_Mask value
out dx,al ;Write DMA_Mask (allow dma on this channel)
ENDIF
mov ax,0 ;Return with no error
@@ExitPt: ;Restore stack and return
popf
pop di si dx cx bx
pop bp
ret
ENDP _dma_setup
;+---------------------------------------------------------------------------+
;| int prevent_dma(int Channel) |
;| ------------------------------------------------------------------------- |
;| Channel = 0-7 |
;| Prevents DMA requests from Channel by masking bit in DMA_C. |
;| ------------------------------------------------------------------------- |
;| Returns 0 if Ok, -1 and sets dma_errno on error |
;+---------------------------------------------------------------------------+
PROC _prevent_dma
ARG Channel:Word
push bp
mov bp,sp
mov ax, reset_cmd ; Disable DMA requests
Send_ax_mask: ; Jump here from _allow_dma
push dx
mov [_dma_errno],0
; Check channel number range
mov [dmac2],0
mov bx,[Channel]
cmp bx,7
jbe @@Set_base
mov [_dma_errno],0Ch
mov ax,-1
jmp @@Exit_Pt
@@Set_base:
cmp bx,4
jb @@OkChannel
sub bx,4
inc [dmac2]
@@OkChannel:
mov dx,DMA_Mask
adjust dx
add ax,bx ; Add the adjusted channel number
out dx,al
mov ax,0
@@Exit_Pt:
pop dx
pop bp
ret
ENDP _prevent_dma
;+---------------------------------------------------------------------------+
;| int allow_dma(int Channel) |
;| ------------------------------------------------------------------------- |
;| Channel = 0-7 |
;| Unmasks DMA on the specified channel. |
;| ------------------------------------------------------------------------- |
;| Returns 0 if Ok, -1 and sets dma_errno on error |
;+---------------------------------------------------------------------------+
PROC _allow_dma
ARG Channel:Word
push bp
mov bp,sp
mov ax,set_cmd
jmp Send_ax_mask
ENDP _allow_dma
;+---------------------------------------------------------------------------+
;| int dma_count(Channel) |
;| ------------------------------------------------------------------------- |
;| Channel = 0-7 |
;| ------------------------------------------------------------------------- |
;| Returns: -1 if DMA transaction completed |
;| (It returns the number of bytes/words left to transfer) |
;| dma_errno == 0 if no error, otherwise equals error number |
;+---------------------------------------------------------------------------+
PROC _dma_count
ARG Channel:Word
push bp
mov bp,sp
pushf
push dx
; Check channel number range
mov [dmac2],0
mov bx,[Channel]
cmp bx,7
jbe @@Set_base
mov [_dma_errno],0Ch
mov ax,-1
jmp @@Exit_Pt
@@Set_base:
cmp bx,4
jb @@OkChannel
sub bx,4
inc [dmac2]
@@OkChannel:
mov dx,bx
shl dx,1
add dx,count
adjust dx
cli
in al,dx
mov ah,al
in al,dx
xchg al,ah
@@Exit_Pt:
pop dx
popf ; re-enables interrupts
pop bp
ret
ENDP _dma_count
;+---------------------------------------------------------------------------+
;| unsigned dma_addr(Channel) |
;| ------------------------------------------------------------------------- |
;| Channel = 0-7 |
;| ------------------------------------------------------------------------- |
;| Returns: Current address word of that channel |
;| Value must be multiplied by 2 for a 16-bit channel. |
;| It is best to start at offset 0, ie on a 64K boundary |
;| dma_errno == 0 if no error, otherwise equals error number |
;+---------------------------------------------------------------------------+
PROC _dma_addr
ARG Channel:Word
push bp
mov bp,sp
pushf
push dx
; Check channel number range
mov [dmac2],0
mov bx,[Channel]
cmp bx,7
jbe @@Set_base
mov [_dma_errno],0Ch
mov ax,-1
jmp @@Exit_Pt
@@Set_base:
cmp bx,4
jb @@OkChannel
sub bx,4
inc [dmac2]
@@OkChannel:
mov dx,bx
shl dx,1
adjust dx
cli
in al,dx
mov ah,al
in al,dx
xchg al,ah
@@Exit_Pt:
pop dx
popf
pop bp
ret
ENDP _dma_addr
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -