home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 21
/
CD_ASCQ_21_040595.iso
/
dos
/
prg
/
c
/
soundss3
/
detsound.asm
< prev
next >
Wrap
Assembly Source File
|
1995-03-10
|
33KB
|
1,337 lines
.MODEL MEDIUM
UGROUP0 GROUP CODE_SEG0
ASSUME CS:UGROUP0, DS:UGROUP0, SS:UGROUP0
.386
CODE_SEG0 SEGMENT PAGE USE16
LOCALS xx
;-----------------------------------------------------------------------------
; Main Routine and Interface
; IN: ES:BX = Zeiger auf Struktur
; OUT: AX = SoundcardType ;0=NO,1=SB/SBPRO,2=SB16,3=PAS,4=GUS
;
; meaning offset size
; baseport 0 dw 0
; dma_number 2 db 0
; irq_number 3 db 0
; samplerate 4 dw 0
; intern_type 6 db 0
; irq_type 7 db 0
; start_pos 8 db 0
; loop_pos 9 db 0
; song_mod 10 db 0
; char master_vol 11 db 0
; char music_vol 12 db 0
; char fx_vol 13 db 0
;-----------------------------------------------------------------------------
PUBLIC _MAIN0
_MAIN0 PROC FAR
CALL DetectSound
SETC DL
XOR DH,DH
MOV AX,CS:SoundPort
MOV ES:[BX],AX
MOV AL,CS:SoundDMA
MOV ES:[BX+2],AL
MOV AL,CS:SoundIRQ
MOV ES:[BX+3],AL
MOV AX,22222
MOV ES:[BX+4],AX ;DEFAULT SAMPLERATE = 22222
XOR AX,AX
MOV ES:[BX+6],AL ;DEFAULT INTERN TYPE = 0
MOV ES:[BX+8],AL ;START_POS = 0
MOV ES:[BX+9],AL ;LOOP_POS = 0 (ENDLESS LOOPING)
MOV ES:[BX+10],AL ;SONG_MOD = 0
INC AL
MOV ES:[BX+7],AL ;IRQ DEFAULT TO WINDOWS (TIMER)
DEC AL
DEC AL
MOV ES:[BX+11],AL ;VOLUMES TO MAX
MOV ES:[BX+12],AL
MOV ES:[BX+13],AL
MOV AL,CS:SoundType
CMP AL,2
JB SHORT MEND
JA SHORT MT1
DEC AL
MOV ES:[BX+6],AL
JMP SHORT MEND
MT1: CMP AL,3
JNE SHORT MT2
INC AL
JMP SHORT MEND
MT2: CMP AL,4
JNE SHORT MT3
DEC AL
JMP SHORT MEND
MT3: CMP AL,5
JNE SHORT MEND
MOV AL,2
MEND: RETF
SoundType db 0 ;0=no,1=SB,2=SBPro,3=GUS,4=PAS16,5=SB16
SoundPort dw 0
SoundDMA db 0
SoundIRQ db 0
_MAIN0 ENDP
;-----------------------------------------------------------------------------
;(Auto)detect Soundkarte: c=0 ok
DetectSound proc near
pusha
push ds es cs
pop es
mov di,offset xxULTRASND
call GetEnv
jnc short xxGUSEnv
xxSBNoGUS: mov di,offset xxBLASTER
call GetEnv
jnc short xxSBEnv
xor dx,dx
mov cs:SoundType,3
call DetGUSHW
mov cs:SoundPort,dx
jnc xxEndDetect
mov cs:SoundType,4
call detectPAS
jnc xxEndDetect
mov cs:SoundType,1
xxSBHW: call detectSBProHW
jnc xxEndDetect
call detectSBHW
jnc xxEndDetect
jmp xxErrorDetect
xxGUSEnv: mov cs:SoundType,3
call GetValue
mov cs:SoundPort,ax
jc short xxSBNoGUS
call GetValue
mov cs:SoundDMA,al
jc short xxSBNoGUS
call GetValue
jc short xxSBNoGUS
call GetValue
mov cs:SoundIRQ,al
jc short xxSBNoGUS
mov dx,cs:SoundPort
call DetGUSHW
jc short xxSBNoGUS
jmp short xxEndDetect
xxSBEnv: mov cs:SoundType,1
xxNextSB: lodsb
cmp al,0
je short xxSBEnd
and al,11011111b
cmp al,'A'
jne short xxNoA
call GetValue
mov cs:SoundPort,ax
jnc short xxNextSB
jmp short xxSBEnd
xxNoA: cmp al,'I'
jne short xxNoI
call GetValue
mov cs:SoundIRQ,al
jnc short xxNextSB
jmp short xxSBEnd
xxNoI: cmp al,'D'
jne short xxNoD
call GetValue
mov cs:SoundDMA,al
jnc short xxNextSB
jmp short xxSBEnd
xxNoD: cmp al,'T'
jne short xxNextSB
call GetValue
pushf
cmp al,3
jb short xxSBOld
mov cs:SoundType,2
cmp al,4
jb short xxSBOld
mov cs:SoundType,5
xxSBOld: popf
jnc short xxNextSB
xxSBEnd: xor ax,ax
cmp cs:SoundPort,ax
je xxSBHW
cmp cs:SoundIRQ,al
je xxSBHW
cmp cs:SoundDMA,al
je xxSBHW
xxEndDetect: xor ax,ax
cmp cs:SoundPort,ax
je short xxErrorDetect
cmp cs:SoundIRQ,al
je short xxErrorDetect
cmp cs:SoundDMA,al
je short xxErrorDetect
clc
pop es ds
popa
ret
xxErrorDetect: stc
mov cs:SoundType,0
jmp short xxEndDetect
xxBLASTER db "BLASTER",0
xxULTRASND db "ULTRASND",0
DetectSound endp
;------------------------------------------------------------------------------
;Liest Wert (hex) ab ds:si, zurück in ax, c=1 String mit 0 terminiert
GetValue proc near
push bx
xor ax,ax
xor bx,bx
xxNoStart: lodsb
cmp al,' '
je short xxNoStart
jmp short xxEntry
xxNext: lodsb
xxEntry: cmp al,' '
je short xxEnd2
cmp al,','
je short xxEnd2
and al,11011111b
cmp al,40h
jb short xxNoChar
add al,9
xxNoChar: and al,0fh
shl bx,4
add bx,ax
jmp short xxNext
xxEnd1: stc
mov ax,bx
pop bx
ret
xxEnd2: clc
mov ax,bx
pop bx
ret
GetValue endp
;------------------------------------------------------------------------------
;holt Umgebungsvariable es:di, ds:si zeigt auf erstes Zeichen, c=1 Fehler
GetEnv proc near
push bx
push di
push es
mov ah,62h ;ds:si points at dos env.
int 21h
mov ds,bx
mov ds,ds:2ch
xor si,si
xxLoop3: xor bx,bx
xxLoop: lodsb
cmp al,0
je short xxError
cmp al,es:[di+bx]
jne short xxNextOne
inc bx
jmp short xxLoop
xxNextOne: cmp al,'='
jne short xxLoop2
cmp es:[di+bx],byte ptr 0
je short xxGotIt
xxLoop2: lodsb
cmp al,0
jne short xxLoop2
jmp short xxLoop3
xxError: stc
jmp short xxEnde
xxGotIt: clc
xxEnde: pop es
pop di
pop bx
ret
GetEnv endp
;------------------------------------------------------------------------------
;Autodetect/Check GUS
;dx = port, dx = 0 -> autodetect, else check port
DetGUSHW proc near
pusha
push ds
push es
mov bp,1
mov si,dx
xor di,di
cmp dx,di
jne short xxnoAutodetect
mov si,210h
mov bp,6
mov di,-1
xxnoAutodetect: mov bx,si
mov cs:xxBasePort,bx
add bx,6h
mov cs:xxStatusPort,bx
add bx,2+1+100h-9h+3
mov cs:xxCommandPort,bx
inc bx
mov cs:xxDataLowPort,bx
inc bx
mov cs:xxDataHighPort,bx
add bx,2
mov cs:xxDRAMIOPort,bx
mov bx,cs:xxCommandPort
mov cx,cs:xxDataHighPort
mov dx,bx
mov al,4ch ;Initialize
out dx,al
mov dx,cx
mov al,0
out dx,al
mov dx,cs:xxBasePort
REPT 8
in al,dx
ENDM
mov dx,bx
mov al,4Ch
out dx,al
mov dx,cx
mov al,1
out dx,al
mov dx,cs:xxBasePort
REPT 8
in al,dx
ENDM
mov dx,bx
mov al,41h ;DMACtrl
out dx,al
mov dx,cx
mov al,0
out dx,al
mov dx,bx
mov al,45h
out dx,al
mov dx,cx
mov al,0
out dx,al
mov dx,bx
mov al,49h
out dx,al
mov dx,cx
mov al,0
out dx,al
mov dx,bx
mov al,0eh ;VoicesActive
out dx,al
mov dx,cx
mov al,20 ;NumVoices
dec al
or al,0C0h
out dx,al
mov dx,cs:xxStatusPort
in al,dx
mov dx,bx
mov al,41h ;DMACtrl
out dx,al
mov dx,cx
in al,dx
mov dx,bx
mov al,49h
out dx,al
mov dx,cx
in al,dx
mov dx,bx
mov al,8Fh
out dx,al
mov dx,cx
in al,dx
mov dx,bx
mov al,4ch
out dx,al
mov dx,cx
mov al,7
out dx,al
mov dx,cs:xxCommandPort
mov al,43h ;DRAMAddrLo
out dx,al
mov dx,cs:xxDataLowPort
mov ax,113h
out dx,ax
mov dx,cs:xxCommandPort
mov al,44h ;DRAMAddrHi
out dx,al
mov dx,cs:xxDataHighPort
xor al,al
out dx,al
mov dx,cs:xxDRAMIOPort
mov al,0d4h ;testwert 1 d4h
out dx,al
mov dx,cs:xxCommandPort
mov al,43h ;DRAMAddrLo
out dx,al
mov dx,cs:xxDataLowPort
mov ax,12h ;testweise mal 12h beschreiben
out dx,ax
mov dx,cs:xxCommandPort
mov al,44h ;DRAMAddrHi
out dx,al
mov dx,cs:xxDataHighPort
xor al,al
out dx,al
mov dx,cs:xxDRAMIOPort
mov al,53h ;testwert 2 53h
out dx,al
mov dx,cs:xxCommandPort
mov al,43h ;DRAMAddrLo
out dx,al
mov dx,cs:xxDataLowPort
mov ax,113h ;also testwert 1 lesen
out dx,ax
mov dx,cs:xxCommandPort
mov al,44h ;DRAMAddrHi
out dx,al
mov dx,cs:xxDataHighPort
xor al,al
out dx,al
mov dx,cs:xxDRAMIOPort
in al,dx ;speicher lesen
cmp al,0d4h ;testwert Ok ?
jne short xxnotfound
mov dx,cs:xxCommandPort
mov al,43h ;DRAMAddrLo
out dx,al
mov dx,cs:xxDataLowPort
mov ax,12h ;testoffset 2
out dx,ax
mov dx,cs:xxCommandPort
mov al,44h ;DRAMAddrHi
out dx,al
mov dx,cs:xxDataHighPort
xor al,al
out dx,al
mov dx,cs:xxDRAMIOPort
in al,dx
cmp al,53h ;wert = testwert 2 ?
jne short xxnotfound ;nö, nicht gefunden
jmp short xxfoundGUS
xxnotfound:
cmp di,0ffffh
jne short xxno
add si,10h
dec bp
jnz xxnoAutodetect
xxno:
pop es
pop ds
popa
xor dx,dx
stc ;Carry setzen
ret
xxfoundGUS: pop es
pop ds
popa
mov dx,cs:xxBasePort
clc
ret
xxBasePort dw 0
xxStatusPort dw 0
xxCommandPort dw 0
xxDataLowPort dw 0
xxDataHighPort dw 0
xxDRAMIOPort dw 0
DetGUSHW endp
; /***********************************************************************
; *
; * File : DETSBHW.ASM
; *
; * Description : Sound Blaster hardware detection routines
; *
; ************************************************************************
waitSB MACRO
local l1
l1:
in al,dx
or al,al
js short l1
ENDM
waitSBport MACRO
local l1
mov dx,cs:SoundPort
add dx,0Ch
l1:
in al,dx
or al,al
js short l1
ENDM
waitSBPROport MACRO
local l1
mov dx,cs:SoundPort
add dx,0Ch
l1:
in al,dx
or al,al
js short l1
ENDM
;/*************************************************************************
; *
; * Function : checkPort_SB
; *
; * Description : Checks if given address is SB's I/O address
; *
; * Input : DX = port to check
; *
; * Returns : AX = 0 successful
; * AX = 1 unsuccessful
; *
; ************************************************************************/
checkPort_SB proc near
push dx
add dl,6 ; Init Sound Blaster
mov al,1
out dx,al
in al,dx ; Wait for awhile
in al,dx
in al,dx
in al,dx
in al,dx
mov al,0
out dx,al
sub dl,6
add dl,0Eh ; DSP data available status
mov cx,1000
xxloop:
in al,dx ; port 22Eh
or al,al
js short xx10
loop short xxloop
mov ax,1
jmp short xxexit
xx10:
sub dl,4
in al,dx ; port 22Ah
cmp al,0AAh ; Is ID 0AAh?
mov ax,0
je short xxexit
mov ax,1
xxexit:
pop dx
or ax,ax ; Set zero-flag accordingly
ret
checkPort_SB endp
;/*************************************************************************
; *
; * Function : findDMAIRQ_SB
; *
; * Description : Finds SB's DMA interrupt number
; *
; * Returns : AX = 0 error
; * AX = port number (2,3,5,7)
; *
; ************************************************************************/
findDMAIRQ_SB proc near
push ds
push es
mov ah,35h
mov al,8+2
int 21h
mov cs:xxsaveVect+2,es
mov cs:xxsaveVect,bx
mov al,8+3
int 21h
mov cs:xxsaveVect+6,es
mov cs:xxsaveVect+4,bx
mov al,8+5
int 21h
mov cs:xxsaveVect+10,es
mov cs:xxsaveVect+8,bx
mov al,8+7
int 21h
mov cs:xxsaveVect+14,es
mov cs:xxsaveVect+12,bx
mov ah,25h
mov dx,offset DMA2 ; Set vectors
mov al,8+2
int 21h
mov dx,offset DMA3
mov al,8+3
int 21h
mov dx,offset DMA5
mov al,8+5
int 21h
mov dx,offset DMA7
mov al,8+7
int 21h
in al,21h
mov cs:xxintMask,al ; Save interrupt mask
mov al,0FFh
out 21h,al ; Mask out all interrupts
cli ; Disable interrupts
mov al,cs:xxintMask
and al,01010011b ; Allow DMA interrupts (2,3,5 & 7)
out 21h,al
sti ; Set DMA up
mov al,5
out 0Ah,al ; Break on
mov al,0
out 0Ch,al ; Reset counter
mov al,49h
out 0Bh,al ; DMA -> DSP (output)
mov al,0
out 83h,al ; page 0
mov al,0
out 2,al ; offset 0
mov al,0
out 2,al ; whole address is 0000:0000
mov al,1
out 3,al ; count = 1
mov al,0
out 3,al
mov al,1
out 0Ah,al ; Break off
mov dx,cs:SoundPort
add dx,0Ch
waitSB
mov al,40h ; Set DSP speed
out dx,al
waitSB
mov al,0D3h ; 22222 Hz
out dx,al
waitSB
mov al,14h ; 14h = output command
out dx,al
waitSB
mov al,1 ; digitize 1 byte
out dx,al
waitSB
mov al,0
out dx,al
mov cx,0FFFFh ; Big loop
mov cs:SoundIRQ,byte ptr 0 ; Clear interrupt value
xxloop:
cmp cs:SoundIRQ,byte ptr 0 ; Wait dmaIRQ to change
loope short xxloop ; loop if it doesn't
mov dx,cs:SoundPort
add dl,0Eh
in al,dx ; Reset SB
mov al,cs:xxintMask
out 21h,al ; Restore interrupt mask
sti ; Allow interrupts
push ds
mov ah,25h
lds dx,dword ptr cs:xxsaveVect
mov al,8+2
int 21h
lds dx,dword ptr cs:xxsaveVect+4
mov al,8+3
int 21h
lds dx,dword ptr cs:xxsaveVect+8
mov al,8+5
int 21h
lds dx,dword ptr cs:xxsaveVect+12
mov al,8+7
int 21h
pop ds
pop es
pop ds
sub ax,ax
mov al,cs:SoundIRQ ; Return with interrupt number
ret
xxsaveVect dw 8 dup(0)
xxintMask db 0
findDMAIRQ_SB endp
;/*************************************************************************
; *
; * Function : findDMAIRQ_SBpro
; *
; * Description : Finds SBpro's DMA interrupt number
; *
; * Returns : AX = 0 error
; * AX = IRQ number (2,3,5,7,10)
; *
; ************************************************************************/
findDMAIRQ_SBpro proc near
push ds
push es
mov ah,35h
mov al,8+2
int 21h
mov cs:xxsaveVect+2,es
mov cs:xxsaveVect,bx
mov al,8+5
int 21h
mov cs:xxsaveVect+6,es
mov cs:xxsaveVect+4,bx
mov al,8+7
int 21h
mov cs:xxsaveVect+10,es
mov cs:xxsaveVect+8,bx
mov al,72h
int 21h
mov cs:xxsaveVect+14,es
mov cs:xxsaveVect+12,bx
in al,21h
mov cs:xxintMask1,al ; Save interrupt mask
mov al,0FFh
out 21h,al ; Mask out all interrupts
in al,0A1h
mov cs:xxintMask2,al ; Save interrupt mask
mov al,0FFh
out 0A1h,al ; Mask out all interrupts
cli ; Disable interrupts
push cs
pop ds
mov ah,25h
mov dx,offset DMA2 ; Set vectors
mov al,8+2
int 21h
mov dx,offset DMA5
mov al,8+5
int 21h
mov dx,offset DMA7
mov al,8+7
int 21h
mov dx,offset DMA10
mov al,72h
int 21h
mov al,cs:xxintMask1
and al,01010011b ; Allow DMA interrupts (2,3,5 & 7)
out 21h,al
mov al,cs:xxintMask2
and al,11111011b ; Allow DMA interrupt 10
out 0A1h,al
sti
mov cx,1000
xxwaitloop:
in al,21h
loop short xxwaitloop
mov al,4
out 0Ah,al ; Break on
mov al,5
out 0Ah,al ; Break on
mov al,7
out 0Ah,al ; Break on
mov dx,cs:SoundPort
add dx,0Ch
waitSB
mov al,40h ; Set DSP speed
out dx,al
waitSB
mov al,0D3h ; 22222 Hz
out dx,al
waitSB
mov al,14h ; 14h = output command
out dx,al
waitSB
mov al,10 ; digitize 1 byte
out dx,al
waitSB
mov al,0
out dx,al
sti
mov ax,1 ; Check for DMA channel 1
call findDMAchannel_SBpro
or ax,ax
jnz short xxchannelFound
mov ax,0 ; Channel 0
call findDMAchannel_SBpro
or ax,ax
jnz short xxchannelFound
mov ax,3 ; Channel 3
call findDMAchannel_SBpro
or ax,ax
jnz short xxchannelFound
mov cs:SoundIRQ,0
xxchannelFound:
mov cs:SoundDMA,al
mov dx,cs:SoundPort
add dl,6 ; Init Sound Blaster
mov al,1
out dx,al
in al,dx ; Wait for awhile
in al,dx
in al,dx
in al,dx
in al,dx
mov al,0
out dx,al
sub dl,6
add dx,0Eh ; Reset SB
in al,dx
push ds
mov ah,25h
lds dx,dword ptr cs:xxsaveVect
mov al,8+2
int 21h
lds dx,dword ptr cs:xxsaveVect+4
mov al,8+5
int 21h
lds dx,dword ptr cs:xxsaveVect+8
mov al,8+7
int 21h
lds dx,dword ptr cs:xxsaveVect+12
mov al,72h
int 21h
pop ds
mov al,cs:xxintMask1
out 21h,al ; Restore interrupt mask
mov al,cs:xxintMask2
out 0A1h,al ; Restore interrupt mask
sti ; Allow interrupts
pop es
pop ds
sub ax,ax
mov al,cs:SoundIRQ ; Return with interrupt number
ret
xxsaveVect dw 8 dup(0)
xxintMask1 db 0
xxintMask2 db 0
findDMAIRQ_SBpro endp
;/*************************************************************************
; *
; * Function : findDMAchannel_SBpro
; *
; * Description : Checks if given channel is the channel SBPro uses
; *
; * Input : AX = Channel to test
; *
; * Returns : AX = 0 if error
; * AX = channel if OK
; *
; ************************************************************************/
findDMAchannel_SBpro proc near
mov cs:xxchannel,al
add al,4
out 0Ah,al ; Break on
mov al,0
out 0Ch,al ; Reset counter
mov al,48h
add al,cs:xxchannel
out 0Bh,al ; DMA -> DSP (output)
mov dx,87h
cmp cs:xxchannel,byte ptr 0
je short xx10
mov dx,83h
cmp cs:xxchannel,byte ptr 1
je short xx10
mov dx,82h ; Channel is 3
xx10:
mov al,0
out dx,al ; page 0
mov dl,cs:xxchannel
shl dx,1
mov al,0
out dx,al ; offset 0
mov al,0
out dx,al ; whole address is 0000:0000
inc dx
mov al,10
out dx,al ; count = 10
mov al,0
out dx,al
mov al,cs:xxchannel
out 0Ah,al ; Break off
mov cx,0FFFFh ; Big loop
mov cs:SoundIRQ,byte ptr 0 ; Clear interrupt value
xxloop:
cmp cs:SoundIRQ,byte ptr 0 ; Wait dmaIRQ to change
loope short xxloop ; loop if it doesn't
mov al,cs:xxchannel
add al,4
out 0Ah,al ; Break on
mov al,0
out 0Ch,al ; Reset counter
mov al,cs:xxchannel
out 0Ah,al ; Break off
sub ax,ax
cmp cs:SoundIRQ,byte ptr 0
je short xxexit
inc ah ; Indicate success
mov al,cs:xxchannel
xxexit:
ret
xxchannel db 0
findDMAchannel_SBpro endp
;/*************************************************************************
; *
; * Function : DMAint_SB
; *
; * Description : Interrupt function that determines SB's interrupt
; *
; ************************************************************************/
DMAint_SB proc near
DMA2:
push ds
push ax
mov cs:SoundIRQ,byte ptr 2 ; Set interrupt number
jmp short xxDMAdone
DMA3:
push ds
push ax
mov cs:SoundIRQ,byte ptr 3
jmp short xxDMAdone
DMA5:
push ds
push ax
mov cs:SoundIRQ,byte ptr 5
jmp short xxDMAdone
DMA7:
push ds
push ax
mov cs:SoundIRQ,byte ptr 7
jmp short xxDMAdone
DMA10:
push ds
push ax
mov cs:SoundIRQ,byte ptr 10
mov al,20h
out 0A0h,al
xxDMAdone:
mov al,20h
out 20h,al ; EOI (end of interrupt)
pop ax
pop ds
iret
DMAint_SB endp
;/*************************************************************************
; *
; * Function : detectSB
; *
; * Description : Checks for presence of SB.
; *
; * Returns : c=0 if succesful
; * c=1 on error (no card found)
; *
; ************************************************************************/
detectSBHW proc near
mov cs:xxretvalue,word ptr -1 ; Assume failure
mov dx,220h
call checkPort_SB
jz short xxOK
mov dx,210h
call checkPort_SB ; Check for every possible I/O value
jz short xxOK
mov dx,230h
call checkPort_SB
jz short xxOK
mov dx,240h
call checkPort_SB
jz short xxOK
mov dx,250h
call checkPort_SB
jz short xxOK
mov dx,260h
call checkPort_SB
jnz short xxexit ; No match found, error exit
xxOK:
mov cs:SoundPort,dx ; ioPort is for internal use only
push es
push di
call findDMAIRQ_SB ; Find DMA interrupt number
pop di
pop es
or ax,ax ; 0 = error
jz short xxexit
mov cs:SoundIRQ,al
mov cs:SoundDMA,1
mov cs:xxretrycount,word ptr 10
xxretry:
dec word ptr cs:xxretrycount
jnz short xxcontinue
mov ax,0 ; not found
jmp short xxdone
xxcontinue:
mov dx,cs:SoundPort
add dx,0Ch
waitSB
mov al,0E1h ; Read version number
out dx,al
add dl,2 ; DX = 22Eh
sub al,al
mov cx,1000
xx10:
in al,dx ; Read version high
or al,al
js short xx10ok
loop short xx10
jmp short xxretry
xx10ok:
mov cx,1000
sub dl,4
in al,dx
mov ah,al
add dl,4
sub al,al
xx20:
in al,dx ; Read version low
or al,al
js short xx20ok
loop short xx20
jmp short xxretry
xx20ok:
sub dl,4
in al,dx
xxdone:
mov cs:xxretvalue,word ptr 0
xxexit:
mov ax,cs:xxretvalue
or ax,ax
jne short xxexiterror
clc
ret
xxexiterror:
stc
ret
xxretvalue dw 0
xxretrycount dw 0
detectSBHW endp
;/*************************************************************************
; *
; * Function : detectSBProHW
; *
; * Description : Checks for presence of SB Pro.
; *
; * Returns : c=0 if succesful
; * c=1 on error (no card found)
; *
; ************************************************************************/
detectSBProHW proc near
mov cs:xxretvalue,word ptr -1 ; Assume failure
mov dx,220h
call checkPort_SB
jz short xxOK
mov dx,210h
call checkPort_SB ; Check for every possible I/O value
jz short xxOK
mov dx,230h
call checkPort_SB
jz short xxOK
mov dx,240h
call checkPort_SB
jz short xxOK
mov dx,250h
call checkPort_SB
jz short xxOK
mov dx,260h
call checkPort_SB
jnz xxexit ; No match found, error exit
xxOK:
mov cs:SoundPort,dx ; ioPort is for internal use only
mov cs:xxretrycount,word ptr 10
xxretry:
dec word ptr cs:xxretrycount
jnz short xxcontinue
mov ax,0 ; not found
jmp short xxdone
xxcontinue:
mov dx,cs:SoundPort
add dx,0Ch
waitSB
mov al,0E1h ; Read version number
out dx,al
add dl,2 ; DX = 22Eh
sub al,al
mov cx,1000
xx10:
in al,dx ; Read version high
or al,al
js short xx10ok
loop short xx10
jmp short xxretry
xx10ok:
mov cx,1000
sub dl,4
in al,dx
mov ah,al
add dl,4
sub al,al
xx20:
in al,dx ; Read version low
or al,al
js short xx20ok
loop short xx20
jmp short xxretry
xx20ok:
sub dl,4
in al,dx
xxdone:
cmp ax,0300h
jl short xxexit ; Not SBpro
mov cs:SoundType,2 ;is sb16
cmp ax,0400h
jl short xxpro
mov cs:SoundType,5 ;is sb16
xxpro:
push es
push di
call findDMAIRQ_SBpro ; Find DMA interrupt number
pop di
pop es
or ax,ax ; 0 = error
jz short xxexit
mov cs:SoundIRQ,al
mov cs:xxretvalue,word ptr 0
xxexit:
mov ax,cs:xxretvalue
or ax,ax
jne short xxexiterror
clc
ret
xxexiterror:
stc
ret
xxretvalue dw 0
xxretrycount dw 0
detectSBProHW endp
;/*************************************************************************
; *
; * Function : detectPAS
; *
; * Description : Checks for presence of PAS16.
; *
; * Returns : c=0 if successful
; * c=1 on error (no card found)
; *
; ************************************************************************/
DEFAULT_BASE EQU 00388h ;; default base I/O address
ALT_BASE_1 EQU 00384h ;; first alternate address
ALT_BASE_2 EQU 0038Ch ;; second alternate address
ALT_BASE_3 EQU 00288h ;; third alternate address
ALT_BASE_4 EQU 00280h ;; 4th alternate address
ALT_BASE_5 EQU 00284h ;; 5th alternate address
ALT_BASE_6 EQU 0028Ch ;; 6th alternate address
INTRCTLR EQU 00B8Bh ;; Interrupt Control Register write
fICrevbits EQU 11100000B ;; revision mask field bits
detectPAS proc near
mov di,DEFAULT_BASE ; try the first address
mov SoundPort,di
call SearchHWVersion
jnc xxpas_ok
mov di,ALT_BASE_1 ; try the first alternate
mov SoundPort,di
call SearchHWVersion
jnc xxpas_ok
mov di,ALT_BASE_2 ; try the second alternate
mov SoundPort,di
call SearchHWVersion
jnc xxpas_ok
mov di,ALT_BASE_3 ; try the third alternate
mov SoundPort,di
call SearchHWVersion
jnc xxpas_ok
mov di,ALT_BASE_4 ; try the 4th alternate
mov SoundPort,di
call SearchHWVersion
jnc xxpas_ok
mov di,ALT_BASE_5 ; try the 5th alternate
mov SoundPort,di
call SearchHWVersion
jnc xxpas_ok
mov di,ALT_BASE_6 ; try the 6th alternate
mov SoundPort,di
call SearchHWVersion
xxpas_ok:
ret
detectPAS endp
; /*\
;---|*|----====< SearchHWVersion >====----
;---|*|
;---|*| Given a specific I/O address, this routine will see if the
;---|*| hardware exists at this address.
;---|*|
;---|*| Entry Conditions:
;---|*| DI holds the I/O address to test
;---|*|
;---|*| Exit Conditions:
;---|*| c=0 ok
;---|*| c=1 no card found
; \*/
SearchHWVersion proc near
;
; calculate the translation code
;
xor di,DEFAULT_BASE ; di holds the translation code
mov ax,0BC00H ; make sure MVSOUND.SYS is loaded
mov bx,'??' ; this is our way of knowing if the
xor cx,cx ; hardware is actually present.
xor dx,dx
int 2fh ; get the ID pattern
xor bx,cx ; build the result
xor bx,dx
cmp bx,'MV' ; if not here, exit...
jnz xxbad
;
; get the MVSOUND.SYS specified DMA and IRQ channel
;
mov ax,0bc04h ; get the DMA and IRQ numbers
int 2fh
mov cs:SoundDMA,bl ; save the correct DMA & IRQ
mov cs:SoundIRQ,cl
;
; grab the version # in the interrupt mask. The top few bits hold the version #
;
mov dx,INTRCTLR ; board ID is in MSB 3 bits
xor dx,di ; adjust to other address
in al,dx
cmp al,-1 ; bus float meaning not present?
je xxbad ; yes, there is no card here
mov ah,al ; save an original copy
xor al,fICrevbits ; the top bits wont change
out dx,al ; send out the inverted bits
jmp xxl1
xxl1: jmp xxl2
xxl2: in al,dx ; get it back...
cmp al,ah ; both should match now...
xchg al,ah ; (restore without touching the flags)
out dx,al
jnz xxbad ; we have a bad board
;
; We do have hardware! Load the product bit definitions
;
clc
ret
xxbad: stc
ret
SearchHWVersion endp
CODE_SEG0 ENDS
END _MAIN0