76a0cbdfe5
git-svn-id: svn://kolibrios.org@5363 a494cfbc-eb01-0410-851d-a64ba20cac60
314 lines
9.6 KiB
Plaintext
314 lines
9.6 KiB
Plaintext
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; ;;
|
|
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
|
|
;; Distributed under terms of the GNU General Public License ;;
|
|
;; ;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;--------------------------------
|
|
; program dma
|
|
;--------------------------------
|
|
sb_set_dma:
|
|
mov ebx, [sound_dma]
|
|
lea eax, [ebx+4];mask required channel
|
|
cmp bl, 4
|
|
ja .use_second_dma_controller
|
|
jb @f
|
|
.dma_setup_error:
|
|
if DEBUG
|
|
mov esi, msgErrDMAsetup
|
|
invoke SysMsgBoardStr
|
|
end if
|
|
mov dword[esp], START.stop
|
|
ret
|
|
@@:
|
|
if use_cli_sti
|
|
cli ;here to minimize time with disabled ints
|
|
end if
|
|
out 0xA, al;mask required channel
|
|
|
|
xor eax, eax
|
|
out 0xC, al;clear byte pointer flip-flop register
|
|
|
|
lea eax, [ebx+0x58];auto-init mode for channel (ebx)
|
|
out 0xB, al;DMA channel 0-3 mode register
|
|
|
|
mov eax, [SB16Buffer]
|
|
invoke GetPhysAddr
|
|
mov ecx, eax
|
|
shr eax, 16
|
|
|
|
movzx edx, byte[ebx+dma_table];page register
|
|
out dx, al
|
|
|
|
lea edx, [ebx*2];DMA channel 0-3 base address
|
|
|
|
mov al, cl;LSB
|
|
out dx, al
|
|
|
|
mov al, ch;MSB
|
|
out dx, al
|
|
|
|
inc edx ;DMA channel 0-3 byte count
|
|
|
|
mov al, ((sb_buffer_size-1) and 0xff)
|
|
out dx, al
|
|
|
|
mov al, ((sb_buffer_size-1) shr 8);it is the same
|
|
out dx, al
|
|
|
|
mov eax, ebx;unmask DMA channel
|
|
out 0xA, al
|
|
|
|
if use_cli_sti
|
|
sti
|
|
end if
|
|
ret
|
|
|
|
.use_second_dma_controller:
|
|
cmp bl, 7
|
|
ja .dma_setup_error
|
|
|
|
sub bl, 4
|
|
sub al, 4
|
|
if use_cli_sti
|
|
cli ;here to minimize time with disabled ints
|
|
end if
|
|
out 0xD4, al;mask required channel
|
|
|
|
xor eax, eax
|
|
out 0xD8, al;clear byte pointer flip-flop register
|
|
|
|
lea eax, [ebx+0x58];auto-init mode for channel (ebx+4)
|
|
out 0xD6, al;DMA channel 4-7 mode register
|
|
|
|
mov eax, [SB16Buffer]
|
|
invoke GetPhysAddr
|
|
mov ecx, eax
|
|
shr eax, 16
|
|
shr ecx, 1 ; 16-bit DMA takes offset in words
|
|
|
|
movzx edx, byte[ebx+dma_table+4];page register
|
|
out dx, al
|
|
|
|
lea edx, [ebx*4+0xC0];DMA channel 4-7 base address
|
|
|
|
mov al, cl;LSB;for 16bit DMA this contains
|
|
out dx, al;A1-A8 lines of address bus, A0 is zero
|
|
|
|
mov al, ch;MSB;for 16bit DMA this contains
|
|
out dx, al;A9-A16 lines of address bus
|
|
|
|
inc edx
|
|
inc edx ;DMA channel 4-7 16bit word count
|
|
|
|
mov al, (((sb_buffer_size/2)-1) and 0xff)
|
|
out dx, al
|
|
|
|
mov al, (((sb_buffer_size/2)-1) shr 8)
|
|
out dx, al
|
|
|
|
mov eax, ebx;unmask DMA channel
|
|
out 0xD4, al
|
|
|
|
if use_cli_sti
|
|
sti
|
|
end if
|
|
ret
|
|
;-------------------------------------------------------------------------------
|
|
; out byte to SB DSP's write port
|
|
;-------------------------------------------------------------------------------
|
|
macro sb_out data_to_out {
|
|
@@:
|
|
in al, dx
|
|
test al, al;is DSP busy?
|
|
js @b ;it's busy
|
|
mov al, data_to_out;it's free
|
|
out dx, al
|
|
}
|
|
;-------------------------------------------------------------------------------
|
|
; stop playing
|
|
;-------------------------------------------------------------------------------
|
|
proc sb_stop
|
|
mov edx, [sb_base_port]
|
|
add dl, 0xC
|
|
sb_out 0xD3 ;turn the speaker off
|
|
sb_out 0xDA ;exit 8bit DMA
|
|
sb_out 0xD9 ;exit 16bit DMA
|
|
ret
|
|
endp
|
|
;-------------------------------------------------------------------------------
|
|
; start playing
|
|
;-------------------------------------------------------------------------------
|
|
proc sb_play
|
|
and [int_flip_flop], 0
|
|
mov edx, [sb_base_port]
|
|
add dl, 0xC
|
|
sb_out 0xD1 ;turn speaker on
|
|
; sb_out 0x48 ;set DSP transfer size ;for older cards, not supported
|
|
; ;in this version
|
|
; mov ax,32767 ;(64k)/2-1
|
|
;@@: ;out the low byte...
|
|
; in al,dx
|
|
; test al,al ;is DSP busy?
|
|
; js @b ;it's busy
|
|
; out dx,al
|
|
|
|
; mov al,ah ;...then the high byte
|
|
;@@:
|
|
; in al,dx
|
|
; test al,al ;is DSP busy?
|
|
; js @b ;it's busy
|
|
; out dx,al
|
|
|
|
; sb_out 0x1C ;auto-init 8bit playback
|
|
|
|
; 0xBXh - 16 bit DMA mode
|
|
; ||||
|
|
sb_out 10110110b ;bCommand
|
|
; ||||
|
|
; |||+-reserved
|
|
; ||+--turn FIFO on (0 for off)
|
|
; |+---auto-init mode on (0 for off)
|
|
; +----A/D: 0-output, 1-input
|
|
; +------stereo on
|
|
; |+-----unsigned (1 for signed)
|
|
; ||
|
|
sb_out 00110000b ;bMode
|
|
; || ||||
|
|
; ---------reserved
|
|
;wSize is a number of 16bit samples less 1. For auto-init mode each half
|
|
;buffer is (64k)/2 bytes long and, obviously, contains ((64k)/2)/2 samples
|
|
sb_out (((sb_buffer_size/2/2)-1) and 0xFF) ;wSize.LowByte
|
|
sb_out (((sb_buffer_size/2/2)-1) shr 8) ;wSize.HighByte
|
|
ret
|
|
endp
|
|
;-------------------------------------------------------------------------------
|
|
; reset DSP
|
|
;-------------------------------------------------------------------------------
|
|
proc sb_reset
|
|
and [int_flip_flop], 0
|
|
mov edx, [sb_base_port]
|
|
add dl, 6
|
|
mov al, 1;start DSP reset
|
|
|
|
if use_cli_sti
|
|
cli ;here to minimize time with disabled ints
|
|
end if
|
|
out dx, al
|
|
mov ecx, 40;wait at least 3 microsec.
|
|
@@:
|
|
in al, dx
|
|
loop @b
|
|
|
|
xor eax, eax;stop DSP reset
|
|
if use_cli_sti
|
|
sti
|
|
end if
|
|
out dx, al
|
|
ret
|
|
endp
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; set the rate for playing, enable stereo
|
|
;-------------------------------------------------------------------------------
|
|
proc sb_setup
|
|
mov edx, [sb_base_port]
|
|
add dl, 0xC
|
|
sb_out 40h ;set time constant, this is for old cards
|
|
sb_out sb_tc
|
|
|
|
sb_out 41h ;set sound rate, this can only SB16
|
|
sb_out (sb_out_rate shr 8) ;first high byte (MSB)
|
|
sb_out (sb_out_rate and 0xff) ;then low byte (LSB)
|
|
|
|
; mov al,0xE ;for older cards, not supported in this version
|
|
; sub dl,(0xC-4) ;talk to SB's mixer
|
|
; out dx,al ;select this register of the mixer
|
|
; mov ecx,6 ;wait for the chip
|
|
;@@:
|
|
; in al,dx
|
|
; loop @b
|
|
|
|
; inc edx ;now read the data port
|
|
; in al,dx
|
|
; or al,22h ;turn on stereo
|
|
; mov ah,al
|
|
|
|
; mov al,0xE
|
|
; dec edx ;talk to SB's mixer
|
|
; out dx,al ;select this register of the mixer
|
|
|
|
; mov ecx,6 ;wait for the chip
|
|
;@@:
|
|
; in al,dx
|
|
; loop @b
|
|
|
|
; inc edx ;now send data to the data port
|
|
; mov al,ah
|
|
; out dx,al
|
|
|
|
; dec edx
|
|
; mov ecx,35 ;wait for the chip
|
|
;@@:
|
|
; in al,dx
|
|
; loop @b
|
|
ret
|
|
endp
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; set master volume of SB mixer, note, not only SB16 but SBPro and older
|
|
; this is the first step to more full support for hardware
|
|
;-------------------------------------------------------------------------------
|
|
;in: eax in range [-10000;0] - master volume for _both_ channels
|
|
;note that x*3*17/2000 and x*3/2000*17 are not the same numbers,
|
|
;because we count in integers
|
|
proc sb_set_master_vol
|
|
mov [sb_master_vol], eax
|
|
add eax, 10000;SB sound level rise from 0 to MAX_LEVEL
|
|
lea eax, [eax+eax*2];*3
|
|
mov ebx, 2000;divisor
|
|
xor edx, edx
|
|
cmp byte[sb_DSP_version_int], 4
|
|
jae @f ;SBPro's MAX_LEVEL is 15, but we *11 because
|
|
;volume byte looks like that: 0xLR, where L - left
|
|
;channel volume, R - right, 0<=R,L<=15
|
|
div ebx
|
|
imul eax, 17
|
|
mov edx, [sb_base_port]
|
|
push eax ;here for optimisation
|
|
add dl, 4
|
|
mov al, 0x22;write mixer register 0x22
|
|
out dx, al
|
|
in al, dx;wait for the chip ;6
|
|
in al, dx;wait for the chip ;5
|
|
in al, dx;wait for the chip ;4
|
|
in al, dx;wait for the chip ;3
|
|
in al, dx;wait for the chip ;2
|
|
in al, dx;wait for the chip ;1
|
|
pop eax ;go!
|
|
inc edx
|
|
out dx, al
|
|
ret
|
|
@@: ;SB16's MAX_LEVEL is 255
|
|
imul eax, 17
|
|
div ebx
|
|
mov edx, [sb_base_port]
|
|
push eax ;here for optimisation
|
|
add dl, 4
|
|
mov al, 0x30;left speaker
|
|
out dx, al
|
|
pop eax ;<--+
|
|
inc edx ; \/
|
|
push eax ;here for optimisation
|
|
out dx, al;write
|
|
dec edx
|
|
mov al, 0x31;right speaker
|
|
out dx, al
|
|
pop eax
|
|
inc edx
|
|
out dx, al;write
|
|
ret
|
|
endp
|
|
;-------------------------------------------------------------------------------
|