;**************************************************************************
; EG7.ASM
;
; This example program does sends some stuff to/from the GUS via DMA.
; Please note that this program requires the GUS.ASM and DMA.ASM library
;
; Written by Adam Seychell
;**************************************************************************
.386
.model flat
.stack 200h
include macros.386
include dma.inc
include gus.inc
GF1_clock equ 617400
.DATA
DMA_buffer_phys dD ?
DMA_buffer_addr dD ?
DMA_DRAM_Address dD ?
GUS_MEMORY dD ?
DMAplay_Chan dB ?
DMASamp_Chan dB ?
DMAPlay_TC dB ?
IRQ dB ?
.CODE
The_Start: ;**************** ENTRY POINT OF THE PROGRAM ************
;********* Allocate a 16KB DMA buffer ***************
mov ax,0EE41h
int 31h
jc exit
mov DMA_buffer_addr,edx
mov DMA_buffer_phys,ebx
;********* Get the Default GUS settings from the "ULTRASND=" string *********
Call GetUltraConfig
jnc Got_EnvString
writeln 'Cannot find ''ULTRASND='' environment string or has invalid settings'
mov ax,4C00h
int 21h
Got_EnvString:
mov DMAplay_Chan,CL ; save DMA channels
mov DMASamp_Chan,CH
mov IRQ,BL
;************ Fully reset the Ultraosund *************************
call Ultrasound_Reset ; Expects DX=port
jnc got_ultra
writeln 'Could not detect and Ultrasound on this computer '
mov ax,4C00h
int 21h
got_ultra:
; Save memory installed
mov GUS_MEMORY,EDI
writeln 'Filling Ultrasound''s DRAM via DMA ( # = 16Kb ).'
;************** Set the Ultrasounds IRQ vevctor *****************
mov edx,offset GUS_ISR
mov cx,cs ; CX:EDX = selectro:offset
mov bl,IRQ ; Convert IRQ to interrupt
cmp bl,8 ; number
jb Jpic1
add bl,60h
Jpic1: add bl,8
mov ax,0205h
int 31h
; ****** program the 8237 DMA contoller *************
mov al,01011000b ; DMA mode register
mov ah,DMAPlay_Chan ; Channel number ( 0..7 )
mov ecx,04000h ; Bytes to transfer
mov ebx,DMA_buffer_PHYS ; Physical base address
call DMA_setup ; Do it ( see DMA.ASM )
; Note: Mode reg bit 4 is set for DMA auto initalizing mode.
; This means that the Address and Count registers don't have to be
;reprogramed after the DMA has finished transfering.
mov DMA_DRAM_Address,0
FILL_GUS_LOOP:
;********* Set the GUS's DMA DRAM staring address register *****
mov dx,GF1_Reg_select
mov al,042h ; Set DMA Start Address
out dx,al
mov eax,DMA_DRAM_address
test DMAPlay_chan,100b
jz _8bitDMA
; ---- do 16 bit DMA address translation ( see the SDK ) -----
mov edi,eax
shr eax,1
and eax,01ffffh ; zero out bit 17..19
and edi,0c0000h ; get bits 18 and 19
or eax,edi
_8bitDMA:
shr eax,4
mov dx,GF1_data_LOW
out dx,ax ; Set the damn register
;********* Set the GF1 DMA Control Register ****************
mov al,041h ;Set DRAM DMA Control Register
mov dx,GF1_Reg_Select
out dx,al
mov ah,DMAPlay_chan
and ah,100b
mov al,00100001b ; Read, 650KB/s, 16bit data, 16/8bit DMA
or al,ah
mov dx,GF1_Data_HIGH
out dx,al
; The DMA cycle will now start
;********************** Wait around for the DMA to finish **************
mov ecx,500000h
waitTC: test DMAPlay_TC,1
loopz waitTC
jz timoutERROR
mov DMAPlay_TC,0
mov dl,'#'
mov ah,2
int 21h
add DMA_DRAM_address,4000h
mov eax,GUS_MEMORY
cmp eax,DMA_DRAM_address
ja FILL_GUS_LOOP
;************************* Stop DRAM DMA cycle ********************
mov al,041h ; Set DRAM DMA Control Register
Mov dx,GF1_reg_select
out dx,al
mov dx,GF1_data_HIGH
mov al,00000000b ; stop IRQ's
out dx,al
writeln
exit:
; ****** program the 8237 DMA contollers *************
; Must turn of auto initalizing ????
; Sometimes my computer goes to about 1/8th of it's speed
; when if DMA auto initalizing bit is left on. Only a hardware reset
; will make it go back to normal.
mov al,00001000b ; DMA mode register
mov ah,DMAPlay_Chan ; Channel number ( 0..7 )
call DMA_setup
; ****** Terminate Program *************
mov ax,4C00h
int 21h
timoutERROR:
writeln 'ERROR: got no IRQ form GUS'
jmp exit
;******************** Gravis ultrasound IRQ handler ********************
GUS_ISR PROC
push ds ; Save all registers used
pushad
mov ax,_TEXT ; Load DS with data selector
mov ds,ax
;
; First determine if IRQ was form DMA Terminal Count or it was
; from one of the Voices. Note: we should never get an IRQ from
; a Voice since none of the GF1 voices registers have been programmed.
; Only the DRAM DMA IRQ thingy has been programmed.
mov dx,GF1_IRQ_status
in al,dx
test al,10000000b ; look for a DMA TC IRQ
jnz was_DMA_TC
;
; Must read the IRQ source register to clear the FIFO interrupts
;
mov dx,GF1_REG_Select
mov al,08fh
out dx,al
mov dx,GF1_DATA_High
in al,dx
jmp exit_ISR
was_DMA_TC:
;
; Read DRAM DMA controll register to allow more DRAM DMA IRQs.
; Reading this register will clear the IRQ pending bit so
; another DRAM DMA IRQ can occurr.
mov dx,GF1_REG_Select
mov al,041h ; DRAM DMA Control Register
out dx,al
mov dx,GF1_DATA_High ; read
in al,dx
or DMAPlay_TC,1
exit_ISR:
mov al,020h ; EOI to both PICs (8259)
out 20h,al
out 0A0h,al
popad
pop ds
iretd
GUS_ISR ENDP
;******************** End of Gravis ultrasound IRQ handler ******************
END The_Start