kolibrios/drivers/audio/emu10k1x.asm
Ivan Baravy 036ce5c69d Apply patch from r7584 to all audio drivers.
Allow audio drivers to use IRQs 1,2,8,12, this is MenuetOS legacy.

git-svn-id: svn://kolibrios.org@7585 a494cfbc-eb01-0410-851d-a64ba20cac60
2019-02-22 22:39:36 +00:00

1143 lines
32 KiB
NASM

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 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
DEBUG equ 1
API_VERSION equ 0x01000100
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
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
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
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