;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2004-2015. 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 IRQ_REMAP equ 0 IRQ_LINE equ 0 ;irq 0,13 unavailable ; FEDCBA9876543210 VALID_IRQ equ 1101111111111110b 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 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