0,0 → 1,313 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2011. 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 |
;------------------------------------------------------------------------------- |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |