$MOD186
NAME DMA_EXAMPLE_1; This example shows code necessary
; to setup of two DMA channels. One
; channel performs an unsynchronized
; transfer from memory to memory.
; The second channel is used by a
; hard disk controller located in
; I/O space.; It is assumed that the constants for PCB register
; addresses are defined elsewhere with EQUates.
; (Works for 80C186EA & EC family of microcontrollers)CODE_SEG SEGMENT
ASSUME CS:CODE_SEGSTART: MOV AX, DATA_SEG ; DATA SEGMENT POINTER
MOV DS, AX
ASSUME DS:DATA_SEG; First we must initialize DMA channel 0. DMA0 will
; an unsynchronized transfer from SOURCE_DATA_1 to
; DEST_DATA_1. The first step is to calculate the
; proper values for the source and destination
; pointers.MOV AX, SEG SOURCE_DATA_1
ROL AX, 4 ; GET HIGH 4 BITS
MOV BX, AX ; SAVE ROTATED VALUE
AND AX, 0FFF0H ; GET SHIFTED LOW 4; NIBBLES
ADD AX, OFFSET SOURCE_DATA_1
; NOW LOW BYTES OF
; POINTER ARE IN AXADC BX, 0 ; ADD IN THE CARRY
; TO THE HIGH NIBBLE
AND BX, 000FH ; GET JUST THE HIGH
; NIBBLE
MOV DX, D0SRCL
OUT DX, AX ; AX=LOW 4 BYTESMOV DX, D0SRCH
MOV AX, BX ; GET HIGH NIBBLE
OUT DX, AX; SOURCE POINTER DONE. REPEAT FOR DEST.
MOV AX, SEG DEST_DATA_1
ROL AX, 4 ; GET HIGH 4 BITS
MOV BX, AX ; SAVE ROTATED VALUE
AND AX, 0FFF0H ; GET SHIFTED LOW 4
; NIBBLESADD AX, OFFSET DEST_DATA_1
; NOW LOW BYTES OF
; POINTER ARE IN AXADC BX, 0 ; ADD IN THE CARRY
; TO THE HIGH NIBBLE
AND BX, 000FH ; GET JUST THE HIGH
; NIBBLE
MOV DX, D0DSTL
OUT DX, AX ; AX=LOW 4 BYTESMOV DX, D0DSTH
MOV AX, BX ; GET HIGH NIBBLEOUT DX, AX
; THE POINTER ADDRESSES HAVE BEEN SET UP. NOW
; WE SET UP THE TRANSFER COUNT.MOV AX, 29 ; THE MESSAGE IS
; 29 BYTES LONG.
MOV DX, D0TC ; XFER COUNT REG
OUT DX, AX; NOW WE NEED TO SET THE PARAMETERS FOR
; THE CHANNEL AS FOLLOWS:
;
; DESTINATION SOURCE
; ----------- ------
; MEMORY SPACE MEMORY SPACE
; INCREMENT PTR INCREMENT PTR
;
; TERMINATE ON TC, NO INTERRUPT, UNSYNCHRONIZED,; LOW PRIORITY RELATIVE TO CHANNEL 1, BYTE XFERS.
; WE START THE CHANNELMOV AX, 1011011000000110B
MOV DX, D0CON
OUT DX, AX; THE UNSYNCHRONIZED BURST IS NOW RUNNING ON
; THE BUS...; NOW SET UP CHANNEL 1 TO SERVICE THE DISK
; CONTROLLER. FOR THIS EXAMPLE WE WILL ONLY
; BE READING FROM THE DISK.; THE SOURCE IS THE I/O PORT FOR THE
; DISK CONTROLLER.MOV AX, DISK_IO_ADDR
MOV DX, D1SRCL
OUT DX, AL ; PROGRAM LOW ADDRXOR AX, AX
MOV DX, D1SRCH ; HI ADDR FOR IO=0
OUT DX, AL; THE DESTINATION IS THE DISK BUFFER IN MEMORY
MOV AX, SEG DISK_BUFF
ROL AX, 4 ; GET HIGH 4 BITS
MOV BX, AX ; SAVE ROTATED VALUE
AND AX, 0FFF0H ; GET SHIFTED LOW 4
; NIBBLESADD AX, OFFSET DISK_BUFF
; NOW LOW BYTES OF
; POINTER ARE IN AXADC BX, 0 ; ADD IN THE CARRY
; TO THE HIGH NIBBLEAND BX, 000FH ; GET JUST THE HIGH
; NIBBLE
MOV DX, D1DSTL
OUT DX, AX ; AX=LOW 4 BYTESMOV DX, D1DSTH
MOV AX, BX ; GET HIGH NIBBLE
OUT DX, AX; THE POINTER ADDRESSES HAVE BEEN SET UP. NOW
; WE SET UP THE TRANSFER COUNT.MOV AX, 512 ; THE DISK READS IN
; 512 BYTE SECTORS.
MOV DX, D1TC ; XFER COUNT REG
OUT DX, AX; NOW WE NEED TO SET THE PARAMETERS FOR
; THE CHANNEL AS FOLLOWS:;
; DESTINATION SOURCE
; ----------- ------
; MEMORY SPACE I/O SPACE
; INCREMENT PTR CONSTANT PTR
;
; TERMINATE ON TC, INTERRUPT, SOURCE SYNC,
; HIGH PRIORITY RELATIVE TO CHANNEL 0, BYTE XFERS,
; USE DRQ PIN FOR REQUEST SOURCE.; THE CHANNEL IS ARMED.
MOV AX, 1010001101100110B
MOV DX, D0CON
OUT DX, AX; REQUESTS ON DRQ1 WILL NOW RESULT IN TRANSFERS
CODE_SEG ENDS
DATA_SEG SEGMENT
SOURCE_DATA_1 DB '80C186EC INTEGRATED PROCESSOR'
DEST_DATA_1 DB 30 DUP('MITCH') ; JUNK DATA FOR TESTDISK_BUFF DB 512 DUP(?)
DATA_SEG ENDS
END START
Legal Stuff © 1997 Intel Corporation