Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 5076 → Rev 5077

/drivers/audio/sisnbook/codec.inc
File deleted
/drivers/audio/sisnbook/readme.txt
File deleted
/drivers/audio/sisnbook/sis.asm
File deleted
\ No newline at end of file
/drivers/audio/sisnbook
Property changes:
Deleted: svn:ignore
-*.o
-*.obj
/drivers/audio/codec.inc
0,0 → 1,326
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
AD_LOSEL equ BIT5
AD_HPSEL equ BIT10
 
align 4
proc detect_codec
locals
codec_id dd ?
endl
 
stdcall codec_read, dword 0x7C
shl eax, 16
mov [codec_id], eax
 
stdcall codec_read, dword 0x7E
or eax, [codec_id]
 
mov [codec.chip_id], eax
and eax, 0xFFFFFF00
 
mov edi, codecs
@@:
mov ebx, [edi]
test ebx, ebx
jz .unknown
 
cmp eax, ebx
jne .next
mov eax, [edi+4]
mov [codec.ac_vendor_ids], eax
mov esi, eax
invoke SysMsgBoardStr
stdcall detect_chip, [edi+8]
 
ret
.next:
add edi, 12
jmp @B
.unknown:
mov [codec.ac_vendor_ids], ac_unknown
mov [codec.chip_ids], chip_unknown
 
mov esi, chip_unknown
invoke SysMsgBoardStr
mov eax, [codec.chip_id]
call dword2str
invoke SysMsgBoardStr
ret
endp
 
align 4
proc detect_chip stdcall, chip_tab:dword
 
mov eax, [codec.chip_id]
and eax, 0xFF
 
mov edi, [chip_tab]
@@:
mov ebx, [edi]
cmp ebx, 0xFF
je .unknown
 
cmp eax, ebx
jne .next
mov eax, [edi+4]
mov [codec.chip_ids], eax
mov esi, eax
invoke SysMsgBoardStr
ret
.next:
add edi, 8
jmp @b
.unknown:
mov [codec.chip_ids], chip_unknown
mov esi, chip_unknown
invoke SysMsgBoardStr
mov eax, [codec.chip_id]
call dword2str
invoke SysMsgBoardStr
ret
endp
 
align 4
proc setup_codec
 
xor eax, eax
stdcall codec_write, dword CODEC_AUX_VOL
 
mov eax, 0x0B0B
stdcall codec_write, dword CODEC_MASTER_VOL_REG
 
mov ax, 0x08
stdcall codec_write, dword 0x0C
 
mov ax, 0x0808
stdcall codec_write, dword CODEC_PCM_OUT_REG
 
mov ax, 0x0808
stdcall codec_write, dword 0x10
 
mov ax, 0x0808
stdcall codec_write, dword 0x12
 
mov ax, 0x0808
stdcall codec_write, dword 0x16
 
 
stdcall codec_read, dword CODEC_EXT_AUDIO_CTRL_REG
and eax, 0FFFFh - BIT1 ; clear DRA (BIT1)
or eax, BIT0 ; set VRA (BIT0)
stdcall codec_write, dword CODEC_EXT_AUDIO_CTRL_REG
 
stdcall set_sample_rate, dword 48000
 
.init_error:
xor eax, eax ; exit with error
ret
endp
 
 
; param
; eax= volume -10000 - 0 for both channels
 
align 4
set_master_vol:
cmp eax, 0
jl @F
xor eax, eax
jmp .set
@@:
cmp eax, -9450
jg .set
mov eax, -9450 ;clamp into 6 bits
.set:
cdq
mov ebx, -150
idiv ebx
mov ah, al
stdcall codec_write, dword CODEC_MASTER_VOL_REG
xor eax, eax
ret
 
align 4
proc get_master_vol stdcall, pvol:dword
 
stdcall codec_read, dword CODEC_MASTER_VOL_REG
and eax, 0x3F
imul eax, -150
mov ebx, [pvol]
mov [ebx], eax
xor eax, eax
ret
endp
 
align 4
proc set_sample_rate stdcall, rate:dword
mov eax, [rate]
stdcall codec_write, dword CODEC_PCM_FRONT_DACRATE_REG
ret
endp
 
patch_AD:
stdcall codec_read, 0x76
or ax, BIT5+BIT10
stdcall codec_write, 0x76
ret
 
 
align 16
ac_unknown db 'unknown manufacturer',13,10,0
ac_Realtek db 'Realtek Semiconductor',13,10,0
ac_Analog db 'Analog Devices',13,10,0
ac_CMedia db 'C-Media Electronics',13,10,0
ac_Cirrus db 'Cirrus Logic',13,10,0
ac_Wolfson db 'Wolfson Microelectronics',13,10,0
ac_VIA db 'VIA Technologies',13,10,0
ac_SigmaTel db 'SigmaTel',13,10,0
ac_eMicro db 'eMicro',13,10,0
 
chip_unknown db 'unknown codec id ', 0
 
CHIP_ANALOG equ 0x41445300
CHIP_REALTEK equ 0x414C4700
CHIP_CMEDIA equ 0x434D4900
CHIP_CIRRUS equ 0x43525900
CHIP_WOLFSON equ 0x574D4C00
CHIP_VIA equ 0x56494100
CHIP_SIGMATEL equ 0x83847600
CHIP_EMICRO equ 0x454D4300
 
align 16
codecs dd CHIP_ANALOG, ac_Analog, chips_Analog
dd CHIP_CMEDIA, ac_CMedia, chips_CMedia
dd CHIP_REALTEK,ac_Realtek, chips_Realtek
dd CHIP_CIRRUS, ac_Cirrus, chips_Cirrus
dd CHIP_WOLFSON,ac_Wolfson, chips_Wolfson
dd CHIP_VIA, ac_VIA, chips_VIA
dd CHIP_SIGMATEL, ac_SigmaTel, chips_SigmaTel
dd CHIP_EMICRO, ac_eMicro, chips_eMicro
dd 0
 
align 16
chips_Analog dd 0x03, chip_AD1819
dd 0x40, chip_AD1881
dd 0x48, chip_AD1881A
dd 0x60, chip_AD1884
dd 0x61, chip_AD1886
dd 0x62, chip_AD1887
dd 0x63, chip_AD1886A
dd 0x70, chip_AD1980
dd 0x72, chip_AD1981A
dd 0x74, chip_AD1981B
dd 0x75, chip_AD1985
dd 0xFF
 
chips_Realtek:
dd 0x10, chip_ALC201a
dd 0x20, chip_ALC650
dd 0x21, chip_ALC650D
dd 0x22, chip_ALC650E
dd 0x23, chip_ALC650F
dd 0x60, chip_ALC655
dd 0x80, chip_ALC658
dd 0x81, chip_ALC658D
dd 0x90, chip_ALC850
dd 0xFF
 
chips_CMedia dd 0x41, chip_CM9738
dd 0x61, chip_CM9739
dd 0x69, chip_CM9780
dd 0x78, chip_CM9761
dd 0x82, chip_CM9761
dd 0x83, chip_CM9761
dd 0xFF
 
chips_Cirrus dd 0x00, chip_CS4297
dd 0x10, chip_CS4297A
dd 0x20, chip_CS4298
dd 0x28, chip_CS4294
dd 0x30, chip_CS4299
dd 0x34, chip_CS4299D
dd 0x48, chip_CS4201
dd 0x58, chip_CS4205
dd 0x60, chip_CS4291
dd 0x70, chip_CS4202
dd 0xFF
 
chips_Wolfson dd 0x00, chip_WM9700
dd 0x03, chip_WM9703
dd 0x04, chip_WM9704
dd 0xFF
 
chips_VIA dd 0x61, chip_VIA1612A
dd 0xFF
 
chips_SigmaTel dd 0x58, chip_STAC9758
dd 0xFF
 
chips_eMicro dd 0x28, chip_EM28028
dd 0xFF
 
align 16
;Analog Devices
chip_AD1819 db 'AD1819 ',0dh,0ah,00h
chip_AD1881 db 'AD1881 ',0dh,0ah,00h
chip_AD1881A db 'AD1881A',0dh,0ah,00h
chip_AD1884 db 'AD1885 ',0dh,0ah,00h
chip_AD1885 db 'AD1885 ',0dh,0ah,00h
chip_AD1886 db 'AD1886 ',0dh,0ah,00h
chip_AD1886A db 'AD1886A',0dh,0ah,00h
chip_AD1887 db 'AD1887 ',0dh,0ah,00h
chip_AD1980 db 'AD1980 ',0dh,0ah,00h
chip_AD1981A db 'AD1981A',0dh,0ah,00h
chip_AD1981B db 'AD1981B',0dh,0ah,00h
chip_AD1985 db 'AD1985 ',0dh,0ah,00h
 
;Realtek
chip_ALC201a db 'ALC201a',0dh,0ah,00h
chip_ALC650 db 'ALC650 ',0dh,0ah,00h
chip_ALC650D db 'ALC650D',0dh,0ah,00h
chip_ALC650E db 'ALC650E',0dh,0ah,00h
chip_ALC650F db 'ALC650F',0dh,0ah,00h
chip_ALC655 db 'ALC655 ',0dh,0ah,00h
chip_ALC658 db 'ALC658 ',0dh,0ah,00h
chip_ALC658D db 'ALC658D',0dh,0ah,00h
chip_ALC850 db 'ALC850 ',0dh,0ah,00h
 
;CMedia
chip_CM9738 db 'CMI9738', 0dh,0ah,0
chip_CM9739 db 'CMI9739', 0dh,0ah,0
chip_CM9780 db 'CMI9780', 0dh,0ah,0
chip_CM9761 db 'CMI9761', 0dh,0ah,0
 
;Cirrus
chip_CS4297 db 'CS4297',13,10,0
chip_CS4297A db 'CS4297A',13,10,0
chip_CS4298 db 'CS4298',13,10,0
chip_CS4294 db 'CS4294',13,10,0
chip_CS4299 db 'CS4299',13,10,0
chip_CS4299D db 'CS4299D',13,10,0
chip_CS4201 db 'CS4201',13,10,0
chip_CS4205 db 'CS4205',13,10,0
chip_CS4291 db 'CS4291',13,10,0
chip_CS4202 db 'CS4202',13,10,0
 
;Wolfson
chip_WM9700 db 'WM9704',13,10,0
chip_WM9703 db 'WM9703/9704',13,10,0
chip_WM9704 db 'WM9704 (quad)',13,10,0
 
;VIA
chip_VIA1612A db 'VIA1612A',13,10,0
 
;SigmaTel
chip_STAC9758 db 'STAC9758,59',13,10,0
 
;eMicro
chip_EM28028 db 'EM28028',13,10,0
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Rev
\ No newline at end of property
/drivers/audio/emu10k1x.asm
0,0 → 1,1153
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format PE DLL native 0.05
entry START
 
DEBUG equ 1
 
API_VERSION equ 0x01000100
 
USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices
IRQ_REMAP equ 0
IRQ_LINE equ 0
 
 
;irq 0,1,2,8,12,13 недоступны
; FEDCBA9876543210
VALID_IRQ equ 1100111011111000b
ATTCH_IRQ equ 0000111010100000b
 
if USE_COM_IRQ
ATTCH_IRQ equ 0000111010111000b
end if
 
CPU_FREQ equ 2600d
 
BIT0 EQU 0x00000001
BIT1 EQU 0x00000002
BIT5 EQU 0x00000020
BIT10 EQU 0x00000400
 
VID_Creative equ 0x1102
 
CTRL_CT0200 equ 0x0006 ; Dell OEM version (EMU10K1X)
 
 
CODEC_MASTER_VOL_REG equ 0x02
CODEC_AUX_VOL equ 0x04 ;
CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume
CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio
CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control
CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate
CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate
CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate
 
 
;EMU10K1(X) host controller registers set
;; common offsets
;; some definitions were borrowed from emu10k1 driver as they seem to be the same
;;**********************************************************************************************;;
;; PCI function 0 registers, address = <val> + PCIBASE0 ;;
;;**********************************************************************************************;;
 
PTR equ 0x00 ;; Indexed register set pointer register ;;
;; NOTE: The CHANNELNUM and ADDRESS words can ;;
;; be modified independently of each other. ;;
 
DATA equ 0x04 ;; Indexed register set data register ;;
 
IPR equ 0x08 ;; Global interrupt pending register ;;
;; Clear pending interrupts by writing a 1 to ;;
;; the relevant bits and zero to the other bits ;;
IPR_MIDITRANSBUFEMPTY equ 0x00000001 ;; MIDI UART transmit buffer empty ;;
IPR_MIDIRECVBUFEMPTY equ 0x00000002 ;; MIDI UART receive buffer empty ;;
IPR_CH_0_LOOP equ 0x00000800 ;; Channel 0 loop ;;
IPR_CH_0_HALF_LOOP equ 0x00000100 ;; Channel 0 half loop ;;
IPR_CAP_0_LOOP equ 0x00080000 ;; Channel capture loop ;;
IPR_CAP_0_HALF_LOOP equ 0x00010000 ;; Channel capture half loop ;;
 
INTE equ 0x0c ;; Interrupt enable register ;;
INTE_MIDITXENABLE equ 0x00000001 ;; Enable MIDI transmit-buffer-empty interrupts ;;
INTE_MIDIRXENABLE equ 0x00000002 ;; Enable MIDI receive-buffer-empty interrupts ;;
INTE_CH_0_LOOP equ 0x00000800 ;; Channel 0 loop ;;
INTE_CH_0_HALF_LOOP equ 0x00000100 ;; Channel 0 half loop ;;
INTE_CAP_0_LOOP equ 0x00080000 ;; Channel capture loop ;;
INTE_CAP_0_HALF_LOOP equ 0x00010000 ;; Channel capture half loop ;;
 
HCFG equ 0x14 ;; Hardware config register ;;
 
HCFG_LOCKSOUNDCACHE equ 0x00000008 ;; 1 = Cancel bustmaster accesses to soundcache ;;
;; NOTE: This should generally never be used. ;;
HCFG_AUDIOENABLE equ 0x00000001 ;; 0 = CODECs transmit zero-valued samples ;;
;; Should be set to 1 when the EMU10K1 is ;;
;; completely initialized. ;;
GPIO equ 0x18 ;; Defaults: 00001080-Analog, 00001000-SPDIF. ;;
 
 
AC97DATA equ 0x1c ;; AC97 register set data register (16 bit) ;;
 
AC97ADDRESS equ 0x1e ;; AC97 register set address register (8 bit) ;;
 
;;******************************************************************************************************;;
;; Emu10k1x pointer-offset register set, accessed through the PTR and DATA registers ;;
;;******************************************************************************************************;;
PLAYBACK_LIST_ADDR equ 0x00 ;; Base DMA address of a list of pointers to each period/size ;;
;; One list entry: 4 bytes for DMA address,
;; 4 bytes for period_size << 16.
;; One list entry is 8 bytes long.
;; One list entry for each period in the buffer.
;;
PLAYBACK_LIST_SIZE equ 0x01 ;; Size of list in bytes << 19. E.g. 8 periods -> 0x00380000 ;;
PLAYBACK_LIST_PTR equ 0x02 ;; Pointer to the current period being played ;;
PLAYBACK_DMA_ADDR equ 0x04 ;; Playback DMA addresss ;;
PLAYBACK_PERIOD_SIZE equ 0x05 ;; Playback period size ;;
PLAYBACK_POINTER equ 0x06 ;; Playback period pointer. Sample currently in DAC ;;
PLAYBACK_UNKNOWN1 equ 0x07
PLAYBACK_UNKNOWN2 equ 0x08
 
;; Only one capture channel supported ;;
CAPTURE_DMA_ADDR equ 0x10 ;; Capture DMA address ;;
CAPTURE_BUFFER_SIZE equ 0x11 ;; Capture buffer size ;;
CAPTURE_POINTER equ 0x12 ;; Capture buffer pointer. Sample currently in ADC ;;
CAPTURE_UNKNOWN equ 0x13
 
;; From 0x20 - 0x3f, last samples played on each channel ;;
 
TRIGGER_CHANNEL equ 0x40 ;; Trigger channel playback ;;
TRIGGER_CHANNEL_0 equ 0x00000001 ;; Trigger channel 0 ;;
TRIGGER_CHANNEL_1 equ 0x00000002 ;; Trigger channel 1 ;;
TRIGGER_CHANNEL_2 equ 0x00000004 ;; Trigger channel 2 ;;
TRIGGER_CAPTURE equ 0x00000100 ;; Trigger capture channel ;;
 
ROUTING equ 0x41 ;; Setup sound routing ? ;;
ROUTING_FRONT_LEFT equ 0x00000001
ROUTING_FRONT_RIGHT equ 0x00000002
ROUTING_REAR_LEFT equ 0x00000004
ROUTING_REAR_RIGHT equ 0x00000008
ROUTING_CENTER_LFE equ 0x00010000
 
SPCS0 equ 0x42 ;; SPDIF output Channel Status 0 register ;;
SPCS1 equ 0x43 ;; SPDIF output Channel Status 1 register ;;
SPCS2 equ 0x44 ;; SPDIF output Channel Status 2 register ;;
 
SPCS_CLKACCYMASK equ 0x30000000 ;; Clock accuracy ;;
SPCS_CLKACCY_1000PPM equ 0x00000000 ;; 1000 parts per million ;;
SPCS_CLKACCY_50PPM equ 0x10000000 ;; 50 parts per million ;;
SPCS_CLKACCY_VARIABLE equ 0x20000000 ;; Variable accuracy ;;
SPCS_SAMPLERATEMASK equ 0x0f000000 ;; Sample rate ;;
SPCS_SAMPLERATE_44 equ 0x00000000 ;; 44.1kHz sample rate ;;
SPCS_SAMPLERATE_48 equ 0x02000000 ;; 48kHz sample rate ;;
SPCS_SAMPLERATE_32 equ 0x03000000 ;; 32kHz sample rate ;;
SPCS_CHANNELNUMMASK equ 0x00f00000 ;; Channel number ;;
SPCS_CHANNELNUM_UNSPEC equ 0x00000000 ;; Unspecified channel number ;;
SPCS_CHANNELNUM_LEFT equ 0x00100000 ;; Left channel ;;
SPCS_CHANNELNUM_RIGHT equ 0x00200000 ;; Right channel ;;
SPCS_SOURCENUMMASK equ 0x000f0000 ;; Source number ;;
SPCS_SOURCENUM_UNSPEC equ 0x00000000 ;; Unspecified source number ;;
SPCS_GENERATIONSTATUS equ 0x00008000 ;; Originality flag (see IEC-958 spec) ;;
SPCS_CATEGORYCODEMASK equ 0x00007f00 ;; Category code (see IEC-958 spec) ;;
SPCS_MODEMASK equ 0x000000c0 ;; Mode (see IEC-958 spec) ;;
SPCS_EMPHASISMASK equ 0x00000038 ;; Emphasis ;;
SPCS_EMPHASIS_NONE equ 0x00000000 ;; No emphasis ;;
SPCS_EMPHASIS_50_15 equ 0x00000008 ;; 50/15 usec 2 channel ;;
SPCS_COPYRIGHT equ 0x00000004 ;; Copyright asserted flag -- do not modify ;;
SPCS_NOTAUDIODATA equ 0x00000002 ;; 0 = Digital audio, 1 = not audio ;;
SPCS_PROFESSIONAL equ 0x00000001 ;; 0 = Consumer (IEC-958), 1 = pro (AES3-1992) ;;
 
SPDIF_SELECT equ 0x45 ;; Enables SPDIF or Analogue outputs 0-Analogue, 0x700-SPDIF ;;
 
;; This is the MPU port on the card ;;
MUDATA equ 0x47
MUCMD equ 0x48
MUSTAT equ MUCMD
 
;; From 0x50 - 0x5f, last samples captured ;;
 
 
SRV_GETVERSION equ 0
DEV_PLAY equ 1
DEV_STOP equ 2
DEV_CALLBACK equ 3
DEV_SET_BUFF equ 4
DEV_NOTIFY equ 5
DEV_SET_MASTERVOL equ 6
DEV_GET_MASTERVOL equ 7
DEV_GET_INFO equ 8
 
struc AC_CNTRL ;AC controller base class
{ .bus dd ?
.devfn dd ?
 
.vendor dd ?
.dev_id dd ?
.pci_cmd dd ?
.pci_stat dd ?
 
.codec_io_base dd ?
.codec_mem_base dd ?
 
.ctrl_io_base dd ?
.ctrl_mem_base dd ?
.cfg_reg dd ?
.int_line dd ?
 
.vendor_ids dd ? ;vendor id string
.ctrl_ids dd ? ;hub id string
 
.buffer dd ?
 
.notify_pos dd ?
.notify_task dd ?
 
.lvi_reg dd ?
.ctrl_setup dd ?
.user_callback dd ?
.codec_read16 dd ?
.codec_write16 dd ?
 
.ctrl_read8 dd ?
.ctrl_read16 dd ?
.ctrl_read32 dd ?
 
.ctrl_write8 dd ?
.ctrl_write16 dd ?
.ctrl_write32 dd ?
}
 
struc CODEC ;Audio Chip base class
{
.chip_id dd ?
.flags dd ?
.status dd ?
 
.ac_vendor_ids dd ? ;ac vendor id string
.chip_ids dd ? ;chip model string
 
.shadow_flag dd ?
dd ?
 
.regs dw ? ; codec registers
.reg_master_vol dw ? ;0x02
.reg_aux_out_vol dw ? ;0x04
.reg_mone_vol dw ? ;0x06
.reg_master_tone dw ? ;0x08
.reg_beep_vol dw ? ;0x0A
.reg_phone_vol dw ? ;0x0C
.reg_mic_vol dw ? ;0x0E
.reg_line_in_vol dw ? ;0x10
.reg_cd_vol dw ? ;0x12
.reg_video_vol dw ? ;0x14
.reg_aux_in_vol dw ? ;0x16
.reg_pcm_out_vol dw ? ;0x18
.reg_rec_select dw ? ;0x1A
.reg_rec_gain dw ? ;0x1C
.reg_rec_gain_mic dw ? ;0x1E
.reg_gen dw ? ;0x20
.reg_3d_ctrl dw ? ;0X22
.reg_page dw ? ;0X24
.reg_powerdown dw ? ;0x26
.reg_ext_audio dw ? ;0x28
.reg_ext_st dw ? ;0x2a
.reg_pcm_front_rate dw ? ;0x2c
.reg_pcm_surr_rate dw ? ;0x2e
.reg_lfe_rate dw ? ;0x30
.reg_pcm_in_rate dw ? ;0x32
dw ? ;0x34
.reg_cent_lfe_vol dw ? ;0x36
.reg_surr_vol dw ? ;0x38
.reg_spdif_ctrl dw ? ;0x3A
dw ? ;0x3C
dw ? ;0x3E
dw ? ;0x40
dw ? ;0x42
dw ? ;0x44
dw ? ;0x46
dw ? ;0x48
dw ? ;0x4A
dw ? ;0x4C
dw ? ;0x4E
dw ? ;0x50
dw ? ;0x52
dw ? ;0x54
dw ? ;0x56
dw ? ;0x58
dw ? ;0x5A
dw ? ;0x5C
dw ? ;0x5E
.reg_page_0 dw ? ;0x60
.reg_page_1 dw ? ;0x62
.reg_page_2 dw ? ;0x64
.reg_page_3 dw ? ;0x66
.reg_page_4 dw ? ;0x68
.reg_page_5 dw ? ;0x6A
.reg_page_6 dw ? ;0x6C
.reg_page_7 dw ? ;0x6E
dw ? ;0x70
dw ? ;0x72
dw ? ;0x74
dw ? ;0x76
dw ? ;0x78
dw ? ;0x7A
.reg_vendor_id_1 dw ? ;0x7C
.reg_vendor_id_2 dw ? ;0x7E
 
 
.reset dd ? ;virual
.set_master_vol dd ?
}
 
struc CTRL_INFO
{ .pci_cmd dd ?
.irq dd ?
.glob_cntrl dd ?
.glob_sta dd ?
.codec_io_base dd ?
.ctrl_io_base dd ?
.codec_mem_base dd ?
.ctrl_mem_base dd ?
.codec_id dd ?
}
 
EVENT_NOTIFY equ 0x00000200
 
section '.flat' code readable writable executable
include '../struct.inc'
include '../macros.inc'
include '../proc32.inc'
include '../peimport.inc'
 
 
proc START c uses ebx esi edi, state:dword, cmdline:dword
 
cmp [state], 1
jne .stop
 
if DEBUG
mov esi, msgInit
invoke SysMsgBoardStr
end if
 
call detect_controller
test eax, eax
jz .fail
 
if DEBUG
mov esi, [ctrl.vendor_ids]
invoke SysMsgBoardStr
mov esi, [ctrl.ctrl_ids]
invoke SysMsgBoardStr
end if
 
call init_controller
test eax, eax
jz .fail
 
call init_codec
test eax, eax
jz .fail
 
call setup_codec
 
mov esi, msgPrimBuff
invoke SysMsgBoardStr
call create_primary_buff
mov esi, msgDone
invoke SysMsgBoardStr
 
if IRQ_REMAP
pushf
cli
 
mov ebx, [ctrl.int_line]
in al, 0xA1
mov ah, al
in al, 0x21
test ebx, ebx
jz .skip
bts ax, bx ;mask old line
.skip:
bts ax, IRQ_LINE ;mask new ine
out 0x21, al
mov al, ah
out 0xA1, al
 
stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE ;remap IRQ
 
mov dx, 0x4d0 ;8259 ELCR1
in al, dx
bts ax, IRQ_LINE
out dx, al ;set level-triggered mode
mov [ctrl.int_line], IRQ_LINE
popf
mov esi, msgRemap
invoke SysMsgBoardStr
end if
 
mov eax, VALID_IRQ
mov ebx, [ctrl.int_line]
mov esi, msgInvIRQ
bt eax, ebx
jnc .fail_msg
mov eax, ATTCH_IRQ
mov esi, msgAttchIRQ
bt eax, ebx
jnc .fail_msg
 
invoke AttachIntHandler, ebx, ac97_irq, dword 0
stdcall create
 
.reg:
invoke RegService, sz_sound_srv, service_proc
ret
.fail:
if DEBUG
mov esi, msgFail
invoke SysMsgBoardStr
end if
xor eax, eax
ret
.fail_msg:
invoke SysMsgBoardStr
xor eax, eax
ret
.stop:
call stop
xor eax, eax
ret
endp
 
handle equ IOCTL.handle
io_code equ IOCTL.io_code
input equ IOCTL.input
inp_size equ IOCTL.inp_size
output equ IOCTL.output
out_size equ IOCTL.out_size
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edi, [ioctl]
mov eax, [edi+io_code]
 
cmp eax, SRV_GETVERSION
jne @F
mov eax, [edi+output]
cmp [edi+out_size], 4
jne .fail
 
mov [eax], dword API_VERSION
xor eax, eax
ret
@@:
cmp eax, DEV_PLAY
jne @F
if DEBUG
mov esi, msgPlay
invoke SysMsgBoardStr
end if
call play
ret
@@:
cmp eax, DEV_STOP
jne @F
if DEBUG
mov esi, msgStop
invoke SysMsgBoardStr
end if
call stop
ret
@@:
cmp eax, DEV_CALLBACK
jne @F
mov ebx, [edi+input]
stdcall set_callback, [ebx]
ret
@@:
cmp eax, DEV_SET_MASTERVOL
jne @F
mov eax, [edi+input]
mov eax, [eax]
call set_master_vol ;eax= vol
ret
@@:
cmp eax, DEV_GET_MASTERVOL
jne @F
mov ebx, [edi+output]
stdcall get_master_vol, ebx
ret
@@:
cmp eax, DEV_GET_INFO
jne @F
mov ebx, [edi+output]
stdcall get_dev_info, ebx
ret
@@:
.fail:
or eax, -1
ret
endp
 
restore handle
restore io_code
restore input
restore inp_size
restore output
restore out_size
 
 
align 4
proc ac97_irq
locals
status dd 0
endl
 
; status = inl(chip->port + IPR);
mov edx, IPR
call [ctrl.ctrl_read32]
test eax, eax
jz @f
 
mov dword [status], eax
 
mov ebx, dword [buff_list]
cmp [ctrl.user_callback], 0
je @f
stdcall [ctrl.user_callback], ebx
@@:
mov eax, dword [status] ;; ack ;;
mov edx, IPR
call [ctrl.ctrl_write32]
ret
endp
 
 
align 4
proc create_primary_buff
 
invoke KernelAlloc, 0x10000
mov [ctrl.buffer], eax
 
mov edi, eax
mov ecx, 0x10000/4
xor eax, eax
cld
rep stosd
 
mov eax, [ctrl.buffer]
invoke GetPgAddr
 
mov edi, pcmout_bdl
stosd
mov eax, 0x4000000
stosd
 
mov edi, buff_list
mov eax, [ctrl.buffer]
stosd ;1.]
 
mov eax, [ctrl.buffer]
invoke GetPgAddr
 
stdcall ptr_write, PLAYBACK_POINTER, 0, 0
stdcall ptr_write, PLAYBACK_UNKNOWN1, 0, 0
stdcall ptr_write, PLAYBACK_UNKNOWN2, 0, 0
stdcall ptr_write, PLAYBACK_DMA_ADDR, 0, eax
 
mov eax, pcmout_bdl
mov ebx, eax
invoke GetPgAddr
and ebx, 0xFFF
add eax, ebx
 
stdcall ptr_write, PLAYBACK_LIST_ADDR, 0, eax
stdcall ptr_write, PLAYBACK_LIST_SIZE, 0, 0
stdcall ptr_write, PLAYBACK_LIST_PTR, 0, 0
 
;mov eax, 0x00004000
;shl eax, 16
stdcall ptr_write, PLAYBACK_PERIOD_SIZE, 0, 0x40000000 ;eax
 
ret
endp
 
 
align 4
proc detect_controller
locals
last_bus dd ?
bus dd ?
devfn dd ?
endl
 
xor eax, eax
mov [bus], eax
inc eax
invoke PciApi
cmp eax, -1
je .err
 
mov [last_bus], eax
 
.next_bus:
and [devfn], 0
.next_dev:
invoke PciRead32, [bus], [devfn], dword 0
test eax, eax
jz .next
cmp eax, -1
je .next
 
mov edi, devices
@@:
mov ebx, [edi]
test ebx, ebx
jz .next
 
cmp eax, ebx
je .found
add edi, 12
jmp @B
.next:
inc [devfn]
cmp [devfn], 256
jb .next_dev
mov eax, [bus]
inc eax
mov [bus], eax
cmp eax, [last_bus]
jna .next_bus
xor eax, eax
ret
.found:
mov ebx, [bus]
mov [ctrl.bus], ebx
 
mov ecx, [devfn]
mov [ctrl.devfn], ecx
 
mov edx, eax
and edx, 0xFFFF
mov [ctrl.vendor], edx
shr eax, 16
mov [ctrl.dev_id], eax
 
mov ebx, [edi+4]
mov [ctrl.ctrl_ids], ebx
mov esi, [edi+8]
mov [ctrl.ctrl_setup], esi
 
cmp edx, VID_Creative
jne @F
mov [ctrl.vendor_ids], msg_Creative
ret
@@:
 
.err:
xor eax, eax
mov [ctrl.vendor_ids], eax ;something wrong ?
ret
endp
 
align 4
proc init_controller
 
invoke PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x2C
mov esi, msgPciSubsys
invoke SysMsgBoardStr
call dword2str
invoke SysMsgBoardStr
 
invoke PciRead32, [ctrl.bus], [ctrl.devfn], dword 4
mov ebx, eax
and eax, 0xFFFF
mov [ctrl.pci_cmd], eax
shr ebx, 16
mov [ctrl.pci_stat], ebx
 
mov esi, msgPciCmd
invoke SysMsgBoardStr
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgPciStat
invoke SysMsgBoardStr
mov eax, [ctrl.pci_stat]
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgCtrlIsaIo
invoke SysMsgBoardStr
invoke PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10
call dword2str
invoke SysMsgBoardStr
 
and eax, 0xFFC0
mov [ctrl.ctrl_io_base], eax
 
.default:
invoke PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C
and eax, 0xFF
@@:
mov [ctrl.int_line], eax
 
call [ctrl.ctrl_setup]
xor eax, eax
inc eax
ret
endp
 
align 4
proc set_Creative
mov [ctrl.codec_read16], codec_io_r16 ;virtual
mov [ctrl.codec_write16], codec_io_w16 ;virtual
 
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual
 
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual
ret
endp
 
 
align 4
proc init_codec
call reset_codec
test eax, eax
jz .err
call detect_codec
xor eax, eax
inc eax
ret
.err:
xor eax, eax
ret
endp
 
align 4
proc reset_codec
locals
counter dd ?
endl
 
if DEBUG
mov esi, msgCold
invoke SysMsgBoardStr
end if
 
mov eax, 100000 ; wait 100 ms ;400000 ; wait 400 ms
call StallExec
 
stdcall ptr_read, TRIGGER_CHANNEL, 0
 
mov [counter], 16 ; total 20*100 ms = 2s
.wait:
stdcall codec_read, dword 0x26
test eax, 1
jnz .ok
 
mov eax, 100000 ; wait 100 ms
call StallExec
 
dec [counter]
jnz .wait
 
if DEBUG
mov esi, msgCRFail
invoke SysMsgBoardStr
end if
 
.fail:
stc
ret
.ok:
 
 
xor eax, eax
inc eax
ret
endp
 
 
align 4
play:
mov eax, INTE_CH_0_LOOP
stdcall intr_enable, eax
 
stdcall ptr_read, TRIGGER_CHANNEL, 0
mov ebx, TRIGGER_CHANNEL_0
or eax, ebx
stdcall ptr_write, TRIGGER_CHANNEL, 0, eax
 
xor eax, eax
ret
 
align 4
stop:
mov eax, INTE_CH_0_LOOP or INTE_CH_0_HALF_LOOP
stdcall intr_disable, eax
 
stdcall ptr_read, TRIGGER_CHANNEL, 0
mov ebx, TRIGGER_CHANNEL_0
xor ebx, -1
or eax, ebx
stdcall ptr_write, TRIGGER_CHANNEL, 0, eax
xor eax, eax
ret
 
align 4
proc get_dev_info stdcall, p_info:dword
virtual at esi
CTRL_INFO CTRL_INFO
end virtual
 
mov esi, [p_info]
mov eax, [ctrl.int_line]
mov ecx, [ctrl.ctrl_io_base]
mov [CTRL_INFO.irq], eax
mov [CTRL_INFO.ctrl_io_base], ecx
mov eax, [codec.chip_id]
mov [CTRL_INFO.codec_id], eax
mov ebx, [ctrl.pci_cmd]
mov [CTRL_INFO.pci_cmd], ebx
 
xor eax, eax
mov [CTRL_INFO.codec_io_base], eax
mov [CTRL_INFO.codec_mem_base], eax
mov [CTRL_INFO.ctrl_mem_base], eax
mov [CTRL_INFO.glob_cntrl], eax
mov [CTRL_INFO.glob_sta], eax
ret
endp
 
align 4
proc set_callback stdcall, handler:dword
mov eax, [handler]
mov [ctrl.user_callback], eax
ret
endp
 
 
align 4
proc create stdcall
invoke PciRead16, [ctrl.bus], [ctrl.devfn], 4
test eax, 4 ; test master bit
jnz @f
or eax, 4
invoke PciWrite16, [ctrl.bus], [ctrl.devfn], 4, eax ; set master bit
@@:
 
xor eax, eax
mov edx, INTE
call [ctrl.ctrl_write32]
 
stdcall ptr_write, SPCS0, 0, \
SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \
SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \
SPCS_GENERATIONSTATUS or 0x00001200 or \
0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT
stdcall ptr_write, SPCS1, 0, \
SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \
SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \
SPCS_GENERATIONSTATUS or 0x00001200 or \
0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT
stdcall ptr_write, SPCS2, 0, \
SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \
SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \
SPCS_GENERATIONSTATUS or 0x00001200 or \
0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT
 
stdcall ptr_write, SPDIF_SELECT, 0, 0x700 ; disable SPDIF
stdcall ptr_write, ROUTING, 0, 0x1003F ; routing
stdcall gpio_write, 0x1080 ; analog mode
 
mov eax, dword HCFG_LOCKSOUNDCACHE or HCFG_AUDIOENABLE
mov edx, HCFG
call [ctrl.ctrl_write32]
ret
endp
 
align 4
proc codec_read stdcall, reg:dword
stdcall ac97_read, dword [reg]
ret
endp
 
 
align 4
proc codec_write stdcall, reg:dword
stdcall ac97_write, dword [reg], eax
ret
endp
 
 
align 4
proc ac97_read stdcall, reg:dword
push edx
mov eax, dword [reg]
mov edx, AC97ADDRESS
call [ctrl.ctrl_write8]
 
mov edx, AC97DATA
call [ctrl.ctrl_read16]
and eax, 0xFFFF
pop edx
ret
endp
 
align 4
proc ac97_write stdcall, reg:dword, val:dword
push eax edx
mov eax, dword [reg]
mov edx, AC97ADDRESS
call [ctrl.ctrl_write8]
 
mov eax, dword [val]
mov edx, AC97DATA
call [ctrl.ctrl_write16]
pop edx eax
ret
endp
 
align 4
proc ptr_read stdcall, reg:dword, chn:dword
push edx
mov eax, dword [reg]
shl eax, 16
or eax, dword [chn]
 
mov edx, PTR
call [ctrl.ctrl_write32]
 
mov edx, DATA
call [ctrl.ctrl_read32]
pop edx
ret
endp
 
align 4
proc ptr_write stdcall, reg:dword, chn:dword, data:dword
push eax edx
mov eax, dword [reg]
shl eax, 16
or eax, dword [chn]
 
mov edx, PTR
call [ctrl.ctrl_write32]
 
mov eax, dword [data]
mov edx, DATA
call [ctrl.ctrl_write32]
pop edx eax
ret
endp
 
align 4
proc intr_enable stdcall, intrenb:dword
push edx
mov edx, INTE
call [ctrl.ctrl_read32]
 
or eax, dword [intrenb]
mov edx, INTE
call [ctrl.ctrl_write32]
pop edx
ret
endp
 
align 4
proc intr_disable stdcall, intrenb:dword
push eax ebx edx
mov edx, INTE
call [ctrl.ctrl_read32]
 
mov ebx, dword [intrenb]
xor ebx, -1
and eax, ebx
mov edx, INTE
call [ctrl.ctrl_write32]
pop edx ebx eax
ret
endp
 
align 4
proc gpio_write stdcall, value:dword
push eax edx
mov eax, dword [value]
mov edx, GPIO
call [ctrl.ctrl_write32]
pop edx eax
ret
endp
 
 
align 4
proc StallExec
push ecx
push edx
push ebx
push eax
 
mov ecx, CPU_FREQ
mul ecx
mov ebx, eax ;low
mov ecx, edx ;high
rdtsc
add ebx, eax
adc ecx, edx
@@:
rdtsc
sub eax, ebx
sbb edx, ecx
js @B
 
pop eax
pop ebx
pop edx
pop ecx
ret
endp
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; CONTROLLER IO functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc codec_io_r16 ;Not used.
;mov edx, [ctrl.ctrl_io_base]
;in eax, dx
ret
endp
 
align 4
proc codec_io_w16 ;Not used.
;mov edx, [ctrl.ctrl_io_base]
;out dx, eax
ret
endp
 
align 4
proc ctrl_io_r8
add edx, [ctrl.ctrl_io_base]
in al, dx
ret
endp
 
align 4
proc ctrl_io_r16
add edx, [ctrl.ctrl_io_base]
in ax, dx
ret
endp
 
align 4
proc ctrl_io_r32
add edx, [ctrl.ctrl_io_base]
in eax, dx
ret
endp
 
align 4
proc ctrl_io_w8
add edx, [ctrl.ctrl_io_base]
out dx, al
ret
endp
 
align 4
proc ctrl_io_w16
add edx, [ctrl.ctrl_io_base]
out dx, ax
ret
endp
 
align 4
proc ctrl_io_w32
add edx, [ctrl.ctrl_io_base]
out dx, eax
ret
endp
 
 
align 4
dword2str:
push eax ebx ecx
mov esi, hex_buff
mov ecx, -8
@@:
rol eax, 4
mov ebx, eax
and ebx, 0x0F
mov bl, [ebx+hexletters]
mov [8+esi+ecx], bl
inc ecx
jnz @B
pop ecx ebx eax
ret
 
hexletters db '0123456789ABCDEF'
hex_buff db 8 dup(0),13,10,0
 
 
include "codec.inc"
 
align 4
devices dd (CTRL_CT0200 shl 16)+VID_Creative,msg_CT_EMU10K1X,set_Creative
dd 0 ;terminator
 
 
msg_CT_EMU10K1X db 'SB Live! Dell OEM', 13,10, 0
msg_Creative db 'Creative ', 0
 
szKernel db 'KERNEL', 0
sz_sound_srv db 'SOUND',0
 
msgInit db 'detect hardware...',13,10,0
msgFail db 'device not found',13,10,0
msgAttchIRQ db 'IRQ line not supported', 13,10, 0
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0
msgPlay db 'start play', 13,10,0
msgStop db 'stop play', 13,10,0
msgIRQ db 'AC97 IRQ', 13,10,0
;msgInitCtrl db 'init controller',13,10,0
;msgInitCodec db 'init codec',13,10,0
msgPrimBuff db 'create primary buffer ...',0
msgDone db 'done',13,10,0
msgRemap db 'Remap IRQ',13,10,0
;msgReg db 'set service handler',13,10,0
;msgOk db 'service installed',13,10,0
msgCold db 'cold reset',13,10,0
;msgWarm db 'warm reset',13,10,0
;msgWRFail db 'warm reset failed',13,10,0
msgCRFail db 'cold reset failed',13,10,0
;msgCFail db 'codec not ready',13,10,0
;msgCInvalid db 'codec is not valid',13,10,0 ;Asper
;msgResetOk db 'reset complete',13,10,0
;msgStatus db 'global status ',0
;msgControl db 'global control ',0
msgPciCmd db 'PCI command ',0
msgPciStat db 'PCI status ',0
msgPciSubsys db 'PCI subsystem ',0
msgCtrlIsaIo db 'controller io base ',0
;msgMixIsaIo db 'codec io base ',0
;msgCtrlMMIo db 'controller mmio base ',0
;msgMixMMIo db 'codec mmio base ',0
;msgIrqMap db 'AC97 irq map as ',0
 
align 4
data fixups
end data
 
align 8
pcmout_bdl rq 32
buff_list rd 32
 
codec CODEC
ctrl AC_CNTRL
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/audio/fm801.asm
0,0 → 1,1047
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format PE DLL native 0.05
entry START
 
DEBUG equ 1
DEBUG_IRQ equ 0
 
API_VERSION equ 0x01000100
 
USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices
 
;irq 0,1,2,8,12,13 недоступны
; FEDCBA9876543210
VALID_IRQ equ 1100111011111000b
ATTCH_IRQ equ 0000111010100000b
 
if USE_COM_IRQ
ATTCH_IRQ equ 0000111010111000b
end if
 
CPU_FREQ equ 2000d
 
BIT0 EQU 0x00000001
BIT1 EQU 0x00000002
BIT2 EQU 0x00000004
BIT3 EQU 0x00000008
BIT4 EQU 0x00000010
BIT5 EQU 0x00000020
BIT6 EQU 0x00000040
BIT7 EQU 0x00000080
BIT8 EQU 0x00000100
BIT9 EQU 0x00000200
BIT10 EQU 0x00000400
BIT11 EQU 0x00000800
BIT12 EQU 0x00001000
BIT13 EQU 0x00002000
BIT14 EQU 0x00004000
BIT15 EQU 0x00008000
BIT16 EQU 0x00010000
BIT17 EQU 0x00020000
BIT18 EQU 0x00040000
BIT19 EQU 0x00080000
BIT20 EQU 0x00100000
BIT21 EQU 0x00200000
BIT22 EQU 0x00400000
BIT23 EQU 0x00800000
BIT24 EQU 0x00100000
BIT25 EQU 0x02000000
BIT26 EQU 0x04000000
BIT27 EQU 0x08000000
BIT28 EQU 0x10000000
BIT29 EQU 0x20000000
BIT30 EQU 0x40000000
BIT31 EQU 0x80000000
 
VID_FM801 equ 0x1319
CTRL_FM801 equ 0x0801
 
FM_PCM_VOLUME equ 0x00
FM_FM_VOLUME equ 0x02
FM_I2S_VOLUME equ 0x04
FM_RECORD_SOURCE equ 0x06
 
FM_PLAY_CTL equ 0x08
FM_PLAY_RATE_MASK equ 0x0f00
FM_PLAY_BUF1_LAST equ 0x0001
FM_PLAY_BUF2_LAST equ 0x0002
FM_PLAY_START equ 0x0020
FM_PLAY_PAUSE equ 0x0040
FM_PLAY_STOPNOW equ 0x0080
FM_PLAY_16BIT equ 0x4000
FM_PLAY_STEREO equ 0x8000
 
FM_PLAY_DMALEN equ 0x0a
FM_PLAY_DMABUF1 equ 0x0c
FM_PLAY_DMABUF2 equ 0x10
 
FM_REC_CTL equ 0x14
FM_REC_RATE_MASK equ 0x0f00
FM_REC_BUF1_LAST equ 0x0001
FM_REC_BUF2_LAST equ 0x0002
FM_REC_START equ 0x0020
FM_REC_PAUSE equ 0x0040
FM_REC_STOPNOW equ 0x0080
FM_REC_16BIT equ 0x4000
FM_REC_STEREO equ 0x8000
 
FM_REC_DMALEN equ 0x16
FM_REC_DMABUF1 equ 0x18
FM_REC_DMABUF2 equ 0x1c
 
FM_CODEC_CTL equ 0x22
FM_VOLUME equ 0x26
FM_VOLUME_MUTE equ 0x8000
 
FM_CODEC_CMD equ 0x2a
FM_CODEC_CMD_READ equ 0x0080
FM_CODEC_CMD_VALID equ 0x0100
FM_CODEC_CMD_BUSY equ 0x0200
 
FM_CODEC_DATA equ 0x2c
 
FM_IO_CTL equ 0x52
FM_CARD_CTL equ 0x54
 
FM_INTMASK equ 0x56
FM_INTMASK_PLAY equ 0x0001
FM_INTMASK_REC equ 0x0002
FM_INTMASK_VOL equ 0x0040
FM_INTMASK_MPU equ 0x0080
 
FM_INTSTATUS equ 0x5a
FM_INTSTATUS_PLAY equ 0x0100
FM_INTSTATUS_REC equ 0x0200
FM_INTSTATUS_VOL equ 0x4000
FM_INTSTATUS_MPU equ 0x8000
 
CODEC_MASTER_VOL_REG equ 0x02 ;
CODEC_AUX_VOL equ 0x04 ;
CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume
CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio
CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control
CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate
CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate
CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate
 
SRV_GETVERSION equ 0
DEV_PLAY equ 1
DEV_STOP equ 2
DEV_CALLBACK equ 3
DEV_SET_BUFF equ 4
DEV_NOTIFY equ 5
DEV_SET_MASTERVOL equ 6
DEV_GET_MASTERVOL equ 7
DEV_GET_INFO equ 8
 
struc AC_CNTRL ;AC controller base class
{ .bus dd ?
.devfn dd ?
 
.vendor dd ?
.dev_id dd ?
.pci_cmd dd ?
.pci_stat dd ?
 
.codec_io_base dd ?
.codec_mem_base dd ?
 
.ctrl_io_base dd ?
.ctrl_mem_base dd ?
.cfg_reg dd ?
.int_line dd ?
 
.vendor_ids dd ? ;vendor id string
.ctrl_ids dd ? ;hub id string
 
.buffer dd ?
 
.notify_pos dd ?
.notify_task dd ?
 
.lvi_reg dd ?
.ctrl_setup dd ?
.user_callback dd ?
.codec_read16 dd ?
.codec_write16 dd ?
 
.ctrl_read8 dd ?
.ctrl_read16 dd ?
.ctrl_read32 dd ?
 
.ctrl_write8 dd ?
.ctrl_write16 dd ?
.ctrl_write32 dd ?
}
 
struc CODEC ;Audio Chip base class
{
.chip_id dd ?
.flags dd ?
.status dd ?
 
.ac_vendor_ids dd ? ;ac vendor id string
.chip_ids dd ? ;chip model string
 
.shadow_flag dd ?
dd ?
 
.regs dw ? ; codec registers
.reg_master_vol dw ? ;0x02
.reg_aux_out_vol dw ? ;0x04
.reg_mone_vol dw ? ;0x06
.reg_master_tone dw ? ;0x08
.reg_beep_vol dw ? ;0x0A
.reg_phone_vol dw ? ;0x0C
.reg_mic_vol dw ? ;0x0E
.reg_line_in_vol dw ? ;0x10
.reg_cd_vol dw ? ;0x12
.reg_video_vol dw ? ;0x14
.reg_aux_in_vol dw ? ;0x16
.reg_pcm_out_vol dw ? ;0x18
.reg_rec_select dw ? ;0x1A
.reg_rec_gain dw ? ;0x1C
.reg_rec_gain_mic dw ? ;0x1E
.reg_gen dw ? ;0x20
.reg_3d_ctrl dw ? ;0X22
.reg_page dw ? ;0X24
.reg_powerdown dw ? ;0x26
.reg_ext_audio dw ? ;0x28
.reg_ext_st dw ? ;0x2a
.reg_pcm_front_rate dw ? ;0x2c
.reg_pcm_surr_rate dw ? ;0x2e
.reg_lfe_rate dw ? ;0x30
.reg_pcm_in_rate dw ? ;0x32
dw ? ;0x34
.reg_cent_lfe_vol dw ? ;0x36
.reg_surr_vol dw ? ;0x38
.reg_spdif_ctrl dw ? ;0x3A
dw ? ;0x3C
dw ? ;0x3E
dw ? ;0x40
dw ? ;0x42
dw ? ;0x44
dw ? ;0x46
dw ? ;0x48
dw ? ;0x4A
dw ? ;0x4C
dw ? ;0x4E
dw ? ;0x50
dw ? ;0x52
dw ? ;0x54
dw ? ;0x56
dw ? ;0x58
dw ? ;0x5A
dw ? ;0x5C
dw ? ;0x5E
.reg_page_0 dw ? ;0x60
.reg_page_1 dw ? ;0x62
.reg_page_2 dw ? ;0x64
.reg_page_3 dw ? ;0x66
.reg_page_4 dw ? ;0x68
.reg_page_5 dw ? ;0x6A
.reg_page_6 dw ? ;0x6C
.reg_page_7 dw ? ;0x6E
dw ? ;0x70
dw ? ;0x72
dw ? ;0x74
dw ? ;0x76
dw ? ;0x78
dw ? ;0x7A
.reg_vendor_id_1 dw ? ;0x7C
.reg_vendor_id_2 dw ? ;0x7E
 
 
.reset dd ? ;virual
.set_master_vol dd ?
}
 
struc CTRL_INFO
{ .pci_cmd dd ?
.irq dd ?
.glob_cntrl dd ?
.glob_sta dd ?
.codec_io_base dd ?
.ctrl_io_base dd ?
.codec_mem_base dd ?
.ctrl_mem_base dd ?
.codec_id dd ?
}
 
EVENT_NOTIFY equ 0x00000200
 
section '.flat' code readable writable executable
include '../struct.inc'
include '../macros.inc'
include '../proc32.inc'
include '../peimport.inc'
 
proc START c uses ebx esi edi, state:dword, cmdline:dword
 
cmp [state], 1
jne .stop
 
if DEBUG
mov eax, START
call dword2str
invoke SysMsgBoardStr
mov esi, msgInit
invoke SysMsgBoardStr
end if
 
call detect_controller
test eax, eax
jz .fail
 
if DEBUG
mov esi, [ctrl.vendor_ids]
invoke SysMsgBoardStr
mov esi, [ctrl.ctrl_ids]
invoke SysMsgBoardStr
 
end if
 
call init_controller
test eax, eax
jz .fail
 
call init_codec
test eax, eax
jz .fail
 
call reset_controller
call setup_codec
 
mov esi, msgPrimBuff
invoke SysMsgBoardStr
call create_primary_buff
 
mov esi, msgDone
invoke SysMsgBoardStr
 
mov eax, VALID_IRQ
mov ebx, [ctrl.int_line]
mov esi, msgInvIRQ
bt eax, ebx
jnc .fail_msg
mov eax, ATTCH_IRQ
mov esi, msgAttchIRQ
bt eax, ebx
jnc .fail_msg
 
invoke AttachIntHandler, ebx, ac97_irq, dword 0
.reg:
 
invoke RegService, sz_sound_srv, service_proc
ret
.fail:
if DEBUG
mov esi, msgFail
invoke SysMsgBoardStr
end if
xor eax, eax
ret
.fail_msg:
invoke SysMsgBoardStr
xor eax, eax
ret
.stop:
call stop
xor eax, eax
ret
endp
 
handle equ IOCTL.handle
io_code equ IOCTL.io_code
input equ IOCTL.input
inp_size equ IOCTL.inp_size
output equ IOCTL.output
out_size equ IOCTL.out_size
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edi, [ioctl]
mov eax, [edi+io_code]
 
cmp eax, SRV_GETVERSION
jne @F
 
mov eax, [edi+output]
cmp [edi+out_size], 4
jne .fail
 
mov [eax], dword API_VERSION
xor eax, eax
ret
@@:
cmp eax, DEV_PLAY
jne @F
if DEBUG
mov esi, msgPlay
invoke SysMsgBoardStr
end if
call play
ret
@@:
cmp eax, DEV_STOP
jne @F
if DEBUG
mov esi, msgStop
invoke SysMsgBoardStr
end if
call stop
ret
@@:
cmp eax, DEV_CALLBACK
jne @F
mov ebx, [edi+input]
stdcall set_callback, [ebx]
ret
@@:
cmp eax, DEV_SET_MASTERVOL
jne @F
mov eax, [edi+input]
mov eax, [eax]
call set_master_vol ;eax= vol
ret
@@:
cmp eax, DEV_GET_MASTERVOL
jne @F
mov ebx, [edi+output]
stdcall get_master_vol, ebx
ret
;@@:
; cmp eax, DEV_GET_INFO
; jne @F
; mov ebx, [edi+output]
; stdcall get_dev_info, ebx
; ret
@@:
.fail:
or eax, -1
ret
endp
 
restore handle
restore io_code
restore input
restore inp_size
restore output
restore out_size
 
align 4
proc fill_buffer
 
cmp [ctrl.user_callback], 0
je .exit
 
mov esi, [ctrl.buffer]
mov eax, int_flip_flop
inc dword [eax]
test dword [eax], 1
je @f
add esi, 0x4000
@@:
stdcall [ctrl.user_callback], esi
 
mov edx, FM_PLAY_DMABUF1
mov eax, [buffer_pgaddr]
mov esi, int_flip_flop
test dword [esi], 1
je @f
mov edx, FM_PLAY_DMABUF2
add eax, 0x4000
@@:
call [ctrl.ctrl_write32]
 
.exit:
ret
endp
 
align 4
proc ac97_irq
 
if DEBUG_IRQ
mov esi, msgIRQ
invoke SysMsgBoardStr
end if
 
mov edx, FM_INTSTATUS
call [ctrl.ctrl_read16]
 
test eax, FM_INTSTATUS_PLAY
je .exit
 
push eax
call fill_buffer
pop eax
 
.exit:
mov edx, FM_INTSTATUS
call [ctrl.ctrl_write16]
 
ret
endp
 
align 4
proc create_primary_buff
 
invoke KernelAlloc, 0x10000
mov [ctrl.buffer], eax
 
mov edi, eax
mov ecx, 0x10000/4
xor eax, eax
cld
rep stosd
 
mov eax, [ctrl.buffer]
invoke GetPgAddr
mov [buffer_pgaddr], eax
 
ret
endp
 
align 4
proc detect_controller
locals
last_bus dd ?
bus dd ?
devfn dd ?
endl
 
xor eax, eax
mov [bus], eax
inc eax
invoke PciApi
cmp eax, -1
je .err
 
mov [last_bus], eax
 
.next_bus:
and [devfn], 0
.next_dev:
invoke PciRead32, [bus], [devfn], dword 0
test eax, eax
jz .next
cmp eax, -1
je .next
 
push eax
invoke PciRead32, [bus], [devfn], dword 0x09
and eax, 0xffffff
cmp eax, 0x060100 ;pci-isa
jne .no_bridge
 
mov eax, [bus]
mov [brg_bus], eax
mov eax, [devfn]
mov [brg_devfn], eax
.no_bridge:
pop eax
 
mov edi, devices
@@:
mov ebx, [edi]
test ebx, ebx
jz .next
 
cmp eax, ebx
je .found
add edi, 12
jmp @B
.next:
inc [devfn]
cmp [devfn], 256
jb .next_dev
mov eax, [bus]
inc eax
mov [bus], eax
cmp eax, [last_bus]
jna .next_bus
xor eax, eax
ret
.found:
mov ebx, [bus]
mov [ctrl.bus], ebx
 
mov ecx, [devfn]
mov [ctrl.devfn], ecx
 
mov edx, eax
and edx, 0xFFFF
mov [ctrl.vendor], edx
shr eax, 16
mov [ctrl.dev_id], eax
 
mov ebx, [edi+4]
mov [ctrl.ctrl_ids], ebx
mov [ctrl.vendor_ids], msg_FM
 
mov esi, [edi+8]
mov [ctrl.ctrl_setup], esi
ret
.err:
xor eax, eax
ret
endp
 
align 4
proc init_controller
 
invoke PciRead32, [ctrl.bus], [ctrl.devfn], 4
mov ebx, eax
and eax, 0xFFFF
mov [ctrl.pci_cmd], eax
shr ebx, 16
mov [ctrl.pci_stat], ebx
 
mov esi, msgPciCmd
invoke SysMsgBoardStr
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgPciStat
invoke SysMsgBoardStr
mov eax, [ctrl.pci_stat]
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgCtrlIsaIo
invoke SysMsgBoardStr
 
invoke PciRead32, [ctrl.bus], [ctrl.devfn], 0x10
 
call dword2str
invoke SysMsgBoardStr
 
and eax, 0xFFFE
mov [ctrl.ctrl_io_base], eax
 
mov esi, msgIrqNum
invoke SysMsgBoardStr
 
invoke PciRead32, [ctrl.bus], [ctrl.devfn], 0x3C
and eax, 0xFF
mov [ctrl.int_line], eax
 
call dword2str
invoke SysMsgBoardStr
 
call [ctrl.ctrl_setup]
xor eax, eax
inc eax
ret
endp
 
align 4
proc set_FM
mov [ctrl.codec_read16], codec_io_r16 ;virtual
mov [ctrl.codec_write16], codec_io_w16 ;virtual
 
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual
 
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual
ret
endp
 
align 4
proc reset_controller
 
mov esi, msgInitCtrl
invoke SysMsgBoardStr
 
mov edx, FM_CARD_CTL
call [ctrl.ctrl_read8]
push eax
or al, 1
mov edx, FM_CARD_CTL
call [ctrl.ctrl_write8]
mov eax, 10
call StallExec
pop eax
and al, 0xFE
mov edx, FM_CARD_CTL
call [ctrl.ctrl_write8]
mov eax, 10
call StallExec
 
mov eax, 0x0404
mov edx, FM_PCM_VOLUME
call [ctrl.ctrl_write16]
mov edx, FM_FM_VOLUME
call [ctrl.ctrl_write16]
mov edx, FM_I2S_VOLUME
call [ctrl.ctrl_write16]
 
mov edx, FM_INTMASK
call [ctrl.ctrl_read16]
and eax, not FM_INTMASK_PLAY
or eax, FM_INTMASK_REC or FM_INTMASK_MPU or FM_INTMASK_VOL
mov edx, FM_INTMASK
call [ctrl.ctrl_write16]
 
mov eax, FM_INTMASK_PLAY or FM_INTMASK_REC or FM_INTMASK_MPU or FM_INTMASK_VOL
mov edx, FM_INTSTATUS
call [ctrl.ctrl_write16]
 
ret
endp
 
align 4
proc init_codec
 
mov esi, msgInitCodec
invoke SysMsgBoardStr
 
mov al, FM_CODEC_CMD_READ
mov edx, FM_CODEC_CMD
call [ctrl.ctrl_write8]
 
call reset_codec
 
call detect_codec
 
xor eax, eax
inc eax
ret
endp
 
align 4
proc reset_codec
 
mov ecx, 255
.L1:
mov edx, FM_CODEC_CMD
call [ctrl.ctrl_read16]
test ah, FM_CODEC_CMD_VALID shr 8
jne .L2
loop .L1
.L2:
mov edx, FM_CODEC_CTL
call [ctrl.ctrl_read8]
push eax
or al, 0x20
mov edx, FM_CODEC_CTL
call [ctrl.ctrl_write8]
pop eax
and al, 0xDF
mov edx, FM_CODEC_CTL
call [ctrl.ctrl_write8]
 
xor eax, eax
inc eax
ret
endp
 
align 4
play:
mov eax, 0x4000-1
mov edx, FM_PLAY_DMALEN
call [ctrl.ctrl_write16]
 
call fill_buffer
 
mov eax, FM_PLAY_START or FM_PLAY_STOPNOW or FM_PLAY_STEREO or FM_PLAY_16BIT or 0xA00
mov edx, FM_PLAY_CTL
call [ctrl.ctrl_write16]
 
xor eax, eax
ret
 
align 4
stop:
mov edx, FM_PLAY_CTL
call [ctrl.ctrl_read16]
and eax, not (FM_PLAY_START or FM_PLAY_STOPNOW)
or eax, FM_PLAY_BUF1_LAST or FM_PLAY_BUF2_LAST
mov edx, FM_PLAY_CTL
call [ctrl.ctrl_write16]
 
xor eax, eax
ret
 
align 4
proc get_dev_info stdcall, p_info:dword
virtual at esi
CTRL_INFO CTRL_INFO
end virtual
 
mov esi, [p_info]
mov eax, [ctrl.int_line]
mov ebx, [ctrl.codec_io_base]
mov ecx, [ctrl.ctrl_io_base]
mov edx, [ctrl.codec_mem_base]
mov edi, [ctrl.ctrl_mem_base]
 
mov [CTRL_INFO.irq], eax
mov [CTRL_INFO.codec_io_base], ebx
mov [CTRL_INFO.ctrl_io_base], ecx
mov [CTRL_INFO.codec_mem_base], edx
mov [CTRL_INFO.ctrl_mem_base], edi
 
mov eax, [codec.chip_id]
mov [CTRL_INFO.codec_id], eax
 
mov ebx, [ctrl.pci_cmd]
mov [CTRL_INFO.pci_cmd], ebx
ret
endp
 
align 4
proc set_callback stdcall, handler:dword
mov eax, [handler]
mov [ctrl.user_callback], eax
ret
endp
 
align 4
proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax
 
mov edx, [ac_reg]
 
mov ebx, edx
shr ebx, 1
bt [codec.shadow_flag], ebx
jc .use_shadow
 
call [ctrl.codec_read16] ;change edx !!!
mov ecx, eax
 
.read_ok:
mov edx, [ac_reg]
mov [codec.regs+edx], cx
bts [codec.shadow_flag], ebx
mov eax, ecx
ret
.use_shadow:
movzx eax, word [codec.regs+edx]
ret
 
endp
 
align 4
proc codec_write stdcall, ac_reg:dword
 
mov esi, [ac_reg]
 
mov edx, esi
 
call [ctrl.codec_write16]
 
mov [codec.regs+esi], ax
shr esi, 1
bts [codec.shadow_flag], esi
 
ret
endp
 
align 4
proc check_semafore
align 4
.ok:
xor eax, eax
inc eax
ret
endp
 
align 4
proc StallExec
push ecx
push edx
push ebx
push eax
 
mov ecx, CPU_FREQ
mul ecx
mov ebx, eax ;low
mov ecx, edx ;high
rdtsc
add ebx, eax
adc ecx, edx
@@:
rdtsc
sub eax, ebx
sbb edx, ecx
js @B
 
pop eax
pop ebx
pop edx
pop ecx
ret
endp
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; CONTROLLER IO functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc codec_io_r16
 
push edx
mov ecx, 255
.L1:
mov edx, FM_CODEC_CMD
call [ctrl.ctrl_read16]
test ah, FM_CODEC_CMD_BUSY shr 8
je .L2
loop .L1
.L2:
pop eax
or al, FM_CODEC_CMD_READ
mov edx, FM_CODEC_CMD
call [ctrl.ctrl_write8]
 
mov ecx, 255
.L3:
mov edx, FM_CODEC_CMD
call [ctrl.ctrl_read16]
test ah, FM_CODEC_CMD_VALID shr 8
jne .L4
loop .L3
.L4:
mov edx, FM_CODEC_DATA
call [ctrl.ctrl_read16]
 
ret
endp
 
align 4
proc codec_io_w16
 
push edx
push eax
mov ecx, 255
.L1:
mov edx, FM_CODEC_CMD
call [ctrl.ctrl_read16]
test ah, FM_CODEC_CMD_BUSY shr 8
je .L2
loop .L1
.L2:
pop eax
mov edx, FM_CODEC_DATA
call [ctrl.ctrl_write16]
 
pop eax
mov edx, FM_CODEC_CMD
call [ctrl.ctrl_write16]
 
ret
endp
 
align 4
proc ctrl_io_r8
add edx, [ctrl.ctrl_io_base]
in al, dx
ret
endp
 
align 4
proc ctrl_io_r16
add edx, [ctrl.ctrl_io_base]
in ax, dx
ret
endp
 
align 4
proc ctrl_io_r32
add edx, [ctrl.ctrl_io_base]
in eax, dx
ret
endp
 
align 4
proc ctrl_io_w8
add edx, [ctrl.ctrl_io_base]
out dx, al
ret
endp
 
align 4
proc ctrl_io_w16
add edx, [ctrl.ctrl_io_base]
out dx, ax
ret
endp
 
align 4
proc ctrl_io_w32
add edx, [ctrl.ctrl_io_base]
out dx, eax
ret
endp
 
align 4
dword2str:
mov esi, hex_buff
mov ecx, -8
@@:
rol eax, 4
mov ebx, eax
and ebx, 0x0F
mov bl, [ebx+hexletters]
mov [8+esi+ecx], bl
inc ecx
jnz @B
ret
 
hexletters db '0123456789ABCDEF'
hex_buff db 8 dup(0),13,10,0
brg_bus dd ?
brg_devfn dd ?
include "codec.inc"
 
align 4
devices dd (CTRL_FM801 shl 16)+VID_FM801, msg_FM801, set_FM
dd 0
 
msg_FM801 db 'FM801 AC97 controller',13,10, 0
msg_FM db 'Forte Media',13,10, 0
 
sz_sound_srv db 'SOUND',0
 
msgInit db 'detect hardware...',13,10,0
msgFail db 'device not found',13,10,0
msgAttchIRQ db 'IRQ line not supported', 13,10, 0
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0
msgPlay db 'start play', 13,10,0
msgStop db 'stop play', 13,10,0
;msgNotify db 'call notify',13,10,0
msgIRQ db 'AC97 IRQ', 13,10,0
msgInitCtrl db 'init controller',13,10,0
msgInitCodec db 'init codec',13,10,0
msgPrimBuff db 'create primary buffer ...',0
msgDone db 'done',13,10,0
;msgReg db 'set service handler',13,10,0
;msgOk db 'service installed',13,10,0
;msgStatus db 'global status ',0
;msgControl db 'global control ',0
msgPciCmd db 'PCI command ',0
msgPciStat db 'PCI status ',0
msgCtrlIsaIo db 'controller io base ',0
msgIrqNum db 'IRQ default ',0
;msgIrqMap db 'AC97 irq map as ',0
 
align 4
data fixups
end data
 
codec CODEC
ctrl AC_CNTRL
 
int_flip_flop rd 1
buffer_pgaddr rd 1
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/audio/infinity/infinity.asm
0,0 → 1,1454
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2006-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; Serge 2006-2008
; email: infinity_sound@mail.ru
 
format PE DLL native 0.05
entry START
 
DEBUG equ 1
 
 
CURRENT_API equ 0x0101 ;1.01
COMPATIBLE_API equ 0x0100 ;1.00
 
API_VERSION equ (COMPATIBLE_API shl 16) or CURRENT_API
SOUND_VERSION equ CURRENT_API
 
 
FORCE_MMX equ 0 ;set to 1 to force use mmx or
FORCE_MMX_128 equ 0 ;integer sse2 extensions
;and reduce driver size
 
;USE_SSE equ 0
 
USE_SSE2_MIXER equ 0 ;floating point mixer. Disabled by default
 
OS_BASE equ 0x80000000
 
CAPS_SSE2 equ 26
PG_SW equ 0x003
 
RT_INP_EMPTY equ 0xFF000001
RT_OUT_EMPTY equ 0xFF000002
RT_INP_FULL equ 0xFF000003
RT_OUT_FULL equ 0xFF000004
 
EVENT_WATCHED equ 0x10000000
EVENT_SIGNALED equ 0x20000000
MANUAL_RESET equ 0x40000000
MANUAL_DESTROY equ 0x80000000
 
DEV_PLAY equ 1
DEV_STOP equ 2
DEV_CALLBACK equ 3
DEV_GET_POS equ 9
 
section '.flat' code readable executable
include '../../struct.inc'
include '../../macros.inc'
include '../../proc32.inc'
include 'main.inc'
include '../../peimport.inc'
 
 
 
proc START c uses ebx esi edi, state:dword, cmdline:dword
 
cmp [state], 1
jne .exit
 
invoke GetService, szSound
test eax, eax
jz .fail
mov [hSound], eax
 
invoke KernelAlloc, 16*512
test eax, eax
jz .out_of_mem
mov [mix_buff], eax
 
mov eax, str.fd-FD_OFFSET
mov [str.fd], eax
mov [str.bk], eax
 
if FORCE_MMX
if FORCE_MMX_128
display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10
stop
end if
mov [mix_2_core], mmx_mix_2
mov [mix_3_core], mmx_mix_3
mov [mix_4_core], mmx_mix_4
end if
 
if FORCE_MMX_128
if FORCE_MMX
display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10
stop
end if
mov [mix_2_core], mmx128_mix_2
mov [mix_3_core], mmx128_mix_3
mov [mix_4_core], mmx128_mix_4
end if
 
if 0
 
if ~(FORCE_MMX or FORCE_MMX_128) ;autodetect
mov eax, 1
cpuid
bt edx, CAPS_SSE2
jc .mmx128
;old 64-bit mmx
mov [mix_2_core], mmx_mix_2
mov [mix_3_core], mmx_mix_3
mov [mix_4_core], mmx_mix_4
jmp @F
.mmx128: ;128-bit integer sse2 extensions
mov [mix_2_core], mmx128_mix_2
mov [mix_3_core], mmx128_mix_3
mov [mix_4_core], mmx128_mix_4
@@:
end if
 
end if
stdcall set_handler, [hSound], new_mix
mov [eng_state], SND_STOP
invoke RegService, szInfinity, service_proc
ret
.fail:
if DEBUG
mov esi, msgFail
invoke SysMsgBoardStr
end if
.exit:
xor eax, eax
ret
 
.out_of_mem:
if DEBUG
mov esi, msgMem
invoke SysMsgBoardStr
end if
xor eax, eax
ret
endp
 
align 4
 
srv_calls dd service_proc.srv_getversion ; 0
dd service_proc.snd_create_buff ; 1
dd service_proc.snd_destroy_buff ; 2
dd service_proc.snd_setformat ; 3
dd service_proc.snd_getformat ; 4
dd service_proc.snd_reset ; 5
dd service_proc.snd_setpos ; 6
dd service_proc.snd_getpos ; 7
dd service_proc.snd_setbuff ; 8
dd service_proc.snd_out ; 9
dd service_proc.snd_play ; 10
dd service_proc.snd_stop ; 11
dd service_proc.snd_setvolume ; 12
dd service_proc.snd_getvolume ; 13
dd service_proc.snd_setpan ; 14
dd service_proc.snd_getpan ; 15
dd service_proc.snd_getbuffsize ; 16
dd service_proc.snd_getfreespace ; 17
dd service_proc.snd_settimebase ; 18
dd service_proc.snd_gettimestamp ; 19
srv_calls_end:
 
proc service_proc stdcall, ioctl:dword
 
mov edi, [ioctl]
mov eax, [edi+IOCTL.io_code]
 
cmp eax, (srv_calls_end-srv_calls)/4
ja .fail
 
cmp eax, SND_DESTROY_BUFF
jb @F
 
; cmp [edi+inp_size], 4
; jb .fali
 
mov ebx, [edi+IOCTL.input]
mov edx, [ebx]
 
cmp [edx+STREAM.magic], 'WAVE'
jne .fail
 
cmp [edx+STREAM.size], STREAM.sizeof
jne .fail
 
@@:
jmp [srv_calls+eax*4]
 
 
.fail:
mov eax, -1
ret
 
align 4
.srv_getversion:
mov eax, [edi+IOCTL.output]
cmp [edi+IOCTL.out_size], 4
jne .fail
mov eax, [eax]
mov [eax], dword API_VERSION
xor eax, eax
ret
 
align 4
.snd_create_buff:
mov ebx, [edi+IOCTL.input]
stdcall CreateBuffer, [ebx], [ebx+4]
mov edi, [ioctl]
mov ecx, [edi+IOCTL.output]
mov ecx, [ecx]
mov [ecx], ebx
ret
 
align 4
.snd_destroy_buff:
mov eax, edx
call DestroyBuffer
ret
 
align 4
.snd_setformat:
stdcall SetFormat, edx, [ebx+4]
ret
 
align 4
.snd_getformat:
movzx eax, word [edx+STREAM.format]
mov ecx, [edi+IOCTL.output]
mov ecx, [ecx]
mov [ecx], eax
xor eax, eax
ret
 
align 4
.snd_reset:
stdcall ResetBuffer, edx, [ebx+4]
ret
 
align 4
.snd_setpos:
stdcall SetBufferPos, edx, [ebx+4]
ret
 
align 4
.snd_getpos:
stdcall GetBufferPos, edx
mov edi, [ioctl]
mov ecx, [edi+IOCTL.output]
mov ecx, [ecx]
mov [ecx], ebx
ret
 
align 4
.snd_setbuff:
mov eax, [ebx+4]
stdcall set_buffer, edx, eax, [ebx+8], [ebx+12]
ret
 
align 4
.snd_out:
mov eax, [ebx+4]
stdcall wave_out, edx, eax, [ebx+8]
ret
 
align 4
.snd_play:
stdcall play_buffer, edx, [ebx+4]
ret
 
align 4
.snd_stop:
stdcall stop_buffer, edx
ret
 
align 4
.snd_setvolume:
stdcall SetBufferVol, edx, [ebx+4], [ebx+8]
ret
 
align 4
.snd_getvolume:
mov eax, [edi+IOCTL.output]
mov ecx, [eax]
mov eax, [eax+4]
stdcall GetBufferVol, edx, ecx, eax
ret
align 4
.snd_setpan:
stdcall SetBufferPan, edx, [ebx+4]
ret
 
align 4
.snd_getpan:
mov eax, [edx+STREAM.pan]
mov ebx, [edi+IOCTL.output]
mov ebx, [ebx]
mov [ebx], eax
xor eax, eax
ret
 
align 4
.snd_getbuffsize:
mov eax, [edx+STREAM.in_size]
mov ecx, [edi+IOCTL.output]
mov ecx, [ecx]
mov [ecx], eax
xor eax, eax
ret
 
align 4
.snd_getfreespace:
test [edx+STREAM.format], PCM_OUT
jz .fail
 
mov ebx, [edx+STREAM.in_free]
mov ecx, [edi+IOCTL.output]
mov [ecx], ebx
xor eax, eax
ret
align 4
.snd_settimebase:
cmp [edi+IOCTL.inp_size], 12
jne .fail
 
mov eax, [ebx+4]
mov ebx, [ebx+8]
 
pushfd
cli
mov dword [edx+STREAM.time_base], eax
mov dword [edx+STREAM.time_base+4], ebx
xor eax, eax
mov dword [edx+STREAM.time_stamp], eax
mov dword [edx+STREAM.time_stamp+4], eax
popfd
 
ret
 
align 4
.snd_gettimestamp:
cmp [edi+IOCTL.out_size], 8
jne .fail
 
pushfd
cli
 
xor ebx, ebx
push 48
push ebx ; local storage
 
cmp [edx+STREAM.flags], SND_STOP
je @F
 
mov eax, esp
 
push ebx
push ecx
push edx
push esi
push edi
 
push 4 ;.out_size
push eax ;.output
push ebx ;.inp_size
push ebx ;.input
push DEV_GET_POS ;.code
push dword [hSound] ;.handle
mov eax, esp
 
invoke ServiceHandler, eax
add esp, 6*4
 
pop edi
pop esi
pop edx
pop ecx
pop ebx
 
test eax, eax
jz @F
 
mov dword [esp], 0 ; clear offset
@@:
mov edi, [edi+IOCTL.output]
 
emms
fild qword [edx+STREAM.time_stamp]
fiadd dword [esp] ; primary buffer offset
fidiv dword [esp+4] ; total_samples / frequency
fadd qword [edx+STREAM.time_base]
fstp qword [edi]
add esp, 8
 
popfd
 
xor eax, eax
ret
endp
 
 
restore handle
restore io_code
restore input
restore inp_size
restore output
restore out_size
 
align 4
proc CreateBuffer stdcall, format:dword, size:dword
locals
str dd ?
ring_size dd ?
ring_pages dd ?
endl
 
mov eax, [format]
cmp ax, PCM_1_8_8
ja .fail
 
test eax, PCM_OUT
jnz .test_out
test eax, PCM_RING
jnz .test_ring
;staic
test eax, PCM_STATIC
jz .test_out ;use PCM_OUT as default format
jmp .test_ok
.test_out:
test eax, PCM_RING+PCM_STATIC
jnz .fail
or [format], PCM_OUT ;force set
jmp .test_ok
.test_ring:
test eax, PCM_OUT+PCM_STATIC
jnz .fail
.test_ok:
 
invoke GetPid
mov ebx, eax
mov eax, STREAM.sizeof
 
invoke CreateObject
test eax, eax
jz .fail
mov [str], eax
 
mov ebx, [format]
mov [eax+STREAM.format], ebx
 
xor ecx, ecx
movzx ebx, bx
cmp ebx, 19
jb @f
mov ecx, 0x80808080
@@:
mov [eax+STREAM.r_silence], ecx
 
shl ebx, 2
lea ebx, [ebx+ebx*2] ;ebx*=12
 
mov ecx, [resampler_params+ebx]
mov edx, [resampler_params+ebx+4]
mov esi, [resampler_params+ebx+8]
 
mov [eax+STREAM.r_size], ecx
mov [eax+STREAM.r_dt], edx
mov [eax+STREAM.resample], esi
xor ecx, ecx
mov [eax+STREAM.l_vol], ecx
mov [eax+STREAM.r_vol], ecx
mov dword [eax+STREAM.l_amp], 0x7FFF7FFF
mov [eax+STREAM.pan], ecx
 
test [format], PCM_STATIC
jnz .static
 
; ring and waveout
 
mov ebx, 0x10000
test [format], PCM_RING
jz .waveout
 
mov ebx, [eax+STREAM.r_size]
add ebx, 4095
and ebx, -4096
add ebx, ebx
.waveout:
mov [ring_size], ebx
mov eax, ebx
shr ebx, 12
mov [ring_pages], ebx
 
invoke CreateRingBuffer, eax, PG_SW
 
mov edi, [str]
mov ecx, [ring_size]
mov [edi+STREAM.in_base], eax
mov [edi+STREAM.in_size], ecx
add eax, 128
mov [edi+STREAM.in_wp], eax
mov [edi+STREAM.in_rp], eax
mov [edi+STREAM.in_count], 0
 
mov [edi+STREAM.in_free], ecx
add eax, ecx
mov [edi+STREAM.in_top], eax
 
jmp .out_buff
.static:
mov ecx, [size]
add ecx, 128 ;resampler required
mov [eax+STREAM.in_size], ecx
invoke KernelAlloc, ecx
 
mov edi, [str]
mov [edi+STREAM.in_base], eax
add eax, 128
mov [edi+STREAM.in_wp], eax
mov [edi+STREAM.in_rp], eax
mov ebx, [size]
mov [edi+STREAM.in_count], ebx
mov [edi+STREAM.in_free], ebx
add eax, ebx
mov [edi+STREAM.in_top], eax
 
.out_buff:
invoke AllocKernelSpace, dword 128*1024
 
mov edi, [str]
xor ebx, ebx
 
mov [edi+STREAM.out_base], eax
mov [edi+STREAM.out_wp], eax
mov [edi+STREAM.out_rp], eax
mov [edi+STREAM.out_count], ebx
add eax, 64*1024
mov [edi+STREAM.out_top], eax
 
mov dword [edi+STREAM.time_base], ebx
mov dword [edi+STREAM.time_base+4], ebx
 
mov dword [edi+STREAM.time_stamp], ebx
mov dword [edi+STREAM.time_stamp+4], ebx
mov dword [edi+STREAM.last_ts], ebx
 
invoke AllocPages, dword 64/4
mov edi, [str]
mov ebx, [edi+STREAM.out_base]
mov ecx, 16
or eax, PG_SW
push eax
push ebx
invoke CommitPages ;eax, ebx, ecx
mov ecx, 16
pop ebx
pop eax
add ebx, 64*1024
invoke CommitPages ;double mapped
 
mov edi, [str]
mov ecx, [edi+STREAM.in_top]
mov edi, [edi+STREAM.in_base]
sub ecx, edi
xor eax, eax
shr ecx, 2
cld
rep stosd
 
mov edi, [str]
mov edi, [edi+STREAM.out_base]
mov ecx, (64*1024)/4
rep stosd
 
xor esi, esi
mov ecx, MANUAL_DESTROY
invoke CreateEvent
 
mov ebx, [str]
mov [ebx+STREAM.notify_event], eax
mov [ebx+STREAM.notify_id], edx
 
mov [ebx+STREAM.magic], 'WAVE'
mov [ebx+STREAM.destroy], DestroyBuffer.destroy
mov [ebx+STREAM.size], STREAM.sizeof
mov [ebx+STREAM.flags], SND_STOP
 
pushf
cli
mov eax, str.fd-FD_OFFSET
mov edx, [eax+STREAM.str_fd]
mov [ebx+STREAM.str_fd], edx
mov [ebx+STREAM.str_bk], eax
mov [eax+STREAM.str_fd], ebx
mov [edx+STREAM.str_bk], ebx
popf
 
xor eax, eax
ret
.fail:
xor ebx, ebx
or eax, -1
ret
endp
 
;param
; eax= buffer handle
 
align 4
DestroyBuffer:
.handle equ esp ;local
 
mov [eax+STREAM.flags], SND_STOP
.destroy:
push eax
 
pushfd
cli
mov ebx, [eax+STREAM.str_fd]
mov ecx, [eax+STREAM.str_bk]
mov [ebx+STREAM.str_bk], ecx
mov [ecx+STREAM.str_fd], ebx
popf
 
invoke KernelFree, [eax+STREAM.in_base]
mov eax, [.handle]
invoke KernelFree, [eax+STREAM.out_base]
 
pop eax ;restore stack
invoke DestroyObject ;eax= stream
xor eax, eax
ret
.fail:
or eax, -1
ret
restore .handle
 
align 4
proc SetFormat stdcall, str:dword, format:dword
 
cmp word [format], PCM_1_8_8
ja .fail
 
mov edx, [str]
mov [edx+STREAM.flags], SND_STOP
 
test [edx+STREAM.format], PCM_RING
jnz .fail
 
; mov eax,[edx+STREAM.out_base]
; mov [edx+STREAM.out_wp], eax
; mov [edx+STREAM.out_rp], eax
; mov [edx+STREAM.out_count], 0
 
movzx eax, word [format]
mov word [edx+STREAM.format], ax
 
xor ebx, ebx
cmp eax, 19
jb @f
mov ebx, 0x80808080
@@:
mov [edx+STREAM.r_silence], ebx
 
shl eax, 2
lea eax, [eax+eax*2] ;eax*=12
 
mov edi, [resampler_params+eax]
mov ecx, [resampler_params+eax+4]
mov ebx, [resampler_params+eax+8]
 
mov [edx+STREAM.r_size], edi
mov [edx+STREAM.r_dt], ecx
mov [edx+STREAM.resample], ebx
 
mov edi, [edx+STREAM.in_base]
mov ecx, 128/4
mov eax, [edx+STREAM.r_silence]
cld
rep stosd
xor eax, eax
ret
.fail:
or eax, -1
ret
endp
 
; for static buffers only
; use waveout for streams
 
align 4
proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword
 
mov edx, [str]
test [edx+STREAM.format], PCM_OUT
jnz .fail
 
mov esi, [src]
mov edi, [offs]
add edi, [edx+STREAM.in_base]
add edi, 128
 
cmp edi, [edx+STREAM.in_top]
jae .fail
 
mov ecx, [size]
lea ebx, [ecx+edi]
sub ebx, [edx+STREAM.in_top]
jb @F
sub ecx, ebx
@@:
shr ecx, 2
cld
rep movsd
xor eax, eax
ret
.fail:
or eax, -1
ret
endp
 
; for stream buffers only
 
align 4
proc wave_out stdcall, str:dword,src:dword,size:dword
locals
state_saved dd ?
fpu_state rb 528
endl
 
mov edx, [str]
mov eax, [edx+STREAM.format]
test eax, PCM_OUT
jz .fail
 
cmp ax, PCM_ALL
je .fail
 
mov esi, [src]
test esi, esi
jz .fail
 
cmp esi, OS_BASE
jae .fail
 
mov [state_saved], 0
 
.main_loop:
mov edx, [str]
 
mov ebx, [size]
test ebx, ebx
jz .done
 
cmp [edx+STREAM.flags], SND_STOP
jne .fill
 
mov edi, [edx+STREAM.in_base]
mov ecx, 128/4
mov eax, [edx+STREAM.r_silence]
cld
rep stosd
 
mov ecx, [edx+STREAM.in_size]
sub ecx, 128
mov [edx+STREAM.in_wp], edi
mov [edx+STREAM.in_rp], edi
mov [edx+STREAM.in_count], 0
mov [edx+STREAM.in_free], ecx
 
mov eax, [edx+STREAM.out_base]
mov [edx+STREAM.out_wp], eax
mov [edx+STREAM.out_rp], eax
mov [edx+STREAM.out_count], 0
.fill:
cli
 
mov ecx, [edx+STREAM.in_free]
test ecx, ecx
jz .wait
 
cmp ecx, ebx
jbe @F
 
mov ecx, ebx
@@:
sub [size], ecx
add [edx+STREAM.in_count], ecx
sub [edx+STREAM.in_free], ecx
 
shr ecx, 2
mov edi, [edx+STREAM.in_wp]
mov esi, [src]
cld
rep movsd
 
mov [src], esi
cmp edi, [edx+STREAM.in_top]
jb @F
sub edi, [edx+STREAM.in_size]
@@:
mov [edx+STREAM.in_wp], edi
 
cmp [edx+STREAM.out_count], 32768
jae .skip
 
cmp [state_saved], 0
jne @F
lea eax, [fpu_state+15]
and eax, -16
invoke FpuSave
mov [state_saved], 1
@@:
stdcall refill, edx
 
.skip:
sti
mov edx, [str]
mov [edx+STREAM.flags], SND_PLAY
cmp [eng_state], SND_PLAY
je .main_loop
 
stdcall dev_play, [hSound]
mov [eng_state], SND_PLAY
jmp .main_loop
.wait:
sti
mov edx, [str]
mov eax, [edx+STREAM.notify_event]
mov ebx, [edx+STREAM.notify_id]
invoke WaitEvent ;eax ebx
jmp .main_loop
.done:
cmp [state_saved], 1
jne @F
 
lea eax, [fpu_state+15]
and eax, -16
invoke FpuRestore
@@:
xor eax, eax
ret
.fail:
or eax, -1
ret
endp
 
; both static and stream
; reset all but not clear buffers
 
 
; flags reserved
; RESET_INPUT equ 1 ;reset and clear input buffer
; RESET_OUTPUT equ 2 ;reset and clear output buffer
; RESET_ALL equ 3
 
 
align 4
proc ResetBuffer stdcall, str:dword, flags:dword
 
mov edx, [str]
mov [edx+STREAM.flags], SND_STOP
 
mov edi, [edx+STREAM.in_base]
mov ecx, 128/4
mov eax, [edx+STREAM.r_silence]
cld
rep stosd
 
mov [edx+STREAM.in_wp], edi
mov [edx+STREAM.in_rp], edi
 
test [edx+STREAM.flags], PCM_STATIC
jnz .static
mov [edx+STREAM.in_count], 0
jmp @F
.static:
mov eax, [edx+STREAM.in_size]
mov [edx+STREAM.in_count], eax
@@:
 
mov eax, [edx+STREAM.in_size]
sub eax, 128
mov [edx+STREAM.in_free], eax
 
xor eax, eax
mov ebx, [edx+STREAM.out_base]
mov [edx+STREAM.out_wp], ebx
mov [edx+STREAM.out_rp], ebx
mov [edx+STREAM.out_count], eax
 
mov dword [edx+STREAM.time_base], eax
mov dword [edx+STREAM.time_base+4], eax
 
mov dword [edx+STREAM.time_stamp], eax
mov dword [edx+STREAM.time_stamp+4], eax
mov dword [edx+STREAM.last_ts], eax
 
 
mov eax, [edx+STREAM.r_silence]
test [flags], 1
jz @F
 
mov ecx, [edx+STREAM.in_top]
mov edi, [edx+STREAM.in_base]
sub ecx, edi
shr ecx, 2
cld
rep stosd
@@:
test [flags], 2
jz @F
 
mov edi, [edx+STREAM.out_base]
mov ecx, (64*1024)/4
rep stosd
@@:
ret
.fail:
or eax, -1
ret
endp
 
; for static buffers only
 
align 4
proc SetBufferPos stdcall, str:dword, pos:dword
 
mov edx, [str]
test [edx+STREAM.format], PCM_STATIC
jz .fail
 
mov [edx+STREAM.flags], SND_STOP
 
mov eax, [pos]
add eax, [edx+STREAM.in_base]
mov ebx, [edx+STREAM.in_top]
add eax, 128
 
cmp eax, ebx
jae .fail
 
mov [edx+STREAM.in_rp], eax
sub ebx, eax
mov [edx+STREAM.in_count], ebx
xor eax, eax
ret
.fail:
or eax, -1
ret
endp
 
align 4
proc GetBufferPos stdcall, str:dword
 
mov edx, [str]
test [edx+STREAM.format], PCM_STATIC
jz .fail
 
mov ebx, [edx+STREAM.in_rp]
sub ebx, [edx+STREAM.in_base]
sub ebx, 128
xor eax, eax
ret
.fail:
xor ebx, ebx
or eax, -1
ret
endp
 
; both
 
align 4
proc SetBufferVol stdcall, str:dword,l_vol:dword,r_vol:dword
 
mov edx, [str]
stdcall set_vol_param, [l_vol], [r_vol], [edx+STREAM.pan]
ret
endp
 
 
proc minw stdcall, arg1:dword, arg2:dword
mov ax, word [arg1]
cmp ax, word [arg2]
jle @f
mov eax, [arg2]
@@:
ret
endp
 
proc maxw stdcall, arg1:dword, arg2:dword
mov ax, word [arg1]
cmp ax, word [arg2]
jge @f
mov eax, [arg2]
@@:
ret
endp
 
 
proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword
locals
_600 dd ?
_32767 dd ?
state rb 108
endl
 
mov [_600], 0x44160000 ;600.0
mov [_32767], 32767
 
lea ebx, [state]
fnsave [ebx]
 
stdcall minw, [l_vol], [vol_max]
stdcall maxw, eax, [vol_min]
mov [l_vol], eax
mov [edx+STREAM.l_vol], eax
stdcall minw, [r_vol], [vol_max+4]
stdcall maxw, eax, [vol_min+4]
mov [r_vol], eax
mov [edx+STREAM.r_vol], eax
 
stdcall minw, [pan], [pan_max]
stdcall maxw, eax, [vol_min]
mov [edx+STREAM.pan], eax
 
cmp word [edx+STREAM.pan], 0
jl @f
 
mov ebx, [l_vol]
sub ebx, eax
stdcall minw, ebx, [vol_max]
stdcall maxw, eax, [vol_min]
mov [l_vol], eax
jmp .calc_amp
@@:
mov ebx, [r_vol]
add ebx, [pan]
stdcall minw, ebx, [vol_max+4]
stdcall maxw, eax, [vol_min+4]
mov [r_vol], eax
.calc_amp:
emms
fild word [l_vol]
 
call .calc
 
fistp word [edx+STREAM.l_amp]
fstp dword [edx+STREAM.l_amp_f]
fstp st0
 
fild word [r_vol]
 
call .calc
 
fistp word [edx+STREAM.r_amp]
fstp dword [edx+STREAM.r_amp_f]
fstp st0
 
fnclex
lea ebx, [state]
frstor [ebx]
 
xor eax, eax
inc eax
ret
.calc:
fdiv dword [_600]
fld st0
frndint
fxch st1
fsub st, st1
f2xm1
fld1
faddp st1, st0
fscale
fld st0
fimul dword [_32767]
ret 0
endp
 
 
align 4
proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword
 
mov edx, [str]
mov eax, [p_lvol]
movsx ecx, word [edx+STREAM.l_vol]
mov [eax], ecx
 
mov eax, [p_rvol]
movsx ecx, word [edx+STREAM.r_vol]
mov [eax], ecx
xor eax, eax
ret
endp
 
align 4
proc SetBufferPan stdcall, str:dword,pan:dword
 
mov edx, [str]
stdcall set_vol_param, [edx+STREAM.l_vol], \
[edx+STREAM.r_vol],[pan]
ret
endp
 
; for static and ring buffers only
 
align 4
proc play_buffer stdcall, str:dword, flags:dword
 
mov ebx, [str]
mov eax, [ebx+STREAM.format]
test eax, PCM_OUT
jnz .fail
 
cmp ax, PCM_ALL
je .fail
 
mov [ebx+STREAM.flags], SND_PLAY
cmp [eng_state], SND_PLAY
je .done
 
stdcall dev_play, [hSound]
mov [eng_state], SND_PLAY
.done:
test [flags], PLAY_SYNC
jz @F
 
mov edx, [str]
.wait:
mov eax, [edx+STREAM.notify_event]
mov ebx, [edx+STREAM.notify_id]
invoke WaitEvent ;eax ebx
 
mov edx, [str]
cmp [edx+STREAM.flags], SND_STOP
jne .wait
@@:
xor eax, eax
ret
.fail:
or eax, -1
ret
endp
 
; for static and ring buffers only
 
align 4
proc stop_buffer stdcall, str:dword
 
mov edx, [str]
test [edx+STREAM.format], PCM_STATIC+PCM_RING
jz .fail
 
mov [edx+STREAM.flags], SND_STOP
 
mov eax, [edx+STREAM.notify_event]
mov ebx, [edx+STREAM.notify_id]
invoke ClearEvent ;eax ebx
 
xor eax, eax
ret
.fail:
or eax, -1
ret
endp
 
; param
; eax= mix_list
 
align 4
do_mix_list:
 
xor edx, edx
mov esi, str.fd-FD_OFFSET
mov ebx, [esi+STREAM.str_fd]
@@:
cmp ebx, esi
je .done
 
cmp [ebx+STREAM.magic], 'WAVE'
jne .next
 
cmp [ebx+STREAM.size], STREAM.sizeof
jne .next
 
cmp [ebx+STREAM.flags], SND_PLAY;
jne .next
 
mov ecx, [ebx+STREAM.out_count]
test ecx, ecx
jnz .l1
 
test [ebx+STREAM.format], PCM_RING
jnz .next
mov [ebx+STREAM.flags], SND_STOP
jmp .next
.l1:
cmp ecx, 512
jae .add_buff
 
mov edi, [ebx+STREAM.out_rp]
add edi, ecx
sub ecx, 512
neg ecx
push eax
xor eax, eax
cld
rep stosb
pop eax
 
mov [ebx+STREAM.out_count], 512
 
.add_buff:
mov ecx, [ebx+STREAM.out_rp]
mov [eax], ecx
 
if USE_SSE2_MIXER
mov edi, dword [ebx+STREAM.l_amp_f]
mov [eax+4], edi
mov edi, dword [ebx+STREAM.r_amp_f]
mov [eax+8], edi
else
mov edi, dword [ebx+STREAM.l_amp]
mov [eax+4], edi
end if
add [ebx+STREAM.out_rp], 512
sub [ebx+STREAM.out_count], 512
 
add eax, 12
inc edx
.next:
mov ebx, [ebx+STREAM.str_fd]
jmp @B
.done:
mov eax, edx
ret
 
align 4
prepare_playlist:
 
xor edx, edx
mov [play_count], edx
mov esi, str.fd-FD_OFFSET
mov edi, [esi+STREAM.str_fd]
@@:
cmp edi, esi
je .done
 
cmp [edi+STREAM.magic], 'WAVE'
jne .next
 
cmp [edi+STREAM.size], STREAM.sizeof
jne .next
 
cmp [edi+STREAM.flags], SND_PLAY;
jne .next
 
mov [play_list+edx], edi
inc [play_count]
add edx, 4
.next:
mov edi, [edi+STREAM.str_fd]
jmp @B
.done:
ret
 
align 4
proc set_handler stdcall, hsrv:dword, handler_proc:dword
locals
handler dd ?
io_code dd ?
input dd ?
inp_size dd ?
output dd ?
out_size dd ?
val dd ?
endl
 
mov eax, [hsrv]
lea ecx, [handler_proc]
xor ebx, ebx
 
mov [handler], eax
mov [io_code], DEV_CALLBACK
mov [input], ecx
mov [inp_size], 4
mov [output], ebx
mov [out_size], 0
 
lea eax, [handler]
invoke ServiceHandler, eax
ret
endp
 
align 4
proc dev_play stdcall, hsrv:dword
locals
handle dd ?
io_code dd ?
input dd ?
inp_size dd ?
output dd ?
out_size dd ?
val dd ?
endl
 
mov eax, [hsrv]
xor ebx, ebx
 
mov [handle], eax
mov [io_code], DEV_PLAY
mov [input], ebx
mov [inp_size], ebx
mov [output], ebx
mov [out_size], ebx
 
lea eax, [handle]
invoke ServiceHandler, eax
ret
endp
 
if 0
align 4
dword2str:
mov esi, hex_buff
mov ecx, -8
@@:
rol eax, 4
mov ebx, eax
and ebx, 0x0F
mov bl, [ebx+hexletters]
mov [8+esi+ecx], bl
inc ecx
jnz @B
ret
 
hexletters db '0123456789ABCDEF'
hex_buff db 8 dup(0),13,10,0
 
end if
 
include 'mixer.asm'
include 'mix_mmx.inc'
include 'mix_sse2.inc'
 
;if USE_SSE
; include 'mix_sse.inc'
;end if
 
align 16
resampler_params:
;r_size r_dt resampler_func
dd 0,0,0 ; 0 PCM_ALL
dd 16384, 0, copy_stream ; 1 PCM_2_16_48
dd 8192, 0, m16_stereo ; 2 PCM_1_16_48
 
dd 16384, 30109, resample_2 ; 3 PCM_2_16_44
dd 8192, 30109, resample_1 ; 4 PCM_1_16_44
 
dd 16384, 21846, resample_2 ; 5 PCM_2_16_32
dd 8192, 21846, resample_1 ; 6 PCM_1_16_32
 
dd 16384, 16384, resample_2 ; 7 PCM_2_16_24
dd 8192, 16384, resample_1 ; 8 PCM_1_16_24
 
dd 8192, 15052, resample_2 ; 9 PCM_2_16_22
dd 4096, 15052, resample_1 ;10 PCM_1_16_22
 
dd 8192, 10923, resample_2 ;11 PCM_2_16_16
dd 4096, 10923, resample_1 ;12 PCM_1_16_16
 
dd 8192, 8192, resample_2 ;13 PCM_2_16_12
dd 4096, 8192, resample_1 ;14 PCM_1_16_12
 
dd 4096, 7527, resample_2 ;15 PCM_2_16_11
dd 2048, 7527, resample_1 ;16 PCM_1_16_11
 
dd 4096, 5462, resample_2 ;17 PCM_2_16_8
dd 2048, 5462, resample_1 ;18 PCM_1_16_8
 
dd 16384, 0, s8_stereo ;19 PCM_2_8_48
dd 8192, 0, m8_stereo ;20 PCM_1_8_48
 
dd 8192, 30109, resample_28 ;21 PCM_2_8_44
dd 4096, 30109, resample_18 ;22 PCM_1_8_44
 
dd 8192, 21846, resample_28 ;23 PCM_2_8_32
dd 4096, 21846, resample_18 ;24 PCM_1_8_32
 
dd 8192, 16384, resample_28 ;25 PCM_2_8_24
dd 4096, 16384, resample_18 ;26 PCM_1_8_24
 
dd 4096, 15052, resample_28 ;27 PCM_2_8_22
dd 2048, 15052, resample_18 ;28 PCM_1_8_22
 
dd 4096, 10923, resample_28 ;29 PCM_2_8_16
dd 2048, 10923, resample_18 ;30 PCM_1_8_16
 
dd 4096, 8192, resample_28 ;31 PCM_2_8_12
dd 2048, 8192, resample_18 ;32 PCM_1_8_12
 
dd 2048, 7527, resample_28 ;33 PCM_2_8_11
dd 1024, 7527, resample_18 ;34 PCM_1_8_11
 
dd 2048, 5462, resample_28 ;35 PCM_2_8_8
dd 1024, 5462, resample_18 ;36 PCM_1_8_8
 
m7 dw 0x8000,0x8000,0x8000,0x8000
mm80 dq 0x8080808080808080
mm_mask dq 0xFF00FF00FF00FF00
 
vol_max dd 0x00000000,0x00000000
vol_min dd 0x0000D8F0,0x0000D8F0
pan_max dd 0x00002710,0x00002710
 
;stream_map dd 0xFFFF ; 16
 
szInfinity db 'INFINITY',0
szSound db 'SOUND',0
 
if DEBUG
msgFail db 'Sound service not loaded',13,10,0
msgPlay db 'Play buffer',13,10,0
msgStop db 'Stop',13,10,0
msgUser db 'User callback',13,10,0
msgMem db 'Not enough memory',13,10,0
msgDestroy db 'Destroy sound buffer', 13,10,0
msgWaveout db 'Play waveout', 13,10,0
msgSetVolume db 'Set volume',13,10,0
end if
 
align 4
data fixups
end data
 
section '.data' data readable writable
 
play_list rd 16
mix_input rd 16
play_count rd 1
hSound rd 1
eng_state rd 1
mix_buff rd 1
mix_buff_map rd 1
str.fd rd 1
str.bk rd 1
 
mix_2_core rd 1
mix_3_core rd 1
mix_4_core rd 1
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Rev
\ No newline at end of property
/drivers/audio/infinity/main.inc
0,0 → 1,173
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2006-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; Serge 2006-2008
; email: infinity_sound@mail.ru
 
 
PLAY_SYNC equ 0x80000000
 
PCM_ALL equ 0
 
PCM_OUT equ 0x08000000
PCM_RING equ 0x10000000
PCM_STATIC equ 0x20000000
PCM_FLOAT equ 0x40000000 ;reserved
PCM_FILTER equ 0x80000000 ;reserved
 
PCM_2_16_48 equ 1
PCM_1_16_48 equ 2
 
PCM_2_16_44 equ 3
PCM_1_16_44 equ 4
 
PCM_2_16_32 equ 5
PCM_1_16_32 equ 6
 
PCM_2_16_24 equ 7
PCM_1_16_24 equ 8
 
PCM_2_16_22 equ 9
PCM_1_16_22 equ 10
 
PCM_2_16_16 equ 11
PCM_1_16_16 equ 12
 
PCM_2_16_12 equ 13
PCM_1_16_12 equ 14
 
PCM_2_16_11 equ 15
PCM_1_16_11 equ 16
 
PCM_2_16_8 equ 17
PCM_1_16_8 equ 18
 
PCM_2_8_48 equ 19
PCM_1_8_48 equ 20
 
PCM_2_8_44 equ 21
PCM_1_8_44 equ 22
 
PCM_2_8_32 equ 23
PCM_1_8_32 equ 24
 
PCM_2_8_24 equ 25
PCM_1_8_24 equ 26
 
PCM_2_8_22 equ 27
PCM_1_8_22 equ 28
 
PCM_2_8_16 equ 29
PCM_1_8_16 equ 30
 
PCM_2_8_12 equ 31
PCM_1_8_12 equ 32
 
PCM_2_8_11 equ 33
PCM_1_8_11 equ 34
 
PCM_2_8_8 equ 35
PCM_1_8_8 equ 36
 
SRV_GETVERSION equ 0
SND_CREATE_BUFF equ 1
SND_DESTROY_BUFF equ 2
SND_SETFORMAT equ 3
SND_GETFORMAT equ 4
SND_RESET equ 5
SND_SETPOS equ 6
SND_GETPOS equ 7
SND_SETBUFF equ 8
SND_OUT equ 9
SND_PLAY equ 10
SND_STOP equ 11
SND_SETVOLUME equ 12
SND_GETVOLUME equ 13
SND_SETPAN equ 14
SND_GETPAN equ 15
SND_GETBUFFSIZE equ 16
SND_GETFREESPACE equ 17
SND_SETTIMEBASE equ 18
SND_GETTIMESTAMP equ 19
 
struc STREAM
{
.magic dd ? ;'WAVE'
.destroy dd ? ;internal destructor
.fd dd ? ;next object in list
.bk dd ? ;prev object in list
.pid dd ? ;owner id
 
.size dd ?
.str_fd dd ?
.str_bk dd ?
.device dd ?
.format dd ?
.flags dd ?
 
.out_base dd ?
.out_wp dd ?
.out_rp dd ?
.out_count dd ?
.out_top dd ? ;16*4
 
.in_base dd ?
.in_size dd ?
.in_wp dd ?
.in_rp dd ?
.in_count dd ?
.in_free dd ?
.in_top dd ?
 
align 8
 
.time_base dq ?
.time_stamp dq ?
.last_ts dd ?
 
.notify_event dd ?
.notify_id dd ?
 
.r_size dd ?
.r_dt dd ?
.r_silence dd ?
.resample dd ?
.l_vol dd ?
.r_vol dd ?
.l_amp dw ?
.r_amp dw ?
.pan dd ?
.l_amp_f dd ? ;float point left
.r_amp_f dd ? ;float point right
 
.sizeof:
}
 
FD_OFFSET equ 24
 
virtual at 0
STREAM STREAM
end virtual
 
struc WAVE_HEADER
{ .riff_id dd ?
.riff_size dd ?
.riff_format dd ?
 
.fmt_id dd ?
.fmt_size dd ?
.format_tag dw ?
.channels dw ?
.freq dd ?
.bytes_sec dd ?
.block_align dw ?
.bits_sample dw ?
 
.data_id dd ?
.data_size dd ?
}
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Rev
\ No newline at end of property
/drivers/audio/infinity/mix_mmx.inc
0,0 → 1,247
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; params
; edi= output
; eax= input stream 1
; ebx= input stream 2
 
if used mmx_mix_2
 
align 4
mmx_mix_2:
movq mm0, [eax]
movq mm1, [eax+8]
movq mm2, [eax+16]
movq mm3, [eax+24]
movq mm4, [eax+32]
movq mm5, [eax+40]
movq mm6, [eax+48]
movq mm7, [eax+56]
 
paddsw mm0, [ebx]
movq [edi], mm0
paddsw mm1, [ebx+8]
movq [edi+8], mm1
paddsw mm2, [ebx+16]
movq [edi+16], mm2
paddsw mm3, [ebx+24]
movq [edi+24], mm3
paddsw mm4, [ebx+32]
movq [edi+32], mm4
paddsw mm5, [ebx+40]
movq [edi+40], mm5
paddsw mm6, [ebx+48]
movq [edi+48], mm6
paddsw mm7, [ebx+56]
movq [edi+56], mm7
 
movq mm0, [eax+64]
movq mm1, [eax+72]
movq mm2, [eax+80]
movq mm3, [eax+88]
movq mm4, [eax+96]
movq mm5, [eax+104]
movq mm6, [eax+112]
movq mm7, [eax+120]
 
paddsw mm0, [ebx+64]
movq [edi+64], mm0
paddsw mm1, [ebx+72]
movq [edi+72], mm1
paddsw mm2, [ebx+80]
movq [edi+80], mm2
paddsw mm3, [ebx+88]
movq [edi+88], mm3
paddsw mm4, [ebx+96]
movq [edi+96], mm4
paddsw mm5, [ecx+104]
movq [edx+104], mm5
paddsw mm6, [ebx+112]
movq [edi+112], mm6
paddsw mm7, [ebx+120]
movq [edi+120], mm7
ret
 
align 4
mmx_mix_3:
movq mm0, [eax]
movq mm1, [eax+8]
movq mm2, [eax+16]
movq mm3, [eax+24]
movq mm4, [eax+32]
movq mm5, [eax+40]
movq mm6, [eax+48]
movq mm7, [eax+56]
 
paddsw mm0, [ebx]
paddsw mm1, [ebx+8]
paddsw mm2, [ebx+16]
paddsw mm3, [ebx+24]
paddsw mm4, [ebx+32]
paddsw mm5, [ebx+40]
paddsw mm6, [ebx+48]
paddsw mm7, [ebx+56]
paddsw mm0, [ecx]
movq [edi], mm0
paddsw mm1, [ecx+8]
movq [edi+8], mm1
paddsw mm2, [ecx+16]
movq [edi+16], mm2
paddsw mm3, [ecx+24]
movq [edi+24], mm3
paddsw mm4, [ecx+32]
movq [edi+32], mm4
paddsw mm5, [ecx+40]
movq [edi+40], mm5
paddsw mm6, [ecx+48]
movq [edi+48], mm6
paddsw mm7, [ecx+56]
movq [edi+56], mm7
 
movq mm0, [eax+64]
movq mm1, [eax+72]
movq mm2, [eax+80]
movq mm3, [eax+88]
movq mm4, [eax+96]
movq mm5, [eax+104]
movq mm6, [eax+112]
movq mm7, [eax+120]
paddsw mm0, [ebx+64]
paddsw mm1, [ebx+72]
paddsw mm2, [ebx+80]
paddsw mm3, [ebx+88]
paddsw mm4, [ebx+96]
paddsw mm5, [ebx+104]
paddsw mm6, [ebx+112]
paddsw mm7, [ebx+120]
paddsw mm0, [ecx+64]
movq [edi+64], mm0
paddsw mm1, [ecx+72]
movq [edi+72], mm1
paddsw mm2, [ecx+80]
movq [edi+80], mm2
paddsw mm3, [ecx+88]
movq [edi+88], mm3
paddsw mm4, [ecx+96]
movq [edi+96], mm4
paddsw mm5, [ecx+104]
movq [edi+104], mm5
paddsw mm6, [ecx+112]
movq [edi+112], mm6
paddsw mm7, [ecx+120]
movq [edi+120], mm7
ret
 
align 4
mmx_mix_4:
 
movq mm0, [eax]
movq mm2, [eax+8]
movq mm4, [eax+16]
movq mm6, [eax+24]
movq mm1, [ebx]
movq mm3, [ebx+8]
movq mm5, [ebx+16]
movq mm7, [ebx+24]
paddsw mm0, [ecx]
paddsw mm2, [ecx+8]
paddsw mm4, [ecx+16]
paddsw mm6, [ecx+24]
paddsw mm1, [edx]
paddsw mm3, [edx+8]
paddsw mm5, [edx+16]
paddsw mm7, [edx+24]
 
paddsw mm0, mm1
movq [edi], mm0
paddsw mm2, mm3
movq [edi+8], mm2
paddsw mm4, mm5
movq [edi+16], mm4
paddsw mm5, mm6
movq [edi+24], mm6
 
movq mm0, [eax+32]
movq mm2, [eax+40]
movq mm4, [eax+48]
movq mm6, [eax+56]
movq mm1, [ebx+32]
movq mm3, [ebx+40]
movq mm5, [ebx+48]
movq mm7, [ebx+56]
paddsw mm0, [ecx+32]
paddsw mm2, [ecx+40]
paddsw mm4, [ecx+48]
paddsw mm6, [ecx+56]
paddsw mm1, [edx+32]
paddsw mm3, [edx+40]
paddsw mm5, [edx+48]
paddsw mm7, [edx+56]
 
paddsw mm0, mm1
movq [edi+32], mm0
paddsw mm2, mm2
movq [edi+40], mm2
paddsw mm4, mm5
movq [edi+48], mm4
paddsw mm6, mm7
movq [edi+56], mm6
 
movq mm0, [eax+64]
movq mm2, [eax+72]
movq mm4, [eax+80]
movq mm6, [eax+88]
movq mm1, [ebx+64]
movq mm3, [ebx+72]
movq mm5, [ebx+80]
movq mm7, [ebx+88]
paddsw mm0, [ecx+64]
paddsw mm2, [ecx+72]
paddsw mm4, [ecx+80]
paddsw mm6, [ecx+88]
paddsw mm1, [edx+64]
paddsw mm3, [edx+72]
paddsw mm5, [edx+80]
paddsw mm7, [edx+88]
 
paddsw mm0, mm1
movq [edi+64], mm0
paddsw mm2, mm3
movq [edi+72], mm2
paddsw mm4, mm5
movq [edi+80], mm4
paddsw mm6, mm5
movq [edi+88], mm7
 
movq mm0, [eax+96]
movq mm2, [eax+104]
movq mm4, [eax+112]
movq mm6, [eax+120]
movq mm1, [ebx+96]
movq mm3, [ebx+104]
movq mm5, [ebx+112]
movq mm7, [ebx+120]
paddsw mm0, [ecx+96]
paddsw mm2, [ecx+104]
paddsw mm4, [ecx+112]
paddsw mm6, [ecx+120]
paddsw mm1, [edx+96]
paddsw mm3, [edx+104]
paddsw mm5, [edx+112]
paddsw mm7, [edx+120]
paddsw mm0, mm1
movq [eax+96], mm0
paddsw mm2, mm3
movq [edi+104], mm2
paddsw mm4, mm5
movq [edi+112], mm4
paddsw mm6, mm7
movq [edi+120], mm6
ret
 
end if
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Rev
\ No newline at end of property
/drivers/audio/infinity/mix_sse2.inc
0,0 → 1,145
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
if used mmx128_mix_2
 
align 4
mmx128_mix_2:
prefetcht1 [eax+128]
prefetcht1 [ebx+128]
 
movaps xmm0, [eax]
movaps xmm1, [eax+16]
movaps xmm2, [eax+32]
movaps xmm3, [eax+48]
movaps xmm4, [eax+64]
movaps xmm5, [eax+80]
movaps xmm6, [eax+96]
movaps xmm7, [eax+112]
 
paddsw xmm0, [ebx]
movaps [edi], xmm0
paddsw xmm1, [ebx+16]
movaps [edi+16], xmm1
paddsw xmm2, [ebx+32]
movaps [edi+32], xmm2
paddsw xmm3, [ebx+48]
movaps [edi+48], xmm3
paddsw xmm4, [ebx+64]
movaps [edi+64], xmm4
paddsw xmm5, [ebx+80]
movaps [edi+80], xmm5
paddsw xmm6, [ebx+96]
movaps [edi+96], xmm6
paddsw xmm7, [ebx+112]
movaps [edi+112], xmm7
ret
 
align 4
mmx128_mix_3:
prefetcht1 [eax+128]
prefetcht1 [ebx+128]
prefetcht1 [ecx+128]
 
movaps xmm0, [eax]
movaps xmm1, [eax+16]
movaps xmm2, [eax+32]
movaps xmm3, [eax+48]
movaps xmm4, [eax+64]
movaps xmm5, [eax+80]
movaps xmm6, [eax+96]
movaps xmm7, [eax+112]
 
paddsw xmm0, [ebx]
paddsw xmm1, [ebx+16]
paddsw xmm2, [ebx+32]
paddsw xmm3, [ebx+48]
paddsw xmm4, [ebx+64]
paddsw xmm5, [ebx+80]
paddsw xmm6, [ebx+96]
paddsw xmm7, [ebx+112]
 
paddsw xmm0, [ecx]
movaps [edi], xmm0
paddsw xmm1, [ecx+16]
movaps [edi+16], xmm1
paddsw xmm2, [ecx+32]
movaps [edi+32], xmm2
paddsw xmm3, [ecx+48]
movaps [edi+48], xmm3
paddsw xmm4, [ecx+64]
movaps [edi+64], xmm4
paddsw xmm5, [ecx+80]
movaps [edi+80], xmm5
paddsw xmm6, [ecx+96]
movaps [edi+96], xmm6
paddsw xmm7, [ecx+112]
movaps [edi+112], xmm7
ret
 
align 4
mmx128_mix_4:
prefetcht1 [eax+128]
prefetcht1 [ebx+128]
prefetcht1 [ecx+128]
prefetcht1 [edx+128]
 
movaps xmm0, [eax]
movaps xmm2, [eax+16]
movaps xmm4, [eax+32]
movaps xmm6, [eax+48]
movaps xmm1, [ebx]
movaps xmm3, [ebx+16]
movaps xmm5, [ebx+32]
movaps xmm7, [ebx+48]
 
paddsw xmm0, [ecx]
paddsw xmm2, [ecx+16]
paddsw xmm4, [ecx+32]
paddsw xmm6, [ecx+48]
paddsw xmm1, [edx]
paddsw xmm3, [edx+16]
paddsw xmm5, [edx+32]
paddsw xmm7, [edx+48]
 
paddsw xmm0, xmm1
movaps [edi], xmm0
paddsw xmm2, xmm3
movaps [edi+16], xmm2
paddsw xmm4, xmm5
movaps [edi+32], xmm4
paddsw xmm6, xmm7
movaps [edi+48], xmm6
 
movaps xmm0, [eax+64]
movaps xmm2, [eax+80]
movaps xmm4, [eax+96]
movaps xmm6, [eax+112]
 
movaps xmm1, [ebx+64]
movaps xmm3, [ebx+80]
movaps xmm5, [ebx+96]
movaps xmm7, [ebx+112]
paddsw xmm0, [ecx+64]
paddsw xmm2, [ecx+80]
paddsw xmm4, [ecx+96]
paddsw xmm6, [ecx+112]
 
paddsw xmm1, [edx+64]
paddsw xmm3, [edx+80]
paddsw xmm5, [edx+96]
paddsw xmm7, [edx+112]
paddsw xmm0, xmm1
movaps [edi+64], xmm0
paddsw xmm2, xmm3
movaps [edi+80], xmm2
paddsw xmm4, xmm5
movaps [edi+96], xmm4
paddsw xmm6, xmm7
movaps [edi+112], xmm6
ret
end if
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Rev
\ No newline at end of property
/drivers/audio/infinity/mixer.asm
0,0 → 1,1266
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2006-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; (C) copyright Serge 2006
; email: infinity_sound@mail.ru
 
 
align 4
 
mix_list rd 32*3
 
align 4
proc new_mix stdcall, output:dword
locals
main_count rd 1
fpu_state rb 528 ;512+16
endl
 
mov [main_count], 32
call prepare_playlist
cmp [play_count], 0
je .clear
 
lea eax, [fpu_state+16]
and eax, -16 ;must be 16b aligned
invoke FpuSave
 
call update_streams
.mix:
lea eax, [mix_list]
call do_mix_list
test eax, eax
je .done
 
if USE_SSE2_MIXER
 
cmp eax, 1
ja @F
;use fast path
mov edi, [output]
lea edx, [mix_list]
call mix_fast
jmp .next
@@:
cmp eax, 2
ja @F
 
mov edi, [output]
lea edx, [mix_list]
call mix_fast_2_stream
jmp .next
@@:
 
end if
 
lea ebx, [mix_list]
stdcall mix_all, [output], ebx, eax
.next:
add [output], 512
dec [main_count]
jnz .mix
.exit:
lea eax, [fpu_state+16]
and eax, -16
invoke FpuRestore
ret
.done:
mov ecx, [main_count]
shl ecx, 7 ;ecx*= 512/4
 
mov edi, [output]
xor eax, eax
cld
rep stosd
jmp .exit
.clear:
mov edi, [output]
mov ecx, 4096
xor eax, eax
cld
rep stosd
ret
endp
 
align 4
proc update_streams
locals
stream_index dd ?
event rd 6
endl
 
mov [stream_index], 0
.l1:
mov edx, [stream_index]
mov esi, [play_list+edx*4]
 
add dword [esi+STREAM.time_stamp], 4096
adc dword [esi+STREAM.time_stamp+4], 0
mov dword [esi+STREAM.last_ts], 0
 
mov eax, [esi+STREAM.out_rp]
cmp eax, [esi+STREAM.out_top]
jb @f
sub eax, 64*1024
@@:
mov [esi+STREAM.out_rp], eax
 
cmp [esi+STREAM.out_count], 16384
ja .skip
 
test [esi+STREAM.format], PCM_RING
jnz .ring
 
stdcall refill, esi
.skip:
inc [stream_index]
dec [play_count]
jnz .l1
ret
.ring:
stdcall refill_ring, esi
jmp .skip
endp
 
align 4
proc refill stdcall, str:dword
locals
r_size rd 1
endl
 
mov ebx, [str]
mov edi, [ebx+STREAM.out_wp]
cmp edi, [ebx+STREAM.out_top]
jb @F
sub edi, 0x10000
mov [ebx+STREAM.out_wp], edi
@@:
mov eax, [ebx+STREAM.in_count]
test eax, eax
jz .done
 
mov ecx, [ebx+STREAM.r_size]
cmp eax, ecx
jle @F
 
mov eax, ecx
@@:
mov ecx, eax
cmp word [ebx+STREAM.format], PCM_1_16_8
ja @F
 
shr eax, 1 ;two channles
@@:
test [ebx+STREAM.format], 1 ;even formats mono
jz @F
 
shr eax, 1 ;eax= samples
@@:
shl eax, 15 ;eax*=32768 =r_end
 
mov [r_size], ecx
 
mov esi, [ebx+STREAM.in_rp]
mov edi, [ebx+STREAM.out_wp]
 
stdcall [ebx+STREAM.resample], edi, esi, \
[ebx+STREAM.r_dt], ecx, eax
 
mov ebx, [str]
 
add [ebx+STREAM.out_count], eax;
add [ebx+STREAM.out_wp], eax;
 
mov eax, [ebx+STREAM.in_rp]
mov ecx, [r_size]
add eax, ecx
add [ebx+STREAM.in_free], ecx
sub [ebx+STREAM.in_count], ecx
 
cmp eax, [ebx+STREAM.in_top]
jb @f
 
sub eax, [ebx+STREAM.in_size]
@@:
mov [ebx+STREAM.in_rp], eax
 
.done:
mov eax, [ebx+STREAM.notify_event]
test eax, eax
jz .exit
 
mov ebx, [ebx+STREAM.notify_id]
mov edx, EVENT_WATCHED
xor esi, esi
invoke RaiseEvent ;eax, ebx, edx, esi
.exit:
ret
endp
 
align 4
proc refill_ring stdcall, str:dword
locals
event rd 6
endl
 
mov ebx, [str]
mov edi, [ebx+STREAM.out_wp]
cmp edi, [ebx+STREAM.out_top]
jb @F
sub edi, 0x10000
mov [ebx+STREAM.out_wp], edi
@@:
mov ecx, [ebx+STREAM.r_size]
mov eax, ecx
cmp word [ebx+STREAM.format], PCM_1_16_8
ja @F
 
shr eax, 1 ;two channles
@@:
test [ebx+STREAM.format], 1 ;even formats mono
jz @F
 
shr eax, 1 ;eax= samples
@@:
shl eax, 15 ;eax*=32768 =r_end
 
mov esi, [ebx+STREAM.in_rp]
mov edi, [ebx+STREAM.out_wp]
 
stdcall [ebx+STREAM.resample], edi, esi, \
[ebx+STREAM.r_dt], ecx, eax
 
mov ebx, [str]
 
add [ebx+STREAM.out_count], eax;
add [ebx+STREAM.out_wp], eax;
 
mov eax, [ebx+STREAM.in_rp]
mov ecx, [ebx+STREAM.r_size]
add eax, ecx
add [ebx+STREAM.in_free], ecx
sub [ebx+STREAM.in_count], ecx
 
cmp eax, [ebx+STREAM.in_top]
jb @f
 
sub eax, [ebx+STREAM.in_size]
@@:
mov [ebx+STREAM.in_rp], eax
 
sub eax, [ebx+STREAM.in_base]
sub eax, 128
lea esi, [event]
 
mov dword [esi], RT_INP_EMPTY
mov dword [esi+4], 0
mov dword [esi+8], ebx
mov dword [esi+12], eax
 
mov eax, [ebx+STREAM.notify_event]
test eax, eax
jz .exit
 
mov ebx, [ebx+STREAM.notify_id]
xor edx, edx
invoke RaiseEvent ;eax, ebx, edx, esi
.exit:
ret
endp
 
if USE_SSE2_MIXER
 
align 4
proc mix_all stdcall, dest:dword, list:dword, count:dword
 
mov edi, [dest]
mov ebx, 32
.mix:
mov edx, [list]
mov ecx, [count]
 
mov eax, [edx]
 
movdqa xmm1, [eax]
movss xmm2, [edx+4]
movss xmm3, [edx+8]
 
punpcklwd xmm0, xmm1
punpckhwd xmm1, xmm1
 
shufps xmm2, xmm3, 0
shufps xmm2, xmm2, 0x88
 
psrad xmm0, 16
psrad xmm1, 16
cvtdq2ps xmm0, xmm0
cvtdq2ps xmm1, xmm1
mulps xmm0, xmm2
mulps xmm1, xmm2
 
.mix_loop:
add dword [edx], 16
add edx, 12
dec ecx
jz @F
 
mov eax, [edx]
 
movdqa xmm3, [eax]
movss xmm4, [edx+4]
movss xmm5, [edx+8]
 
punpcklwd xmm2, xmm3
punpckhwd xmm3, xmm3
 
shufps xmm4, xmm5, 0
shufps xmm4, xmm4, 0x88
 
psrad xmm2, 16
psrad xmm3, 16
 
cvtdq2ps xmm2, xmm2
cvtdq2ps xmm3, xmm3
 
mulps xmm2, xmm4
mulps xmm3, xmm4
addps xmm0, xmm2
addps xmm1, xmm3
 
jmp .mix_loop
@@:
cvtps2dq xmm0, xmm0
cvtps2dq xmm1, xmm1
packssdw xmm0, xmm0
packssdw xmm1, xmm1
punpcklqdq xmm0, xmm1
movntdq [edi], xmm0
 
add edi, 16
dec ebx
jnz .mix
 
ret
endp
 
; param
; edi = dest
; edx = mix_list
 
align 4
mix_fast:
 
mov ebx, 32
mov eax, [edx]
 
movss xmm2, [edx+4] ; vol Lf
movss xmm3, [edx+8] ; vol Rf
shufps xmm2, xmm3, 0 ; Rf Rf Lf Lf
shufps xmm2, xmm2, 0x88 ; volume level Rf Lf Rf Lf
.mix:
movdqa xmm1, [eax] ; R3w L3w R2w L2w R1w L1w R0w L0w
add eax, 16
punpcklwd xmm0, xmm1 ; R1w R1w L1w L1W R0w R0w L0w L0w
punpckhwd xmm1, xmm1 ; R3w R3w L3w L3w R2w R2w L2w L2w
 
psrad xmm0, 16 ; R1d L1d R0d L0d
psrad xmm1, 16 ; R3d L3d R2d L2d
 
cvtdq2ps xmm0, xmm0 ; time to use all power
cvtdq2ps xmm1, xmm1 ; of the dark side
 
mulps xmm0, xmm2 ; R1f' L1f' R0f' L0f'
mulps xmm1, xmm2 ; R3f' L3f' R2f' L2f'
 
cvtps2dq xmm0, xmm0 ; R1d' L1d' R0d' L0d'
cvtps2dq xmm1, xmm1 ; R3d' L3d' R2d' L2d'
packssdw xmm0, xmm0 ; R1w' L1w' R0w' L0w' R1w' L1w' R0w' L0w'
packssdw xmm1, xmm1 ; R3w' L3w' R2w' L2w' R3w' L3w' R2w' L2w'
punpcklqdq xmm0, xmm1 ; R3w' L3w' R2w' L2w' R1w' L1w' R0w' L0w'
movntdq [edi], xmm0
 
add edi, 16
dec ebx
jnz .mix
 
ret
 
align 4
mix_fast_2_stream:
 
mov ebx, 32
mov eax, [edx]
 
movss xmm4, [edx+4] ; vol Lf
movss xmm5, [edx+8] ; vol Rf
mov ecx, [edx+12]
 
movss xmm6, [edx+16] ; vol Lf
movss xmm7, [edx+20] ; vol Rf
 
shufps xmm4, xmm5, 0 ; Rf Rf Lf Lf
shufps xmm4, xmm4, 0x88 ; volume level Rf Lf Rf Lf
 
shufps xmm6, xmm7, 0 ; Rf Rf Lf Lf
shufps xmm6, xmm6, 0x88 ; volume level Rf Lf Rf Lf
 
.mix:
movdqa xmm1, [eax] ; R3w L3w R2w L2w R1w L1w R0w L0w
movdqa xmm3, [ecx] ; R3w L3w R2w L2w R1w L1w R0w L0w
 
add eax, 16
add ecx, 16
 
punpcklwd xmm0, xmm1 ; R1w R1w L1w L1W R0w R0w L0w L0w
punpckhwd xmm1, xmm1 ; R3w R3w L3w L3w R2w R2w L2w L2w
 
psrad xmm0, 16 ; R1d L1d R0d L0d
psrad xmm1, 16 ; R3d L3d R2d L2d
 
cvtdq2ps xmm0, xmm0 ; time to use all power
cvtdq2ps xmm1, xmm1 ; of the dark side
 
mulps xmm0, xmm4 ; R1f' L1f' R0f' L0f'
mulps xmm1, xmm4 ; R3f' L3f' R2f' L2f'
 
punpcklwd xmm2, xmm3 ; R1w R1w L1w L1W R0w R0w L0w L0w
punpckhwd xmm3, xmm3 ; R3w R3w L3w L3w R2w R2w L2w L2w
 
psrad xmm2, 16 ; R1d L1d R0d L0d
psrad xmm3, 16 ; R3d L3d R2d L2d
 
cvtdq2ps xmm2, xmm2 ; time to use all power
cvtdq2ps xmm3, xmm3 ; of the dark side
 
mulps xmm2, xmm6 ; R1f' L1f' R0f' L0f'
mulps xmm3, xmm6 ; R3f' L3f' R2f' L2f'
 
addps xmm0, xmm2
addps xmm1, xmm3
 
cvtps2dq xmm0, xmm0 ; R1d' L1d' R0d' L0d'
cvtps2dq xmm1, xmm1 ; R3d' L3d' R2d' L2d'
packssdw xmm0, xmm0 ; R1w' L1w' R0w' L0w' R1w' L1w' R0w' L0w'
packssdw xmm1, xmm1 ; R3w' L3w' R2w' L2w' R3w' L3w' R2w' L2w'
punpcklqdq xmm0, xmm1 ; R3w' L3w' R2w' L2w' R1w' L1w' R0w' L0w'
movntdq [edi], xmm0
 
add edi, 16
dec ebx
jnz .mix
 
ret
 
else ; fixed point mmx version
 
align 4
proc mix_all stdcall, dest:dword, list:dword, count:dword
 
mov edi, [dest]
mov ebx, 64
.mix:
mov edx, [list]
mov ecx, [count]
 
mov eax, [edx]
 
movq mm0, [eax]
 
movd mm1, [edx+4]
punpckldq mm1, mm1
pmulhw mm0, mm1
psllw mm0, 1
 
.mix_loop:
add dword [edx], 8
add edx, 12
dec ecx
jz @F
 
mov eax, [edx]
movq mm1, [eax]
movd mm2, [edx+4]
punpckldq mm2, mm2
pmulhw mm1, mm2
psllw mm1, 1
paddsw mm0, mm1
jmp .mix_loop
@@:
movq [edi], mm0
add edi, 8
dec ebx
jnz .mix
 
ret
endp
 
end if
 
 
align 4
proc resample_1 stdcall, dest:dword,src:dword,\
r_dt:dword, r_size:dword,r_end:dword
 
; dest equ esp+8
; src equ esp+12
; r_dt equ esp+16
; r_size equ esp+20
; r_end equ esp+24
 
mov edi, [dest]
mov edx, [src]
sub edx, 32*2
mov eax, 16
 
align 4
.l1:
mov ecx, eax
mov esi, eax
and ecx, 0x7FFF
shr esi, 15
lea esi, [edx+esi*2]
 
movsx ebp, word [esi]
movsx esi, word [esi+2]
mov ebx, 32768
imul esi, ecx
sub ebx, ecx
imul ebx, ebp
lea ecx, [ebx+esi+16384]
sar ecx, 15
cmp ecx, 32767 ; 00007fffH
jle @f
mov ecx, 32767 ; 00007fffH
jmp .write
@@:
cmp ecx, -32768 ; ffff8000H
jge .write
mov ecx, -32768 ; ffff8000H
.write:
mov ebx, ecx
shl ebx, 16
mov bx, cx
mov [edi], ebx
add edi, 4
 
add eax, [esp+16]
cmp eax, [esp+24]
jb .l1
 
mov ebp, esp
 
sub edi, [dest]
mov eax, edi
ret
endp
 
align 4
proc resample_18 stdcall, dest:dword,src:dword,\
r_dt:dword, r_size:dword,r_end:dword
 
 
mov edi, [dest]
mov edx, [src]
sub edx, 32
 
mov esi, 16
 
align 4
.l1:
mov ecx, esi
mov eax, esi
and ecx, 0x7FFF
shr eax, 15
lea eax, [edx+eax]
 
mov bx, word [eax]
sub bh, 0x80
sub bl, 0x80
movsx eax, bh
shl eax, 8
movsx ebp, bl
shl ebp, 8
mov ebx, 32768
imul eax, ecx
sub ebx, ecx
imul ebx, ebp
lea ecx, [ebx+eax+16384]
sar ecx, 15
cmp ecx, 32767 ; 00007fffH
jle @f
mov ecx, 32767 ; 00007fffH
jmp .write
@@:
cmp ecx, -32768 ; ffff8000H
jge .write
mov ecx, -32768 ; ffff8000H
.write:
mov ebx, ecx
shl ebx, 16
mov bx, cx
mov [edi], ebx
add edi, 4
 
add esi, [esp+16]
cmp esi, [esp+24]
jb .l1
 
mov ebp, esp
sub edi, [dest]
mov eax, edi
ret
endp
 
align 4
proc copy_stream stdcall, dest:dword,src:dword,\
r_dt:dword, r_size:dword,r_end:dword
 
mov ecx, [r_size]
mov eax, ecx
shr ecx, 2
mov esi, [src]
mov edi, [dest]
cld
rep movsd
ret
endp
 
align 4
proc resample_2 stdcall, dest:dword,src:dword,\
r_dt:dword, r_size:dword,r_end:dword
 
mov edx, [src]
sub edx, 32*4
mov edi, [dest]
mov ebx, [r_dt]
mov eax, 16
emms
 
align 4
.l1:
mov ecx, eax
mov esi, eax
and ecx, 0x7FFF
shr esi, 15
lea esi, [edx+esi*4]
 
movq mm0, [esi]
movq mm1, mm0
 
movd mm2, ecx
punpcklwd mm2, mm2
movq mm3, qword [m7] ;0x8000
 
psubw mm3, mm2 ; ;0x8000 - iconst
punpckldq mm3, mm2
 
pmulhw mm0, mm3
pmullw mm1, mm3
 
movq mm4, mm1
punpcklwd mm1, mm0
punpckhwd mm4, mm0
paddd mm1, mm4
psrad mm1, 15
packssdw mm1, mm1
movd [edi], mm1
add edi, 4
 
add eax, ebx
cmp eax, [r_end]
jb .l1
emms
 
sub edi, [dest]
mov eax, edi
ret
endp
 
align 4
proc resample_28 stdcall, dest:dword,src:dword,\
r_dt:dword, r_size:dword,r_end:dword
 
mov edx, [src]
sub edx, 32*2
mov edi, [dest]
mov ebx, [r_dt]
mov eax, 16
emms
movq mm7, [mm80]
movq mm6, [mm_mask]
 
align 4
.l1:
mov ecx, eax
mov esi, eax
and ecx, 0x7FFF
shr esi, 15
lea esi, [edx+esi*2]
 
movq mm0, [esi]
psubb mm0, mm7
punpcklbw mm0, mm0
pand mm0, mm6
 
movq mm1, mm0
 
movd mm2, ecx
punpcklwd mm2, mm2
movq mm3, qword [m7] ; // 0x8000
 
psubw mm3, mm2 ; // 0x8000 - iconst
punpckldq mm3, mm2
 
pmulhw mm0, mm3
pmullw mm1, mm3
 
movq mm4, mm1
punpcklwd mm1, mm0
punpckhwd mm4, mm0
paddd mm1, mm4
psrad mm1, 15
packssdw mm1, mm1
movd [edi], mm1
add edi, 4
 
add eax, ebx
cmp eax, [r_end]
jb .l1
emms
 
 
sub edi, [dest]
mov eax, edi
ret
endp
 
 
proc m16_stereo stdcall, dest:dword,src:dword,\
r_dt:dword, r_size:dword,r_end:dword
 
mov esi, [src]
mov edi, [dest]
mov ecx, [r_size]
shr ecx, 8
@@:
call m16_s_mmx
add edi, 128
add esi, 64
call m16_s_mmx
add edi, 128
add esi, 64
call m16_s_mmx
add edi, 128
add esi, 64
call m16_s_mmx
add edi, 128
add esi, 64
dec ecx
jnz @b
 
mov eax, [r_size]
add eax, eax
ret
endp
 
align 4
proc s8_stereo stdcall, dest:dword,src:dword,\
r_dt:dword, r_size:dword,r_end:dword
 
mov esi, [src]
mov edi, [dest]
mov ecx, [r_size]
shr ecx, 7
 
movq mm7, [mm80]
movq mm6, [mm_mask]
@@:
call s8_s_mmx
add edi, 64
add esi, 32
call s8_s_mmx
add edi, 64
add esi, 32
call s8_s_mmx
add edi, 64
add esi, 32
call s8_s_mmx
add edi, 64
add esi, 32
dec ecx
jnz @b
 
mov eax, [r_size]
add eax, eax
ret
endp
 
proc m8_stereo stdcall, dest:dword,src:dword,\
r_dt:dword, r_size:dword,r_end:dword
 
mov esi, [src]
mov edi, [dest]
mov ecx, [r_size]
shr ecx, 6
 
movq mm7, [mm80]
movq mm6, [mm_mask]
@@:
call m8_s_mmx
add edi, 64
add esi, 16
call m8_s_mmx
add edi, 64
add esi, 16
call m8_s_mmx
add edi, 64
add esi, 16
call m8_s_mmx
add edi, 64
add esi, 16
dec ecx
jnz @b
 
mov eax, [r_size]
add eax, eax
add eax, eax
ret
endp
 
align 4
proc alloc_mix_buff
 
bsf eax, [mix_buff_map]
jnz .find
xor eax, eax
ret
.find:
btr [mix_buff_map], eax
shl eax, 9
add eax, [mix_buff]
ret
endp
 
align 4
proc m16_s_mmx
 
movq mm0, [esi]
movq mm1, mm0
punpcklwd mm0, mm0
punpckhwd mm1, mm1
movq [edi], mm0
movq [edi+8], mm1
 
movq mm0, [esi+8]
movq mm1, mm0
punpcklwd mm0, mm0
punpckhwd mm1, mm1
movq [edi+16], mm0
movq [edi+24], mm1
 
movq mm0, [esi+16]
movq mm1, mm0
punpcklwd mm0, mm0
punpckhwd mm1, mm1
movq [edi+32], mm0
movq [edi+40], mm1
 
movq mm0, [esi+24]
movq mm1, mm0
punpcklwd mm0, mm0
punpckhwd mm1, mm1
movq [edi+48], mm0
movq [edi+56], mm1
 
movq mm0, [esi+32]
movq mm1, mm0
punpcklwd mm0, mm0
punpckhwd mm1, mm1
movq [edi+64], mm0
movq [edi+72], mm1
 
movq mm0, [esi+40]
movq mm1, mm0
punpcklwd mm0, mm0
punpckhwd mm1, mm1
movq [edi+80], mm0
movq [edi+88], mm1
 
 
movq mm0, [esi+48]
movq mm1, mm0
punpcklwd mm0, mm0
punpckhwd mm1, mm1
movq [edi+96], mm0
movq [edi+104], mm1
 
movq mm0, [esi+56]
movq mm1, mm0
punpcklwd mm0, mm0
punpckhwd mm1, mm1
movq [edi+112], mm0
movq [edi+120], mm1
 
ret
endp
 
align 4
proc s8_s_mmx
 
movq mm0, [esi]
psubb mm0, mm7
movq mm1, mm0
punpcklbw mm0, mm0
pand mm0, mm6
punpckhbw mm1, mm1
pand mm1, mm6
movq [edi], mm0
movq [edi+8], mm1
 
movq mm0, [esi+8]
psubb mm0, mm7
movq mm1, mm0
punpcklbw mm0, mm0
pand mm0, mm6
punpckhbw mm1, mm1
pand mm1, mm6
movq [edi+16], mm0
movq [edi+24], mm1
 
movq mm0, [esi+16]
psubb mm0, mm7
movq mm1, mm0
punpcklbw mm0, mm0
pand mm0, mm6
punpckhbw mm1, mm1
pand mm1, mm6
movq [edi+32], mm0
movq [edi+40], mm1
 
movq mm0, [esi+24]
psubb mm0, mm7
movq mm1, mm0
punpcklbw mm0, mm0
pand mm0, mm6
punpckhbw mm1, mm1
pand mm1, mm6
movq [edi+48], mm0
movq [edi+56], mm1
 
ret
 
endp
 
align 4
proc m8_s_mmx
 
movq mm0, [esi]
psubb mm0, mm7
movq mm1, mm0
punpcklbw mm0, mm0
pand mm0, mm6
punpckhbw mm1, mm1
pand mm1, mm6
movq mm2, mm0
punpcklwd mm0, mm0
punpckhwd mm2, mm2
 
movq mm3, mm1
punpcklwd mm1, mm1
punpckhwd mm3, mm3
 
movq [edi], mm0
movq [edi+8], mm2
movq [edi+16], mm1
movq [edi+24], mm3
 
movq mm0, [esi+8]
psubb mm0, mm7
movq mm1, mm0
punpcklbw mm0, mm0
pand mm0, mm6
punpckhbw mm1, mm1
pand mm1, mm6
movq mm2, mm0
punpcklwd mm0, mm0
punpckhwd mm2, mm2
 
movq mm3, mm1
punpcklwd mm1, mm1
punpckhwd mm3, mm3
 
movq [edi+32], mm0
movq [edi+40], mm2
movq [edi+48], mm1
movq [edi+56], mm3
 
ret
endp
 
align 4
proc mix_2_1 stdcall, output:dword, str0:dword, str1:dword
 
mov edi, [output]
mov eax, [str0]
mov ebx, [str1]
mov esi, 128
call [mix_2_core] ;edi, eax, ebx
 
add edi, esi
add eax, esi
add ebx, esi
call [mix_2_core] ;edi, eax, ebx
 
add edi, esi
add eax, esi
add ebx, esi
call [mix_2_core] ;edi, eax, ebx
 
add edi, esi
add eax, esi
add ebx, esi
call [mix_2_core] ;edi, eax, ebx
ret
endp
 
align 4
proc mix_3_1 stdcall, output:dword, str0:dword, str1:dword, str2:dword
 
mov edi, [output]
mov eax, [str0]
mov ebx, [str1]
mov ecx, [str2]
mov esi, 128
call [mix_3_core]
 
add edi, esi
add eax, esi
add ebx, esi
add ecx, esi
call [mix_3_core]
 
add edi, esi
add eax, esi
add ebx, esi
add ecx, esi
call [mix_3_core]
 
add edi, esi
add eax, esi
add ebx, esi
add ecx, esi
call [mix_3_core]
ret
endp
 
align 4
proc mix_4_1 stdcall, str0:dword, str1:dword,\
str2:dword, str3:dword
 
local output:DWORD
 
call alloc_mix_buff
and eax, eax
jz .err
 
mov [output], eax
 
mov edi, eax
mov eax, [str0]
mov ebx, [str1]
mov ecx, [str2]
mov edx, [str3]
mov esi, 128
call [mix_4_core] ;edi, eax, ebx, ecx, edx
 
add edi, esi
add eax, esi
add ebx, esi
add ecx, esi
add edx, esi
call [mix_4_core] ;edi, eax, ebx, ecx, edx
 
add edi, esi
add eax, esi
add ebx, esi
add ecx, esi
add edx, esi
call [mix_4_core] ;edi, eax, ebx, ecx, edx
 
add edi, esi
add eax, esi
add ebx, esi
add ecx, esi
add edx, esi
call [mix_4_core] ;edi, eax, ebx, ecx, edx
mov eax, [output]
ret
.err:
xor eax, eax
ret
endp
 
 
align 4
proc final_mix stdcall, output:dword, str0:dword, str1:dword,\
str2:dword, str3:dword
 
mov edi, [output]
 
mov eax, [str0]
mov ebx, [str1]
mov ecx, [str2]
mov edx, [str3]
mov esi, 128
call [mix_4_core] ;edi, eax, ebx, ecx, edx
 
add edi, esi
add eax, esi
add ebx, esi
add ecx, esi
add edx, esi
call [mix_4_core] ;edi, eax, ebx, ecx, edx
 
add edi, esi
add eax, esi
add ebx, esi
add ecx, esi
add edx, esi
call [mix_4_core] ;edi, eax, ebx, ecx, edx
 
add edi, esi
add eax, esi
add ebx, esi
add ecx, esi
add edx, esi
call [mix_4_core] ;edi, eax, ebx, ecx, edx
ret
endp
 
align 4
proc copy_mem stdcall, output:dword, input:dword
 
mov edi, [output]
mov esi, [input]
mov ecx, 0x80
.l1:
mov eax, [esi]
mov [edi], eax
add esi, 4
add edi, 4
loop .l1
 
ret
endp
 
proc memcpy
@@:
mov eax, [esi]
mov [edi], eax
add esi, 4
add edi, 4
dec ecx
jnz @B
ret
endp
 
if 0
 
align 4
proc new_mix stdcall, output:dword
locals
mixCounter dd ?
mixIndex dd ?
streamIndex dd ?
inputCount dd ?
main_count dd ?
blockCount dd ?
mix_out dd ?
endl
 
call prepare_playlist
 
cmp [play_count], 0
je .exit
call FpuSave
mov [main_count], 32;
.l00:
mov [mix_buff_map], 0x0000FFFF;
xor eax, eax
mov [mixCounter], eax
mov [mixIndex], eax
mov [streamIndex], eax;
mov ebx, [play_count]
mov [inputCount], ebx
.l0:
mov ecx, 4
.l1:
mov ebx, [streamIndex]
mov esi, [play_list+ebx*4]
mov eax, [esi+STREAM.work_read]
add [esi+STREAM.work_read], 512
 
mov ebx, [mixIndex]
mov [mix_input+ebx*4], eax
inc [mixCounter]
inc [mixIndex]
inc [streamIndex]
dec [inputCount]
jz .m2
 
dec ecx
jnz .l1
 
cmp [mixCounter], 4
jnz .m2
 
stdcall mix_4_1, [mix_input], [mix_input+4], [mix_input+8], [mix_input+12]
sub [mixIndex], 4
mov ebx, [mixIndex]
mov [mix_input+ebx*4], eax
inc [mixIndex]
mov [mixCounter], 0
 
cmp [inputCount], 0
jnz .l0
.m2:
cmp [mixIndex], 1
jne @f
stdcall copy_mem, [output], [mix_input]
jmp .m3
@@:
cmp [mixIndex], 2
jne @f
stdcall mix_2_1, [output], [mix_input], [mix_input+4]
jmp .m3
@@:
cmp [mixIndex], 3
jne @f
stdcall mix_3_1, [output], [mix_input], [mix_input+4], [mix_input+8]
jmp .m3
@@:
stdcall final_mix, [output], [mix_input], [mix_input+4], [mix_input+8], [mix_input+12]
.m3:
add [output], 512
 
dec [main_count]
jnz .l00
 
call update_stream
emms
call FpuRestore
ret
.exit:
mov edi, [output]
mov ecx, 0x1000
xor eax, eax
cld
rep stosd
ret
endp
 
end if
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Rev
\ No newline at end of property
/drivers/audio/intel_hda/intel_hda.asm
500,10 → 500,9
include 'CODEC_H.INC'
 
entry START
section '.flat' readable writable executable
 
;proc START stdcall, state:dword
proc START c, state:dword, cmdline:dword
;proc START c, reason:dword, cmdline:dword
proc START
push ebx esi ; save used registers to be stdcall
virtual at esp
rd 2 ; saved registers
512,8 → 511,8
.cmdline dd ? ; normally NULL
end virtual
; 1. Check the reason for the call, do nothing unless initializing.
;cmp [.reason], DRV_ENTRY
;jne .stop
cmp [.reason], DRV_ENTRY
jne .stop
 
if DEBUG
mov esi, msgTV
/drivers/audio/intelac97.asm
0,0 → 1,1472
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format PE DLL native 0.05
entry START
 
include '../struct.inc'
 
DEBUG equ 1
 
API_VERSION equ 0x01000100
 
DEBUG_IRQ equ 0
 
USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices
IRQ_REMAP equ 0
IRQ_LINE equ 0
 
 
;irq 0,1,2,8,12,13 недоступны
; FEDCBA9876543210
VALID_IRQ equ 1100111011111000b
ATTCH_IRQ equ 0000111010100000b
 
if USE_COM_IRQ
ATTCH_IRQ equ 0000111010111000b
end if
 
CPU_FREQ equ 2600d
 
BIT0 EQU 0x00000001
BIT1 EQU 0x00000002
BIT2 EQU 0x00000004
BIT3 EQU 0x00000008
BIT4 EQU 0x00000010
BIT5 EQU 0x00000020
BIT6 EQU 0x00000040
BIT7 EQU 0x00000080
BIT8 EQU 0x00000100
BIT9 EQU 0x00000200
BIT10 EQU 0x00000400
BIT11 EQU 0x00000800
BIT12 EQU 0x00001000
BIT13 EQU 0x00002000
BIT14 EQU 0x00004000
BIT15 EQU 0x00008000
BIT16 EQU 0x00010000
BIT17 EQU 0x00020000
BIT18 EQU 0x00040000
BIT19 EQU 0x00080000
BIT20 EQU 0x00100000
BIT21 EQU 0x00200000
BIT22 EQU 0x00400000
BIT23 EQU 0x00800000
BIT24 EQU 0x00100000
BIT25 EQU 0x02000000
BIT26 EQU 0x04000000
BIT27 EQU 0x08000000
BIT28 EQU 0x10000000
BIT29 EQU 0x20000000
BIT30 EQU 0x40000000
BIT31 EQU 0x80000000
 
PCM_4 equ BIT20
PCM_6 equ BIT21
 
VID_INTEL equ 0x8086
VID_NVIDIA equ 0x10DE
 
CTRL_ICH equ 0x2415
CTRL_ICH0 equ 0x2425
CTRL_ICH2 equ 0x2435
CTRL_ICH3 equ 0x2445
CTRL_ICH4 equ 0x24C5
CTRL_ICH5 equ 0x24D5
CTRL_ICH6 equ 0x266E
CTRL_ICH7 equ 0x27DE
 
CTRL_NFORCE equ 0x01B1
CTRL_NFORCE2 equ 0x006A
CTRL_NFORCE3 equ 0x00DA
CTRL_MCP04 equ 0x003A
CTRL_CK804 equ 0x0059
CTRL_CK8 equ 0x008A
CTRL_CK8S equ 0x00EA
CTRL_MCP51 equ 0x026B
 
 
PCM_OUT_BDL equ 0x10 ; PCM out buffer descriptors list
PCM_OUT_CR_REG equ 0x1b ; PCM out Control Register
PCM_OUT_LVI_REG equ 0x15 ; PCM last valid index
PCM_OUT_SR_REG equ 0x16 ; PCM out Status register
PCM_OUT_PIV_REG equ 0x1a
PCM_OUT_CIV_REG equ 0x14 ; PCM out current index
 
PCM_IN_CR_REG equ 0x0b ; PCM in Control Register
MC_IN_CR_REG equ 0x2b ; MIC in Control Register
RR equ BIT1 ; reset registers. Nukes all regs
 
CODEC_MASTER_VOL_REG equ 0x02
CODEC_AUX_VOL equ 0x04 ;
CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume
CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio
CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control
CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate
CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate
CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate
 
GLOB_CTRL equ 0x2C ; Global Control
CTRL_STAT equ 0x30 ; Global Status
CTRL_CAS equ 0x34 ; Codec Access Semiphore
 
CAS_FLAG equ 0x01 ; Codec Access Semiphore Bit
 
CTRL_ST_CREADY equ BIT8+BIT9+BIT28 ; Primary Codec Ready
 
CTRL_ST_RCS equ 0x00008000 ; Read Completion Status
 
CTRL_CNT_CRIE equ BIT4+BIT5+BIT6 ; Codecs Resume Interrupt Enable
CTRL_CNT_AC_OFF equ 0x00000008 ; ACLINK Off
CTRL_CNT_WARM equ 0x00000004 ; AC97 Warm Reset
CTRL_CNT_COLD equ 0x00000002 ; AC97 Cold Reset
CTRL_CNT_GIE equ 0x00000001 ; GPI Interrupt Enable
 
CODEC_REG_POWERDOWN equ 0x26
CODEC_REG_ST equ 0x26
 
SRV_GETVERSION equ 0
DEV_PLAY equ 1
DEV_STOP equ 2
DEV_CALLBACK equ 3
DEV_SET_BUFF equ 4
DEV_NOTIFY equ 5
DEV_SET_MASTERVOL equ 6
DEV_GET_MASTERVOL equ 7
DEV_GET_INFO equ 8
DEV_GET_POS equ 9
 
struc AC_CNTRL ;AC controller base class
{ .bus dd ?
.devfn dd ?
 
.vendor dd ?
.dev_id dd ?
.pci_cmd dd ?
.pci_stat dd ?
 
.codec_io_base dd ?
.codec_mem_base dd ?
 
.ctrl_io_base dd ?
.ctrl_mem_base dd ?
.cfg_reg dd ?
.int_line dd ?
 
.vendor_ids dd ? ;vendor id string
.ctrl_ids dd ? ;hub id string
 
.buffer dd ?
 
.notify_pos dd ?
.notify_task dd ?
 
.lvi_reg dd ?
.ctrl_setup dd ?
.user_callback dd ?
.codec_read16 dd ?
.codec_write16 dd ?
 
.ctrl_read8 dd ?
.ctrl_read16 dd ?
.ctrl_read32 dd ?
 
.ctrl_write8 dd ?
.ctrl_write16 dd ?
.ctrl_write32 dd ?
}
 
struc CODEC ;Audio Chip base class
{
.chip_id dd ?
.flags dd ?
.status dd ?
 
.ac_vendor_ids dd ? ;ac vendor id string
.chip_ids dd ? ;chip model string
 
.shadow_flag dd ?
dd ?
 
.regs dw ? ; codec registers
.reg_master_vol dw ? ;0x02
.reg_aux_out_vol dw ? ;0x04
.reg_mone_vol dw ? ;0x06
.reg_master_tone dw ? ;0x08
.reg_beep_vol dw ? ;0x0A
.reg_phone_vol dw ? ;0x0C
.reg_mic_vol dw ? ;0x0E
.reg_line_in_vol dw ? ;0x10
.reg_cd_vol dw ? ;0x12
.reg_video_vol dw ? ;0x14
.reg_aux_in_vol dw ? ;0x16
.reg_pcm_out_vol dw ? ;0x18
.reg_rec_select dw ? ;0x1A
.reg_rec_gain dw ? ;0x1C
.reg_rec_gain_mic dw ? ;0x1E
.reg_gen dw ? ;0x20
.reg_3d_ctrl dw ? ;0X22
.reg_page dw ? ;0X24
.reg_powerdown dw ? ;0x26
.reg_ext_audio dw ? ;0x28
.reg_ext_st dw ? ;0x2a
.reg_pcm_front_rate dw ? ;0x2c
.reg_pcm_surr_rate dw ? ;0x2e
.reg_lfe_rate dw ? ;0x30
.reg_pcm_in_rate dw ? ;0x32
dw ? ;0x34
.reg_cent_lfe_vol dw ? ;0x36
.reg_surr_vol dw ? ;0x38
.reg_spdif_ctrl dw ? ;0x3A
dw ? ;0x3C
dw ? ;0x3E
dw ? ;0x40
dw ? ;0x42
dw ? ;0x44
dw ? ;0x46
dw ? ;0x48
dw ? ;0x4A
dw ? ;0x4C
dw ? ;0x4E
dw ? ;0x50
dw ? ;0x52
dw ? ;0x54
dw ? ;0x56
dw ? ;0x58
dw ? ;0x5A
dw ? ;0x5C
dw ? ;0x5E
.reg_page_0 dw ? ;0x60
.reg_page_1 dw ? ;0x62
.reg_page_2 dw ? ;0x64
.reg_page_3 dw ? ;0x66
.reg_page_4 dw ? ;0x68
.reg_page_5 dw ? ;0x6A
.reg_page_6 dw ? ;0x6C
.reg_page_7 dw ? ;0x6E
dw ? ;0x70
dw ? ;0x72
dw ? ;0x74
dw ? ;0x76
dw ? ;0x78
dw ? ;0x7A
.reg_vendor_id_1 dw ? ;0x7C
.reg_vendor_id_2 dw ? ;0x7E
 
 
.reset dd ? ;virual
.set_master_vol dd ?
}
 
struc CTRL_INFO
{ .pci_cmd dd ?
.irq dd ?
.glob_cntrl dd ?
.glob_sta dd ?
.codec_io_base dd ?
.ctrl_io_base dd ?
.codec_mem_base dd ?
.ctrl_mem_base dd ?
.codec_id dd ?
}
 
EVENT_NOTIFY equ 0x00000200
 
section '.flat' code readable executable
include '../macros.inc'
include '../proc32.inc'
include '../peimport.inc'
 
proc START c uses ebx esi edi, state:dword, cmdline:dword
 
cmp [state], 1
jne .stop
 
if DEBUG
mov esi, msgInit
invoke SysMsgBoardStr
end if
 
call detect_controller
test eax, eax
jz .fail
 
if DEBUG
mov esi, [ctrl.vendor_ids]
invoke SysMsgBoardStr
mov esi, [ctrl.ctrl_ids]
invoke SysMsgBoardStr
 
end if
 
call init_controller
test eax, eax
jz .fail
 
call init_codec
test eax, eax
jz .fail
 
call reset_controller
call setup_codec
 
mov esi, msgPrimBuff
invoke SysMsgBoardStr
call create_primary_buff
mov esi, msgDone
invoke SysMsgBoardStr
 
if IRQ_REMAP
pushf
cli
 
mov ebx, [ctrl.int_line]
in al, 0xA1
mov ah, al
in al, 0x21
test ebx, ebx
jz .skip
bts ax, bx ;mask old line
.skip
bts ax, IRQ_LINE ;mask new ine
out 0x21, al
mov al, ah
out 0xA1, al
;remap IRQ
stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE
 
mov dx, 0x4d0 ;8259 ELCR1
in al, dx
bts ax, IRQ_LINE
out dx, al ;set level-triggered mode
mov [ctrl.int_line], IRQ_LINE
popf
mov esi, msgRemap
invoke SysMsgBoardStr
end if
 
mov ebx, [ctrl.int_line]
invoke AttachIntHandler, ebx, ac97_irq, 0
.reg:
invoke RegService, sz_sound_srv, service_proc
ret
.fail:
if DEBUG
mov esi, msgFail
invoke SysMsgBoardStr
end if
xor eax, eax
ret
.fail_msg:
invoke SysMsgBoardStr
xor eax, eax
ret
.stop:
call stop
xor eax, eax
ret
endp
 
handle equ IOCTL.handle
io_code equ IOCTL.io_code
input equ IOCTL.input
inp_size equ IOCTL.inp_size
output equ IOCTL.output
out_size equ IOCTL.out_size
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edi, [ioctl]
mov eax, [edi+io_code]
 
cmp eax, SRV_GETVERSION
jne @F
 
mov eax, [edi+output]
cmp [edi+out_size], 4
jne .fail
 
mov [eax], dword API_VERSION
xor eax, eax
ret
@@:
cmp eax, DEV_PLAY
jne @F
if DEBUG
mov esi, msgPlay
invoke SysMsgBoardStr
end if
call play
ret
@@:
cmp eax, DEV_STOP
jne @F
if DEBUG
mov esi, msgStop
invoke SysMsgBoardStr
end if
call stop
ret
@@:
cmp eax, DEV_CALLBACK
jne @F
mov ebx, [edi+input]
stdcall set_callback, [ebx]
ret
@@:
cmp eax, DEV_SET_MASTERVOL
jne @F
mov eax, [edi+input]
mov eax, [eax]
call set_master_vol ;eax= vol
ret
@@:
cmp eax, DEV_GET_MASTERVOL
jne @F
mov ebx, [edi+output]
stdcall get_master_vol, ebx
ret
 
@@:
cmp eax, DEV_GET_POS
jne @F
 
mov ebx, 8192
mov edx, 0x18
xor eax, eax
call [ctrl.ctrl_read16]
sub ebx, eax
shr ebx, 1
mov edx, [edi+output]
mov [edx], ebx
xor eax, eax
ret
;@@:
; cmp eax, DEV_GET_INFO
; jne @F
; mov ebx, [edi+output]
; stdcall get_dev_info, ebx
; ret
@@:
.fail:
or eax, -1
ret
endp
 
restore handle
restore io_code
restore input
restore inp_size
restore output
restore out_size
 
align 4
proc ac97_irq
 
if DEBUG_IRQ
mov esi, msgIRQ
invoke SysMsgBoardStr
end if
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
 
cmp eax, 0xffffffff
je .exit
 
test eax, 0x40
jnz .do_intr
 
test eax, eax
jz .exit
 
mov edx, CTRL_STAT
call [ctrl.ctrl_write32]
.exit:
xor eax, eax
ret
 
.do_intr:
push eax
 
; mov edx, PCM_OUT_CR_REG
; mov al, 0x10; 0x10
; call [ctrl.ctrl_write8]
 
mov ax, 0x1c
mov edx, PCM_OUT_SR_REG
call [ctrl.ctrl_write16]
 
mov edx, PCM_OUT_CIV_REG
call [ctrl.ctrl_read8]
 
and eax, 0x1F
cmp eax, [civ_val]
je .skip
 
mov [civ_val], eax
dec eax
and eax, 0x1F
mov [ctrl.lvi_reg], eax
 
mov edx, PCM_OUT_LVI_REG
call [ctrl.ctrl_write8]
 
; mov edx, PCM_OUT_CR_REG
; mov ax, 0x11 ;0x1D
; call [ctrl.ctrl_write8]
 
cmp [ctrl.user_callback], 0
je .done
 
mov eax, [ctrl.lvi_reg]
stdcall [ctrl.user_callback], [buff_list+eax*4]
 
.done:
pop eax
and eax, 0x40
mov edx, CTRL_STAT
call [ctrl.ctrl_write32]
or eax, 1
ret
.skip:
; mov edx, PCM_OUT_CR_REG
; mov ax, 0x11 ;0x1D
; call [ctrl.ctrl_write8]
jmp .done
endp
 
align 4
proc create_primary_buff
 
invoke KernelAlloc, 0x10000
mov [ctrl.buffer], eax
 
mov edi, eax
mov ecx, 0x10000/4
xor eax, eax
cld
rep stosd
 
mov eax, [ctrl.buffer]
invoke GetPgAddr
 
mov ebx, 0xC0002000
mov ecx, 4
mov edi, pcmout_bdl
@@:
mov [edi], eax
mov [edi+4], ebx
 
mov [edi+32], eax
mov [edi+4+32], ebx
 
mov [edi+64], eax
mov [edi+4+64], ebx
 
mov [edi+96], eax
mov [edi+4+96], ebx
 
mov [edi+128], eax
mov [edi+4+128], ebx
 
mov [edi+160], eax
mov [edi+4+160], ebx
 
mov [edi+192], eax
mov [edi+4+192], ebx
 
mov [edi+224], eax
mov [edi+4+224], ebx
 
add eax, 0x4000
add edi, 8
loop @B
 
mov edi, buff_list
mov eax, [ctrl.buffer]
mov ecx, 4
@@:
mov [edi], eax
mov [edi+16], eax
mov [edi+32], eax
mov [edi+48], eax
mov [edi+64], eax
mov [edi+80], eax
mov [edi+96], eax
mov [edi+112], eax
 
add eax, 0x4000
add edi, 4
loop @B
 
mov eax, pcmout_bdl
mov ebx, eax
invoke GetPgAddr ;eax
and ebx, 0xFFF
add eax, ebx
 
mov edx, PCM_OUT_BDL
call [ctrl.ctrl_write32]
 
mov eax, 16
mov [ctrl.lvi_reg], eax
mov edx, PCM_OUT_LVI_REG
call [ctrl.ctrl_write8]
ret
endp
 
align 4
proc detect_controller
push ebx edi
invoke GetPCIList
mov ebx, eax
.next_dev:
mov eax, [eax+PCIDEV.fd]
cmp eax, ebx
jz .not_found
mov edx, [eax+PCIDEV.vendor_device_id]
 
mov edi, devices
@@:
cmp dword [edi], 0
jz .next_dev
cmp edx, [edi]
jz .found
add edi, 12
jmp @B
 
.not_found:
xor eax, eax
pop edi ebx
ret
.found:
movzx ebx, [eax+PCIDEV.bus]
mov [ctrl.bus], ebx
 
movzx ecx, [eax+PCIDEV.devfn]
mov [ctrl.devfn], ecx
 
mov eax, edx
and edx, 0xFFFF
mov [ctrl.vendor], edx
shr eax, 16
mov [ctrl.dev_id], eax
 
mov ebx, [edi+4]
mov [ctrl.ctrl_ids], ebx
mov eax, [edi+8]
mov [ctrl.ctrl_setup], eax
 
cmp edx, VID_INTEL
jne @F
mov [ctrl.vendor_ids], msg_Intel
pop edi ebx
ret
@@:
cmp edx, VID_NVIDIA
jne @F
mov [ctrl.vendor_ids], msg_NVidia
pop edi ebx
ret
@@:
.err:
xor eax, eax
mov [ctrl.vendor_ids], eax ;something wrong ?
pop edi ebx
ret
endp
 
align 4
proc init_controller
 
invoke PciRead32, [ctrl.bus], [ctrl.devfn], 4
mov ebx, eax
and eax, 0xFFFF
mov [ctrl.pci_cmd], eax
shr ebx, 16
mov [ctrl.pci_stat], ebx
 
mov esi, msgPciCmd
invoke SysMsgBoardStr
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgPciStat
invoke SysMsgBoardStr
mov eax, [ctrl.pci_stat]
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgMixIsaIo
invoke SysMsgBoardStr
 
invoke PciRead32, [ctrl.bus], [ctrl.devfn], 0x10
 
call dword2str
invoke SysMsgBoardStr
 
and eax, 0xFFFE
mov [ctrl.codec_io_base], eax
 
mov esi, msgCtrlIsaIo
invoke SysMsgBoardStr
 
invoke PciRead32, [ctrl.bus], [ctrl.devfn], 0x14
 
call dword2str
invoke SysMsgBoardStr
 
and eax, 0xFFC0
mov [ctrl.ctrl_io_base], eax
 
mov esi, msgMixMMIo
invoke SysMsgBoardStr
 
invoke PciRead32, [ctrl.bus], [ctrl.devfn], 0x18
mov [ctrl.codec_mem_base], eax
 
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgCtrlMMIo
invoke SysMsgBoardStr
 
invoke PciRead32, [ctrl.bus], [ctrl.devfn], 0x1C
mov [ctrl.ctrl_mem_base], eax
 
call dword2str
invoke SysMsgBoardStr
 
if 0
 
;;patch for some ugly BIOS ICH-ICH5 compatible
cmp [ctrl.vendor], VID_INTEL
jne .default
 
mov esi, msgIrqMap
invoke SysMsgBoardStr
invoke PciRead8, 0, 0xF8, 0x61
and eax, 0xFF
call dword2str
invoke SysMsgBoardStr
btr eax, 7 ;when bit 7 set remap disabled
jnc @F
xor eax, eax
jmp @F
end if
 
.default:
invoke PciRead32, [ctrl.bus], [ctrl.devfn], 0x3C
and eax, 0xFF
@@:
mov [ctrl.int_line], eax
 
invoke PciRead8, [ctrl.bus], [ctrl.devfn], 0x41
and eax, 0xFF
mov [ctrl.cfg_reg], eax
 
mov [ctrl.user_callback], 0
 
call [ctrl.ctrl_setup]
xor eax, eax
inc eax
ret
endp
 
align 4
proc set_ICH
mov [ctrl.codec_read16], codec_io_r16 ;virtual
mov [ctrl.codec_write16], codec_io_w16 ;virtual
 
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual
 
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual
ret
endp
 
PG_SW equ 0x003
PG_NOCACHE equ 0x018
 
align 4
proc set_ICH4
 
invoke MapIoMem, [ctrl.codec_mem_base], 0x1000, PG_SW+PG_NOCACHE
mov [ctrl.codec_mem_base], eax
 
invoke MapIoMem, [ctrl.ctrl_mem_base], 0x1000, PG_SW+PG_NOCACHE
mov [ctrl.ctrl_mem_base], eax
 
mov [ctrl.codec_read16], codec_mem_r16 ;virtual
mov [ctrl.codec_write16], codec_mem_w16 ;virtual
 
mov [ctrl.ctrl_read8 ], ctrl_mem_r8 ;virtual
mov [ctrl.ctrl_read16], ctrl_mem_r16 ;virtual
mov [ctrl.ctrl_read32], ctrl_mem_r32 ;virtual
 
mov [ctrl.ctrl_write8 ], ctrl_mem_w8 ;virtual
mov [ctrl.ctrl_write16], ctrl_mem_w16 ;virtual
mov [ctrl.ctrl_write32], ctrl_mem_w32 ;virtual
ret
endp
 
align 4
proc reset_controller
 
xor eax, eax
mov edx, PCM_IN_CR_REG
call [ctrl.ctrl_write8]
 
mov edx, PCM_OUT_CR_REG
call [ctrl.ctrl_write8]
 
mov edx, MC_IN_CR_REG
call [ctrl.ctrl_write8]
 
mov eax, RR
mov edx, PCM_IN_CR_REG
call [ctrl.ctrl_write8]
 
mov edx, PCM_OUT_CR_REG
call [ctrl.ctrl_write8]
 
mov edx, MC_IN_CR_REG
call [ctrl.ctrl_write8]
ret
endp
 
align 4
proc init_codec
locals
counter dd ?
endl
 
mov esi, msgControl
invoke SysMsgBoardStr
 
mov edx, GLOB_CTRL
call [ctrl.ctrl_read32]
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgStatus
invoke SysMsgBoardStr
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
push eax
call dword2str
invoke SysMsgBoardStr
pop eax
cmp eax, 0xFFFFFFFF
je .err
 
test eax, CTRL_ST_CREADY
jnz .ready
 
call reset_codec
test eax, eax
jz .err
 
.ready:
xor edx, edx ;ac_reg_0
call [ctrl.codec_write16]
 
xor eax, eax
mov edx, CODEC_REG_POWERDOWN
call [ctrl.codec_write16]
 
mov [counter], 200 ; total 200*5 ms = 1s
.wait:
mov eax, 5000 ; wait 5 ms
call StallExec
 
mov edx, CODEC_REG_POWERDOWN
call [ctrl.codec_read16]
and eax, 0x0F
cmp eax, 0x0F
jz .done
 
sub [counter] , 1
jnz .wait
.err:
xor eax, eax ; timeout error
ret
.done:
mov eax, 2 ;force set 16-bit 2-channel PCM
mov edx, GLOB_CTRL
call [ctrl.ctrl_write32]
mov eax, 5000 ; wait 5 ms
call StallExec
 
call detect_codec
 
xor eax, eax
inc eax
ret
endp
 
align 4
proc reset_codec
mov edx, GLOB_CTRL
call [ctrl.ctrl_read32]
 
test eax, 0x02
jz .cold
 
call warm_reset
jnc .ok
.cold:
call cold_reset
jnc .ok
 
if DEBUG
mov esi, msgCFail
invoke SysMsgBoardStr
end if
xor eax, eax ; timeout error
ret
.ok:
if DEBUG
mov esi, msgResetOk
invoke SysMsgBoardStr
end if
 
xor eax, eax
inc eax
ret
endp
 
align 4
proc warm_reset
locals
counter dd ?
endl
 
mov eax, 0x06
mov edx, GLOB_CTRL
call [ctrl.ctrl_write32]
 
if DEBUG
mov esi, msgWarm
invoke SysMsgBoardStr
end if
 
mov [counter], 10 ; total 10*100 ms = 1s
.wait:
mov eax, 100000 ; wait 100 ms
call StallExec
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
test eax, CTRL_ST_CREADY
jnz .ok
 
dec [counter]
jnz .wait
 
if DEBUG
mov esi, msgWRFail
invoke SysMsgBoardStr
end if
.fail:
stc
ret
.ok:
clc
ret
endp
 
align 4
proc cold_reset
locals
counter dd ?
endl
 
mov eax, 0x02
mov edx, GLOB_CTRL
call [ctrl.ctrl_write32]
 
if DEBUG
mov esi, msgCold
invoke SysMsgBoardStr
end if
 
mov eax, 400000 ; wait 400 ms
call StallExec
 
mov [counter], 16 ; total 20*100 ms = 2s
.wait:
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
test eax, CTRL_ST_CREADY
jnz .ok
 
mov eax, 100000 ; wait 100 ms
call StallExec
 
dec [counter]
jnz .wait
 
if DEBUG
mov esi, msgCRFail
invoke SysMsgBoardStr
end if
 
.fail:
stc
ret
.ok:
mov esi, msgControl
invoke SysMsgBoardStr
 
mov edx, GLOB_CTRL
call [ctrl.ctrl_read32]
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgStatus
invoke SysMsgBoardStr
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
push eax
call dword2str
invoke SysMsgBoardStr
pop eax
 
test eax, CTRL_ST_CREADY
jz .fail
clc
ret
endp
 
align 4
play:
mov eax, 16
mov [ctrl.lvi_reg], eax
mov edx, PCM_OUT_LVI_REG
call [ctrl.ctrl_write8]
 
mov edx, PCM_OUT_CR_REG
mov ax, 0x1D
call [ctrl.ctrl_write8]
xor eax, eax
ret
 
align 4
stop:
mov edx, PCM_OUT_CR_REG
mov ax, 0x0
call [ctrl.ctrl_write8]
 
mov ax, 0x1c
mov edx, PCM_OUT_SR_REG
call [ctrl.ctrl_write16]
xor eax, eax
ret
 
align 4
proc get_dev_info stdcall, p_info:dword
virtual at esi
CTRL_INFO CTRL_INFO
end virtual
 
mov esi, [p_info]
mov eax, [ctrl.int_line]
mov ebx, [ctrl.codec_io_base]
mov ecx, [ctrl.ctrl_io_base]
mov edx, [ctrl.codec_mem_base]
mov edi, [ctrl.ctrl_mem_base]
 
mov [CTRL_INFO.irq], eax
mov [CTRL_INFO.codec_io_base], ebx
mov [CTRL_INFO.ctrl_io_base], ecx
mov [CTRL_INFO.codec_mem_base], edx
mov [CTRL_INFO.ctrl_mem_base], edi
 
mov eax, [codec.chip_id]
mov [CTRL_INFO.codec_id], eax
 
mov edx, GLOB_CTRL
call [ctrl.ctrl_read32]
mov [CTRL_INFO.glob_cntrl], eax
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
mov [CTRL_INFO.glob_sta], eax
 
mov ebx, [ctrl.pci_cmd]
mov [CTRL_INFO.pci_cmd], ebx
ret
endp
 
align 4
proc set_callback stdcall, handler:dword
mov eax, [handler]
mov [ctrl.user_callback], eax
ret
endp
 
align 4
proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax
 
mov edx, [ac_reg]
 
mov ebx, edx
shr ebx, 1
bt [codec.shadow_flag], ebx
jc .use_shadow
 
call [ctrl.codec_read16] ;change edx !!!
mov ecx, eax
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
test eax, CTRL_ST_RCS
jz .read_ok
 
mov edx, CTRL_STAT
call [ctrl.ctrl_write32]
xor eax, eax
not eax ;timeout
ret
.read_ok:
mov edx, [ac_reg]
mov [codec.regs+edx], cx
bts [codec.shadow_flag], ebx
mov eax, ecx
ret
.use_shadow:
movzx eax, word [codec.regs+edx]
ret
endp
 
align 4
proc codec_write stdcall, ac_reg:dword
push eax
call check_semafore
and eax, eax
jz .err
pop eax
 
mov esi, [ac_reg]
mov edx, esi
call [ctrl.codec_write16]
mov [codec.regs+esi], ax
shr esi, 1
bts [codec.shadow_flag], esi
ret
.err:
pop eax
ret
endp
 
align 4
proc codec_check_ready
 
mov edx, CTRL_ST
call [ctrl.ctrl_read32]
and eax, CTRL_ST_CREADY
jz .not_ready
 
xor eax, wax
inc eax
ret
.not_ready:
xor eax, eax
ret
endp
 
align 4
proc check_semafore
local counter:DWORD
 
mov [counter], 100
.l1:
mov edx, CTRL_CAS
call [ctrl.ctrl_read8]
and eax, CAS_FLAG
jz .ok
 
mov eax, 1
call StallExec
sub [counter], 1
jnz .l1
xor eax, eax
ret
align 4
.ok:
xor eax, eax
inc eax
ret
endp
 
align 4
proc StallExec
push ecx
push edx
push ebx
push eax
 
mov ecx, CPU_FREQ
mul ecx
mov ebx, eax ;low
mov ecx, edx ;high
rdtsc
add ebx, eax
adc ecx, edx
@@:
rdtsc
sub eax, ebx
sbb edx, ecx
js @B
 
pop eax
pop ebx
pop edx
pop ecx
ret
endp
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; CONTROLLER IO functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc codec_io_r16
add edx, [ctrl.codec_io_base]
in ax, dx
ret
endp
 
align 4
proc codec_io_w16
add edx, [ctrl.codec_io_base]
out dx, ax
ret
endp
 
align 4
proc ctrl_io_r8
add edx, [ctrl.ctrl_io_base]
in al, dx
ret
endp
 
align 4
proc ctrl_io_r16
add edx, [ctrl.ctrl_io_base]
in ax, dx
ret
endp
 
align 4
proc ctrl_io_r32
add edx, [ctrl.ctrl_io_base]
in eax, dx
ret
endp
 
align 4
proc ctrl_io_w8
add edx, [ctrl.ctrl_io_base]
out dx, al
ret
endp
 
align 4
proc ctrl_io_w16
add edx, [ctrl.ctrl_io_base]
out dx, ax
ret
endp
 
align 4
proc ctrl_io_w32
add edx, [ctrl.ctrl_io_base]
out dx, eax
ret
endp
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; MEMORY MAPPED IO (os depended)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc codec_mem_r16
add edx, [ctrl.codec_mem_base]
mov ax, word [edx]
ret
endp
 
align 4
proc codec_mem_w16
add edx, [ctrl.codec_mem_base]
mov word [edx], ax
ret
endp
 
align 4
proc ctrl_mem_r8
add edx, [ctrl.ctrl_mem_base]
mov al, [edx]
ret
endp
 
align 4
proc ctrl_mem_r16
add edx, [ctrl.ctrl_mem_base]
mov ax, [edx]
ret
endp
 
align 4
proc ctrl_mem_r32
add edx, [ctrl.ctrl_mem_base]
mov eax, [edx]
ret
endp
 
align 4
proc ctrl_mem_w8
add edx, [ctrl.ctrl_mem_base]
mov [edx], al
ret
endp
 
align 4
proc ctrl_mem_w16
add edx, [ctrl.ctrl_mem_base]
mov [edx], ax
ret
endp
 
align 4
proc ctrl_mem_w32
add edx, [ctrl.ctrl_mem_base]
mov [edx], eax
ret
endp
 
align 4
dword2str:
mov esi, hex_buff
mov ecx, -8
@@:
rol eax, 4
mov ebx, eax
and ebx, 0x0F
mov bl, [ebx+hexletters]
mov [8+esi+ecx], bl
inc ecx
jnz @B
ret
 
hexletters db '0123456789ABCDEF'
hex_buff db 8 dup(0),13,10,0
 
 
include "codec.inc"
 
align 4
devices dd (CTRL_ICH shl 16)+VID_INTEL,msg_ICH, set_ICH
dd (CTRL_ICH0 shl 16)+VID_INTEL,msg_ICH0,set_ICH
dd (CTRL_ICH2 shl 16)+VID_INTEL,msg_ICH2,set_ICH
dd (CTRL_ICH3 shl 16)+VID_INTEL,msg_ICH3,set_ICH
dd (CTRL_ICH4 shl 16)+VID_INTEL,msg_ICH4,set_ICH4
dd (CTRL_ICH5 shl 16)+VID_INTEL,msg_ICH5,set_ICH4
dd (CTRL_ICH6 shl 16)+VID_INTEL,msg_ICH6,set_ICH4
dd (CTRL_ICH7 shl 16)+VID_INTEL,msg_ICH7,set_ICH4
 
dd (CTRL_NFORCE shl 16)+VID_NVIDIA,msg_NForce, set_ICH
dd (CTRL_NFORCE2 shl 16)+VID_NVIDIA,msg_NForce2,set_ICH
dd (CTRL_NFORCE3 shl 16)+VID_NVIDIA,msg_NForce3,set_ICH
dd (CTRL_MCP04 shl 16)+VID_NVIDIA,msg_MCP04,set_ICH
dd (CTRL_CK804 shl 16)+VID_NVIDIA,msg_CK804,set_ICH
dd (CTRL_CK8 shl 16)+VID_NVIDIA,msg_CK8,set_ICH
dd (CTRL_CK8S shl 16)+VID_NVIDIA,msg_CK8S,set_ICH
dd (CTRL_MCP51 shl 16)+VID_NVIDIA,msg_MCP51,set_ICH
 
dd 0 ;terminator
 
 
msg_ICH db '802801AA (ICH)', 13,10, 0
msg_ICH0 db '802801AB (ICH0)', 13,10, 0
msg_ICH2 db '802801BA (ICH2)', 13,10, 0
msg_ICH3 db '802801CA (ICH3)', 13,10, 0
msg_ICH4 db '802801DB (ICH4)', 13,10, 0
msg_ICH5 db '802801EB (ICH5)', 13,10, 0
msg_ICH6 db '802801FB (ICH6)', 13,10, 0
msg_ICH7 db '802801GB (ICH7)', 13,10, 0
msg_Intel db 'Intel ', 0
 
msg_NForce db 'NForce', 13,10, 0
msg_NForce2 db 'NForce 2', 13,10, 0
msg_NForce3 db 'NForce 3', 13,10, 0
msg_MCP04 db 'NForce MCP04',13,10, 0
msg_CK804 db 'NForce CK804',13,10, 0
msg_CK8 db 'NForce CK8', 13,10, 0
msg_CK8S db 'NForce CK8S', 13,10, 0
msg_MCP51 db 'NForce MCP51',13,10, 0
 
msg_NVidia db 'NVidia', 0
 
szKernel db 'KERNEL', 0
sz_sound_srv db 'SOUND',0
 
msgInit db 'detect hardware...',13,10,0
msgFail db 'device not found',13,10,0
msgAttchIRQ db 'IRQ line not supported', 13,10, 0
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0
msgPlay db 'start play', 13,10,0
msgStop db 'stop play', 13,10,0
;msgNotify db 'call notify',13,10,0
msgIRQ db 'AC97 IRQ', 13,10,0
msgInitCtrl db 'init controller',13,10,0
;msgInitCodec db 'init codec',13,10,0
msgPrimBuff db 'create primary buffer ...',0
msgDone db 'done',13,10,0
msgRemap db 'Remap IRQ',13,10,0
;msgReg db 'set service handler',13,10,0
msgOk db 'service installed',13,10,0
msgCold db 'cold reset',13,10,0
msgWarm db 'warm reset',13,10,0
msgWRFail db 'warm reset failed',13,10,0
msgCRFail db 'cold reset failed',13,10,0
msgCFail db 'codec not ready',13,10,0
msgResetOk db 'reset complete',13,10,0
msgStatus db 'global status ',0
msgControl db 'global control ',0
msgPciCmd db 'PCI command ',0
msgPciStat db 'PCI status ',0
msgCtrlIsaIo db 'controller io base ',0
msgMixIsaIo db 'codec io base ',0
msgCtrlMMIo db 'controller mmio base ',0
msgMixMMIo db 'codec mmio base ',0
msgIrqMap db 'AC97 irq map as ',0
 
align 4
data fixups
end data
 
section '.data' data readable writable
 
pcmout_bdl rq 32
buff_list rd 32
 
codec CODEC
ctrl AC_CNTRL
 
lpc_bus rd 1
civ_val rd 1
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/audio/sis.asm
0,0 → 1,1288
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format PE DLL native 0.05
entry START
 
DEBUG equ 1
 
API_VERSION equ 0x01000100
DEBUG_IRQ equ 0
 
USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices
IRQ_REMAP equ 0
IRQ_LINE equ 0
 
 
;irq 0,1,2,8,12,13 недоступны
; FEDCBA9876543210
VALID_IRQ equ 1100111011111000b
ATTCH_IRQ equ 0000111010100000b
 
if USE_COM_IRQ
ATTCH_IRQ equ 0000111010111000b
end if
 
CPU_FREQ equ 2000d
 
BIT0 EQU 0x00000001
BIT1 EQU 0x00000002
BIT2 EQU 0x00000004
BIT3 EQU 0x00000008
BIT4 EQU 0x00000010
BIT5 EQU 0x00000020
BIT6 EQU 0x00000040
BIT7 EQU 0x00000080
BIT8 EQU 0x00000100
BIT9 EQU 0x00000200
BIT10 EQU 0x00000400
BIT11 EQU 0x00000800
BIT12 EQU 0x00001000
BIT13 EQU 0x00002000
BIT14 EQU 0x00004000
BIT15 EQU 0x00008000
BIT16 EQU 0x00010000
BIT17 EQU 0x00020000
BIT18 EQU 0x00040000
BIT19 EQU 0x00080000
BIT20 EQU 0x00100000
BIT21 EQU 0x00200000
BIT22 EQU 0x00400000
BIT23 EQU 0x00800000
BIT24 EQU 0x00100000
BIT25 EQU 0x02000000
BIT26 EQU 0x04000000
BIT27 EQU 0x08000000
BIT28 EQU 0x10000000
BIT29 EQU 0x20000000
BIT30 EQU 0x40000000
BIT31 EQU 0x80000000
 
VID_SIS equ 0x1039
CTRL_SIS equ 0x7012
 
PCM_OUT_BDL equ 0x10 ; PCM out buffer descriptors list
PCM_OUT_CR_REG equ 0x1b ; PCM out Control Register
PCM_OUT_LVI_REG equ 0x15 ; PCM last valid index
PCM_OUT_SR_REG equ 0x18 ; PCM out Status register
PCM_OUT_PIV_REG equ 0x1a ; PCM out prefetched index
PCM_OUT_CIV_REG equ 0x14 ; PCM out current index
 
PCM_IN_CR_REG equ 0x0b ; PCM in Control Register
MC_IN_CR_REG equ 0x2b ; MIC in Control Register
RR equ BIT1 ; reset registers. Nukes all regs
 
CODEC_MASTER_VOL_REG equ 0x02
CODEC_AUX_VOL equ 0x04 ;
CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume
CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio
CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control
CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate
CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate
CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate
 
GLOB_CTRL equ 0x2C ; Global Control
CTRL_STAT equ 0x30 ; Global Status
CTRL_CAS equ 0x34 ; Codec Access Semiphore
 
CAS_FLAG equ 0x01 ; Codec Access Semiphore Bit
 
CTRL_ST_CREADY equ BIT8+BIT9+BIT28 ; Primary Codec Ready
 
CTRL_ST_RCS equ 0x00008000 ; Read Completion Status
 
CTRL_CNT_CRIE equ BIT4+BIT5+BIT6 ; Codecs Resume Interrupt Enable
CTRL_CNT_AC_OFF equ 0x00000008 ; ACLINK Off
CTRL_CNT_WARM equ 0x00000004 ; AC97 Warm Reset
CTRL_CNT_COLD equ 0x00000002 ; AC97 Cold Reset
CTRL_CNT_GIE equ 0x00000001 ; GPI Interrupt Enable
 
CODEC_REG_POWERDOWN equ 0x26
CODEC_REG_ST equ 0x26
 
SRV_GETVERSION equ 0
DEV_PLAY equ 1
DEV_STOP equ 2
DEV_CALLBACK equ 3
DEV_SET_BUFF equ 4
DEV_NOTIFY equ 5
DEV_SET_MASTERVOL equ 6
DEV_GET_MASTERVOL equ 7
DEV_GET_INFO equ 8
 
struc AC_CNTRL ;AC controller base class
{ .bus dd ?
.devfn dd ?
 
.vendor dd ?
.dev_id dd ?
.pci_cmd dd ?
.pci_stat dd ?
 
.codec_io_base dd ?
.codec_mem_base dd ?
 
.ctrl_io_base dd ?
.ctrl_mem_base dd ?
.cfg_reg dd ?
.int_line dd ?
 
.vendor_ids dd ? ;vendor id string
.ctrl_ids dd ? ;hub id string
 
.buffer dd ?
 
.notify_pos dd ?
.notify_task dd ?
 
.lvi_reg dd ?
.ctrl_setup dd ?
.user_callback dd ?
.codec_read16 dd ?
.codec_write16 dd ?
 
.ctrl_read8 dd ?
.ctrl_read16 dd ?
.ctrl_read32 dd ?
 
.ctrl_write8 dd ?
.ctrl_write16 dd ?
.ctrl_write32 dd ?
}
 
struc CODEC ;Audio Chip base class
{
.chip_id dd ?
.flags dd ?
.status dd ?
 
.ac_vendor_ids dd ? ;ac vendor id string
.chip_ids dd ? ;chip model string
 
.shadow_flag dd ?
dd ?
 
.regs dw ? ; codec registers
.reg_master_vol dw ? ;0x02
.reg_aux_out_vol dw ? ;0x04
.reg_mone_vol dw ? ;0x06
.reg_master_tone dw ? ;0x08
.reg_beep_vol dw ? ;0x0A
.reg_phone_vol dw ? ;0x0C
.reg_mic_vol dw ? ;0x0E
.reg_line_in_vol dw ? ;0x10
.reg_cd_vol dw ? ;0x12
.reg_video_vol dw ? ;0x14
.reg_aux_in_vol dw ? ;0x16
.reg_pcm_out_vol dw ? ;0x18
.reg_rec_select dw ? ;0x1A
.reg_rec_gain dw ? ;0x1C
.reg_rec_gain_mic dw ? ;0x1E
.reg_gen dw ? ;0x20
.reg_3d_ctrl dw ? ;0X22
.reg_page dw ? ;0X24
.reg_powerdown dw ? ;0x26
.reg_ext_audio dw ? ;0x28
.reg_ext_st dw ? ;0x2a
.reg_pcm_front_rate dw ? ;0x2c
.reg_pcm_surr_rate dw ? ;0x2e
.reg_lfe_rate dw ? ;0x30
.reg_pcm_in_rate dw ? ;0x32
dw ? ;0x34
.reg_cent_lfe_vol dw ? ;0x36
.reg_surr_vol dw ? ;0x38
.reg_spdif_ctrl dw ? ;0x3A
dw ? ;0x3C
dw ? ;0x3E
dw ? ;0x40
dw ? ;0x42
dw ? ;0x44
dw ? ;0x46
dw ? ;0x48
dw ? ;0x4A
dw ? ;0x4C
dw ? ;0x4E
dw ? ;0x50
dw ? ;0x52
dw ? ;0x54
dw ? ;0x56
dw ? ;0x58
dw ? ;0x5A
dw ? ;0x5C
dw ? ;0x5E
.reg_page_0 dw ? ;0x60
.reg_page_1 dw ? ;0x62
.reg_page_2 dw ? ;0x64
.reg_page_3 dw ? ;0x66
.reg_page_4 dw ? ;0x68
.reg_page_5 dw ? ;0x6A
.reg_page_6 dw ? ;0x6C
.reg_page_7 dw ? ;0x6E
dw ? ;0x70
dw ? ;0x72
dw ? ;0x74
dw ? ;0x76
dw ? ;0x78
dw ? ;0x7A
.reg_vendor_id_1 dw ? ;0x7C
.reg_vendor_id_2 dw ? ;0x7E
 
 
.reset dd ? ;virual
.set_master_vol dd ?
}
 
struc CTRL_INFO
{ .pci_cmd dd ?
.irq dd ?
.glob_cntrl dd ?
.glob_sta dd ?
.codec_io_base dd ?
.ctrl_io_base dd ?
.codec_mem_base dd ?
.ctrl_mem_base dd ?
.codec_id dd ?
}
 
EVENT_NOTIFY equ 0x00000200
 
section '.flat' code readable writable executable
include '../struct.inc'
include '../macros.inc'
include '../proc32.inc'
include '../peimport.inc'
 
 
proc START c uses ebx esi edi, state:dword, cmdline:dword
 
cmp [state], 1
jne .stop
 
if DEBUG
mov esi, msgInit
invoke SysMsgBoardStr
end if
 
call detect_controller
test eax, eax
jz .fail
 
if DEBUG
mov esi, [ctrl.vendor_ids]
invoke SysMsgBoardStr
mov esi, [ctrl.ctrl_ids]
invoke SysMsgBoardStr
 
end if
 
call init_controller
test eax, eax
jz .fail
 
call init_codec
test eax, eax
jz .fail
 
call reset_controller
call setup_codec
 
mov esi, msgPrimBuff
invoke SysMsgBoardStr
call create_primary_buff
mov esi, msgDone
invoke SysMsgBoardStr
 
if IRQ_REMAP
pushf
cli
 
mov ebx, [ctrl.int_line]
in al, 0xA1
mov ah, al
in al, 0x21
test ebx, ebx
jz .skip
bts ax, bx ;mask old line
.skip:
bts ax, IRQ_LINE ;mask new ine
out 0x21, al
mov al, ah
out 0xA1, al
;remap IRQ
invoke PciWrite8, 0, 0xF8, 0x61, IRQ_LINE
 
mov dx, 0x4d0 ;8259 ELCR1
in al, dx
bts ax, IRQ_LINE
out dx, al ;set level-triggered mode
mov [ctrl.int_line], IRQ_LINE
popf
mov esi, msgRemap
invoke SysMsgBoardStr
end if
 
mov eax, VALID_IRQ
mov ebx, [ctrl.int_line]
mov esi, msgInvIRQ
bt eax, ebx
jnc .fail_msg
mov eax, ATTCH_IRQ
mov esi, msgAttchIRQ
bt eax, ebx
jnc .fail_msg
 
invoke AttachIntHandler, ebx, ac97_irq, 0
.reg:
invoke RegService, sz_sound_srv, service_proc
ret
.fail:
if DEBUG
mov esi, msgFail
invoke SysMsgBoardStr
end if
xor eax, eax
ret
.fail_msg:
invoke SysMsgBoardStr
xor eax, eax
ret
.stop:
call stop
xor eax, eax
ret
endp
 
handle equ IOCTL.handle
io_code equ IOCTL.io_code
input equ IOCTL.input
inp_size equ IOCTL.inp_size
output equ IOCTL.output
out_size equ IOCTL.out_size
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edi, [ioctl]
mov eax, [edi+io_code]
 
cmp eax, SRV_GETVERSION
jne @F
 
mov eax, [edi+output]
cmp [edi+out_size], 4
jne .fail
 
mov [eax], dword API_VERSION
xor eax, eax
ret
@@:
cmp eax, DEV_PLAY
jne @F
if DEBUG
mov esi, msgPlay
invoke SysMsgBoardStr
end if
call play
ret
@@:
cmp eax, DEV_STOP
jne @F
if DEBUG
mov esi, msgStop
invoke SysMsgBoardStr
end if
call stop
ret
@@:
cmp eax, DEV_CALLBACK
jne @F
mov ebx, [edi+input]
stdcall set_callback, [ebx]
ret
@@:
cmp eax, DEV_SET_MASTERVOL
jne @F
mov eax, [edi+input]
mov eax, [eax]
call set_master_vol ;eax= vol
ret
@@:
cmp eax, DEV_GET_MASTERVOL
jne @F
mov ebx, [edi+output]
stdcall get_master_vol, ebx
ret
;@@:
; cmp eax, DEV_GET_INFO
; jne @F
; mov ebx, [edi+output]
; stdcall get_dev_info, ebx
; ret
@@:
.fail:
or eax, -1
ret
endp
 
restore handle
restore io_code
restore input
restore inp_size
restore output
restore out_size
 
align 4
proc ac97_irq
 
if DEBUG_IRQ
mov esi, msgIRQ
invoke SysMsgBoardStr
end if
 
mov edx, PCM_OUT_CR_REG
mov al, 0x10
call [ctrl.ctrl_write8]
 
mov ax, 0x1c
mov edx, PCM_OUT_SR_REG
call [ctrl.ctrl_write16]
 
mov edx, PCM_OUT_CIV_REG
call [ctrl.ctrl_read8]
 
and eax, 0x1F
cmp eax, [civ_val]
je .skip
 
mov [civ_val], eax
dec eax
and eax, 0x1F
mov [ctrl.lvi_reg], eax
 
mov edx, PCM_OUT_LVI_REG
call [ctrl.ctrl_write8]
 
mov edx, PCM_OUT_CR_REG
mov ax, 0x11
call [ctrl.ctrl_write8]
 
mov eax, [civ_val]
add eax, 1
and eax, 31
mov ebx, dword [buff_list+eax*4]
 
cmp [ctrl.user_callback], 0
je @f
 
stdcall [ctrl.user_callback], ebx
@@:
ret
 
.skip:
mov edx, PCM_OUT_CR_REG
mov ax, 0x11
call [ctrl.ctrl_write8]
ret
endp
 
align 4
proc create_primary_buff
 
invoke KernelAlloc, 0x10000
mov [ctrl.buffer], eax
 
mov edi, eax
mov ecx, 0x10000/4
xor eax, eax
cld
rep stosd
 
mov eax, [ctrl.buffer]
invoke GetPgAddr
 
mov ebx, 0xC0004000
mov ecx, 4
mov edi, pcmout_bdl
@@:
mov [edi], eax
mov [edi+4], ebx
 
mov [edi+32], eax
mov [edi+4+32], ebx
 
mov [edi+64], eax
mov [edi+4+64], ebx
 
mov [edi+96], eax
mov [edi+4+96], ebx
 
mov [edi+128], eax
mov [edi+4+128], ebx
 
mov [edi+160], eax
mov [edi+4+160], ebx
 
mov [edi+192], eax
mov [edi+4+192], ebx
 
mov [edi+224], eax
mov [edi+4+224], ebx
 
add eax, 0x4000
add edi, 8
loop @B
 
mov edi, buff_list
mov eax, [ctrl.buffer]
mov ecx, 4
@@:
mov [edi], eax
mov [edi+16], eax
mov [edi+32], eax
mov [edi+48], eax
mov [edi+64], eax
mov [edi+80], eax
mov [edi+96], eax
mov [edi+112], eax
 
add eax, 0x4000
add edi, 4
loop @B
 
mov eax, pcmout_bdl
mov ebx, eax
invoke GetPgAddr ;eax
and ebx, 0xFFF
add eax, ebx
 
mov edx, PCM_OUT_BDL
call [ctrl.ctrl_write32]
 
mov eax, 16
mov [ctrl.lvi_reg], eax
mov edx, PCM_OUT_LVI_REG
call [ctrl.ctrl_write8]
 
mov edx, GLOB_CTRL
call [ctrl.ctrl_read32]
and eax, not 0x000000C0
mov edx, GLOB_CTRL
call [ctrl.ctrl_write32]
 
ret
endp
 
align 4
proc detect_controller
push ebx
invoke GetPCIList
mov ebx, eax
.next_dev:
mov eax, [eax+PCIDEV.fd]
cmp eax, ebx
je .err
cmp [eax+PCIDEV.class], 0x060100 ;pci-isa
jne .no_bridge
movzx edx, [eax+PCIDEV.bus]
mov [brg_bus], edx
movzx edx, [eax+PCIDEV.devfn]
mov [brg_devfn], edx
.no_bridge:
mov edx, [eax+PCIDEV.vendor_device_id]
mov esi, devices
@@:
cmp dword [esi], 0
jz .next_dev
cmp dword [esi], edx
jz .found
add esi, 12
jmp @b
.err:
xor eax, eax
pop ebx
ret
.found:
movzx ebx, [eax+PCIDEV.bus]
mov [ctrl.bus], ebx
 
movzx ecx, [eax+PCIDEV.devfn]
mov [ctrl.devfn], ecx
 
mov eax, edx
and edx, 0xFFFF
mov [ctrl.vendor], edx
shr eax, 16
mov [ctrl.dev_id], eax
 
mov ebx, [esi+4]
mov [ctrl.ctrl_ids], ebx
mov [ctrl.vendor_ids], msg_SIS
 
mov eax, [esi+8]
mov [ctrl.ctrl_setup], eax
pop ebx
ret
endp
 
align 4
proc init_controller
 
invoke PciRead32, [ctrl.bus], [ctrl.devfn], 4
mov ebx, eax
or al, 5
invoke PciWrite16, [ctrl.bus], [ctrl.devfn], 4, eax
movzx eax, bx
mov [ctrl.pci_cmd], eax
shr ebx, 16
mov [ctrl.pci_stat], ebx
 
mov esi, msgPciCmd
invoke SysMsgBoardStr
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgPciStat
invoke SysMsgBoardStr
mov eax, [ctrl.pci_stat]
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgMixIsaIo
invoke SysMsgBoardStr
 
invoke PciRead32, [ctrl.bus], [ctrl.devfn], 0x10
 
call dword2str
invoke SysMsgBoardStr
 
and eax, 0xFFFE
mov [ctrl.codec_io_base], eax
 
mov esi, msgCtrlIsaIo
invoke SysMsgBoardStr
 
invoke PciRead32, [ctrl.bus], [ctrl.devfn], 0x14
 
call dword2str
invoke SysMsgBoardStr
 
and eax, 0xFFC0
mov [ctrl.ctrl_io_base], eax
 
mov esi, msgMixMMIo
invoke SysMsgBoardStr
 
invoke PciRead32, [ctrl.bus], [ctrl.devfn], 0x18
mov [ctrl.codec_mem_base], eax
 
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgCtrlMMIo
invoke SysMsgBoardStr
 
invoke PciRead32, [ctrl.bus], [ctrl.devfn], 0x1C
mov [ctrl.ctrl_mem_base], eax
 
call dword2str
invoke SysMsgBoardStr
 
invoke PciRead32, [ctrl.bus], [ctrl.devfn], 0x3C
cmp al, 0xFF
jnz @f
movzx eax, ah
add eax, 0x40
invoke PciWrite8, [brg_bus], [brg_devfn], eax, 5
invoke PciWrite8, [ctrl.bus], [ctrl.devfn], 0x3C, 5
mov al, 5
@@:
and eax, 0xFF
mov [ctrl.int_line], eax
 
invoke PciRead8, [ctrl.bus], [ctrl.devfn], 0x41
and eax, 0xFF
mov [ctrl.cfg_reg], eax
 
call [ctrl.ctrl_setup]
xor eax, eax
inc eax
ret
endp
 
align 4
proc set_SIS
mov [ctrl.codec_read16], codec_io_r16 ;virtual
mov [ctrl.codec_write16], codec_io_w16 ;virtual
 
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual
 
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual
ret
endp
 
align 4
proc reset_controller
 
xor eax, eax
mov edx, PCM_IN_CR_REG
call [ctrl.ctrl_write8]
 
mov edx, PCM_OUT_CR_REG
call [ctrl.ctrl_write8]
 
mov edx, MC_IN_CR_REG
call [ctrl.ctrl_write8]
 
mov eax, RR
mov edx, PCM_IN_CR_REG
call [ctrl.ctrl_write8]
 
mov edx, PCM_OUT_CR_REG
call [ctrl.ctrl_write8]
 
mov edx, MC_IN_CR_REG
call [ctrl.ctrl_write8]
ret
endp
 
align 4
proc init_codec
locals
counter dd ?
endl
 
mov esi, msgControl
invoke SysMsgBoardStr
 
mov edx, GLOB_CTRL
call [ctrl.ctrl_read32]
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgStatus
invoke SysMsgBoardStr
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
push eax
call dword2str
invoke SysMsgBoardStr
pop eax
cmp eax, 0xFFFFFFFF
je .err
 
test eax, CTRL_ST_CREADY
jnz .ready
 
call reset_codec
test eax, eax
jz .err
 
.ready:
xor edx, edx ;ac_reg_0
call [ctrl.codec_write16]
 
xor eax, eax
mov edx, CODEC_REG_POWERDOWN
call [ctrl.codec_write16]
 
mov [counter], 200 ; total 200*5 ms = 1s
.wait:
mov eax, 5000 ; wait 5 ms
call StallExec
 
mov edx, CODEC_REG_POWERDOWN
call [ctrl.codec_read16]
and eax, 0x0F
cmp eax, 0x0F
je .done
 
sub [counter] , 1
jnz .wait
.err:
xor eax, eax ; timeout error
ret
.done:
mov eax, 2 ;force set 16-bit 2-channel PCM
mov edx, GLOB_CTRL
call [ctrl.ctrl_write32]
mov eax, 5000 ; wait 5 ms
call StallExec
 
call detect_codec
 
xor eax, eax
inc eax
ret
endp
 
align 4
proc reset_codec
mov edx, GLOB_CTRL
call [ctrl.ctrl_read32]
 
test eax, 0x02
jz .cold
 
call warm_reset
jnc .ok
.cold:
call cold_reset
jnc .ok
 
if DEBUG
mov esi, msgCFail
invoke SysMsgBoardStr
end if
xor eax, eax ; timeout error
ret
.ok:
xor eax, eax
inc eax
ret
endp
 
align 4
proc warm_reset
locals
counter dd ?
endl
 
mov eax, 0x06
mov edx, GLOB_CTRL
call [ctrl.ctrl_write32]
 
if DEBUG
mov esi, msgWarm
invoke SysMsgBoardStr
end if
 
mov [counter], 10 ; total 10*100 ms = 1s
.wait:
mov eax, 100000 ; wait 100 ms
call StallExec
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
test eax, CTRL_ST_CREADY
jnz .ok
 
dec [counter]
jnz .wait
 
if DEBUG
mov esi, msgWRFail
invoke SysMsgBoardStr
end if
.fail:
stc
ret
.ok:
clc
ret
endp
 
align 4
proc cold_reset
locals
counter dd ?
endl
 
mov eax, 0x02
mov edx, GLOB_CTRL
call [ctrl.ctrl_write32]
 
if DEBUG
mov esi, msgCold
invoke SysMsgBoardStr
end if
 
mov eax, 400000 ; wait 400 ms
call StallExec
 
mov [counter], 16 ; total 20*100 ms = 2s
.wait:
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
test eax, CTRL_ST_CREADY
jnz .ok
 
mov eax, 100000 ; wait 100 ms
call StallExec
 
dec [counter]
jnz .wait
 
if DEBUG
mov esi, msgCRFail
invoke SysMsgBoardStr
end if
 
.fail:
stc
ret
.ok:
mov esi, msgControl
invoke SysMsgBoardStr
 
mov edx, GLOB_CTRL
call [ctrl.ctrl_read32]
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgStatus
invoke SysMsgBoardStr
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
push eax
call dword2str
invoke SysMsgBoardStr
pop eax
 
test eax, CTRL_ST_CREADY
jz .fail
clc
ret
endp
 
align 4
play:
xor eax, eax
mov [civ_val], eax
mov edx, PCM_OUT_CIV_REG
call [ctrl.ctrl_write8]
 
mov eax, 16
mov [ctrl.lvi_reg], eax
mov edx, PCM_OUT_LVI_REG
call [ctrl.ctrl_write8]
 
mov edx, PCM_OUT_CR_REG
mov ax, 0x1D
call [ctrl.ctrl_write8]
xor eax, eax
ret
 
align 4
stop:
mov edx, PCM_OUT_CR_REG
mov ax, 0x0
call [ctrl.ctrl_write8]
 
mov ax, 0x1c
mov edx, PCM_OUT_SR_REG
call [ctrl.ctrl_write16]
xor eax, eax
ret
 
align 4
proc get_dev_info stdcall, p_info:dword
virtual at esi
CTRL_INFO CTRL_INFO
end virtual
 
mov esi, [p_info]
mov eax, [ctrl.int_line]
mov ebx, [ctrl.codec_io_base]
mov ecx, [ctrl.ctrl_io_base]
mov edx, [ctrl.codec_mem_base]
mov edi, [ctrl.ctrl_mem_base]
 
mov [CTRL_INFO.irq], eax
mov [CTRL_INFO.codec_io_base], ebx
mov [CTRL_INFO.ctrl_io_base], ecx
mov [CTRL_INFO.codec_mem_base], edx
mov [CTRL_INFO.ctrl_mem_base], edi
 
mov eax, [codec.chip_id]
mov [CTRL_INFO.codec_id], eax
 
mov edx, GLOB_CTRL
call [ctrl.ctrl_read32]
mov [CTRL_INFO.glob_cntrl], eax
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
mov [CTRL_INFO.glob_sta], eax
 
mov ebx, [ctrl.pci_cmd]
mov [CTRL_INFO.pci_cmd], ebx
ret
endp
 
align 4
proc set_callback stdcall, handler:dword
mov eax, [handler]
mov [ctrl.user_callback], eax
ret
endp
 
align 4
proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax
 
mov edx, [ac_reg]
 
mov ebx, edx
shr ebx, 1
bt [codec.shadow_flag], ebx
jc .use_shadow
 
call [ctrl.codec_read16] ;change edx !!!
mov ecx, eax
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
test eax, CTRL_ST_RCS
jz .read_ok
 
mov edx, CTRL_STAT
call [ctrl.ctrl_write32]
xor eax, eax
not eax ;timeout
ret
.read_ok:
mov edx, [ac_reg]
mov [codec.regs+edx], cx
bts [codec.shadow_flag], ebx
mov eax, ecx
ret
.use_shadow:
movzx eax, word [codec.regs+edx]
ret
endp
 
align 4
proc codec_write stdcall, ac_reg:dword
mov esi, [ac_reg]
mov edx, esi
call [ctrl.codec_write16]
mov [codec.regs+esi], ax
shr esi, 1
bts [codec.shadow_flag], esi
ret
endp
 
align 4
proc codec_check_ready
 
mov edx, CTRL_ST
call [ctrl.ctrl_read32]
and eax, CTRL_ST_CREADY
jz .not_ready
 
xor eax, wax
inc eax
ret
.not_ready:
xor eax, eax
ret
endp
 
align 4
proc check_semaphore
local counter:DWORD
 
mov [counter], 100
.l1:
mov edx, CTRL_CAS
call [ctrl.ctrl_read8]
and eax, CAS_FLAG
jz .ok
 
mov eax, 1
call StallExec
sub [counter], 1
jnz .l1
xor eax, eax
ret
align 4
.ok:
xor eax, eax
inc eax
ret
endp
 
align 4
proc StallExec
push ecx
push edx
push ebx
push eax
 
mov ecx, CPU_FREQ
mul ecx
mov ebx, eax ;low
mov ecx, edx ;high
rdtsc
add ebx, eax
adc ecx, edx
@@:
rdtsc
sub eax, ebx
sbb edx, ecx
js @B
 
pop eax
pop ebx
pop edx
pop ecx
ret
endp
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; CONTROLLER IO functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc codec_io_r16
push eax edx
call check_semaphore
test eax, eax
pop edx eax
jz .err
add edx, [ctrl.codec_io_base]
in ax, dx
.err:
ret
endp
 
align 4
proc codec_io_w16
push eax edx
call check_semaphore
test eax, eax
pop edx eax
jz .err
add edx, [ctrl.codec_io_base]
out dx, ax
.err:
ret
endp
 
align 4
proc ctrl_io_r8
add edx, [ctrl.ctrl_io_base]
in al, dx
ret
endp
 
align 4
proc ctrl_io_r16
add edx, [ctrl.ctrl_io_base]
in ax, dx
ret
endp
 
align 4
proc ctrl_io_r32
add edx, [ctrl.ctrl_io_base]
in eax, dx
ret
endp
 
align 4
proc ctrl_io_w8
add edx, [ctrl.ctrl_io_base]
out dx, al
ret
endp
 
align 4
proc ctrl_io_w16
add edx, [ctrl.ctrl_io_base]
out dx, ax
ret
endp
 
align 4
proc ctrl_io_w32
add edx, [ctrl.ctrl_io_base]
out dx, eax
ret
endp
 
align 4
dword2str:
mov esi, hex_buff
mov ecx, -8
@@:
rol eax, 4
mov ebx, eax
and ebx, 0x0F
mov bl, [ebx+hexletters]
mov [8+esi+ecx], bl
inc ecx
jnz @B
ret
 
hexletters db '0123456789ABCDEF'
hex_buff db 8 dup(0),13,10,0
 
include "codec.inc"
 
align 4
devices dd (CTRL_SIS shl 16)+VID_SIS,msg_AC, set_SIS
dd 0
 
msg_AC db '7012 AC97 controller',13,10, 0
msg_SIS db 'Silicon Integrated Systems',13,10, 0
 
sz_sound_srv db 'SOUND',0
 
msgInit db 'detect hardware...',13,10,0
msgFail db 'device not found',13,10,0
msgAttchIRQ db 'IRQ line not supported', 13,10, 0
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0
msgPlay db 'start play', 13,10,0
msgStop db 'stop play', 13,10,0
;msgNotify db 'call notify',13,10,0
msgIRQ db 'AC97 IRQ', 13,10,0
msgInitCtrl db 'init controller',13,10,0
;msgInitCodec db 'init codec',13,10,0
msgPrimBuff db 'create primary buffer ...',0
msgDone db 'done',13,10,0
msgRemap db 'Remap IRQ',13,10,0
;msgReg db 'set service handler',13,10,0
msgOk db 'service installed',13,10,0
msgCold db 'cold reset',13,10,0
msgWarm db 'warm reset',13,10,0
msgWRFail db 'warm reset failed',13,10,0
msgCRFail db 'cold reset failed',13,10,0
msgCFail db 'codec not ready',13,10,0
msgResetOk db 'reset complete',13,10,0
msgStatus db 'global status ',0
msgControl db 'global control ',0
msgPciCmd db 'PCI command ',0
msgPciStat db 'PCI status ',0
msgCtrlIsaIo db 'controller io base ',0
msgMixIsaIo db 'codec io base ',0
msgCtrlMMIo db 'controller mmio base ',0
msgMixMMIo db 'codec mmio base ',0
msgIrqMap db 'AC97 irq map as ',0
 
align 4
data fixups
end data
 
align 8
pcmout_bdl rq 32
buff_list rd 32
 
codec CODEC
ctrl AC_CNTRL
 
lpc_bus rd 1
civ_val rd 1
 
brg_bus dd ?
brg_devfn dd ?
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/audio/sound.asm
11,10 → 11,10
DEBUG = 1
 
section '.flat' code readable writable executable
 
include '../proc32.inc'
include '../struct.inc'
include '../macros.inc'
include '../peimport.inc'
 
VID_INTEL = 0x8086
VID_NVIDIA = 0x10DE
160,10 → 160,11
ends
 
 
proc START c, state:dword, cmdline:dword
proc START c uses ebx esi edi, state:dword, cmdline:dword
 
mov eax, [srv_entry]
cmp [state], 1
jne .fail
jne .stop
 
if DEBUG
mov esi, msgInit
170,10 → 171,16
invoke SysMsgBoardStr
end if
 
test eax, eax
jnz .done
call detect_controller
ret
 
.fail:
.stop:
test eax, eax
jz .done
leave
jmp eax
.done:
xor eax, eax
ret
endp
229,10 → 236,6
mov [bus], eax
cmp eax, [last_bus]
jna .next_bus
if DEBUG
mov esi, msgNotFound
invoke SysMsgBoardStr
end if
xor eax, eax
ret
.found:
402,8 → 405,7
intelhda db 'INTEL_HDA', 0
 
msgInit db 'Detecting hardware...',13,10,0
msgNotFound db 'No compatible soundcard found!',13,10,0
msgFail db 'Failed',13,10,0
msgFail db 'No compatible soundcard found!',13,10,0
msgLoading db 'Loading ',0
msgNewline db 13,10,0
 
410,5 → 412,3
align 4
data fixups
end data
 
include '../peimport.inc'
/drivers/audio/vt823x.asm
0,0 → 1,1281
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format PE DLL native 0.05
entry START
 
DEBUG equ 1
 
API_VERSION equ 0x01000100
 
USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices
IRQ_REMAP equ 0
IRQ_LINE equ 0
 
 
;irq 0,1,2,8,12,13 unavailable
; FEDCBA9876543210
VALID_IRQ equ 1100111011111000b
ATTCH_IRQ equ 0000111010100000b
 
if USE_COM_IRQ
ATTCH_IRQ equ 0000111010111000b
end if
 
CPU_FREQ equ 2600d
 
BIT0 EQU 0x00000001
BIT1 EQU 0x00000002
BIT5 EQU 0x00000020
BIT10 EQU 0x00000400
 
VID_VIA equ 0x1106
 
CTRL_VT82C686 equ 0x3058
CTRL_VT8233_5 equ 0x3059
 
 
CODEC_MASTER_VOL_REG equ 0x02
CODEC_AUX_VOL equ 0x04 ;
CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume
CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio
CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control
CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate
CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate
CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate
 
 
;VIA host controller registers set
;; common offsets
VIA_REG_OFFSET_STATUS equ 0x00 ;; byte - channel status
VIA_REG_STAT_ACTIVE equ 0x80 ;; RO
VIA_REG_STAT_PAUSED equ 0x40 ;; RO
VIA_REG_STAT_TRIGGER_QUEUED equ 0x08 ;; RO
VIA_REG_STAT_STOPPED equ 0x04 ;; RWC
VIA_REG_STAT_EOL equ 0x02 ;; RWC
VIA_REG_STAT_FLAG equ 0x01 ;; RWC
VIA_REG_OFFSET_CONTROL equ 0x01 ;; byte - channel control
VIA_REG_CTRL_START equ 0x80 ;; WO
VIA_REG_CTRL_TERMINATE equ 0x40 ;; WO
VIA_REG_CTRL_AUTOSTART equ 0x20
VIA_REG_CTRL_PAUSE equ 0x08 ;; RW
VIA_REG_CTRL_INT_STOP equ 0x04
VIA_REG_CTRL_INT_EOL equ 0x02
VIA_REG_CTRL_INT_FLAG equ 0x01
VIA_REG_CTRL_RESET equ 0x01 ;; RW - probably reset? undocumented
VIA_REG_CTRL_INT equ (VIA_REG_CTRL_INT_FLAG or \
VIA_REG_CTRL_INT_EOL or \
VIA_REG_CTRL_AUTOSTART)
VIA_REG_OFFSET_TYPE equ 0x02 ;; byte - channel type (686 only)
VIA_REG_TYPE_AUTOSTART equ 0x80 ;; RW - autostart at EOL
VIA_REG_TYPE_16BIT equ 0x20 ;; RW
VIA_REG_TYPE_STEREO equ 0x10 ;; RW
VIA_REG_TYPE_INT_LLINE equ 0x00
VIA_REG_TYPE_INT_LSAMPLE equ 0x04
VIA_REG_TYPE_INT_LESSONE equ 0x08
VIA_REG_TYPE_INT_MASK equ 0x0c
VIA_REG_TYPE_INT_EOL equ 0x02
VIA_REG_TYPE_INT_FLAG equ 0x01
VIA_REG_OFFSET_TABLE_PTR equ 0x04 ;; dword - channel table pointer
VIA_REG_OFFSET_CURR_PTR equ 0x04 ;; dword - channel current pointer
VIA_REG_OFFSET_STOP_IDX equ 0x08 ;; dword - stop index, channel type, sample rate
VIA8233_REG_TYPE_16BIT equ 0x00200000 ;; RW
VIA8233_REG_TYPE_STEREO equ 0x00100000 ;; RW
VIA_REG_OFFSET_CURR_COUNT equ 0x0c ;; dword - channel current count (24 bit)
VIA_REG_OFFSET_CURR_INDEX equ 0x0f ;; byte - channel current index (for via8233 only)
 
 
VIADEV_PLAYBACK equ 0x00
VIADEV_CAPTURE equ 0x10
VIADEV_FM equ 0x20
 
;; AC'97 ;;
VIA_REG_AC97 equ 0x80 ; dword
VIA_REG_AC97_CODEC_ID_MASK equ 0xC0000000 ;(3<<30)
VIA_REG_AC97_CODEC_ID_SHIFT equ 30
VIA_REG_AC97_CODEC_ID_PRIMARY equ 0x00
VIA_REG_AC97_CODEC_ID_SECONDARY equ 0x01
VIA_REG_AC97_SECONDARY_VALID equ 0x08000000 ;(1<<27)
VIA_REG_AC97_PRIMARY_VALID equ 0x02000000 ;(1<<25)
VIA_REG_AC97_BUSY equ 0x01000000 ;(1<<24)
VIA_REG_AC97_READ equ 0x00800000 ;(1<<23)
VIA_REG_AC97_CMD_SHIFT equ 16
VIA_REG_AC97_CMD_MASK equ 0x7E
VIA_REG_AC97_DATA_SHIFT equ 0
VIA_REG_AC97_DATA_MASK equ 0xFFFF
 
VIA_REG_SGD_SHADOW equ 0x84 ; dword
 
;; via8233-specific registers ;;
VIA_REG_OFS_PLAYBACK_VOLUME_L equ 0x02 ;; byte
VIA_REG_OFS_PLAYBACK_VOLUME_R equ 0x03 ;; byte
VIA_REG_OFS_MULTPLAY_FORMAT equ 0x02 ;; byte - format and channels
VIA_REG_MULTPLAY_FMT_8BIT equ 0x00
VIA_REG_MULTPLAY_FMT_16BIT equ 0x80
VIA_REG_MULTPLAY_FMT_CH_MASK equ 0x70 ;; # channels << 4 (valid = 1,2,4,6)
VIA_REG_OFS_CAPTURE_FIFO equ 0x02 ;; byte - bit 6 = fifo enable
VIA_REG_CAPTURE_FIFO_ENABLE equ 0x40
 
VIA_DXS_MAX_VOLUME equ 31 ;; max. volume (attenuation) of reg 0x32/33
 
VIA_TBL_BIT_FLAG equ 0x40000000
VIA_TBL_BIT_EOL equ 0x80000000
 
;; pci space ;;
VIA_ACLINK_STAT equ 0x40
;...
VIA_ACLINK_C00_READY equ 0x01 ; primary codec ready
VIA_ACLINK_CTRL equ 0x41
VIA_ACLINK_CTRL_ENABLE equ 0x80 ; 0: disable, 1: enable
VIA_ACLINK_CTRL_RESET equ 0x40 ; 0: assert, 1: de-assert
VIA_ACLINK_CTRL_SYNC equ 0x20 ; 0: release SYNC, 1: force SYNC hi
VIA_ACLINK_CTRL_SDO equ 0x10 ; 0: release SDO, 1: force SDO hi
VIA_ACLINK_CTRL_VRA equ 0x08 ; 0: disable VRA, 1: enable VRA
VIA_ACLINK_CTRL_PCM equ 0x04 ; 0: disable PCM, 1: enable PCM
VIA_ACLINK_CTRL_FM equ 0x02 ; via686 only
VIA_ACLINK_CTRL_SB equ 0x01 ; via686 only
VIA_ACLINK_CTRL_INIT equ (VIA_ACLINK_CTRL_ENABLE or \
VIA_ACLINK_CTRL_RESET or \
VIA_ACLINK_CTRL_PCM or \
VIA_ACLINK_CTRL_VRA)
VIA_FUNC_ENABLE equ 0x42
VIA_FUNC_MIDI_PNP equ 0x80 ; FIXME: it's 0x40 in the datasheet!
VIA_FUNC_MIDI_IRQMASK equ 0x40 ; FIXME: not documented!
VIA_FUNC_RX2C_WRITE equ 0x20
VIA_FUNC_SB_FIFO_EMPTY equ 0x10
VIA_FUNC_ENABLE_GAME equ 0x08
VIA_FUNC_ENABLE_FM equ 0x04
VIA_FUNC_ENABLE_MIDI equ 0x02
VIA_FUNC_ENABLE_SB equ 0x01
VIA_PNP_CONTROL equ 0x43
VIA_FM_NMI_CTRL equ 0x48
VIA8233_VOLCHG_CTRL equ 0x48
VIA8233_SPDIF_CTRL equ 0x49
VIA8233_SPDIF_DX3 equ 0x08
VIA8233_SPDIF_SLOT_MASK equ 0x03
VIA8233_SPDIF_SLOT_1011 equ 0x00
VIA8233_SPDIF_SLOT_34 equ 0x01
VIA8233_SPDIF_SLOT_78 equ 0x02
VIA8233_SPDIF_SLOT_69 equ 0x03
;] Asper
 
 
SRV_GETVERSION equ 0
DEV_PLAY equ 1
DEV_STOP equ 2
DEV_CALLBACK equ 3
DEV_SET_BUFF equ 4
DEV_NOTIFY equ 5
DEV_SET_MASTERVOL equ 6
DEV_GET_MASTERVOL equ 7
DEV_GET_INFO equ 8
DEV_GET_POS equ 9
 
struc AC_CNTRL ;AC controller base class
{ .bus dd ?
.devfn dd ?
 
.vendor dd ?
.dev_id dd ?
.pci_cmd dd ?
.pci_stat dd ?
 
.codec_io_base dd ?
.codec_mem_base dd ?
 
.ctrl_io_base dd ?
.ctrl_mem_base dd ?
.cfg_reg dd ?
.int_line dd ?
 
.vendor_ids dd ? ;vendor id string
.ctrl_ids dd ? ;hub id string
 
.buffer dd ?
 
.notify_pos dd ?
.notify_task dd ?
 
.lvi_reg dd ?
.ctrl_setup dd ?
.user_callback dd ?
.codec_read16 dd ?
.codec_write16 dd ?
 
.ctrl_read8 dd ?
.ctrl_read16 dd ?
.ctrl_read32 dd ?
 
.ctrl_write8 dd ?
.ctrl_write16 dd ?
.ctrl_write32 dd ?
}
 
struc CODEC ;Audio Chip base class
{
.chip_id dd ?
.flags dd ?
.status dd ?
 
.ac_vendor_ids dd ? ;ac vendor id string
.chip_ids dd ? ;chip model string
 
.shadow_flag dd ?
dd ?
 
.regs dw ? ; codec registers
.reg_master_vol dw ? ;0x02
.reg_aux_out_vol dw ? ;0x04
.reg_mone_vol dw ? ;0x06
.reg_master_tone dw ? ;0x08
.reg_beep_vol dw ? ;0x0A
.reg_phone_vol dw ? ;0x0C
.reg_mic_vol dw ? ;0x0E
.reg_line_in_vol dw ? ;0x10
.reg_cd_vol dw ? ;0x12
.reg_video_vol dw ? ;0x14
.reg_aux_in_vol dw ? ;0x16
.reg_pcm_out_vol dw ? ;0x18
.reg_rec_select dw ? ;0x1A
.reg_rec_gain dw ? ;0x1C
.reg_rec_gain_mic dw ? ;0x1E
.reg_gen dw ? ;0x20
.reg_3d_ctrl dw ? ;0X22
.reg_page dw ? ;0X24
.reg_powerdown dw ? ;0x26
.reg_ext_audio dw ? ;0x28
.reg_ext_st dw ? ;0x2a
.reg_pcm_front_rate dw ? ;0x2c
.reg_pcm_surr_rate dw ? ;0x2e
.reg_lfe_rate dw ? ;0x30
.reg_pcm_in_rate dw ? ;0x32
dw ? ;0x34
.reg_cent_lfe_vol dw ? ;0x36
.reg_surr_vol dw ? ;0x38
.reg_spdif_ctrl dw ? ;0x3A
dw ? ;0x3C
dw ? ;0x3E
dw ? ;0x40
dw ? ;0x42
dw ? ;0x44
dw ? ;0x46
dw ? ;0x48
dw ? ;0x4A
dw ? ;0x4C
dw ? ;0x4E
dw ? ;0x50
dw ? ;0x52
dw ? ;0x54
dw ? ;0x56
dw ? ;0x58
dw ? ;0x5A
dw ? ;0x5C
dw ? ;0x5E
.reg_page_0 dw ? ;0x60
.reg_page_1 dw ? ;0x62
.reg_page_2 dw ? ;0x64
.reg_page_3 dw ? ;0x66
.reg_page_4 dw ? ;0x68
.reg_page_5 dw ? ;0x6A
.reg_page_6 dw ? ;0x6C
.reg_page_7 dw ? ;0x6E
dw ? ;0x70
dw ? ;0x72
dw ? ;0x74
dw ? ;0x76
dw ? ;0x78
dw ? ;0x7A
.reg_vendor_id_1 dw ? ;0x7C
.reg_vendor_id_2 dw ? ;0x7E
 
 
.reset dd ? ;virtual
.set_master_vol dd ?
}
 
struc CTRL_INFO
{ .pci_cmd dd ?
.irq dd ?
.glob_cntrl dd ?
.glob_sta dd ?
.codec_io_base dd ?
.ctrl_io_base dd ?
.codec_mem_base dd ?
.ctrl_mem_base dd ?
.codec_id dd ?
}
 
EVENT_NOTIFY equ 0x00000200
 
section '.flat' code readable writable executable
include '../struct.inc'
include '../macros.inc'
include '../proc32.inc'
include '../peimport.inc'
 
proc START c, state:dword, cmdline:dword
 
cmp [state], 1
jne .stop
 
if DEBUG
mov esi, msgInit
invoke SysMsgBoardStr
end if
 
call detect_controller
test eax, eax
jz .fail
 
if DEBUG
mov esi, [ctrl.vendor_ids]
invoke SysMsgBoardStr
mov esi, [ctrl.ctrl_ids]
invoke SysMsgBoardStr
end if
 
call init_controller
test eax, eax
jz .fail
 
call init_codec
test eax, eax
jz .fail
 
call setup_codec
 
mov esi, msgPrimBuff
invoke SysMsgBoardStr
call create_primary_buff
mov esi, msgDone
invoke SysMsgBoardStr
 
if IRQ_REMAP
pushf
cli
 
mov ebx, [ctrl.int_line]
in al, 0xA1
mov ah, al
in al, 0x21
test ebx, ebx
jz .skip
bts ax, bx ;mask old line
.skip:
bts ax, IRQ_LINE ;mask new ine
out 0x21, al
mov al, ah
out 0xA1, al
 
invoke PciWrite8, 0, 0xF8, 0x61, IRQ_LINE ;remap IRQ
 
mov dx, 0x4d0 ;8259 ELCR1
in al, dx
bts ax, IRQ_LINE
out dx, al ;set level-triggered mode
mov [ctrl.int_line], IRQ_LINE
popf
mov esi, msgRemap
invoke SysMsgBoardStr
end if
 
mov eax, VALID_IRQ
mov ebx, [ctrl.int_line]
mov esi, msgInvIRQ
bt eax, ebx
jnc .fail_msg
mov eax, ATTCH_IRQ
mov esi, msgAttchIRQ
bt eax, ebx
jnc .fail_msg
 
invoke AttachIntHandler, ebx, ac97_irq_VIA, 0
.reg:
invoke RegService, sz_sound_srv, service_proc
ret
.fail:
if DEBUG
mov esi, msgFail
invoke SysMsgBoardStr
end if
xor eax, eax
ret
.fail_msg:
invoke SysMsgBoardStr
xor eax, eax
ret
.stop:
call stop
xor eax, eax
ret
endp
 
handle equ IOCTL.handle
io_code equ IOCTL.io_code
input equ IOCTL.input
inp_size equ IOCTL.inp_size
output equ IOCTL.output
out_size equ IOCTL.out_size
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edi, [ioctl]
mov eax, [edi+io_code]
 
cmp eax, SRV_GETVERSION
jne @F
mov eax, [edi+output]
cmp [edi+out_size], 4
jne .fail
 
mov [eax], dword API_VERSION
xor eax, eax
ret
@@:
cmp eax, DEV_PLAY
jne @F
if DEBUG
mov esi, msgPlay
invoke SysMsgBoardStr
end if
call play
ret
@@:
cmp eax, DEV_STOP
jne @F
if DEBUG
mov esi, msgStop
invoke SysMsgBoardStr
end if
call stop
ret
@@:
cmp eax, DEV_CALLBACK
jne @F
mov ebx, [edi+input]
stdcall set_callback, [ebx]
ret
@@:
cmp eax, DEV_SET_MASTERVOL
jne @F
mov eax, [edi+input]
mov eax, [eax]
call set_master_vol ;eax= vol
ret
@@:
cmp eax, DEV_GET_MASTERVOL
jne @F
mov ebx, [edi+output]
stdcall get_master_vol, ebx
ret
@@:
cmp eax, DEV_GET_INFO
jne @F
mov ebx, [edi+output]
stdcall get_dev_info, ebx
ret
@@:
cmp eax, DEV_GET_POS
jne @F
push ebx edx
mov edx, VIADEV_PLAYBACK + VIA_REG_OFFSET_CURR_COUNT
call [ctrl.ctrl_read32]
and eax, 0x00FFFFFF
mov ebx, 4096
sub ebx, eax
shr ebx, 2
mov edx, [edi+output]
mov [edx], ebx
pop edx ebx
ret
@@:
.fail:
or eax, -1
ret
endp
 
restore handle
restore io_code
restore input
restore inp_size
restore output
restore out_size
 
 
align 4
proc ac97_irq_VIA
locals
status db 0
endl
 
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STATUS
call [ctrl.ctrl_read8]
test al, VIA_REG_STAT_ACTIVE
jz @f
 
and al, VIA_REG_STAT_EOL or VIA_REG_STAT_FLAG or VIA_REG_STAT_STOPPED
mov byte [status], al
 
mov ebx, dword [buff_list]
cmp [ctrl.user_callback], 0
je @f
stdcall [ctrl.user_callback], ebx
@@:
mov al, byte [status] ;; ack ;;
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STATUS
call [ctrl.ctrl_write8]
 
ret
endp
 
 
align 4
proc create_primary_buff
 
invoke KernelAlloc, 0x10000
mov [ctrl.buffer], eax
 
mov edi, eax
mov ecx, 0x10000/4
xor eax, eax
cld
rep stosd
 
mov eax, [ctrl.buffer]
invoke GetPgAddr
mov edi, pcmout_bdl
stosd
mov eax, 0x80004000
stosd
 
mov edi, buff_list
mov eax, [ctrl.buffer]
mov ecx, 4
@@:
mov [edi], eax
mov [edi+16], eax
mov [edi+32], eax
mov [edi+48], eax
mov [edi+64], eax
mov [edi+80], eax
mov [edi+96], eax
mov [edi+112], eax
 
;add eax, 0x4000
add edi, 4
loop @B
 
stdcall channel_reset, VIADEV_PLAYBACK
stdcall codec_check_ready
 
mov eax, pcmout_bdl
mov ebx, eax
invoke GetPgAddr
and ebx, 0xFFF
add eax, ebx
 
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_TABLE_PTR
call [ctrl.ctrl_write32]
 
stdcall codec_check_ready
 
mov edx, VIADEV_PLAYBACK +VIA_REG_OFS_PLAYBACK_VOLUME_L
mov eax, 7 ;31
call [ctrl.ctrl_write8]
 
mov edx, VIADEV_PLAYBACK +VIA_REG_OFS_PLAYBACK_VOLUME_R
mov eax, 7 ;31
call [ctrl.ctrl_write8]
 
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STOP_IDX
mov eax, VIA8233_REG_TYPE_16BIT or VIA8233_REG_TYPE_STEREO or 0xfffff or 0xff000000
mov [ctrl.lvi_reg], 16 ;0xF;eax
call [ctrl.ctrl_write32]
 
stdcall codec_check_ready
ret
endp
 
 
proc channel_reset channel:dword
mov esi, dword [channel]
mov edx, esi
add edx, VIA_REG_OFFSET_CONTROL
mov eax, VIA_REG_CTRL_PAUSE or VIA_REG_CTRL_TERMINATE or VIA_REG_CTRL_RESET
call [ctrl.ctrl_write8]
 
mov edx, esi
add edx, VIA_REG_OFFSET_CONTROL
call [ctrl.ctrl_read8]
 
mov eax, 50000 ; wait 50 ms
call StallExec
; disable interrupts
mov edx, esi
add edx, VIA_REG_OFFSET_CONTROL
xor eax, eax
call [ctrl.ctrl_write8]
 
; clear interrupts
mov edx, esi
add edx, VIA_REG_OFFSET_STATUS
mov eax, 0x03
call [ctrl.ctrl_write8]
 
;outb(0x00, VIADEV_REG(viadev, OFFSET_TYPE)); /* for via686 */
; mov edx, esi ;; for via686
; add edx, VIA_REG_OFFSET_TYPE
; mov eax, 0x03
; call [ctrl.ctrl_write8]
 
;; outl(0, VIADEV_REG(viadev, OFFSET_CURR_PTR));
;mov edx, esi
;add edx, VIA_REG_OFFSET_CURR_PTR
;xor eax, eax
;call [ctrl.ctrl_write8]
 
ret
endp
 
 
align 4
proc detect_controller
locals
last_bus dd ?
bus dd ?
devfn dd ?
endl
 
xor eax, eax
mov [bus], eax
inc eax
invoke PciApi
cmp eax, -1
je .err
 
mov [last_bus], eax
 
.next_bus:
and [devfn], 0
.next_dev:
invoke PciRead32, [bus], [devfn], dword 0
test eax, eax
jz .next
cmp eax, -1
je .next
 
mov edi, devices
@@:
mov ebx, [edi]
test ebx, ebx
jz .next
 
cmp eax, ebx
je .found
add edi, 12
jmp @B
.next:
inc [devfn]
cmp [devfn], 256
jb .next_dev
mov eax, [bus]
inc eax
mov [bus], eax
cmp eax, [last_bus]
jna .next_bus
xor eax, eax
ret
.found:
mov ebx, [bus]
mov [ctrl.bus], ebx
 
mov ecx, [devfn]
mov [ctrl.devfn], ecx
 
mov edx, eax
and edx, 0xFFFF
mov [ctrl.vendor], edx
shr eax, 16
mov [ctrl.dev_id], eax
 
mov ebx, [edi+4]
mov [ctrl.ctrl_ids], ebx
mov esi, [edi+8]
mov [ctrl.ctrl_setup], esi
 
cmp edx, VID_VIA
jne @F
mov [ctrl.vendor_ids], msg_VIA
ret
@@:
 
.err:
xor eax, eax
mov [ctrl.vendor_ids], eax ;something wrong ?
ret
endp
 
align 4
proc init_controller
 
invoke PciRead32, [ctrl.bus], [ctrl.devfn], dword 4
mov ebx, eax
and eax, 0xFFFF
mov [ctrl.pci_cmd], eax
shr ebx, 16
mov [ctrl.pci_stat], ebx
 
mov esi, msgPciCmd
invoke SysMsgBoardStr
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgPciStat
invoke SysMsgBoardStr
mov eax, [ctrl.pci_stat]
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgCtrlIsaIo
invoke SysMsgBoardStr
invoke PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10
call dword2str
invoke SysMsgBoardStr
 
and eax, 0xFFC0
mov [ctrl.ctrl_io_base], eax
 
.default:
invoke PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C
and eax, 0xFF
@@:
mov [ctrl.int_line], eax
 
;stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_FUNC_ENABLE ;0x42
;mov byte [old_legacy], al
 
;stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_PNP_CONTROL ;0x43
;mov byte [old_legacy_cfg], al
 
;mov al, VIA_FUNC_ENABLE_SB or VIA_FUNC_ENABLE_FM
;xor al, 0xFF
;and al, byte [old_legacy]
;and eax, 0xFF
;stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_FUNC_ENABLE, eax ;0x42
;mov byte [old_legacy], al
 
call [ctrl.ctrl_setup]
xor eax, eax
inc eax
ret
endp
 
align 4
proc set_VIA
mov [ctrl.codec_read16], codec_io_r16 ;virtual
mov [ctrl.codec_write16], codec_io_w16 ;virtual
 
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual
 
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual
ret
endp
 
 
align 4
proc init_codec
locals
counter dd ?
endl
 
mov esi, msgControl
invoke SysMsgBoardStr
invoke PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL
and eax, 0xFF
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgStatus
invoke SysMsgBoardStr
invoke PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT
and eax, 0xFF
push eax
call dword2str
invoke SysMsgBoardStr
pop eax
 
test eax, VIA_ACLINK_C00_READY
jnz .ready
 
call reset_codec
test eax, eax
jz .err
 
.ready:
xor edx, edx ; ac_reg_0
call [ctrl.codec_write16]
jmp .done
 
.err:
xor eax, eax ; timeout error
ret
 
.done:
call detect_codec
 
xor eax, eax
inc eax
ret
endp
 
align 4
proc reset_codec
invoke PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, \
VIA_ACLINK_CTRL_ENABLE or VIA_ACLINK_CTRL_RESET or VIA_ACLINK_CTRL_SYNC
mov eax, 100000 ; wait 100 ms
call StallExec
.cold:
call cold_reset
jnc .ok
 
if DEBUG
mov esi, msgCFail
invoke SysMsgBoardStr
end if
xor eax, eax ; timeout error
ret
.ok:
if DEBUG
mov esi, msgResetOk
invoke SysMsgBoardStr
end if
xor eax, eax
inc eax
ret
endp
 
 
align 4
proc cold_reset
locals
counter dd ?
endl
 
invoke PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, dword 0
 
if DEBUG
mov esi, msgCold
invoke SysMsgBoardStr
end if
 
mov eax, 100000 ; wait 100 ms ;400000 ; wait 400 ms
call StallExec
 
;; ACLink on, deassert ACLink reset, VSR, SGD data out
;; note - FM data out has trouble with non VRA codecs !!
invoke PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, dword VIA_ACLINK_CTRL_INIT
 
mov [counter], 16 ; total 20*100 ms = 2s
.wait:
invoke PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT
test eax, VIA_ACLINK_C00_READY
jnz .ok
 
mov eax, 100000 ; wait 100 ms
call StallExec
 
dec [counter]
jnz .wait
 
if DEBUG
mov esi, msgCRFail
invoke SysMsgBoardStr
end if
 
.fail:
stc
ret
.ok:
mov esi, msgControl
invoke SysMsgBoardStr
invoke PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL
call dword2str
invoke SysMsgBoardStr
 
mov esi, msgStatus
invoke SysMsgBoardStr
invoke PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT
and eax, 0xFF
push eax
call dword2str
invoke SysMsgBoardStr
pop eax
 
test eax, VIA_ACLINK_C00_READY ;CTRL_ST_CREADY
jz .fail
clc
ret
endp
 
align 4
play:
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STOP_IDX
mov eax, VIA8233_REG_TYPE_16BIT or VIA8233_REG_TYPE_STEREO or 0xfffff or 0xff000000
mov [ctrl.lvi_reg], 16
call [ctrl.ctrl_write32]
 
mov eax, VIA_REG_CTRL_INT
or eax, VIA_REG_CTRL_START
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CONTROL
call [ctrl.ctrl_write8]
 
xor eax, eax
ret
 
align 4
stop:
mov eax, VIA_REG_CTRL_INT
or eax, VIA_REG_CTRL_TERMINATE
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CONTROL
call [ctrl.ctrl_write8]
 
stdcall channel_reset, VIADEV_PLAYBACK
xor eax, eax
ret
 
align 4
proc get_dev_info stdcall, p_info:dword
virtual at esi
CTRL_INFO CTRL_INFO
end virtual
 
mov esi, [p_info]
mov eax, [ctrl.int_line]
mov ecx, [ctrl.ctrl_io_base]
mov [CTRL_INFO.irq], eax
mov [CTRL_INFO.ctrl_io_base], ecx
 
xor eax, eax
;mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_TABLE_PTR
;call [ctrl.ctrl_read32]
mov [CTRL_INFO.codec_io_base], eax
;mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STOP_IDX
;call [ctrl.ctrl_read32]
mov [CTRL_INFO.codec_mem_base], eax
;mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CURR_COUNT
;call [ctrl.ctrl_read32]
mov [CTRL_INFO.ctrl_mem_base], eax
 
mov eax, [codec.chip_id]
mov [CTRL_INFO.codec_id], eax
 
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CONTROL
call [ctrl.ctrl_read8]
and eax, 0xFF
mov [CTRL_INFO.glob_cntrl], eax
 
mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STATUS
call [ctrl.ctrl_read8]
and eax, 0xFF
mov [CTRL_INFO.glob_sta], eax
 
mov ebx, [ctrl.pci_cmd]
mov [CTRL_INFO.pci_cmd], ebx
ret
endp
 
align 4
proc set_callback stdcall, handler:dword
mov eax, [handler]
mov [ctrl.user_callback], eax
ret
endp
 
 
align 4
proc codec_check_ready stdcall
locals
counter dd ?
endl
 
mov [counter], 1000 ; total 1000*1 ms = 1s
.wait:
call [ctrl.codec_read16]
test eax, VIA_REG_AC97_BUSY
jz .ok
 
mov eax, 1000 ; wait 1 ms
call StallExec
 
sub [counter] , 1
jnz .wait
.err:
mov eax, -1
ret
.ok:
and eax, 0xFFFF
ret
endp
 
 
align 4
proc codec_valid stdcall
stdcall codec_check_ready
ret
endp
 
align 4
proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax
locals
counter dd ?
endl
 
;Use only primary codec.
mov eax, [ac_reg]
and eax, 0x7F
shl eax, VIA_REG_AC97_CMD_SHIFT
or eax, VIA_REG_AC97_PRIMARY_VALID or VIA_REG_AC97_READ
 
mov [counter], 3 ; total 3*20 ms = 60ms
.wait:
push eax
call [ctrl.codec_write16]
 
mov eax, 20000 ; wait 20 ms
call StallExec
 
stdcall codec_valid
cmp eax, 0
pop eax
jge .ok
 
sub [counter] , 1
jnz .wait
jmp .err
 
.ok:
mov eax, 25000 ; wait 25 ms
call StallExec
 
call [ctrl.codec_read16] ;change edx !!!
and eax, 0xFFFF
ret
.err:
if DEBUG
mov esi, msgCInvalid
invoke SysMsgBoardStr
end if
mov eax, -1 ; invalid codec error
ret
endp
 
align 4
proc codec_write stdcall, ac_reg:dword
;Use only primary codec.
mov esi, [ac_reg]
mov edx, esi
shl edx, VIA_REG_AC97_CMD_SHIFT
 
shl eax, VIA_REG_AC97_DATA_SHIFT
or edx, eax
 
mov eax, VIA_REG_AC97_CODEC_ID_PRIMARY ;not VIA_REG_AC97_CODEC_ID_PRIMARY
shl eax, VIA_REG_AC97_CODEC_ID_SHIFT
or edx, eax
 
mov eax, edx
mov edx, esi
call [ctrl.codec_write16]
mov [codec.regs+esi], ax
 
stdcall codec_check_ready
cmp eax, 0
jl .err
.ok:
ret
.err:
if DEBUG
mov esi, msgCFail
invoke SysMsgBoardStr
end if
;mov eax, -1 ; codec not ready error
ret
endp
 
align 4
proc StallExec
push ecx
push edx
push ebx
push eax
 
mov ecx, CPU_FREQ
mul ecx
mov ebx, eax ;low
mov ecx, edx ;high
rdtsc
add ebx, eax
adc ecx, edx
@@:
rdtsc
sub eax, ebx
sbb edx, ecx
js @B
 
pop eax
pop ebx
pop edx
pop ecx
ret
endp
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; CONTROLLER IO functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc codec_io_r16 ;r32
mov edx, [ctrl.ctrl_io_base]
add edx, VIA_REG_AC97
in eax, dx
ret
endp
 
align 4
proc codec_io_w16 ;w32
mov edx, [ctrl.ctrl_io_base]
add edx, VIA_REG_AC97
out dx, eax
ret
endp
 
align 4
proc ctrl_io_r8
add edx, [ctrl.ctrl_io_base]
in al, dx
ret
endp
 
align 4
proc ctrl_io_r16
add edx, [ctrl.ctrl_io_base]
in ax, dx
ret
endp
 
align 4
proc ctrl_io_r32
add edx, [ctrl.ctrl_io_base]
in eax, dx
ret
endp
 
align 4
proc ctrl_io_w8
add edx, [ctrl.ctrl_io_base]
out dx, al
ret
endp
 
align 4
proc ctrl_io_w16
add edx, [ctrl.ctrl_io_base]
out dx, ax
ret
endp
 
align 4
proc ctrl_io_w32
add edx, [ctrl.ctrl_io_base]
out dx, eax
ret
endp
 
 
align 4
dword2str:
push eax ebx ecx
mov esi, hex_buff
mov ecx, -8
@@:
rol eax, 4
mov ebx, eax
and ebx, 0x0F
mov bl, [ebx+hexletters]
mov [8+esi+ecx], bl
inc ecx
jnz @B
pop ecx ebx eax
ret
 
hexletters db '0123456789ABCDEF'
hex_buff db 8 dup(0),13,10,0
 
 
include "codec.inc"
 
align 4
devices dd (CTRL_VT82C686 shl 16)+VID_VIA,msg_VT82C686,set_VIA
dd (CTRL_VT8233_5 shl 16)+VID_VIA,msg_VT8233,set_VIA
dd 0 ;terminator
 
 
msg_VT82C686 db 'VT82C686', 13,10, 0
msg_VT8233 db 'VT8233', 13,10, 0
msg_VIA db 'VIA' , 13,10, 0
 
szKernel db 'KERNEL', 0
sz_sound_srv db 'SOUND',0
 
msgInit db 'detect hardware...',13,10,0
msgFail db 'device not found',13,10,0
msgAttchIRQ db 'IRQ line not supported', 13,10, 0
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0
msgPlay db 'start play', 13,10,0
msgStop db 'stop play', 13,10,0
;msgIRQ db 'AC97 IRQ', 13,10,0
;msgInitCtrl db 'init controller',13,10,0
;msgInitCodec db 'init codec',13,10,0
msgPrimBuff db 'create primary buffer ...',0
msgDone db 'done',13,10,0
msgRemap db 'Remap IRQ',13,10,0
;msgReg db 'set service handler',13,10,0
;msgOk db 'service installed',13,10,0
msgCold db 'cold reset',13,10,0
;msgWarm db 'warm reset',13,10,0
;msgWRFail db 'warm reset failed',13,10,0
msgCRFail db 'cold reset failed',13,10,0
msgCFail db 'codec not ready',13,10,0
msgCInvalid db 'codec is not valid',13,10,0 ;Asper
msgResetOk db 'reset complete',13,10,0
msgStatus db 'global status ',0
msgControl db 'global control ',0
msgPciCmd db 'PCI command ',0
msgPciStat db 'PCI status ',0
msgCtrlIsaIo db 'controller io base ',0
;msgMixIsaIo db 'codec io base ',0
;msgCtrlMMIo db 'controller mmio base ',0
;msgMixMMIo db 'codec mmio base ',0
;msgIrqMap db 'AC97 irq map as ',0
 
align 4
data fixups
end data
 
align 8
pcmout_bdl rq 32
buff_list rd 32
 
codec CODEC
ctrl AC_CNTRL
 
chip_type rb 1
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property