;================================================================================================== ; Z80 DMA DRIVER FOR ECB-DMA ;================================================================================================== ; ; DUE TO LOW CLOCK SPEED CONTRAINTS OF Z80 DMA CHIP, THE HALF CLOCK FACILITY ; IS USED DURING DMA PROGRAMMING AND CONTINUOUS BLOCK TRANSFERS. ; TESTING CONDUCTED ON A SBC-V2-005 @ 10Mhz ; DMA_CONTINUOUS .equ %10111101 ; + Pulse DMA_BYTE .equ %10011101 ; + Pulse DMA_BURST .equ %11011101 ; + Pulse DMA_LOAD .equ $cf ; %11001111 DMA_ENABLE .equ $87 ; %10000111 DMA_FORCE_READY .equ $b3 DMA_DISABLE .equ $83 ; ;DMA_RESET .equ $c3 ;DMA_RESET_PORT_A_TIMING .equ $c7 ;DMA_RESET_PORT_B_TIMING .equ $cb ;DMA_CONTINUE .equ $d3 ;DMA_DISABLE_INTERUPTS .equ $af ;DMA_ENABLE_INTERUPTS .equ $ab ;DMA_RESET_DISABLE_INTERUPTS .equ $a3 ;DMA_ENABLE_AFTER_RETI .equ $b7 ;DMA_READ_STATUS_BYTE .equ $bf ;DMA_REINIT_STATUS_BYTE .equ $8b ;DMA_START_READ_SEQUENCE .equ $a7 ;DMA_WRITE_REGISTER_COMMAND .equ $bb ; ;================================================================================================== ; DMA INITIALIZATION CODE ;================================================================================================== ; DMA_INIT: CALL NEWLINE PRTS("DMA: IO=0x$") LD A, DMABASE CALL PRTHEXBYTE ; ld a,0 out (DMABASE+1),a ; force ready off ; ld hl,DMACode ; program the ld b,DMACode_Len ; dma command ld c,DMABASE ; block ; ld a,(RTCVAL) or %00001000 ; half out (112),a ; clock di otir ; load dma ei and %11110111 ; full out (112),a ; clock ret ; DMACode ;.db DMA_DISABLE ; R6-Command Disable DMA .db %01111101 ; R0-Transfer mode, A -> B, start address, block length follow .dw 0 ; R0-Port A, Start address .dw 0 ; R0-Block length .db %00010100 ; R1-No timing bytes follow, address increments, is memory .db %00010000 ; R2-No timing bytes follow, address increments, is memory .db %10000000 ; R3-DMA, interrupt, stop on match disabled .db DMA_CONTINUOUS ; R4-Continuous mode, destination address, interrupt and control byte follow .dw 0 ; R4-Port B, Destination address .db %00001100 ; R4-Pulse byte follows, Pulse generated .db 0 ; R4-Pulse offset .db %10011010 ; R5-Stop on end of block, ce/wait multiplexed, READY active HIGH .db DMA_LOAD ; R6-Command Load ; .db DMA_FORCE_READY ; R6-Command Force ready ; .db DMA_ENABLE ; R6-Command Enable DMA DMACode_Len .equ $-DMACode ; ;================================================================================================== ; DMA COPY BLOCK CODE - ASSUMES DMA PREINITIALIZED ;================================================================================================== ; DMALDIR: ld (DMASource),hl ; populate the dma ld (DMADest),de ; register template ld (DMALength),bc ; ld hl,DMACopy ; program the ld b,DMACopy_Len ; dma command ld c,DMABASE ; block ; ld a,(RTCVAL) or %00001000 ; half out (112),a ; clock di otir ; load and execute dma ei and %11110111 ; full out (112),a ; clock ret ; DMACopy ;.db DMA_DISABLE ; R6-Command Disable DMA .db %01111101 ; R0-Transfer mode, A -> B, start address, block length follow DMASource .dw 0 ; R0-Port A, Start address DMALength .dw 0 ; R0-Block length .db %00010100 ; R1-No timing bytes follow, address increments, is memory .db %00010000 ; R2-No timing bytes follow, address increments, is memory .db %10000000 ; R3-DMA, interrupt, stop on match disabled .db DMA_CONTINUOUS ; R4-Continuous mode, destination address, interrupt and control byte follow DMADest .dw 0 ; R4-Port B, Destination address .db %00001100 ; R4-Pulse byte follows, Pulse generated .db 0 ; R4-Pulse offset ; .db %10011010 ; R5-Stop on end of block, ce/wait multiplexed, READY active HIGH .db DMA_LOAD ; R6-Command Load .db DMA_FORCE_READY ; R6-Command Force ready .db DMA_ENABLE ; R6-Command Enable DMA DMACopy_Len .equ $-DMACopy ; ;================================================================================================== ; DMA I/O OUT BLOCK CODE - ADDRESS TO I/O PORT ;================================================================================================== ; DMAOTIR: ld (DMAOutSource),hl ; populate the dma ld (DMAOutDest),a ; register template ld (DMAOutLength),bc ; ld hl,DMAOutCode ; program the ld b,DMAOut_Len ; dma command ld c,DMABASE ; block ; ld a,(RTCVAL) or %00001000 ; half out (112),a ; clock di otir ; load and execute dma ei and %11110111 ; full out (112),a ; clock ret ; DMAOutCode ;.db DMA_DISABLE ; R6-Command Disable DMA .db %01111001 ; R0-Transfer mode, B -> A (temp), start address, block length follow DMAOutSource .dw 0 ; R0-Port A, Start address DMAOutLength .dw 0 ; R0-Block length .db %00010100 ; R1-No timing bytes follow, fixed incrementing address, is memory .db %00101000 ; R2-No timing bytes follow, address static, is i/o .db %10000000 ; R3-DMA, interrupt, stop on match disabled .db %10100101 ; R4-Continuous mode, destination port, interrupt and control byte follow DMAOutDest .db 0 ; R4-Port B, Destination port ; .db %00001100 ; R4-Pulse byte follows, Pulse generated ; .db 0 ; R4-Pulse offset .db %10011010 ; R5-Stop on end of block, ce/wait multiplexed, READY active HIGH .db DMA_LOAD ; R6-Command Load .db %00000101 ; R0-Port A is Source .db DMA_LOAD ; R6-Command Load .db DMA_FORCE_READY ; R6-Command Force ready .db DMA_ENABLE ; R6-Command Enable DMA DMAOut_Len .equ $-DMAOutCode ; ;================================================================================================== ; DMA I/O INPUT BLOCK CODE - I/O PORT TO ADDRESS ;================================================================================================== ; DMAINIR: ld (DMAInDest),hl ; populate the dma ld (DMAInSource),a ; register template ld (DMAInLength),bc ; ld hl,DMAInCode ; program the ld b,DMAIn_Len ; dma command ld c,DMABASE ; block ; ld a,(RTCVAL) or %00001000 ; half out (112),a ; clock di otir ; load and execute dma ei and %11110111 ; full out (112),a ; clock ret ; DMAInCode ;.db DMA_DISABLE ; R6-Command Disable DMA .db %01111001 ; R0-Transfer mode, B -> A, start address, block length follow DMAInDest .dw 0 ; R0-Port A, Start address DMAInLength .dw 0 ; R0-Block length .db %00010100 ; R1-No timing bytes follow, address increments, is memory .db %00111000 ; R2-No timing bytes follow, address static, is i/o .db %10000000 ; R3-DMA, interrupt, stop on match disabled .db %10100101 ; R4-Continuous mode, destination port, no interrupt, control byte. DMAInSource .db 0 ; R4-Port B, Destination port ; .db %00001100 ; R4-Pulse byte follows, Pulse generated ; .db 0 ; R4-Pulse offset .db %10011010 ; R5-Stop on end of block, ce/wait multiplexed, READY active HIGH .db DMA_LOAD ; R6-Command Load .db DMA_FORCE_READY ; R6-Command Force ready .db DMA_ENABLE ; R6-Command Enable DMA DMAIn_Len .equ $-DMAInCode