⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dma_code.asm

📁 C语言和ASM语言混和开发声卡源程序 RAR压缩解压后包括多个源程序和调试文件
💻 ASM
📖 第 1 页 / 共 2 页
字号:
        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 + -