home *** CD-ROM | disk | FTP | other *** search
- ; DMA.ASM Copyright (C) 1994 by Chris Malcheski, Novatech Design
- ; FAX phone (303) 972-9107
-
- ; This file is a direct extraction from my upcoming diagnostics program, which
- ; I am stupidly making available to public domain for DMA programming education-
- ; al purposes. Note that even though the second DMA channel is provided for
- ; in this routine, it is set up for 8 bit operation and has never been tested
- ; above channel 3.
-
- ; ───── variable definitions ───────────────────────────────────────────────────
-
- ; dma_cbpt DMA clear byte pointer port location
- ; dma_chnl Requested DMA channel
- ; dma_mask DMA mask register port location
- ; dma_memr DMA memory register port location
- ; dma_mode DMA mode value holder (0 for read, 1 for write)
- ; dma_page DMA page register port location
- ; dma_rmod DMA mode register port location
- ; dma_work Adjusted DMA channel (0-3 down from 4-7)
- ; dma_xcnt DMA xfer count register port location
- ; hold_hi Utility work variable (word size)
- ; hold_lo Utility work variable (word size)
-
- ;╒═════════════════════════════════════════════════════════════════════════════╕
- ;│ DMA_SET: program DMA controller for diskette I/O. │
- ;├─────────────────────────────────────────────────────────────────────────────┤
- ;│ Call: AL = 0 to read; 1 to write │
- ;│ ES:DI = buffer address for read / write │
- ;│ BX = transfer count in bytes │
- ;├─────────────────────────────────────────────────────────────────────────────┤
- ;│ Uses: DMA_CBPT DMA_CHNL DMA_MASK DMA_MEMR DMA_MODE │
- ;│ DMA_PAGE DMA_RMOD DMA_WORK DMA_XCNT HOLD_HI │
- ;│ HOLD_LO │
- ;├─────────────────────────────────────────────────────────────────────────────┤
- ;│ Calls: Nothing. │
- ;├─────────────────────────────────────────────────────────────────────────────┤
- ;│ Returns: Nothing. │
- ;├─────────────────────────────────────────────────────────────────────────────┤
- ;│ Destroy: None. │
- ;╘═════════════════════════════════════════════════════════════════════════════╛
-
- public dma_set ; Declare procedure public
-
- even ; Set even alignment
- dma_set proc near ; Declare procedure
-
- ;────── Save altered registers ─────────────────────────────────────────────────
-
- push ax ; Save entry AX value
- push cx ; Save entry CX value
- push dx ; Save entry DX value
-
- ;────── Select the DMA channel ─────────────────────────────────────────────────
-
- cli ; Disable interrupts
- mov dma_mode,al ; Save incoming read/write
- mov al,04h ; Set mask bit
- or al,dma_work ; OR with DMA work channel
- mov dx,dma_mask ; Mask register to DX
- out dx,al ; Execute value output
- jmp short $+2 ; Clear prefetch queue
-
- ;────── Set 20 bit address value ───────────────────────────────────────────────
-
- mov ax,es ; Get segment value in AX
- mov cx,16 ; Paragraph multiplier to CX
- mul cx ; Execute multiply
- add ax,di ; Add offset value to AX
- jnc dmas_1 ; Skip carryover process
- inc dx ; Process carryover
-
- ;────── Set page / address registers for DMA transfer ──────────────────────────
-
- even ; Set even alignment
- dmas_1: mov hold_hi,dx ; Save hold value high word
- mov hold_lo,ax ; Save hold value low word
- mov al,dl ; Get page value in AL
- mov dx,dma_page ; Page register to DX
- out dx,al ; Send out page value
- jmp short $+2 ; Clear prefetch queue
-
- ;────── Activate DMA clear byte pointer ────────────────────────────────────────
-
- xor al,al ; Out value to AL
- mov dx,dma_cbpt ; Clear byte pointer to DX
- out dx,al ; Send out clear byte value
- jmp short $+2 ; Clear prefetch queue
-
- ;────── Send out value to DMAC first / last flip flop ──────────────────────────
-
- mov al,44h ; Assume read operation
- cmp dma_mode,0 ; Read operation?
- jz dmas_2 ; Yes -- leave AL as is
- xor al,0Ch ; Set AL for write
- even ; Set even alignment
- dmas_2: or al,dma_chnl ; Set bits 0-1 for channel
- mov dx,dma_rmod ; DMA mode register to DX
- out dx,al ; Send out DMA clear byte ptr
- jmp short $+2 ; Clear prefetch queue
-
- ;────── Send out low word address to memory address registers ──────────────────
-
- mov ax,hold_lo ; Get low word address in AX
- mov dx,dma_memr ; DMA memory address to DX
- out dx,al ; LSB out to DMA address reg
- jmp short $+2 ; Clear prefetch queue
- mov al,ah ; Get high byte in AH
- out dx,al ; MSB out to DMA address reg
- jmp short $+2 ; Clear prefetch queue
-
- ;────── Send out read count ────────────────────────────────────────────────────
-
- mov ax,bx ; Get xfer count in AX
- dec ax ; Adjust for DMA interpret
- mov dx,dma_xcnt ; Transfer count register to DX
- out dx,al ; LSB out to DMA word count
- jmp short $ + 2 ; Clear prefetch queue
- mov al,ah ; MSB to AL for out
- out dx,al ; MSB out to DMA word count
- jmp short $ + 2 ; Clear prefetch queue
-
- ;────── Activate current DMA channel ───────────────────────────────────────────
-
- sti ; Enable interrupts
- mov al,dma_chnl ; Enable DMA channel
- mov dx,dma_mask ; Mask register to DX
- out dx,al ; Activate DMA channel
- jmp short $+2 ; Clear prefetch queue
- clc ; Clear carry flag for no error
-
- ;────── Restore altered registers ──────────────────────────────────────────────
-
- even ; Set even alignment
- dmas_x: pop dx ; Restore entry DX value
- pop cx ; Restore entry CX value
- pop ax ; Restore entry AX value
-
- ;────── Return to caller ───────────────────────────────────────────────────────
-
- ret ; Return to caller
-
- dma_set endp ; End procedure
-