/kernel/branches/Kolibri-acpi/drivers/emu10k1x.asm |
---|
0,0 → 1,1166 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
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 ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi,[ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call 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 |
call SysMsgBoardStr |
call create_primary_buff |
mov esi, msgDone |
call 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 |
call 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 |
stdcall AttachIntHandler, ebx, ac97_irq, dword 0 |
stdcall create |
.reg: |
stdcall RegService, sz_sound_srv, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
.fail_msg: |
call 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 |
call SysMsgBoardStr |
end if |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call 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 |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call GetPgAddr |
mov edi, pcmout_bdl |
stosd |
mov eax, 0x4000000 |
stosd |
mov edi, buff_list |
mov eax, [ctrl.buffer] |
stosd ;1.] |
mov eax, [ctrl.buffer] |
call 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 |
call 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 |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall 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 |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x2C |
mov esi, msgPciSubsys |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
stdcall 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 |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciStat |
call SysMsgBoardStr |
mov eax, [ctrl.pci_stat] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgCtrlIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
call dword2str |
call SysMsgBoardStr |
and eax, 0xFFC0 |
mov [ctrl.ctrl_io_base], eax |
.default: |
stdcall 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 |
call 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 |
call 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 |
stdcall PciRead16, [ctrl.bus], [ctrl.devfn], dword 4 |
test eax, 4 ; test master bit |
jnz @f |
or eax, 4 |
stdcall PciWrite16, [ctrl.bus], [ctrl.devfn], dword 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 |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
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 |
section '.data' data readable writable align 16 |
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 |
/kernel/branches/Kolibri-acpi/drivers/imports.inc |
---|
0,0 → 1,93 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
macro kernel_export [name]{ |
forward |
if used name |
if DEBUG |
display 'uses: ',`name,#13,#10 |
end if |
extrn name |
end if |
} |
; all exported kernel functions and data |
kernel_export \ |
RegService,\ |
GetService,\ |
ServiceHandler,\ |
AttachIntHandler,\ |
GetIntHandler,\ |
FpuSave,\ |
FpuRestore,\ |
ReservePortArea,\ |
Boot_Log,\ |
\ |
MutexInit,\ |
MutexLock,\ |
MutexUnlock,\ |
\ |
PciApi,\ |
PciRead32,\ |
PciRead16,\ |
PciRead8,\ |
PciWrite8,\ |
PciWrite16,\ |
PciWrite32,\ |
\ |
AllocPage,\ |
AllocPages,\ |
FreePage,\ |
MapPage,\ |
MapSpace,\ |
MapIoMem,\ |
GetPgAddr,\ |
CommitPages,\ |
ReleasePages,\ |
\ |
AllocKernelSpace,\ |
FreeKernelSpace,\ |
KernelAlloc,\ |
KernelFree,\ |
UserAlloc,\ |
UserFree,\ |
Kmalloc,\ |
Kfree,\ |
CreateRingBuffer,\ |
\ |
GetPid,\ |
CreateObject,\ |
DestroyObject,\ |
CreateEvent,\ |
RaiseEvent,\ |
WaitEvent,\ |
DestroyEvent,\ |
ClearEvent,\ |
\ |
LoadCursor,\ |
SelectHwCursor,\ |
SetHwCursor,\ |
HwCursorRestore,\ |
HwCursorCreate,\ |
\ |
SysMsgBoardStr,\ |
SysMsgBoardChar,\ |
GetCurrentTask,\ |
LoadFile,\ |
SendEvent,\ |
SetMouseData,\ |
Sleep,\ |
GetTimerTicks,\ |
\ |
strncat,\ |
strncpy,\ |
strncmp,\ |
strnlen,\ |
strchr,\ |
strrchr,\ |
\ |
LFBAddress |
Property changes: |
Added: svn:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/drivers/viasound.asm |
---|
0,0 → 1,1281 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
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_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 |
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 ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi,[ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call 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 |
call SysMsgBoardStr |
call create_primary_buff |
mov esi, msgDone |
call 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 |
call 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 |
stdcall AttachIntHandler, ebx, ac97_irq_VIA, dword 0 |
.reg: |
stdcall RegService, sz_sound_srv, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
.fail_msg: |
call 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 |
call SysMsgBoardStr |
end if |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call 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_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 |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call 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 |
call 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 |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall 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 |
stdcall 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 |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciStat |
call SysMsgBoardStr |
mov eax, [ctrl.pci_stat] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgCtrlIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
call dword2str |
call SysMsgBoardStr |
and eax, 0xFFC0 |
mov [ctrl.ctrl_io_base], eax |
.default: |
stdcall 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 |
call SysMsgBoardStr |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL |
and eax, 0xFF |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT |
and eax, 0xFF |
push eax |
call dword2str |
call SysMsgBoardStr |
pop eax |
test eax, VIA_ACLINK_C00_READY |
jz .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 |
stdcall 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 |
call SysMsgBoardStr |
end if |
xor eax, eax ; timeout error |
ret |
.ok: |
if DEBUG |
mov esi, msgResetOk |
call SysMsgBoardStr |
end if |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc cold_reset |
locals |
counter dd ? |
endl |
stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, dword 0 |
if DEBUG |
mov esi, msgCold |
call 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 !! |
stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, dword VIA_ACLINK_CTRL_INIT |
mov [counter], 16 ; total 20*100 ms = 2s |
.wait: |
stdcall 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 |
call SysMsgBoardStr |
end if |
.fail: |
stc |
ret |
.ok: |
mov esi, msgControl |
call SysMsgBoardStr |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT |
and eax, 0xFF |
push eax |
call dword2str |
call 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 |
call 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 |
call 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 |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
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 |
section '.data' data readable writable align 16 |
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 |
/kernel/branches/Kolibri-acpi/drivers/vt823(x).asm |
---|
0,0 → 1,1281 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
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_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 |
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 ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi,[ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call 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 |
call SysMsgBoardStr |
call create_primary_buff |
mov esi, msgDone |
call 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 |
call 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 |
stdcall AttachIntHandler, ebx, ac97_irq_VIA, dword 0 |
.reg: |
stdcall RegService, sz_sound_srv, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
.fail_msg: |
call 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 |
call SysMsgBoardStr |
end if |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call 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_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 |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call 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 |
call 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 |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall 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 |
stdcall 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 |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciStat |
call SysMsgBoardStr |
mov eax, [ctrl.pci_stat] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgCtrlIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
call dword2str |
call SysMsgBoardStr |
and eax, 0xFFC0 |
mov [ctrl.ctrl_io_base], eax |
.default: |
stdcall 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 |
call SysMsgBoardStr |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL |
and eax, 0xFF |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT |
and eax, 0xFF |
push eax |
call dword2str |
call SysMsgBoardStr |
pop eax |
test eax, VIA_ACLINK_C00_READY |
jz .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 |
stdcall 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 |
call SysMsgBoardStr |
end if |
xor eax, eax ; timeout error |
ret |
.ok: |
if DEBUG |
mov esi, msgResetOk |
call SysMsgBoardStr |
end if |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc cold_reset |
locals |
counter dd ? |
endl |
stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, dword 0 |
if DEBUG |
mov esi, msgCold |
call 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 !! |
stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, dword VIA_ACLINK_CTRL_INIT |
mov [counter], 16 ; total 20*100 ms = 2s |
.wait: |
stdcall 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 |
call SysMsgBoardStr |
end if |
.fail: |
stc |
ret |
.ok: |
mov esi, msgControl |
call SysMsgBoardStr |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT |
and eax, 0xFF |
push eax |
call dword2str |
call 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 |
call 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 |
call 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 |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
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 |
section '.data' data readable writable align 16 |
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 |
/kernel/branches/Kolibri-acpi/drivers/codec.inc |
---|
0,0 → 1,326 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. 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 |
call 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 |
call SysMsgBoardStr |
mov eax, [codec.chip_id] |
call dword2str |
call 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 |
call SysMsgBoardStr |
ret |
.next: |
add edi, 8 |
jmp @b |
.unknown: |
mov [codec.chip_ids], chip_unknown |
mov esi, chip_unknown |
call SysMsgBoardStr |
mov eax, [codec.chip_id] |
call dword2str |
call 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:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/drivers/fm801.asm |
---|
0,0 → 1,1061 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
DEBUG equ 1 |
DEBUG_IRQ equ 0 |
include 'proc32.inc' |
include 'imports.inc' |
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 ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov eax, START |
call dword2str |
call SysMsgBoardStr |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi, [ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call 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 |
call SysMsgBoardStr |
call create_primary_buff |
mov esi, msgDone |
call 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 |
stdcall AttachIntHandler, ebx, ac97_irq, dword 0 |
.reg: |
stdcall RegService, sz_sound_srv, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
.fail_msg: |
call 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 |
call SysMsgBoardStr |
end if |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call 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 |
call 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 |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call 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 |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
push eax |
stdcall 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 |
stdcall 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 |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciStat |
call SysMsgBoardStr |
mov eax, [ctrl.pci_stat] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgCtrlIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
call dword2str |
call SysMsgBoardStr |
and eax,0xFFFE |
mov [ctrl.ctrl_io_base], eax |
mov esi, msgIrqNum |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C |
and eax, 0xFF |
mov [ctrl.int_line], eax |
call dword2str |
call 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 |
call 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 |
call 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 |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
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 |
section '.data' data readable writable align 16 |
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 |
/kernel/branches/Kolibri-acpi/drivers/com_mouse.asm |
---|
0,0 → 1,382 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; Includes source code by Kulakov Vladimir Gennadievich. ;; |
;; Modified by Mario79 and Rus. ;; |
;; 02.12.2009 <Lrz> ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;driver sceletone |
format MS COFF |
DEBUG equ 0 |
include 'proc32.inc' |
include 'imports.inc' |
API_VERSION equ 5 ;debug |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
public START |
public version |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
STRIDE equ 4 ;size of row in devices table |
SRV_GETVERSION equ 0 |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .exit |
.entry: |
;Detect_COM_Mouse: |
if DEBUG |
mov esi, msgInit |
call Boot_Log |
end if |
mov bx, 0x3f8 |
call MSMouseSearch |
cmp AL,'M' |
jne @f |
;mov [com1_mouse_detected],1 |
;mov [irq_owner+4*4], 1 ; IRQ4 owner is System |
mov dx, bx |
inc dx ; 0x3f8 + 1 |
mov al, 1 |
out dx, al |
stdcall AttachIntHandler, 4, irq4_handler, dword 0 |
if DEBUG |
test eax, eax |
jne .label1 |
mov esi, msg_error_attach_int_handler |
call Boot_Log |
end if |
.label1: |
; mov eax, 0 |
; mov ebx, 0x3F8 |
; mov ecx, 0x3FF |
xor ebx,ebx |
mov ecx, 0x3F8 |
mov edx, 0x3FF |
call ReservePortArea |
if DEBUG |
cmp eax, 1 |
jne .go |
mov esi, msg_error_reserve_ports |
call Boot_Log |
.go: |
mov esi,boot_setmouse_type |
call Boot_Log |
end if |
@@: |
mov bx, 0x2f8 |
call MSMouseSearch |
cmp AL,'M' |
jne .resume |
;mov [com2_mouse_detected],1 |
;mov [irq_owner+3*4], 1 ; IRQ3 owner is System |
stdcall AttachIntHandler, 3, irq3_handler, dword 0 |
; mov eax, 0 |
; mov ebx, 0x2F8 |
; mov ecx, 0x3F8 |
xor ebx,ebx |
mov ecx, 0x2F8 |
mov edx, 0x3F8 |
call ReservePortArea |
if DEBUG |
cmp eax, 1 |
jne @f |
mov esi, msg_error_reserve_ports |
call Boot_Log |
@@: |
mov esi,boot_setmouse_type + 22 |
call Boot_Log |
end if |
.resume: |
stdcall RegService, my_service, service_proc |
if DEBUG |
test eax, eax |
jne @f |
mov esi, msg_exit |
call Boot_Log |
end if |
@@: |
ret |
.fail: |
.exit: |
if DEBUG |
mov esi, msg_exit |
call Boot_Log |
end if |
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 ebx, [ioctl] |
mov eax, [ebx+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [ebx+output] |
cmp [ebx+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
align 4 |
MSMouseSearch: |
; ÏÎÈÑÊ ÌÛØÈ ×ÅÐÅÇ COM-ÏÎÐÒÛ |
MouseSearch: |
; Óñòàíàâëèâàåì ñêîðîñòü |
; ïðèåìà/ïåðåäà÷è 1200 áîä |
; in bx COM Port Base Address |
mov DX, bx |
add DX,3 |
in AL,DX |
or AL,80h ;óñòàíîâèòü áèò DLAB |
out DX,AL |
mov DX, bx |
mov AL,60h ;1200 áîä |
out DX,AL |
inc DX |
mov AL,0 |
out DX,AL |
; Óñòàíîâèòü äëèíó ñëîâà 7 áèò, 1 ñòîïîâûé áèò, |
; ÷åòíîñòü íå êîíòðîëèðîâàòü |
mov DX, bx |
add DX,3 |
mov AL,00000010b |
out DX,AL |
; Çàïðåòèòü âñå ïðåðûâàíè |
mov dx, bx |
inc dx |
mov AL,0 |
out DX,AL |
; Ïðîâåðèòü, ÷òî óñòðîéñòâî ïîäêëþ÷åíî è ÿâëÿåòñ |
; ìûøüþ òèïà MSMouse |
; Îòêëþ÷èòü ïèòàíèå ìûøè è ïðåðûâàíè |
mov DX, bx |
add EDX,4 ;ðåãèñòð óïðàâëåíèÿ ìîäåìîì |
mov AL,0 ;ñáðîñèòü DTR, RTS è OUT2 |
out DX,AL |
; Îæèäàòü 5 "òèêîâ" (0,2 ñ) |
mov ecx, 0xFFFF |
loop $ |
; Âêëþ÷èòü ïèòàíèå ìûøè |
mov al, 1 |
out dx, al |
mov ecx, 0xFFFF |
loop $ |
; Î÷èñòèòü ðåãèñòð äàííûõ |
mov dx, bx |
in AL,DX |
add edx, 4 |
mov AL, 1011b ;óñòàíîâèòü DTR è RTS è OUT2 |
out DX,AL |
mov ecx, 0x1FFFF |
; Öèêë îïðîñà ïîðòà |
WaitData: |
; Îæèäàòü åùå 10 "òèêîâ" |
dec ecx |
; cmp ecx,0 |
jz NoMouse |
; Ïðîâåðèòü íàëè÷èå èäåíòèôèêàöèîííîãî áàéòà |
mov DX, bx |
add DX,5 |
in AL,DX |
test AL,1 ;Äàííûå ãîòîâû? |
jz WaitData |
; Ââåñòè äàííûå |
mov DX, bx |
in AL,DX |
NoMouse: |
ret |
align 4 |
irq3_handler: |
mov dx, 0x2f8 |
mov esi, com2_mouse |
jmp irq_handler |
align 4 |
irq4_handler: |
mov dx, 0x3f8 |
mov esi, com1_mouse |
irq_handler: |
; in: esi -> COM_MOUSE_DATA struc, dx = base port (xF8h) |
add edx, 5 ; xFDh |
in al, dx |
test al, 1 ; Äàííûå ãîòîâû? |
jz .Error |
; Ââåñòè äàííûå |
sub edx, 5 |
in al, dx |
; Ñáðîñèòü ñòàðøèé íåçíà÷àùèé áèò |
and al, 01111111b |
; Îïðåäåëèòü ïîðÿäêîâûé íîìåð ïðèíèìàåìîãî áàéòà |
cmp [esi+COM_MOUSE_DATA.MouseByteNumber], 2 |
ja .Error |
jz .ThirdByte |
jp .SecondByte |
; Ñîõðàíèòü ïåðâûé áàéò äàííûõ |
.FirstByte: |
test al, 1000000b ; Ïåðâûé áàéò ïîñûëêè? |
jz .Error |
mov [esi+COM_MOUSE_DATA.FirstByte], al |
inc [esi+COM_MOUSE_DATA.MouseByteNumber] |
jmp .EndMouseInterrupt |
; Ñîõðàíèòü âòîðîé áàéò äàííûõ |
.SecondByte: |
test al, 1000000b |
jnz .Error |
mov [esi+COM_MOUSE_DATA.SecondByte], al |
inc [esi+COM_MOUSE_DATA.MouseByteNumber] |
jmp .EndMouseInterrupt |
; Ñîõðàíèòü òðåòèé áàéò äàííûõ |
.ThirdByte: |
test al, 1000000b |
jnz .Error |
mov [esi+COM_MOUSE_DATA.ThirdByte], al |
mov [esi+COM_MOUSE_DATA.MouseByteNumber], 0 |
; (Ïàêåò äàííûõ îò ìûøè ïðèíÿò ïîëíîñòüþ). |
; Çàïèñàòü íîâîå çíà÷åíèå ñîñòîÿíèÿ êíîïîê ìûøè |
mov al, [esi+COM_MOUSE_DATA.FirstByte] |
mov ah, al |
shr al, 3 |
and al, 2 |
shr ah, 5 |
and ah, 1 |
add al, ah |
movzx eax, al |
mov [BTN_DOWN], eax |
; Ïðèáàâèòü ïåðåìåùåíèå ïî X ê êîîðäèíàòå X |
mov al, [esi+COM_MOUSE_DATA.FirstByte] |
shl al, 6 |
or al, [esi+COM_MOUSE_DATA.SecondByte] |
cbw |
movzx eax, ax |
mov [MOUSE_X], eax |
; Ïðèáàâèòü ïåðåìåùåíèå ïî Y ê êîîðäèíàòå Y |
mov al, [esi+COM_MOUSE_DATA.FirstByte] |
and al, 00001100b |
shl al, 4 |
or al, [esi+COM_MOUSE_DATA.ThirdByte] |
cbw |
movzx eax, ax |
neg eax |
mov [MOUSE_Y], eax |
stdcall SetMouseData, [BTN_DOWN], [MOUSE_X], [MOUSE_Y], 0, 0 |
jmp .EndMouseInterrupt |
.Error: |
; Ïðîèçîøåë ñáîé â ïîðÿäêå ïåðåäà÷è èíôîðìàöèè îò |
; ìûøè, îáíóëèòü ñ÷åò÷èê áàéòîâ ïàêåòà äàííûõ |
mov [esi+COM_MOUSE_DATA.MouseByteNumber],0 |
.EndMouseInterrupt: |
ret |
;all initialized data place here |
align 4 |
struc COM_MOUSE_DATA { |
; Íîìåð ïðèíèìàåìîãî îò ìûøè áàéòà |
.MouseByteNumber db ? |
; Òðåõáàéòîâàÿ ñòðóêòóðà äàííûõ, ïåðåäàâàåìàÿ ìûøüþ |
.FirstByte db ? |
.SecondByte db ? |
.ThirdByte db ? |
;.timer_ticks_com dd ? |
} |
virtual at 0 |
COM_MOUSE_DATA COM_MOUSE_DATA |
end virtual |
com1_mouse COM_MOUSE_DATA |
com2_mouse COM_MOUSE_DATA |
MOUSE_X dd 0 |
MOUSE_Y dd 0 |
BTN_DOWN dd 0 |
COMPortBaseAddr dw 3F8h |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
my_service db 'COM_Mouse',0 ;max 16 chars include zero |
if DEBUG |
msgInit db 'Preved bugoga!',13,10,0 |
boot_setmouse_type db 'Detected - COM1 mouse',13,10,0 |
db 'Detected - COM2 mouse',13,10,0 |
msg_error_reserve_ports db 'Error reserving ports!',13,10,0 |
msg_error_attach_int_handler db 'Error attach interrupt handler!',13,10,0 |
msg_exit db 'Exit!',13,10,0 |
end if |
section '.data' data readable writable align 16 |
;all uninitialized data place here |
/kernel/branches/Kolibri-acpi/drivers/sb16/sb16.asm |
---|
0,0 → 1,393 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
include 'config.inc' |
;structs---------------------------------------------------------- |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
;something-------------------------------------------------------- |
public START |
public service_proc |
public version |
include '..\proc32.inc' |
include '..\imports.inc' |
section '.flat' code readable align 16 |
include 'sb16.inc' |
;------------------------------------------------------------------------------- |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
.entry: |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect ;returns DSP version or zero if |
test eax,eax ;SB card not found |
jz .exit |
if DEBUG |
movzx eax,al ;major version |
mov esi,sb_DSP_description |
dec eax |
jz .sb_say_about_found_dsp |
mov dword[esi],'2.x ' |
dec eax |
jz .sb_say_about_found_dsp |
mov dword[esi],'Pro ' |
dec eax |
jz .sb_say_about_found_dsp |
mov dword[esi],'16 ' |
.sb_say_about_found_dsp: |
mov esi,msgDSPFound |
call SysMsgBoardStr |
end if |
; xor eax,eax |
; mov ebx,[sb_base_port] |
; lea ecx,[ebx+0xF] |
xor ebx,ebx |
mov ecx,[sb_base_port] |
lea edx,[ebx+0xF] |
call ReservePortArea ;these ports must be my! |
if DEBUG |
dec eax |
jnz @f |
mov esi,msgErrRsrvPorts |
call SysMsgBoardStr |
@@: |
end if |
call sb_setup ;clock it, etc |
stdcall AttachIntHandler, sb_irq_num, sb_irq, 0 |
if DEBUG |
test eax,eax |
jnz @f |
mov esi,msgErrAtchIRQ |
call SysMsgBoardStr |
stdcall GetIntHandler, sb_irq_num |
call SysMsgBoardNum |
jmp .stop |
@@: |
mov esi,msgSucAtchIRQ |
call SysMsgBoardStr |
end if |
stdcall RegService, my_service, service_proc |
ret |
.stop: |
call sb_reset |
.exit: |
if DEBUG |
mov esi,msgExit |
call SysMsgBoardStr |
end if |
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 |
call SysMsgBoardStr |
end if |
call sb_stop ;to play smth new we must stop smth old |
call pre_fill_data ;fill first and second half of the buffer |
call pre_fill_data ; |
call sb_set_dma ;is it really needed here? Paranoia. |
call sb_play |
xor eax,eax ;set maximum volume |
call sb_set_master_vol |
xor eax,eax |
ret |
;@@: ;all this commented stuff in service proc |
; cmp eax,DEV_STOP ;is never used. Mixer do this virtually, |
; jne @f ;e.g. instead of stopping driver it |
;if DEBUG ;outputs silence |
; mov esi,msgStop |
; call SysMsgBoardStr |
;end if |
; call sb_stop |
; xor eax,eax |
; ret |
@@: |
cmp eax,DEV_CALLBACK |
jne @f |
if DEBUG |
mov esi,msgCallback |
call SysMsgBoardStr |
end if |
mov edi,[edi+input] |
mov eax,[edi] |
mov [callback],eax |
if DEBUG |
call SysMsgBoardNum |
end if |
xor eax,eax |
ret |
@@: |
cmp eax,DEV_SET_MASTERVOL ;Serge asked me to unlock |
jne @F ;DEV_SET(GET)_MASTERVOL, although mixer doesn't use it. |
;It doesn't use it _in current version_ - but in the future... |
if DEBUG |
mov esi,msgSetVol |
call SysMsgBoardStr |
end if |
mov eax,[edi+input] |
mov eax,[eax] |
call sb_set_master_vol |
xor eax,eax |
ret |
@@: |
cmp eax,DEV_GET_MASTERVOL |
jne @F |
if DEBUG |
mov esi,msgGetVol |
call SysMsgBoardStr |
end if |
mov eax,[edi+output] |
mov edx,[sb_master_vol] |
mov [eax],edx |
xor eax,eax |
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 sb_irq |
mov edx,[sb_base_port] ;tell the DSP that we have processed IRQ |
add dl,0xF ;0xF for 16 bit sound, 0xE for 8 bit sound |
in al,dx ;for non-stop sound |
pre_fill_data: |
mov eax,int_flip_flop |
not dword[eax] |
mov eax,[eax] |
test eax,eax |
jns .fill_second_half |
if sb_buffer_size eq small_buffer |
stdcall [callback],SB16Buffer0 ;for 32k buffer |
else if sb_buffer_size eq full_buffer |
stdcall [callback],SB16Buffer0 ;for 64k buffer |
stdcall [callback],SB16Buffer1 ;for 64k buffer |
end if |
xor eax,eax |
ret |
.fill_second_half: |
if sb_buffer_size eq small_buffer |
stdcall [callback],SB16Buffer1 ;for 32k buffer |
else if sb_buffer_size eq full_buffer |
stdcall [callback],SB16Buffer2 ;for 64k buffer |
stdcall [callback],SB16Buffer3 ;for 64k buffer |
end if |
xor eax,eax |
ret |
endp |
;------------------------------------------------------------------------------- |
align 4 |
proc detect |
.sb_detect_next_port: |
if DEBUG |
inc dword[port_second_digit_num] |
end if |
mov edx,sb_base_port |
add byte[edx],10h |
cmp byte[edx],80h |
jbe .sb_try_to_detect_at_specified_port |
;error - no SB card detected |
.sb_not_found_err: |
xor eax, eax |
ret |
.sb_try_to_detect_at_specified_port: |
call sb_reset |
add dl,8 |
mov ecx,100 |
.sb_check_port: |
in al,dx |
test al,al ;is DSP port ready to be read? |
jns .sb_port_not_ready |
sub dl,4 |
in al,dx ;check for AAh response |
add dl,4 |
cmp al,0xAA |
jne .sb_port_not_ready |
.sb_card_found: |
and dl,0xF0 |
add dl,0xC |
sb_out 0xE1 ;get DSP version |
add dl,2 |
@@: |
in al,dx |
test al,al ;is DSP port ready to be read? |
jns @b |
sub dl,4 |
in al,dx ;get major version |
ror eax,16 |
add dl,4 |
@@: |
in al,dx |
test al,al ;is DSP port ready to be read? |
jns @b |
sub dl,4 |
in al,dx ;get minor version |
xor edx,edx |
mov dl,10 |
div dl |
ror eax,16 |
xor ah,ah |
mov [sb_DSP_version_int],eax ;for internal usage |
if DEBUG |
add [sb_DSP_version],eax |
end if |
ret |
.sb_port_not_ready: |
loop .sb_check_port ;100 retries (~100 microsec.) |
jmp .sb_detect_next_port |
endp |
;------------------------------------------------------------------------------- |
if DEBUG |
proc SysMsgBoardNum ;warning: destroys eax,ebx,ecx,esi |
mov ebx,eax |
mov ecx,8 |
mov esi,(number_to_out+1) |
.1: |
mov eax,ebx |
and eax,0xF |
add al,'0' |
cmp al,(10+'0') |
jb @f |
add al,('A'-'0'-10) |
@@: |
mov [esi+ecx],al |
shr ebx,4 |
loop .1 |
dec esi |
call SysMsgBoardStr |
ret |
endp |
end if |
;all initialized data place here |
align 4 |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
sb_base_port: dd 200h ;don't ask me why - see the code&docs |
sound_dma dd sb_dma_num |
;note that 4th DMA channel doesn't exist, it is used for cascade |
;plugging the first DMA controler to the second |
dma_table db 0x87,0x83,0x81,0x82,0xFF,0x8B,0x89,0x8A |
my_service db 'SOUND',0 ;max 16 chars include zero |
if DEBUG |
number_to_out db '0x00000000',13,10,0 |
msgInit db 'detecting hardware...',13,10,0 |
msgExit db 'exiting... May be some problems found?',13,10,0 |
msgPlay db 'start play',13,10,0 |
;msgStop db 'stop play',13,10,0 |
msgCallback db 'set_callback received from the mixer!',13,10 |
db 'callback handler is: ',0 |
msgErrAtchIRQ db 'failed to attach IRQ',(sb_irq_num+'0'),13,10 |
db 'owner',39,'s handler: ',0 |
msgSucAtchIRQ db 'succesfully attached IRQ',(sb_irq_num+'0') |
db ' as hardcoded',13,10,0 |
msgErrRsrvPorts db 'failed to reserve needed ports.',13,10 |
db 'Driver may work unstable',13,10,0 |
msgSetVol db 'DEV_SET_MASTERVOL call came',13,10,0 |
msgGetVol db 'DEV_GET_MASTERVOL call came',13,10,0 |
msgErrDMAsetup db 'failed to setup DMA - bad channel',13,10,0 |
;------------------------------------------------------------------------------- |
msgDSPFound db 'DSP found at port 2' |
label port_second_digit_num dword at $ |
db '00h',13,10,'DSP version ' |
sb_DSP_version: db '0.00 - SB' |
sb_DSP_description: db 32,32,32,32,13,10,0 |
;------------------------------------------------------------------------------- |
end if |
section '.data' data readable writable align 16 |
;all uninitialized data place here |
;pTempBuf rd 1 |
callback rd 1 |
int_flip_flop rd 1 |
sb_master_vol rd 1 |
sb_DSP_version_int rd 1 |
/kernel/branches/Kolibri-acpi/drivers/sb16/CONFIG.INC |
---|
0,0 → 1,50 |
;flags------------------------------------------------------------ |
DEBUG equ 1 ;show messages at debug board |
use_cli_sti equ 1 ;driver become more stable (theoretically) |
;constants-------------------------------------------------------- |
API_VERSION equ 0 ;debug |
OS_BASE equ 0x80000000 |
new_app_base equ 0x0 |
PROC_BASE equ (OS_BASE+0x080000) |
SB16Buffer equ (OS_BASE+0x2A0000) |
SB16_Status equ (OS_BASE+0x2B0000) |
DMAPage equ ((SB16Buffer-OS_BASE) shr 16) |
SB16Buffer0 equ SB16Buffer |
SB16Buffer1 equ (SB16Buffer+16384) |
SB16Buffer2 equ (SB16Buffer+(2*16384)) |
SB16Buffer3 equ (SB16Buffer+(3*16384)) |
sb_irq_num equ 5 ;default values for SB16, may be overrided by autodetect |
sb_dma_num equ 5 ;default values for SB16, may be overrided by autodetect |
small_buffer equ 32768 |
full_buffer equ 65536 |
sb_buffer_size equ small_buffer ; FIX ring buffer overlapped events issue; full_buffer |
__supported_buffer_sizes fix <small_buffer, full_buffer> |
if ~(sb_buffer_size in __supported_buffer_sizes) |
display 13,10,'unsupported buffer size was selected, check config.inc',13,10 |
stop |
end if |
sb_out_rate equ 48000 |
;time constant for cards older than SB16 |
sb_tc equ (256-(1000000/(sb_out_rate*2))) |
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 |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
/kernel/branches/Kolibri-acpi/drivers/sb16/README.TXT |
---|
0,0 → 1,72 |
Nable 21.05.2008. |
This driver is my contribution (or donation) to KolibriOS. This is provided |
AS IS in hope it'll be useful, but WITHOUT ANY WARRANTY! No responcibility |
for any hardware damage or data loss. Use at your own risk! |
;------------------------------------------------------------------------------- |
;Changelog: |
;------------------------------------------------------------------------------- |
v0.2 - DEV_SET(GET)_MASTERVOL functions are unlocked and implemented. |
v0.1 - first release. |
;------------------------------------------------------------------------------- |
;Tiny FAQ for sound driver by Nable for SB16 sound card. |
;------------------------------------------------------------------------------- |
;What is it?-------------------------------------------------------------------- |
As you may know there is a sound subsystem ('INFINITY') in KolibriOS. |
This subsystem includes mixer and separate interface for soundplayer |
program and driver, so player application don't need to know what soundcard |
is installed and how to cope with it, all work with card do the driver. |
Before this time there were drivers only for AC97 integrated sound, but I |
don't have such at home and if I would upgrade my computer with a newest |
hardware, with 100% probability integrated sound will be HD Codec, nowadays |
AC97 is not actual (2008 year is at calendar). But I'm not planning to upgrade |
my computer so much now (and in next 5-6 years), writing the driver for my PCI |
ESS Maestro1 card is difficult for me (may be some time later), so I decided |
to write a driver for SB16. At first it is easy, there are many working |
examples for DOS, there are heaps of good documentation and as an ISA device |
SB16 can be programmed through I/O ports (about 5 ports are used), that is |
more easy than PCI access. Now, enough lirics, lets go to physics :-) |
If you still don't understand what stuff is it, I'll tell this in brief: |
with this driver you can play MP3 and WAV music (using AC97SND player) and |
sounds (some games and DOSBOX can produce sound output through sound |
subsystem) in KolibriOS. |
;Yeah! I need sound in Kolibri and I have SB16 card. Whats then?---------------- |
At first copy my SOUND.OBJ to /sys/drivers at your Kolibri system. Note, |
that if you have AC97 card and it's driver started - then new driver won't |
run until reboot. Then run BOARD and go to 'user' tab. Then try to run |
AC97SND player. At BOARD you will see the following (if you had a proper |
card): |
|----------------------------| |
|detecting hardware... | <- detector startup message |
|DSP found at port 220h | <- if you have a proper card, it'll be |
|DSP version 4.13 - SB16 | autodetected. Numbers may be different. |
|failed to attach IRQ5 | <- don't mention. Old kernels reserve IRQ5 |
|owner's handler: 0x80D74284 | see below how to fix it. |
|----------------------------| |
At first, note that DSP version must be 4.xx or higher. Older cards are not |
supported in this first release, maybe some time later. If nothing detected |
but PNP/BIOS or some other OS detects your card - I'm sorry, it's perverted |
PNP card like OPTi16, that is like HD Codec - until you init it through |
PCI->ISA bridge (HD Codec of course through PCI->PCI bridge), map it, etc, |
you can't use it in any way. I'd rather write a PCI device driver, than |
for this extreme perversion. If your card detected and has a proper version |
but you see 'failed to attach IRQ' - delete stroke 'mov [irq_owner+4*5],1' from the |
file kernel.asm of your kernel source, save it, rebuild kernel, copy new |
kernel to /sys/ (did you rename 'kernel' to 'kernel.mnt'? You should do it), |
restart kernel (Ctrl+Alt+F12, Home). THE EASIER WAY IS TO USE A NEWER KERNEL, |
since SVN802 it's fixed. |
Now everything should be OK. |
;It works for a part of the second and then stops, but system doesn't hang------ |
Go to 'config.inc' of my driver and change 'sb_irq_num' value from 5 to 7. |
Then save, rebuild driver (compile 'sound.asm'), put 'sound' to /sys/drivers/ |
(you need to rename file 'sound' to 'sound.obj'), restart kernel and try again |
to produce sound. |
;------------------------------------------------------------------------------- |
Ask your questions at KolibriOS forum: board.kolibrios.org |
I'll try to answer you if possible. |
/kernel/branches/Kolibri-acpi/drivers/sb16/SB16.INC |
---|
0,0 → 1,297 |
;-------------------------------- |
; program dma |
;-------------------------------- |
sb_set_dma: |
mov ebx,[sound_dma] |
lea eax,[ebx+4] ;mask required channel |
cmp bl,4 |
ja .use_second_dma_controller |
jb @f |
.dma_setup_error: |
if DEBUG |
mov esi,msgErrDMAsetup |
call SysMsgBoardStr |
end if |
mov dword[esp],START.stop |
ret |
@@: |
if use_cli_sti |
cli ;here to minimize time with disabled ints |
end if |
out 0xA,al ;mask required channel |
xor eax,eax |
out 0xC,al ;clear byte pointer flip-flop register |
lea eax,[ebx+0x58] ;auto-init mode for channel (ebx) |
out 0xB,al ;DMA channel 0-3 mode register |
movzx edx,byte[ebx+dma_table] ;page register |
mov al,DMAPage |
out dx,al |
lea edx,[ebx*2] ;DMA channel 0-3 base address |
mov al,0 ;LSB is 0 |
out dx,al |
; mov al,0 ;MSB is 0 too |
out dx,al |
inc edx ;DMA channel 0-3 byte count |
mov al,((sb_buffer_size-1) and 0xff) |
out dx,al |
mov al,((sb_buffer_size-1) shr 8) ;it is the same |
out dx,al |
mov eax,ebx ;unmask DMA channel |
out 0xA,al |
if use_cli_sti |
sti |
end if |
ret |
.use_second_dma_controller: |
cmp bl,7 |
ja .dma_setup_error |
sub bl,4 |
sub al,4 |
if use_cli_sti |
cli ;here to minimize time with disabled ints |
end if |
out 0xD4,al ;mask required channel |
xor eax,eax |
out 0xD8,al ;clear byte pointer flip-flop register |
lea eax,[ebx+0x58] ;auto-init mode for channel (ebx+4) |
out 0xD6,al ;DMA channel 4-7 mode register |
movzx edx,byte[ebx+dma_table+4] ;page register |
mov al,DMAPage |
out dx,al |
lea edx,[ebx*4+0xC0] ;DMA channel 4-7 base address |
mov al,0 ;LSB is 0 ;for 16bit DMA this contains |
out dx,al ;A1-A8 lines of address bus, A0 is zero |
; mov al,0 ;MSB is 0 too ;for 16bit DMA this contains |
out dx,al ;A9-A16 lines of address bus |
inc edx |
inc edx ;DMA channel 4-7 16bit word count |
mov al,(((sb_buffer_size/2)-1) and 0xff) |
out dx,al |
mov al,(((sb_buffer_size/2)-1) shr 8) |
out dx,al |
mov eax,ebx ;unmask DMA channel |
out 0xD4,al |
if use_cli_sti |
sti |
end if |
ret |
;------------------------------------------------------------------------------- |
; out byte to SB DSP's write port |
;------------------------------------------------------------------------------- |
macro sb_out data_to_out { |
@@: |
in al,dx |
test al,al ;is DSP busy? |
js @b ;it's busy |
mov al,data_to_out ;it's free |
out dx,al |
} |
;------------------------------------------------------------------------------- |
; stop playing |
;------------------------------------------------------------------------------- |
proc sb_stop |
mov edx,[sb_base_port] |
add dl,0xC |
sb_out 0xD3 ;turn the speaker off |
sb_out 0xDA ;exit 8bit DMA |
sb_out 0xD9 ;exit 16bit DMA |
ret |
endp |
;------------------------------------------------------------------------------- |
; start playing |
;------------------------------------------------------------------------------- |
proc sb_play |
and [int_flip_flop],0 |
mov edx,[sb_base_port] |
add dl,0xC |
sb_out 0xD1 ;turn speaker on |
; sb_out 0x48 ;set DSP transfer size ;for older cards, not supported |
; ;in this version |
; mov ax,32767 ;(64k)/2-1 |
;@@: ;out the low byte... |
; in al,dx |
; test al,al ;is DSP busy? |
; js @b ;it's busy |
; out dx,al |
; mov al,ah ;...then the high byte |
;@@: |
; in al,dx |
; test al,al ;is DSP busy? |
; js @b ;it's busy |
; out dx,al |
; sb_out 0x1C ;auto-init 8bit playback |
; 0xBXh - 16 bit DMA mode |
; |||| |
sb_out 10110110b ;bCommand |
; |||| |
; |||+-reserved |
; ||+--turn FIFO on (0 for off) |
; |+---auto-init mode on (0 for off) |
; +----A/D: 0-output, 1-input |
; +------stereo on |
; |+-----unsigned (1 for signed) |
; || |
sb_out 00110000b ;bMode |
; || |||| |
; ---------reserved |
;wSize is a number of 16bit samples less 1. For auto-init mode each half |
;buffer is (64k)/2 bytes long and, obviously, contains ((64k)/2)/2 samples |
sb_out (((sb_buffer_size/2/2)-1) and 0xFF) ;wSize.LowByte |
sb_out (((sb_buffer_size/2/2)-1) shr 8) ;wSize.HighByte |
ret |
endp |
;------------------------------------------------------------------------------- |
; reset DSP |
;------------------------------------------------------------------------------- |
proc sb_reset |
and [int_flip_flop],0 |
mov edx,[sb_base_port] |
add dl,6 |
mov al,1 ;start DSP reset |
if use_cli_sti |
cli ;here to minimize time with disabled ints |
end if |
out dx,al |
mov ecx,40 ;wait at least 3 microsec. |
@@: |
in al,dx |
loop @b |
xor eax,eax ;stop DSP reset |
if use_cli_sti |
sti |
end if |
out dx,al |
ret |
endp |
;------------------------------------------------------------------------------- |
; set the rate for playing, enable stereo |
;------------------------------------------------------------------------------- |
proc sb_setup |
mov edx,[sb_base_port] |
add dl,0xC |
sb_out 40h ;set time constant, this is for old cards |
sb_out sb_tc |
sb_out 41h ;set sound rate, this can only SB16 |
sb_out (sb_out_rate shr 8) ;first high byte (MSB) |
sb_out (sb_out_rate and 0xff) ;then low byte (LSB) |
; mov al,0xE ;for older cards, not supported in this version |
; sub dl,(0xC-4) ;talk to SB's mixer |
; out dx,al ;select this register of the mixer |
; mov ecx,6 ;wait for the chip |
;@@: |
; in al,dx |
; loop @b |
; inc edx ;now read the data port |
; in al,dx |
; or al,22h ;turn on stereo |
; mov ah,al |
; mov al,0xE |
; dec edx ;talk to SB's mixer |
; out dx,al ;select this register of the mixer |
; mov ecx,6 ;wait for the chip |
;@@: |
; in al,dx |
; loop @b |
; inc edx ;now send data to the data port |
; mov al,ah |
; out dx,al |
; dec edx |
; mov ecx,35 ;wait for the chip |
;@@: |
; in al,dx |
; loop @b |
ret |
endp |
;------------------------------------------------------------------------------- |
; set master volume of SB mixer, note, not only SB16 but SBPro and older |
; this is the first step to more full support for hardware |
;------------------------------------------------------------------------------- |
;in: eax in range [-10000;0] - master volume for _both_ channels |
;note that x*3*17/2000 and x*3/2000*17 are not the same numbers, |
;because we count in integers |
proc sb_set_master_vol |
mov [sb_master_vol],eax |
add eax,10000 ;SB sound level rise from 0 to MAX_LEVEL |
lea eax,[eax+eax*2] ;*3 |
mov ebx,2000 ;divisor |
xor edx,edx |
cmp byte[sb_DSP_version_int],4 |
jae @f ;SBPro's MAX_LEVEL is 15, but we *11 because |
;volume byte looks like that: 0xLR, where L - left |
;channel volume, R - right, 0<=R,L<=15 |
div ebx |
imul eax,17 |
mov edx,[sb_base_port] |
push eax ;here for optimisation |
add dl,4 |
mov al,0x22 ;write mixer register 0x22 |
out dx,al |
in al,dx ;wait for the chip ;6 |
in al,dx ;wait for the chip ;5 |
in al,dx ;wait for the chip ;4 |
in al,dx ;wait for the chip ;3 |
in al,dx ;wait for the chip ;2 |
in al,dx ;wait for the chip ;1 |
pop eax ;go! |
inc edx |
out dx,al |
ret |
@@: ;SB16's MAX_LEVEL is 255 |
imul eax,17 |
div ebx |
mov edx,[sb_base_port] |
push eax ;here for optimisation |
add dl,4 |
mov al,0x30 ;left speaker |
out dx,al |
pop eax ;<--+ |
inc edx ; \/ |
push eax ;here for optimisation |
out dx,al ;write |
dec edx |
mov al,0x31 ;right speaker |
out dx,al |
pop eax |
inc edx |
out dx,al ;write |
ret |
endp |
;------------------------------------------------------------------------------- |
/kernel/branches/Kolibri-acpi/drivers/infinity.asm |
---|
0,0 → 1,1306 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; Serge 2006-2008 |
; email: infinity_sound@mail.ru |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'main.inc' |
include 'imports.inc' |
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 |
public START |
public service_proc |
public version |
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 |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .exit |
stdcall GetService, szSound |
test eax, eax |
jz .fail |
mov [hSound], eax |
stdcall 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 |
stdcall RegService, szInfinity, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
.exit: |
xor eax, eax |
ret |
.out_of_mem: |
if DEBUG |
mov esi, msgMem |
call SysMsgBoardStr |
end if |
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, [eax] |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
cmp eax, SND_CREATE_BUFF |
jne @F |
mov ebx, [edi+input] |
stdcall CreateBuffer,[ebx],[ebx+4] |
mov edi, [ioctl] |
mov ecx, [edi+output] |
mov ecx, [ecx] |
mov [ecx], ebx |
ret |
@@: |
mov ebx, [edi+input] |
mov edx, [ebx] |
cmp [edx+STREAM.magic], 'WAVE' |
jne .fail |
cmp [edx+STREAM.size], STREAM_SIZE |
jne .fail |
cmp eax, SND_DESTROY_BUFF |
jne @F |
mov eax, edx |
call DestroyBuffer ;edx= stream |
ret |
@@: |
cmp eax, SND_SETFORMAT |
jne @F |
stdcall SetFormat,edx,[ebx+4] |
ret |
@@: |
cmp eax, SND_GETFORMAT |
jne @F |
movzx eax, word [edx+STREAM.format] |
mov ecx, [edi+output] |
mov ecx, [ecx] |
mov [ecx], eax |
xor eax, eax |
ret |
@@: |
cmp eax, SND_RESET |
jne @F |
stdcall ResetBuffer,edx,[ebx+4] |
ret |
@@: |
cmp eax, SND_SETPOS |
jne @F |
stdcall SetBufferPos,edx,[ebx+4] |
ret |
@@: |
cmp eax, SND_GETPOS |
jne @F |
stdcall GetBufferPos, edx |
mov edi, [ioctl] |
mov ecx, [edi+output] |
mov ecx, [ecx] |
mov [ecx], ebx |
ret |
@@: |
cmp eax, SND_SETBUFF |
jne @F |
mov eax, [ebx+4] |
stdcall set_buffer, edx,eax,[ebx+8],[ebx+12] |
ret |
@@: |
cmp eax, SND_SETVOLUME |
jne @F |
stdcall SetBufferVol,edx,[ebx+4],[ebx+8] |
ret |
@@: |
cmp eax, SND_GETVOLUME |
jne @F |
mov eax, [edi+output] |
mov ecx, [eax] |
mov eax, [eax+4] |
stdcall GetBufferVol,edx,ecx,eax |
ret |
@@: |
cmp eax, SND_SETPAN |
jne @F |
stdcall SetBufferPan,edx,[ebx+4] |
ret |
@@: |
cmp eax, SND_GETPAN |
jne @F |
mov eax, [edx+STREAM.pan] |
mov ebx, [edi+output] |
mov ebx, [ebx] |
mov [ebx], eax |
xor eax, eax |
ret |
@@: |
cmp eax, SND_OUT |
jne @F |
mov eax, [ebx+4] |
stdcall wave_out, edx,eax,[ebx+8] |
ret |
@@: |
cmp eax, SND_PLAY |
jne @F |
stdcall play_buffer, edx,[ebx+4] |
ret |
@@: |
cmp eax, SND_STOP |
jne @F |
stdcall stop_buffer, edx |
ret |
@@: |
cmp eax, SND_GETBUFFSIZE |
jne @F |
mov eax, [edx+STREAM.in_size] |
mov ecx, [edi+output] |
mov ecx, [ecx] |
mov [ecx], eax |
xor eax, eax |
ret |
@@: |
cmp eax, SND_GETFREESPACE |
jne @F |
test [edx+STREAM.format], PCM_OUT |
jz .fail |
mov ebx, [edx+STREAM.in_free] |
mov ecx, [edi+output] |
mov [ecx], ebx |
xor eax, eax |
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 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: |
call GetPid |
mov ebx, eax |
mov eax, STREAM_SIZE |
call 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 |
stdcall 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 |
; sub ecx, 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 |
stdcall 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: |
stdcall AllocKernelSpace, dword 128*1024 |
mov edi, [str] |
mov [edi+STREAM.out_base], eax |
mov [edi+STREAM.out_wp], eax |
mov [edi+STREAM.out_rp], eax |
mov [edi+STREAM.out_count], 0 |
add eax, 64*1024 |
mov [edi+STREAM.out_top], eax |
stdcall AllocPages, dword 64/4 |
mov edi, [str] |
mov ebx, [edi+STREAM.out_base] |
mov ecx, 16 |
or eax, PG_SW |
push eax |
push ebx |
call CommitPages ;eax, ebx, ecx |
mov ecx, 16 |
pop ebx |
pop eax |
add ebx, 64*1024 |
call 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 |
call 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_SIZE |
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 |
stdcall KernelFree, [eax+STREAM.in_base] |
mov eax, [.handle] |
stdcall KernelFree, [eax+STREAM.out_base] |
pop eax ;restore stack |
call 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 |
call 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] |
call WaitEvent ;eax ebx |
jmp .main_loop |
.done: |
cmp [state_saved], 1 |
jne @F |
lea eax, [fpu_state+15] |
and eax, -16 |
call 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 ;reserved reset and clear input buffer |
; RESET_OUTPUT equ 2 ;reserved 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 |
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 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] |
movq mm0, qword [l_vol] |
pminsw mm0, qword [vol_max] |
pmaxsw mm0, qword [vol_min] |
movq qword [l_vol], mm0 |
movq qword [edx+STREAM.l_vol], mm0 |
movd mm1,[pan] |
pminsw mm1, qword [pan_max] |
pmaxsw mm1, qword [vol_min] |
movd [edx+STREAM.pan], mm1 |
cmp word [edx+STREAM.pan], 0 |
jl @F |
psubsw mm0,mm1 |
pminsw mm0, qword [vol_max] |
pmaxsw mm0, qword [vol_min] |
movd [l_vol],mm0 |
jmp .calc_amp |
@@: |
punpckhdq mm0,mm0 |
paddsw mm0,mm1 |
pminsw mm0, qword [vol_max] |
pmaxsw mm0, qword [vol_min] |
movd [r_vol], mm0 |
.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] |
call 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 |
; stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0 |
mov eax, [edx+STREAM.notify_event] |
mov ebx, [edx+STREAM.notify_id] |
call 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_SIZE |
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_SIZE |
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] |
stdcall 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] |
stdcall 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 |
version dd (5 shl 16) or SOUND_VERSION |
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 |
section '.data' data readable writable align 16 |
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:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/drivers/mixer.asm |
---|
0,0 → 1,1262 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2006-2008. 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 |
call FpuSave |
call update_stream |
.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 |
call 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_stream |
locals |
stream_index dd ? |
event rd 6 |
endl |
mov [stream_index], 0 |
.l1: |
mov edx, [stream_index] |
mov esi, [play_list+edx*4] |
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 |
call 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 |
call 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:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/drivers/uart.asm |
---|
0,0 → 1,976 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
API_VERSION equ 0 |
UART_VERSION equ API_VERSION |
PG_SW equ 0x003 |
page_tabs equ 0xFDC00000 ;hack |
OS_BASE equ 0x80000000 |
SLOT_BASE equ (OS_BASE+0x0080000) |
TASK_COUNT equ (OS_BASE+0x0003004) |
CURRENT_TASK equ (OS_BASE+0x0003000) |
struc APPOBJ ;common object header |
{ |
.magic dd ? ; |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
}; |
virtual at 0 |
APPOBJ APPOBJ |
end virtual |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
DEBUG equ 1 |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
THR_REG equ 0; x3f8 ;transtitter/reciever |
IER_REG equ 1; x3f9 ;interrupt enable |
IIR_REG equ 2; x3fA ;interrupt info |
LCR_REG equ 3; x3FB ;line control |
MCR_REG equ 4; x3FC ;modem control |
LSR_REG equ 5; x3FD ;line status |
MSR_REG equ 6; x3FE ;modem status |
LCR_5BIT equ 0x00 |
LCR_6BIT equ 0x01 |
LCR_7BIT equ 0x02 |
LCR_8BIT equ 0x03 |
LCR_STOP_1 equ 0x00 |
LCR_STOP_2 equ 0x04 |
LCR_PARITY equ 0x08 |
LCR_EVEN equ 0x10 |
LCR_STICK equ 0x20 |
LCR_BREAK equ 0x40 |
LCR_DLAB equ 0x80 |
LSR_DR equ 0x01 ;data ready |
LSR_OE equ 0x02 ;overrun error |
LSR_PE equ 0x04 ;parity error |
LSR_FE equ 0x08 ;framing error |
LSR_BI equ 0x10 ;break interrupt |
LSR_THRE equ 0x20 ;transmitter holding empty |
LSR_TEMT equ 0x40 ;transmitter empty |
LSR_FER equ 0x80 ;FIFO error |
FCR_EFIFO equ 0x01 ;enable FIFO |
FCR_CRB equ 0x02 ;clear reciever FIFO |
FCR_CXMIT equ 0x04 ;clear transmitter FIFO |
FCR_RDY equ 0x08 ;set RXRDY and TXRDY pins |
FCR_FIFO_1 equ 0x00 ;1 byte trigger |
FCR_FIFO_4 equ 0x40 ;4 bytes trigger |
FCR_FIFO_8 equ 0x80 ;8 bytes trigger |
FCR_FIFO_14 equ 0xC0 ;14 bytes trigger |
IIR_INTR equ 0x01 ;1= no interrupts |
IER_RDAI equ 0x01 ;reciever data interrupt |
IER_THRI equ 0x02 ;transmitter empty interrupt |
IER_LSI equ 0x04 ;line status interrupt |
IER_MSI equ 0x08 ;modem status interrupt |
MCR_DTR equ 0x01 ;0-> DTR=1, 1-> DTR=0 |
MCR_RTS equ 0x02 ;0-> RTS=1, 1-> RTS=0 |
MCR_OUT_1 equ 0x04 ;0-> OUT1=1, 1-> OUT1=0 |
MCR_OUT_2 equ 0x08 ;0-> OUT2=1, 1-> OUT2=0; enable intr |
MCR_LOOP equ 0x10 ;lopback mode |
MSR_DCTS equ 0x01 ;delta clear to send |
MSR_DDSR equ 0x02 ;delta data set redy |
MSR_TERI equ 0x04 ;trailinh edge of ring |
MSR_DDCD equ 0x08 ;delta carrier detect |
RATE_50 equ 0 |
RATE_75 equ 1 |
RATE_110 equ 2 |
RATE_134 equ 3 |
RATE_150 equ 4 |
RATE_300 equ 5 |
RATE_600 equ 6 |
RATE_1200 equ 7 |
RATE_1800 equ 8 |
RATE_2000 equ 9 |
RATE_2400 equ 10 |
RATE_3600 equ 11 |
RATE_4800 equ 12 |
RATE_7200 equ 13 |
RATE_9600 equ 14 |
RATE_19200 equ 15 |
RATE_38400 equ 16 |
RATE_57600 equ 17 |
RATE_115200 equ 18 |
COM_1 equ 1 |
COM_2 equ 2 |
COM_3 equ 3 |
COM_4 equ 4 |
COM_MAX equ 2 ;only two port supported |
COM_1_BASE equ 0x3F8 |
COM_2_BASE equ 0x2F8 |
COM_1_IRQ equ 4 |
COM_2_IRQ equ 3 |
UART_CLOSED equ 0 |
UART_TRANSMIT equ 1 |
UART_STOP equ 2 |
struc UART |
{ |
.lock dd ? |
.base dd ? |
.lcr_reg dd ? |
.mcr_reg dd ? |
.rate dd ? |
.mode dd ? |
.state dd ? |
.rcvr_buff dd ? |
.rcvr_rp dd ? |
.rcvr_wp dd ? |
.rcvr_count dd ? |
.rcvr_top dd ? |
.xmit_buff dd ? |
.xmit_rp dd ? |
.xmit_wp dd ? |
.xmit_count dd ? |
.xmit_free dd ? |
.xmit_top dd ? |
} |
virtual at 0 |
UART UART |
end virtual |
UART_SIZE equ 18*4 |
struc CONNECTION |
{ |
.magic dd ? ;'CNCT' |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
.id dd ? ;reserved |
.uart dd ? ;uart pointer |
} |
virtual at 0 |
CONNECTION CONNECTION |
end virtual |
CONNECTION_SIZE equ 7*4 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
mov eax, UART_SIZE |
call Kmalloc |
test eax, eax |
jz .fail |
mov [com1], eax |
mov edi, eax |
mov ecx, UART_SIZE/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [com1] |
mov [eax+UART.base], COM_1_BASE |
stdcall AllocKernelSpace, 32768 |
mov edi, [com1] |
mov edx, eax |
mov [edi+UART.rcvr_buff], eax |
add eax, 8192 |
mov [edi+UART.rcvr_top], eax |
add eax, 8192 |
mov [edi+UART.xmit_buff], eax |
add eax, 8192 |
mov [edi+UART.xmit_top], eax |
call AllocPage |
test eax, eax |
jz .fail |
shr edx, 12 |
or eax, PG_SW |
mov [page_tabs+edx*4], eax |
mov [page_tabs+edx*4+8], eax |
call AllocPage |
test eax, eax |
jz .fail |
or eax, PG_SW |
mov [page_tabs+edx*4+4], eax |
mov [page_tabs+edx*4+12], eax |
call AllocPage |
test eax, eax |
jz .fail |
or eax, PG_SW |
mov [page_tabs+edx*4+16], eax |
mov [page_tabs+edx*4+24], eax |
call AllocPage |
test eax, eax |
jz .fail |
or eax, PG_SW |
mov [page_tabs+edx*4+20], eax |
mov [page_tabs+edx*4+28], eax |
mov eax, [edi+UART.rcvr_buff] |
invlpg [eax] |
invlpg [eax+0x1000] |
invlpg [eax+0x2000] |
invlpg [eax+0x3000] |
invlpg [eax+0x4000] |
invlpg [eax+0x5000] |
invlpg [eax+0x6000] |
invlpg [eax+0x7000] |
mov eax, edi |
call uart_reset.internal ;eax= uart |
stdcall AttachIntHandler, COM_1_IRQ, com_1_isr, dword 0 |
stdcall RegService, sz_uart_srv, service_proc |
ret |
.fail: |
.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 |
SRV_GETVERSION equ 0 |
PORT_OPEN equ 1 |
PORT_CLOSE equ 2 |
PORT_RESET equ 3 |
PORT_SETMODE equ 4 |
PORT_GETMODE equ 5 |
PORT_SETMCR equ 6 |
PORT_GETMCR equ 7 |
PORT_READ equ 8 |
PORT_WRITE equ 9 |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov ebx, [ioctl] |
mov eax, [ebx+io_code] |
cmp eax, PORT_WRITE |
ja .fail |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [ebx+output] |
cmp [ebx+out_size], 4 |
jne .fail |
mov [eax], dword UART_VERSION |
xor eax, eax |
ret |
@@: |
cmp eax, PORT_OPEN |
jne @F |
cmp [ebx+out_size], 4 |
jne .fail |
mov ebx, [ebx+input] |
mov eax, [ebx] |
call uart_open |
mov ebx, [ioctl] |
mov ebx, [ebx+output] |
mov [ebx], ecx |
ret |
@@: |
mov esi, [ebx+input] ;input buffer |
mov edi, [ebx+output] |
call [uart_func+eax*4] |
ret |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
; param |
; esi= input buffer |
; +0 connection |
; |
; retval |
; eax= error code |
align 4 |
uart_reset: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
mov eax, [eax+CONNECTION.uart] |
test eax, eax |
jz .fail |
; set mode 2400 bod 8-bit |
; disable DTR & RTS |
; clear FIFO |
; clear pending interrupts |
; |
; param |
; eax= uart |
align 4 |
.internal: |
mov esi, eax |
mov [eax+UART.state], UART_CLOSED |
mov edx, [eax+UART.base] |
add edx, MCR_REG |
xor eax, eax |
out dx, al ;clear DTR & RTS |
mov eax, esi |
mov ebx, RATE_2400 |
mov ecx, LCR_8BIT+LCR_STOP_1 |
call uart_set_mode.internal |
mov edx, [esi+UART.base] |
add edx, IIR_REG |
mov eax,FCR_EFIFO+FCR_CRB+FCR_CXMIT+FCR_FIFO_14 |
out dx, al |
.clear_RB: |
mov edx, [esi+UART.base] |
add edx, LSR_REG |
in al, dx |
test eax, LSR_DR |
jz @F |
mov edx, [esi+UART.base] |
in al, dx |
jmp .clear_RB |
@@: |
mov edx, [esi+UART.base] |
add edx, IER_REG |
mov eax,IER_RDAI+IER_THRI+IER_LSI |
out dx, al |
.clear_IIR: |
mov edx, [esi+UART.base] |
add edx, IIR_REG |
in al, dx |
test al, IIR_INTR |
jnz .done |
shr eax, 1 |
and eax, 3 |
jnz @F |
mov edx, [esi+UART.base] |
add edx, MSR_REG |
in al, dx |
jmp .clear_IIR |
@@: |
cmp eax, 1 |
je .clear_IIR |
cmp eax, 2 |
jne @F |
mov edx, [esi+UART.base] |
in al, dx |
jmp .clear_IIR |
@@: |
mov edx, [esi+UART.base] |
add edx, LSR_REG |
in al, dx |
jmp .clear_IIR |
.done: |
mov edi, [esi+UART.rcvr_buff] |
mov ecx, 8192/4 |
xor eax, eax |
mov [esi+UART.rcvr_rp], edi |
mov [esi+UART.rcvr_wp], edi |
mov [esi+UART.rcvr_count], eax |
cld |
rep stosd |
mov edi, [esi+UART.xmit_buff] |
mov ecx, 8192/4 |
mov [esi+UART.xmit_rp], edi |
mov [esi+UART.xmit_wp], edi |
mov [esi+UART.xmit_count], eax |
mov [esi+UART.xmit_free], 8192 |
rep stosd |
ret ;eax= 0 |
.fail: |
or eax, -1 |
ret |
; param |
; esi= input buffer |
; +0 connection |
; +4 rate |
; +8 mode |
; |
; retval |
; eax= error code |
align 4 |
uart_set_mode: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
mov eax, [eax+CONNECTION.uart] |
test eax, eax |
jz .fail |
mov ebx, [esi+4] |
mov ecx, [esi+8] |
; param |
; eax= uart |
; ebx= baud rate |
; ecx= mode |
align 4 |
.internal: |
cmp ebx, RATE_115200 |
ja .fail |
cmp ecx, LCR_BREAK |
jae .fail |
mov [eax+UART.rate], ebx |
mov [eax+UART.mode], ecx |
mov esi, eax |
mov bx, [divisor+ebx*2] |
mov edx, [esi+UART.base] |
push edx |
add edx, LCR_REG |
in al, dx |
or al, 0x80 |
out dx, al |
pop edx |
mov al, bl |
out dx, al |
inc dx |
mov al, bh |
out dx, al |
add edx, LCR_REG-1 |
mov eax, ecx |
out dx, al |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
; param |
; esi= input buffer |
; +0 connection |
; +4 modem control reg valie |
; |
; retval |
; eax= error code |
align 4 |
uart_set_mcr: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
mov eax, [eax+CONNECTION.uart] |
test eax, eax |
jz .fail |
mov ebx, [esi+4] |
mov [eax+UART.mcr_reg], ebx |
mov edx, [eax+UART.base] |
add edx, MCR_REG |
mov al, bl |
out dx, al |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
; param |
; eax= port |
; |
; retval |
; ecx= connection |
; eax= error code |
align 4 |
uart_open: |
dec eax |
cmp eax, COM_MAX |
jae .fail |
mov esi, [com1+eax*4] ;uart |
push esi |
.do_wait: |
cmp dword [esi+UART.lock],0 |
je .get_lock |
; call change_task |
jmp .do_wait |
.get_lock: |
mov eax, 1 |
xchg eax, [esi+UART.lock] |
test eax, eax |
jnz .do_wait |
mov eax, esi ;uart |
call uart_reset.internal |
mov ebx, [CURRENT_TASK] |
shl ebx, 5 |
mov ebx, [CURRENT_TASK+ebx+4] |
mov eax, CONNECTION_SIZE |
call CreateObject |
pop esi ;uart |
test eax, eax |
jz .fail |
mov [eax+APPOBJ.magic], 'CNCT' |
mov [eax+APPOBJ.destroy], uart_close.destroy |
mov [eax+CONNECTION.uart], esi |
mov ecx, eax |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
restore .uart |
; param |
; esi= input buffer |
align 4 |
uart_close: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
.destroy: |
push [eax+CONNECTION.uart] |
call DestroyObject ;eax= object |
pop eax ;eax= uart |
test eax, eax |
jz .fail |
mov [eax+UART.state], UART_CLOSED |
mov [eax+UART.lock], 0 ;release port |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
; param |
; eax= uart |
; ebx= baud rate |
align 4 |
set_rate: |
cmp ebx, RATE_115200 |
ja .fail |
mov [eax+UART.rate], ebx |
mov bx, [divisor+ebx*2] |
mov edx, [eax+UART.base] |
add edx, LCR_REG |
in al, dx |
push eax |
or al, 0x80 |
out dx, al |
sub edx, LCR_REG |
mov al, bl |
out dx, al |
inc edx |
mov al, bh |
out dx, al |
pop eax |
add edx, LCR_REG-1 |
out dx, al |
.fail: |
ret |
; param |
; ebx= uart |
align 4 |
transmit: |
push esi |
push edi |
mov edx, [ebx+UART.base] |
pushfd |
cli |
mov esi, [ebx+UART.xmit_rp] |
mov ecx, [ebx+UART.xmit_count] |
test ecx, ecx |
je .stop |
cmp ecx, 16 |
jbe @F |
mov ecx, 16 |
@@: |
sub [ebx+UART.xmit_count], ecx |
add [ebx+UART.xmit_free], ecx |
cld |
@@: |
lodsb |
out dx, al |
dec ecx |
jnz @B |
cmp esi,[ebx+UART.xmit_top] |
jb @F |
sub esi, 8192 |
@@: |
mov [ebx+UART.xmit_rp], esi |
cmp [ebx+UART.xmit_count], 0 |
je .stop |
mov [ebx+UART.state], UART_TRANSMIT |
jmp @F |
.stop: |
mov [ebx+UART.state], UART_STOP |
@@: |
popfd |
pop edi |
pop esi |
ret |
; param |
; esi= input buffer |
; +0 connection |
; +4 dst buffer |
; +8 dst size |
; edi= output buffer |
; +0 bytes read |
; retval |
; eax= error code |
align 4 |
uart_read: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
mov eax, [eax+CONNECTION.uart] |
test eax, eax |
jz .fail |
mov ebx, [esi+8] ;dst size |
mov ecx, [eax+UART.rcvr_count] |
cmp ecx, ebx |
jbe @F |
mov ecx, ebx |
@@: |
mov [edi], ecx ;bytes read |
test ecx, ecx |
jz .done |
push ecx |
mov edi, [esi+4] ;dst |
mov esi, [eax+UART.rcvr_rp] |
cld |
rep movsb |
pop ecx |
cmp esi, [eax+UART.rcvr_top] |
jb @F |
sub esi, 8192 |
@@: |
mov [eax+UART.rcvr_rp], esi |
sub [eax+UART.rcvr_count], ecx |
.done: |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
; param |
; esi= input buffer |
; +0 connection |
; +4 src buffer |
; +8 src size |
; |
; retval |
; eax= error code |
align 4 |
uart_write: |
mov eax, [esi] |
cmp [eax+APPOBJ.magic], 'CNCT' |
jne .fail |
cmp [eax+APPOBJ.destroy], uart_close.destroy |
jne .fail |
mov eax, [eax+CONNECTION.uart] |
test eax, eax |
jz .fail |
mov ebx, [esi+4] |
mov edx, [esi+8] |
; param |
; eax= uart |
; ebx= src |
; edx= count |
align 4 |
.internal: |
mov esi, ebx |
mov edi, [eax+UART.xmit_wp] |
.write: |
test edx, edx |
jz .fail |
.wait: |
cmp [eax+UART.xmit_free], 0 |
jne .fill |
cmp [eax+UART.state], UART_TRANSMIT |
je .wait |
mov ebx, eax |
push edx |
call transmit |
pop edx |
mov eax, ebx |
jmp .write |
.fill: |
mov ecx, [eax+UART.xmit_free] |
cmp ecx, edx |
jbe @F |
mov ecx, edx |
@@: |
push ecx |
cld |
rep movsb |
pop ecx |
sub [eax+UART.xmit_free], ecx |
add [eax+UART.xmit_count], ecx |
sub edx, ecx |
jnz .wait |
.done: |
cmp edi, [eax+UART.xmit_top] |
jb @F |
sub edi, 8192 |
@@: |
mov [eax+UART.xmit_wp], edi |
cmp [eax+UART.state], UART_TRANSMIT |
je @F |
mov ebx, eax |
call transmit |
@@: |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
align 4 |
com_2_isr: |
mov ebx, [com2] |
jmp com_1_isr.get_info |
align 4 |
com_1_isr: |
mov ebx, [com1] |
.get_info: |
mov edx, [ebx+UART.base] |
add edx, IIR_REG |
in al, dx |
test al, IIR_INTR |
jnz .done |
shr eax, 1 |
and eax, 3 |
call [isr_action+eax*4] |
jmp .get_info |
.done: |
ret |
align 4 |
isr_line: |
mov edx, [ebx+UART.base] |
add edx, LSR_REG |
in al, dx |
ret |
align 4 |
isr_recieve: |
mov esi, [ebx+UART.base] |
add esi, LSR_REG |
mov edi, [ebx+UART.rcvr_wp] |
xor ecx, ecx |
cld |
.read: |
mov edx, esi |
in al, dx |
test eax, LSR_DR |
jz .done |
mov edx, [ebx+UART.base] |
in al, dx |
stosb |
inc ecx |
jmp .read |
.done: |
cmp edi, [ebx+UART.rcvr_top] |
jb @F |
sub edi, 8192 |
@@: |
mov [ebx+UART.rcvr_wp], edi |
add [ebx+UART.rcvr_count], ecx |
ret |
align 4 |
isr_modem: |
mov edx, [ebx+UART.base] |
add edx, MSR_REG |
in al, dx |
ret |
align 4 |
divisor dw 2304, 1536, 1047, 857, 768, 384 |
dw 192, 96, 64, 58, 48, 32 |
dw 24, 16, 12, 6, 3, 2, 1 |
align 4 |
uart_func dd 0 ;SRV_GETVERSION |
dd 0 ;PORT_OPEN |
dd uart_close ;PORT_CLOSE |
dd uart_reset ;PORT_RESET |
dd uart_set_mode ;PORT_SETMODE |
dd 0 ;PORT_GETMODE |
dd uart_set_mcr ;PORT_SETMODEM |
dd 0 ;PORT_GETMODEM |
dd uart_read ;PORT_READ |
dd uart_write ;PORT_WRITE |
isr_action dd isr_modem |
dd transmit |
dd isr_recieve |
dd isr_line |
version dd (5 shl 16) or (UART_VERSION and 0xFFFF) |
sz_uart_srv db 'UART',0 |
align 4 |
com1 rd 1 |
com2 rd 1 |
/kernel/branches/Kolibri-acpi/drivers/ensoniq.asm |
---|
0,0 → 1,1177 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;alpha version |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
REMAP_IRQ equ 0 |
;irq 0,1,2,8,12,13 íåäîñòóïíû |
; FEDCBA9876543210 |
VALID_IRQ equ 1100111011111000b |
ATTCH_IRQ equ 0000111010101000b |
IRQ_LINE equ 0 |
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_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 18h ; PCM output volume |
CODEC_EXT_AUDIO_REG equ 28h ; extended audio |
CODEC_EXT_AUDIO_CTRL_REG equ 2ah ; extended audio control |
CODEC_PCM_FRONT_DACRATE_REG equ 2ch ; PCM out sample rate |
CODEC_PCM_SURND_DACRATE_REG equ 2eh ; surround sound sample rate |
CODEC_PCM_LFE_DACRATE_REG equ 30h ; 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 |
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 ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
OS_BASE equ 0x80000000 |
SLOT_BASE equ OS_BASE+0x0080000 |
new_app_base equ 0 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov esi, msgDetect |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi,[ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call SysMsgBoardStr |
end if |
call init_controller |
test eax, eax |
jz .fail |
jmp .fail ;force fail |
if DEBUG |
mov esi, msgInitCodec |
call SysMsgBoardStr |
end if |
call init_codec |
test eax, eax |
jz .fail |
if DEBUG |
mov esi, [codec.ac_vendor_ids] |
call SysMsgBoardStr |
mov esi, [codec.chip_ids] |
call SysMsgBoardStr |
end if |
call reset_controller |
call setup_codec |
mov esi, msgPrimBuff |
call SysMsgBoardStr |
call create_primary_buff |
mov eax, VALID_IRQ |
mov ebx, [ctrl.int_line] |
mov esi, msgInvIRQ |
bt eax, ebx |
jnc .fail |
mov eax, ATTCH_IRQ |
mov esi, msgAttchIRQ |
bt eax, ebx |
jnc .fail |
stdcall AttachIntHandler, ebx, ac97_irq, dword 0 |
stdcall RegService, sz_sound_srv, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
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, DEV_PLAY |
jne @F |
if DEBUG |
mov esi, msgPlay |
call SysMsgBoardStr |
end if |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call 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 |
; mov esi, msgIRQ |
; call SysMsgBoardStr |
; end if |
cmp [ctrl.user_callback], 0 |
je @f |
stdcall [ctrl.user_callback], ebx |
@@: |
ret |
.skip: |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x11 ;0x1D |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc create_primary_buff |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call 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 |
call 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 |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall 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 ebx, 0x1274 |
jne @F |
mov [ctrl.vendor_ids], msgEnsoniq |
ret |
@@: |
mov [ctrl.vendor_ids], 0 ;something wrong ? |
ret |
.err: |
xor eax, eax |
ret |
endp |
align 4 |
proc init_controller |
mov esi, msgPCIcmd |
call SysMsgBoardStr |
stdcall 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 |
call dword2str |
call SysMsgBoardStr |
mov esi, msgIObase |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
; and eax, -16 |
mov [ctrl.ctrl_io_base], eax |
call dword2str |
call SysMsgBoardStr |
mov esi, msgIRQline |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C |
and eax, 0xFF |
mov [ctrl.int_line], eax |
call dword2str |
call SysMsgBoardStr |
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 |
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 |
call SysMsgBoardStr |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
test eax, CTRL_ST_CREADY |
jnz .ready |
call reset_codec |
and eax, eax |
jz .err |
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 edx, CODEC_REG_POWERDOWN |
call [ctrl.codec_read16] |
and eax, 0x0F |
cmp eax, 0x0F |
jz .ready |
mov eax, 5000 ; wait 5 ms |
call StallExec |
sub [counter] , 1 |
jnz .wait |
.err: |
xor eax, eax ; timeout error |
ret |
.ready: |
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 |
call SysMsgBoardStr |
end if |
xor eax, eax ; timeout error |
ret |
.ok: |
if DEBUG |
mov esi, msgResetOk |
call 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 |
call SysMsgBoardStr |
end if |
mov [counter], 10 ; total 10*100 ms = 1s |
.wait: |
mov eax, 100000 ; wait 100 ms |
call StallExec |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
test eax, 4 |
jz .ok |
sub [counter], 1 |
jnz .wait |
if DEBUG |
mov esi, msgWRFail |
call SysMsgBoardStr |
end if |
stc |
ret |
.ok: |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
and eax, CTRL_ST_CREADY |
jz .fail |
clc |
ret |
.fail: |
stc |
ret |
endp |
align 4 |
proc cold_reset |
locals |
counter dd ? |
endl |
xor eax, eax |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
if DEBUG |
mov esi, msgCold |
call SysMsgBoardStr |
end if |
mov eax, 1000000 ; wait 1 s |
call StallExec |
mov eax, 2 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
mov [counter], 10 ; total 10*100 ms = 1s |
.wait: |
mov eax, 100000 ; wait 100 ms |
call StallExec |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
test eax, 4 |
jz .ok |
sub [counter], 1 |
jnz .wait |
if DEBUG |
mov esi, msgCRFail |
call SysMsgBoardStr |
end if |
stc |
ret |
.ok: |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
and eax, CTRL_ST_CREADY |
jz .fail |
clc |
ret |
.fail: |
stc |
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 |
codec_io_r16: |
add edx, [ctrl.codec_io_base] |
in ax, dx |
ret |
align 4 |
codec_io_w16: |
add edx, [ctrl.codec_io_base] |
out dx, ax |
ret |
align 4 |
ctrl_io_r8: |
add edx, [ctrl.ctrl_io_base] |
in al, dx |
ret |
align 4 |
ctrl_io_r16: |
add edx, [ctrl.ctrl_io_base] |
in ax, dx |
ret |
align 4 |
ctrl_io_r32: |
add edx, [ctrl.ctrl_io_base] |
in eax, dx |
ret |
align 4 |
ctrl_io_w8: |
add edx, [ctrl.ctrl_io_base] |
out dx, al |
ret |
align 4 |
ctrl_io_w16: |
add edx, [ctrl.ctrl_io_base] |
out dx, ax |
ret |
align 4 |
ctrl_io_w32: |
add edx, [ctrl.ctrl_io_base] |
out dx, eax |
ret |
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 (0x5000 shl 16)+0x1274,msgEnsoniq,set_ICH |
dd (0x5880 shl 16)+0x1274,msgVibra128,set_ICH |
dd 0 ;terminator |
version dd 0x00040004 |
msgEnsoniq db 'Ensonic 1371',13,10,0 |
msgVibra128 db 'Sound Blaster AudioPCI Vibra 128',13,10,0 |
sz_sound_srv db 'SOUND',0 |
msgDetect 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',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 |
msgIObase db 'IO base ',0 |
msgIRQline db 'IRQ line ',0 |
section '.data' data readable writable align 16 |
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:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/drivers/proc32.inc |
---|
0,0 → 1,268 |
; Macroinstructions for defining and calling procedures |
macro stdcall proc,[arg] ; directly call STDCALL procedure |
{ common |
if ~ arg eq |
reverse |
pushd arg |
common |
end if |
call proc } |
macro invoke proc,[arg] ; indirectly call STDCALL procedure |
{ common |
if ~ arg eq |
reverse |
pushd arg |
common |
end if |
call [proc] } |
macro ccall proc,[arg] ; directly call CDECL procedure |
{ common |
size@ccall = 0 |
if ~ arg eq |
reverse |
pushd arg |
size@ccall = size@ccall+4 |
common |
end if |
call proc |
if size@ccall |
add esp,size@ccall |
end if } |
macro cinvoke proc,[arg] ; indirectly call CDECL procedure |
{ common |
size@ccall = 0 |
if ~ arg eq |
reverse |
pushd arg |
size@ccall = size@ccall+4 |
common |
end if |
call [proc] |
if size@ccall |
add esp,size@ccall |
end if } |
macro proc [args] ; define procedure |
{ common |
match name params, args> |
\{ define@proc name,<params \} } |
prologue@proc equ prologuedef |
macro prologuedef procname,flag,parmbytes,localbytes,reglist |
{ if parmbytes | localbytes |
push ebp |
mov ebp,esp |
if localbytes |
sub esp,localbytes |
end if |
end if |
irps reg, reglist \{ push reg \} } |
epilogue@proc equ epiloguedef |
macro epiloguedef procname,flag,parmbytes,localbytes,reglist |
{ irps reg, reglist \{ reverse pop reg \} |
if parmbytes | localbytes |
leave |
end if |
if flag and 10000b |
retn |
else |
retn parmbytes |
end if } |
macro define@proc name,statement |
{ local params,flag,regs,parmbytes,localbytes,current |
if used name |
name: |
match =stdcall args, statement \{ params equ args |
flag = 11b \} |
match =stdcall, statement \{ params equ |
flag = 11b \} |
match =c args, statement \{ params equ args |
flag = 10001b \} |
match =c, statement \{ params equ |
flag = 10001b \} |
match =params, params \{ params equ statement |
flag = 0 \} |
virtual at ebp+8 |
match =uses reglist=,args, params \{ regs equ reglist |
params equ args \} |
match =regs =uses reglist, regs params \{ regs equ reglist |
params equ \} |
match =regs, regs \{ regs equ \} |
match =,args, params \{ defargs@proc args \} |
match =args@proc args, args@proc params \{ defargs@proc args \} |
parmbytes = $ - (ebp+8) |
end virtual |
name # % = parmbytes/4 |
all@vars equ |
current = 0 |
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \} |
macro locals |
\{ virtual at ebp-localbytes+current |
macro label . \\{ deflocal@proc .,:, \\} |
struc db [val] \\{ \common deflocal@proc .,db,val \\} |
struc dw [val] \\{ \common deflocal@proc .,dw,val \\} |
struc dp [val] \\{ \common deflocal@proc .,dp,val \\} |
struc dd [val] \\{ \common deflocal@proc .,dd,val \\} |
struc dt [val] \\{ \common deflocal@proc .,dt,val \\} |
struc dq [val] \\{ \common deflocal@proc .,dq,val \\} |
struc rb cnt \\{ deflocal@proc .,rb cnt, \\} |
struc rw cnt \\{ deflocal@proc .,rw cnt, \\} |
struc rp cnt \\{ deflocal@proc .,rp cnt, \\} |
struc rd cnt \\{ deflocal@proc .,rd cnt, \\} |
struc rt cnt \\{ deflocal@proc .,rt cnt, \\} |
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \} |
macro endl |
\{ purge label |
restruc db,dw,dp,dd,dt,dq |
restruc rb,rw,rp,rd,rt,rq |
restruc byte,word,dword,pword,tword,qword |
current = $-(ebp-localbytes) |
end virtual \} |
macro ret operand |
\{ match any, operand \\{ retn operand \\} |
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs> |
\\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \} |
macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2 |
end if \} } |
macro defargs@proc [arg] |
{ common |
if ~ arg eq |
forward |
local ..arg,current@arg |
match argname:type, arg |
\{ current@arg equ argname |
label ..arg type |
argname equ ..arg |
if dqword eq type |
dd ?,?,?,? |
else if tbyte eq type |
dd ?,?,? |
else if qword eq type | pword eq type |
dd ?,? |
else |
dd ? |
end if \} |
match =current@arg,current@arg |
\{ current@arg equ arg |
arg equ ..arg |
..arg dd ? \} |
common |
args@proc equ current@arg |
forward |
restore current@arg |
common |
end if } |
macro deflocal@proc name,def,[val] |
{ common |
match vars, all@vars \{ all@vars equ all@vars, \} |
all@vars equ all@vars name |
forward |
local ..var,..tmp |
..var def val |
match =?, val \{ ..tmp equ \} |
match any =dup (=?), val \{ ..tmp equ \} |
match tmp : value, ..tmp : val |
\{ tmp: end virtual |
initlocal@proc ..var,def value |
virtual at tmp\} |
common |
match first rest, ..var, \{ name equ first \} } |
macro initlocal@proc name,def |
{ virtual at name |
def |
size@initlocal = $ - name |
end virtual |
position@initlocal = 0 |
while size@initlocal > position@initlocal |
virtual at name |
def |
if size@initlocal - position@initlocal < 2 |
current@initlocal = 1 |
load byte@initlocal byte from name+position@initlocal |
else if size@initlocal - position@initlocal < 4 |
current@initlocal = 2 |
load word@initlocal word from name+position@initlocal |
else |
current@initlocal = 4 |
load dword@initlocal dword from name+position@initlocal |
end if |
end virtual |
if current@initlocal = 1 |
mov byte [name+position@initlocal],byte@initlocal |
else if current@initlocal = 2 |
mov word [name+position@initlocal],word@initlocal |
else |
mov dword [name+position@initlocal],dword@initlocal |
end if |
position@initlocal = position@initlocal + current@initlocal |
end while } |
macro endp |
{ purge ret,locals,endl |
finish@proc |
purge finish@proc |
restore regs@proc |
match all,args@proc \{ restore all \} |
restore args@proc |
match all,all@vars \{ restore all \} } |
macro local [var] |
{ common |
locals |
forward done@local equ |
match varname[count]:vartype, var |
\{ match =BYTE, vartype \\{ varname rb count |
restore done@local \\} |
match =WORD, vartype \\{ varname rw count |
restore done@local \\} |
match =DWORD, vartype \\{ varname rd count |
restore done@local \\} |
match =PWORD, vartype \\{ varname rp count |
restore done@local \\} |
match =QWORD, vartype \\{ varname rq count |
restore done@local \\} |
match =TBYTE, vartype \\{ varname rt count |
restore done@local \\} |
match =DQWORD, vartype \\{ label varname dqword |
rq count+count |
restore done@local \\} |
match , done@local \\{ virtual |
varname vartype |
end virtual |
rb count*sizeof.\#vartype |
restore done@local \\} \} |
match :varname:vartype, done@local:var |
\{ match =BYTE, vartype \\{ varname db ? |
restore done@local \\} |
match =WORD, vartype \\{ varname dw ? |
restore done@local \\} |
match =DWORD, vartype \\{ varname dd ? |
restore done@local \\} |
match =PWORD, vartype \\{ varname dp ? |
restore done@local \\} |
match =QWORD, vartype \\{ varname dq ? |
restore done@local \\} |
match =TBYTE, vartype \\{ varname dt ? |
restore done@local \\} |
match =DQWORD, vartype \\{ label varname dqword |
dq ?,? |
restore done@local \\} |
match , done@local \\{ varname vartype |
restore done@local \\} \} |
match ,done@local |
\{ var |
restore done@local \} |
common |
endl } |
Property changes: |
Added: svn:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/drivers/sceletone.asm |
---|
0,0 → 1,177 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;driver sceletone |
format MS COFF |
DEBUG equ 1 |
API_VERSION equ 0 ;debug |
include 'proc32.inc' |
include 'imports.inc' |
OS_BASE equ 0; |
new_app_base equ 0x60400000 |
PROC_BASE equ OS_BASE+0x0080000 |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
public START |
public service_proc |
public version |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
STRIDE equ 4 ;size of row in devices table |
SRV_GETVERSION equ 0 |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .exit |
.entry: |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
stdcall RegService, my_service, service_proc |
ret |
.fail: |
.exit: |
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 ebx, [ioctl] |
mov eax, [ebx+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [ebx+output] |
cmp [ebx+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
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 detect |
locals |
last_bus dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall 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, STRIDE |
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: |
xor eax, eax |
inc eax |
ret |
.err: |
xor eax, eax |
ret |
endp |
DEVICE_ID equ 1234; pci device id |
VENDOR_ID equ 5678; device vendor id |
;all initialized data place here |
align 4 |
devices dd (DEVICE_ID shl 16)+VENDOR_ID |
dd 0 ;terminator |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
my_service db 'MY_SERVICE',0 ;max 16 chars include zero |
msgInit db 'detect hardware...',13,10,0 |
msgPCI db 'PCI accsess not supported',13,10,0 |
msgFail db 'device not found',13,10,0 |
section '.data' data readable writable align 16 |
;all uninitialized data place here |
Property changes: |
Added: svn:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/drivers/sis.asm |
---|
0,0 → 1,1307 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
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 |
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 ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi,[ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call 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 |
call SysMsgBoardStr |
call create_primary_buff |
mov esi, msgDone |
call 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 |
call 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 |
stdcall AttachIntHandler, ebx, ac97_irq, dword 0 |
.reg: |
stdcall RegService, sz_sound_srv, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
.fail_msg: |
call 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 |
call SysMsgBoardStr |
end if |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call 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 |
call 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 |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call 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 |
call 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 |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall 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 [ctrl.vendor_ids], msg_SIS |
mov esi, [edi+8] |
mov [ctrl.ctrl_setup], esi |
ret |
.err: |
xor eax, eax |
ret |
endp |
align 4 |
proc init_controller |
stdcall 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 |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciStat |
call SysMsgBoardStr |
mov eax, [ctrl.pci_stat] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgMixIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
call dword2str |
call SysMsgBoardStr |
and eax,0xFFFE |
mov [ctrl.codec_io_base], eax |
mov esi, msgCtrlIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x14 |
call dword2str |
call SysMsgBoardStr |
and eax, 0xFFC0 |
mov [ctrl.ctrl_io_base], eax |
mov esi, msgMixMMIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x18 |
mov [ctrl.codec_mem_base], eax |
call dword2str |
call SysMsgBoardStr |
mov esi, msgCtrlMMIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x1C |
mov [ctrl.ctrl_mem_base], eax |
call dword2str |
call SysMsgBoardStr |
.default: |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C |
and eax, 0xFF |
@@: |
mov [ctrl.int_line], eax |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword 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 |
call SysMsgBoardStr |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
push eax |
call dword2str |
call SysMsgBoardStr |
pop eax |
cmp eax, 0xFFFFFFFF |
je .err |
test eax, CTRL_ST_CREADY |
jnz .done ;;;;;.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 |
call 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 |
call 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 |
call 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 |
call 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 |
call SysMsgBoardStr |
end if |
.fail: |
stc |
ret |
.ok: |
mov esi, msgControl |
call SysMsgBoardStr |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
push eax |
call dword2str |
call 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 |
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 |
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 |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
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 |
section '.data' data readable writable align 16 |
pcmout_bdl rq 32 |
buff_list rd 32 |
codec CODEC |
ctrl AC_CNTRL |
lpc_bus rd 1 |
civ_val rd 1 |
/kernel/branches/Kolibri-acpi/drivers/sound.asm |
---|
0,0 → 1,1473 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
format MS COFF |
DEBUG equ 1 |
include 'proc32.inc' |
include 'imports.inc' |
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 |
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 ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi,[ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call 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 |
call SysMsgBoardStr |
call create_primary_buff |
mov esi, msgDone |
call 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 |
call 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 |
stdcall AttachIntHandler, ebx, ac97_irq, dword 0 |
.reg: |
stdcall RegService, sz_sound_srv, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
.fail_msg: |
call 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 |
call SysMsgBoardStr |
end if |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call 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 |
call SysMsgBoardStr |
end if |
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] |
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 ;0x1D |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc create_primary_buff |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call 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 |
call 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 |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall 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_INTEL |
jne @F |
mov [ctrl.vendor_ids], msg_Intel |
ret |
@@: |
cmp edx, VID_NVIDIA |
jne @F |
mov [ctrl.vendor_ids], msg_NVidia |
ret |
@@: |
.err: |
xor eax, eax |
mov [ctrl.vendor_ids], eax ;something wrong ? |
ret |
endp |
align 4 |
proc init_controller |
stdcall 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 |
call SysMsgBoardStr |
call dword2str |
call SysMsgBoardStr |
mov esi, msgPciStat |
call SysMsgBoardStr |
mov eax, [ctrl.pci_stat] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgMixIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 |
call dword2str |
call SysMsgBoardStr |
and eax,0xFFFE |
mov [ctrl.codec_io_base], eax |
mov esi, msgCtrlIsaIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x14 |
call dword2str |
call SysMsgBoardStr |
and eax, 0xFFC0 |
mov [ctrl.ctrl_io_base], eax |
mov esi, msgMixMMIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x18 |
mov [ctrl.codec_mem_base], eax |
call dword2str |
call SysMsgBoardStr |
mov esi, msgCtrlMMIo |
call SysMsgBoardStr |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x1C |
mov [ctrl.ctrl_mem_base], eax |
call dword2str |
call SysMsgBoardStr |
if 0 |
;;patch for some ugly BIOS ICH-ICH5 compatible |
cmp [ctrl.vendor], VID_INTEL |
jne .default |
mov esi, msgIrqMap |
call SysMsgBoardStr |
stdcall PciRead8, 0, 0xF8, 0x61 |
and eax, 0xFF |
call dword2str |
call SysMsgBoardStr |
btr eax, 7 ;when bit 7 set remap disabled |
jnc @F |
xor eax, eax |
jmp @F |
end if |
.default: |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C |
and eax, 0xFF |
@@: |
mov [ctrl.int_line], eax |
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword 0x41 |
and eax, 0xFF |
mov [ctrl.cfg_reg], eax |
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 |
stdcall MapIoMem,[ctrl.codec_mem_base],0x1000,PG_SW+PG_NOCACHE |
mov [ctrl.codec_mem_base], eax |
stdcall 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 |
call SysMsgBoardStr |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
push eax |
call dword2str |
call 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 |
call SysMsgBoardStr |
end if |
xor eax, eax ; timeout error |
ret |
.ok: |
if DEBUG |
mov esi, msgResetOk |
call 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 |
call 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 |
call 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 |
call 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 |
call SysMsgBoardStr |
end if |
.fail: |
stc |
ret |
.ok: |
mov esi, msgControl |
call SysMsgBoardStr |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
push eax |
call dword2str |
call 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 |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
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 |
section '.data' data readable writable align 16 |
pcmout_bdl rq 32 |
buff_list rd 32 |
codec CODEC |
ctrl AC_CNTRL |
lpc_bus rd 1 |
civ_val rd 1 |
/kernel/branches/Kolibri-acpi/drivers/main.inc |
---|
0,0 → 1,164 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2006-2008. 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 |
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 |
.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 |
.in_base dd ? |
.in_size dd ? |
.in_wp dd ? |
.in_rp dd ? |
.in_count dd ? |
.in_free dd ? |
.in_top dd ? |
.notify_event dd ? |
.notify_id dd ? |
} |
STREAM_SIZE equ 36*4 |
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:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/drivers/vmode.asm |
---|
0,0 → 1,736 |
; |
; MenuetOS Driver (vmode.mdr) |
; Target: Vertical Refresh Rate programming and videomode changing |
; |
; Author: Trans <<<<<13>>>>> |
; Date: 20.07.2003 |
; |
; Version: 1.0 |
; OS: MenuetOS |
; Compiler: FASM |
; |
OS_BASE equ 0x80000000 |
use32 |
macro align value { rb (value-1) - ($ + value-1) mod value } |
org OS_BASE+0x0328000 |
headerstart=$ |
mdid db 'MDAZ' ; 4 byte id |
mdhver dd 0x00 ; header version |
mdcode dd MDSTART ; start of code |
mdver dd 0x00000001 ; driver version (subversion*65536+version) |
mdname db 'Trans VideoDriver' ; 32 bytes of full driver name |
times (32-($-mdname)) db ' ' ; |
headerlen=$-headerstart |
times (256-headerlen) db 0 ; reserved area for future |
MDSTART: ; start of driver code ( base_adr+256 bytes) |
; ebx(=ecx in program): |
; 1 - Get DriverInfo and Driver Initial Set |
; 2 - Get Current Video Mode With Vertical Refresh Rate |
; 3 - Change Video Mode |
; 4 - Return at Start System Video Mode |
; 5 - Change vertical and horizontal size of visible screen area |
; 6 - Change Vert/Hor position visible area on screen (not complete yet) |
; |
; MAXF - ... |
MAXF=5 |
;-------Main Manager------------- |
pushad |
cmp ebx,1 |
jb mdvm_00 |
cmp ebx,MAXF |
ja mdvm_00 |
shl ebx,2 |
add ebx,mdvm_func_table |
call dword [ebx] |
mov [esp+28],eax |
mov [esp+24],ecx |
mov [esp+20],edx |
mov [esp+16],ebx |
popad |
retn |
mdvm_00: |
popad |
xor eax,eax |
dec eax |
retn |
; ------Drivers Functions---------- |
align 4 |
; EBX=1 (in applications ECX=1)- Get DriverInfo and Driver Initial Set |
; |
; IN: ecx (in app. edx) - pointer to 512-bytes info area in application |
; OUT: |
; |
vm_info_init: |
push ecx |
cmp [mdrvm],dword 0 |
jnz .vmii_00 |
call vm_safe_reg |
call vm_get_initial_videomode |
mov eax,[initvm] |
mov [currvm],eax |
call vm_search_sys_func_table |
call vm_get_cur_vert_rate |
mov [initrr],eax |
call vm_calc_pixelclock |
call vm_calc_refrate |
inc [mdrvm] |
.vmii_00: |
pop ecx |
call vm_transfer_drv_info |
mov ebx,dword [refrate] |
mov eax,dword [mdid] ;dword [systlb] |
retn |
align 4 |
; EBX=2 (in applications ECX=2)- Get Current Video Mode |
; |
; OUT: eax = X_screen*65536+Y_screen |
; ebx = current vertical rate |
; ecx = current video mode (number) |
vm_get_cur_mode: |
cmp [mdrvm],dword 0 |
jz .vmgcm_00 |
call vm_get_cur_vert_rate |
mov eax,[OS_BASE+0FE00h] |
mov ebx,[OS_BASE+0FE04h] |
shl eax,16 |
add eax,ebx |
add eax,00010001h |
mov ebx,[refrate] |
mov ecx,[currvm] |
retn |
.vmgcm_00: |
xor eax,eax |
dec eax |
retn |
align 4 |
; EBX=3 (in applications ECX=3)- Change Video Mode |
; |
; IN: ecx = VertRate*65536+VideoMode |
; OUT: eax = 0 if no error |
; |
vm_set_video_mode: |
cmp [mdrvm],dword 0 |
jz .vmsvm_00 |
call vm_set_selected_mode |
; xor eax,eax |
retn |
.vmsvm_00: |
xor eax,eax |
dec eax |
retn |
align 4 |
; EBX=4 (in applications ECX=4)- Return at Start System Video Mode |
; |
; IN: |
; OUT: eax = = 0 if no error |
; |
vm_restore_init_video_mode: |
cmp [mdrvm],dword 0 |
jz .vmrivm_00 |
call vm_restore_reg |
xor eax,eax |
retn |
.vmrivm_00: |
xor eax,eax |
dec eax |
retn |
align 4 |
; EBX=5 (in applications ECX=5)- Change vertical and horizontal size |
; of visible screen area |
; IN: ecx (in app. edx) = 0/1 - -/+ horizontal size on 1 position |
; = 2/3 - -/+ vertical size on 1 position (8 pixels) |
; ^-^----- not complete yet |
; OUT: eax = = 0 if no error |
; |
vm_change_screen_size: |
cmp [mdrvm],dword 0 |
jz .vmcss_00 |
cmp cl,1 |
ja .vmcss_01 |
mov eax,ecx |
call vm_inc_dec_width |
xor eax,eax |
retn |
.vmcss_01: |
and ecx,01h |
mov eax,ecx |
; call vm_inc_dec_high ; not complete yet |
xor eax,eax |
retn |
.vmcss_00: |
xor eax,eax |
dec eax |
retn |
align 4 |
; EBX=6 (in applications ECX=6)- Change Vert/Hor position visible area on screen |
; |
; IN: ecx (in app. edx) = 0/1 - -/+ horizontal position on 1 point |
; = 2/3 - -/+ vertical position on 1 pixel |
; ^-^----- not complete yet |
; OUT: eax = 0 if no error |
; |
vm_change_position_screen: |
cmp [mdrvm],dword 0 |
jz .vmcps_00 |
; ... |
xor eax,eax |
retn |
.vmcps_00: |
xor eax,eax |
dec eax |
retn |
;-----Drivers Subfunctions--------- |
; |
; Searching i40 system functions pointer table in kernel area location |
; |
vm_search_sys_func_table: |
push eax ; eax - current value |
push ecx ; ecx - will be counter of equevalent value |
push edx ; edx - last value |
push esi ; esi - current address |
xor ecx,ecx |
mov esi,OS_BASE+010000h ; Start address of kernel location |
lodsd |
mov edx,eax |
cld |
.vmssft_00: |
cmp esi,OS_BASE+30000h |
ja .vmssft_03 |
inc ecx |
lodsd |
cmp edx,eax |
mov edx,eax |
je .vmssft_00 |
cmp ecx,128 |
ja .vmssft_02 |
.vmssft_01: |
xor ecx,ecx |
jmp .vmssft_00 |
.vmssft_02: |
cmp edx,0 |
je .vmssft_01 |
sub esi,256*4-1 |
mov [systlb],esi |
xor ecx,ecx |
.vmssft_03_0: |
inc ecx |
lodsd |
cmp edx,eax |
mov edx,eax |
jne .vmssft_03_0 |
mov esi,dword [systlb] |
cmp cx,60 |
jae .vmssft_03 |
add esi,256*4-4 |
lodsb |
mov edx,eax |
jmp .vmssft_01 |
.vmssft_03: |
mov [systlb],esi |
pop esi |
pop edx |
pop ecx |
pop eax |
retn |
; IN: |
; OUT: eax= vertical rate in Hz |
vm_get_cur_vert_rate: |
push edx |
push ebx |
xor eax,eax |
mov edx,eax |
mov ebx,eax |
mov dx,03DAh |
.vmgcvt_00: |
in al,dx |
test al,8 |
jz .vmgcvt_00 |
.vmgcvt_01: |
in al,dx |
test al,8 |
jnz .vmgcvt_01 |
mov ebx,edx |
rdtsc |
mov edx,ebx |
mov ebx,eax |
.vmgcvt_02: |
in al,dx |
test al,8 |
jz .vmgcvt_02 |
.vmgcvt_03: |
in al,dx |
test al,8 |
jnz .vmgcvt_03 |
rdtsc |
sub eax,ebx |
mov ebx,eax |
mov eax,[OS_BASE+0F600h] |
xor edx,edx |
div ebx |
inc eax |
mov [refrate],eax |
pop ebx |
pop edx |
retn |
vm_calc_pixelclock: |
push ebx |
push edx |
xor eax,eax |
mov al,[_00] |
add ax,5 |
shl eax,3 |
xor ebx,ebx |
mov bl,[_06] |
mov bh,[_07] |
and bh,00100001b |
btr bx,13 |
jnc .vmcpc_00 |
or bh,2 |
.vmcpc_00: |
xor edx,edx |
mul ebx |
xor edx,edx |
mul [initrr] |
mov [pclock],eax |
pop edx |
pop ebx |
retn |
; |
; Safe of initial CRTC state |
; |
vm_safe_reg: |
push edx |
push ebx |
push ecx |
push edi |
cli |
mov dx,3d4h ; CRTC |
mov al,11h |
out dx,al |
inc dx |
in al,dx |
and al,7fh |
out dx,al ; Clear protection bit |
dec dx |
xor ecx,ecx |
mov cl,19h |
xor bl,bl |
mov edi,CRTCreg |
.vmsr_00: |
mov al,bl |
out dx,al |
inc dx |
in al,dx |
dec dx |
stosb |
inc bl |
loop .vmsr_00 |
sti |
pop edi |
pop ecx |
pop ebx |
pop edx |
retn |
; |
; Restore of initial CRTC state |
; |
vm_restore_reg: |
push eax |
push ebx |
push edx |
push esi |
mov eax,[oldX] |
mov [OS_BASE+0FE00h],eax |
mov eax,[oldY] |
mov [OS_BASE+0FE04h],eax |
mov dx,03dah |
.vmrr_00: |
in al,dx |
test al,8 |
jnz .vmrr_00 |
.vmrr_01: |
in al,dx |
test al,8 |
jnz .vmrr_01 |
cli |
mov dx,03c4h |
mov ax,0101h |
out dx,ax |
mov dx,3d4h ; CRTC |
mov al,11h |
out dx,al |
inc dx |
in al,dx |
and al,7fh ; Clear Protection bit |
out dx,al |
dec dx |
xor ecx,ecx |
mov cl,19h |
mov esi,CRTCreg |
xor bl,bl |
.vmrr_02: |
lodsb |
mov ah,al |
mov al,bl |
out dx,ax |
inc bl |
loop .vmrr_02 |
sti |
; call ref_screen |
pop esi |
pop edx |
pop ecx |
pop eax |
retn |
; Calculate of possible vertical refrash rate |
; (light version of function) |
vm_calc_refrate: |
push ebx |
push ecx |
push edx |
push edi |
push esi |
mov eax,[pclock] |
xor edx,edx |
mov edi,_m1 |
mov ebx,eax |
mov ecx,(1696*1065) |
div ecx |
xor edx,edx |
stosw |
add edi,8 |
mov eax,ebx |
mov ecx,(1344*804) |
div ecx |
xor edx,edx |
stosw |
add edi,8 |
mov eax,ebx |
mov ecx,(1056*636) |
div ecx |
xor edx,edx |
stosw |
add edi,8 |
mov eax,ebx |
mov ecx,(800*524) |
div ecx |
xor edx,edx |
stosw |
mov edi,_m1 |
mov esi,edi |
mov ecx,5*4 |
.vmcrr_00: |
lodsw |
cmp ax,55 |
jb .vmcrr_01 |
stosw |
loop .vmcrr_00 |
pop esi |
pop edi |
pop edx |
pop ecx |
pop ebx |
retn |
.vmcrr_01: |
xor ax,ax |
stosw |
loop .vmcrr_00 |
pop esi |
pop edi |
pop edx |
pop ecx |
pop ebx |
retn |
vm_get_initial_videomode: |
push eax |
mov eax,dword [OS_BASE+0FE00h] |
mov [oldX],eax |
mov eax,dword [OS_BASE+0FE04h] |
mov [oldY],eax |
mov eax,dword [OS_BASE+0FE0Ch] ; initial video mode |
and ax,01FFh |
mov dword [initvm],eax |
pop eax |
retn |
; IN: eax = 0/1 - -/+ 1 position of width |
vm_inc_dec_width: |
push ebx |
push edx |
mov ebx,eax |
mov dx,3d4h ; CRTC |
mov al,11h |
out dx,al |
inc dx |
in al,dx |
and al,7fh ; Clear Protection bit |
out dx,al |
dec dx |
xor al,al |
out dx,al |
inc dx |
in al,dx |
dec al |
cmp bl,0 |
jnz .vmidr_00 |
inc al |
inc al |
.vmidr_00: |
out dx,al |
pop edx |
pop ebx |
retn |
; |
; Copy driver info to application area |
; |
; IN: ecx (in app. edx) - pointer to 512-bytes info area in application |
; OUT: |
vm_transfer_drv_info: |
push ecx |
push edi |
push esi |
mov eax,ecx |
xor ecx,ecx |
mov cl,32/4 |
mov esi,mdname |
mov edi,drvname |
rep movsd |
mov ecx,eax |
mov eax,[mdver] |
mov [drvver],eax |
mov edi,[OS_BASE+3010h] |
mov edi,[edi+10h] |
add edi,ecx |
mov esi,drvinfo |
xor ecx,ecx |
mov cx,512 |
rep movsb |
pop esi |
pop edi |
pop ecx |
retn |
; |
; Set selected video mode |
; (light version) |
; |
; IN: ecx = VertRate*65536+VideoMode |
; |
vm_set_selected_mode: |
push edx |
push ecx |
push esi |
ror ecx,16 |
cmp cx,00h |
je .vmssm_03 |
rol ecx,16 |
mov eax,ecx |
shl eax,16 |
shr eax,16 |
mov [currvm],eax |
cmp cx,112h |
jne .vmssm_00 |
mov esi,mode0 |
mov ecx,639 |
mov edx,479 |
jmp .vmssm_st00 |
.vmssm_00: |
cmp cx,115h |
jne .vmssm_01 |
mov esi,mode1 |
mov ecx,799 |
mov edx,599 |
jmp .vmssm_st00 |
.vmssm_01: |
cmp cx,118h |
jne .vmssm_02 |
mov esi,mode2 |
mov ecx,1023 |
mov edx,767 |
jmp .vmssm_st00 |
.vmssm_02: |
cmp cx,11Bh |
jne .vmssm_03 |
mov esi,mode2 |
mov ecx,1279 |
mov edx,1023 |
jmp .vmssm_st00 |
.vmssm_03: |
xor eax,eax |
dec eax |
pop esi |
pop ecx |
pop edx |
retn |
.vmssm_st00: |
mov [OS_BASE+0FE00h],ecx |
mov [OS_BASE+0FE04h],edx |
cli |
mov dx,03c4h |
lodsw |
out dx,ax |
mov dx,03d4h |
mov al,11h |
out dx,al |
inc dx |
in al,dx |
and al,7fh |
out dx,al |
dec dx |
mov ecx,13 |
.vmssm_st01: |
lodsw |
out dx,ax |
loop .vmssm_st01 |
sti |
xor eax,eax |
pop esi |
pop ecx |
pop edx |
retn |
;------------DATA AREA--------------- |
align 4 |
mdvm_func_table: |
dd MDSTART |
dd vm_info_init, vm_get_cur_mode |
dd vm_set_video_mode, vm_restore_init_video_mode |
dd vm_change_screen_size, vm_change_position_screen |
CRTCreg: |
_00 db ? |
_01 db ? |
_02 db ? |
_03 db ? |
_04 db ? |
_05 db ? |
_06 db ? |
_07 db ? |
_08 db ? |
_09 db ? |
_0a db ? |
_0b db ? |
_0c db ? |
_0d db ? |
_0e db ? |
_0f db ? |
_10 db ? |
_11 db ? |
_12 db ? |
_13 db ? |
_14 db ? |
_15 db ? |
_16 db ? |
_17 db ? |
_18 db ? |
_19 db ? |
align 4 |
oldX dd ? |
oldY dd ? |
initvm dd ? |
currvm dd 0 |
refrate dd 0 |
initrr dd 0 |
systlb dd 0 |
pclock dd ? |
mdrvm dd 0 ; 0 - not drv init yet, 1 - already drv init |
drvinfo: |
drvname: times 32 db ' ' |
drvver dd 0 |
times (32-($-drvver))/4 dd 0 |
drvmode dw 011Bh,0118h,0115h,0112h |
times (64-($-drvmode))/2 dw 00h |
_m1 dw 0,0,0,0,0 |
_m2 dw 0,0,0,0,0 |
_m3 dw 0,0,0,0,0 |
_m4 dw 0,0,0,0,0 |
_m5 dw 0,0,0,0,0 |
times (512-($-drvinfo)) db 0 |
drvinfoend: |
;1280x1024 - 11Bh |
mode3: |
dw 0101h |
dw 0d000h,9f01h,9f02h,9303h,0a904h,1905h,2806h,5a07h |
dw 0110h,8411h,0ff12h,0ff15h,2916h |
;1024x768 - 118h |
mode2: |
dw 0101h |
dw 0a400h,7f01h,7f02h,8703h,8404h,9505h,2406h,0f507h |
dw 0310h,8911h,0ff12h,0ff15h,2516h |
;800x600 - 115h |
mode1: |
dw 0101h |
dw 8000h,6301h,6302h,8303h,6a04h,1a05h,7206h,0f007h |
dw 5910h,8d11h,5712h,5715h,7316h |
;640x480 - 112h, 12h |
mode0: |
dw 0101h |
dw 6000h,4f01h,4f02h,8303h,5304h,9f05h,00b06h,3e07h |
dw 0ea10h,8c11h,0df12h,0df15h,0c16h |
; 640x400 |
;mymode0: |
; dw 0101h |
;_0_7 dw 5f00h,4f01h,4f02h,8303h,5304h,9f05h,0BF06h,1f07h |
; dw 9c10h,8e11h,8f12h,9615h,0B916h ;,4013h |
; 640x800 |
;mymode1: |
; dw 0101h |
; dw 5f00h,4f01h,4f02h,8003h,5004h,9f05h,06006h,0FF07h |
; dw 2d10h,8f11h,2012h,2615h,05716h ;,4013h |
DRVM_END: |
/kernel/branches/Kolibri-acpi/drivers/usb/urb.inc |
---|
0,0 → 1,115 |
struc URB |
{ |
.fd dd ? |
.bk dd ? |
.dev dd ? ; pointer to associated device |
.pipe dd ? ; pipe information |
.status dd ? ; non-ISO status |
.transfer_flags dd ? ; URB_SHORT_NOT_OK | ... |
.transfer_buffer dd ? ; associated data buffer |
.transfer_dma dd ? ; dma addr for transfer_buffer |
.transfer_buffer_length dd ? ; data buffer length |
.actual_length dd ? ; actual transfer length |
.setup_packet dd ? ; setup packet (control only) |
.setup_dma dd ? ; dma addr for setup_packet |
.start_frame dd ? ; start frame (ISO) |
.number_of_packets dd ? ; number of ISO packets |
.interval dd ? ; transfer interval |
.error_count dd ? ; number of ISO errors |
.context dd ? ; context for completion |
.complete dd ? ; (in) completion routine |
.iso_frame_desc: |
} |
virtual at 0 |
URB URB |
end virtual |
struc REQ ;usb request |
{ |
.request_type db ? |
.request db ? |
.value dw ? |
.index dw ? |
.length dw ? |
} |
virtual at 0 |
REQ REQ |
end virtual |
align 4 |
proc usb_control_msg stdcall, dev:dword, pipe:dword, request:dword,\ |
requesttype:dword, value:dword, index:dword,\ |
data:dword, size:dword, timeout:dword |
locals |
req REQ |
endl |
lea eax, [req] |
mov ecx, [request] |
mov ebx, [requesttupe] |
mov edx, [value] |
mov esi, [index] |
mov edi, [size] |
mov [eax+REQ.request_type], bl |
mov [eax+REQ.request], cl |
mov [eax+REQ.value], dx |
mov [eax+REQ.index], si |
mov [eax+REQ.length], di |
stdcall usb_internal_control_msg, [dev], [pipe],\ |
eax, [data], [size], [timeout] |
ret |
endp |
; returns status (negative) or length (positive) |
static int usb_internal_control_msg(struct usb_device *usb_dev, |
unsigned int pipe, |
struct usb_ctrlrequest *cmd, |
void *data, int len, int timeout) |
{ |
struct urb *urb; |
int retv; |
int length; |
urb = usb_alloc_urb(0, GFP_NOIO); |
if (!urb) |
return -ENOMEM; |
usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data, |
len, usb_api_blocking_completion, NULL); |
retv = usb_start_wait_urb(urb, timeout, &length); |
if (retv < 0) |
return retv; |
else |
return length; |
} |
void usb_fill_control_urb (struct urb *urb, |
struct usb_device *dev, |
unsigned int pipe, |
unsigned char *setup_packet, |
void *transfer_buffer, |
int buffer_length, |
usb_complete_t complete_fn, |
void *context) |
{ |
urb->dev = dev; |
urb->pipe = pipe; |
urb->setup_packet = setup_packet; |
urb->transfer_buffer = transfer_buffer; |
urb->transfer_buffer_length = buffer_length; |
urb->complete = complete_fn; |
urb->context = context; |
} |
/kernel/branches/Kolibri-acpi/drivers/usb/usb.asm |
---|
0,0 → 1,435 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;driver sceletone |
format MS COFF |
API_VERSION equ 0 ;debug |
include '../proc32.inc' |
include '../imports.inc' |
include 'urb.inc' |
struc UHCI |
{ |
.bus dd ? |
.devfn dd ? |
.io_base dd ? |
.mm_base dd ? |
.irq dd ? |
.flags dd ? |
.reset dd ? |
.start dd ? |
.stop dd ? |
.port_c_suspend dd ? |
.resuming_ports dd ? |
.rh_state dd ? |
.rh_numports dd ? |
.is_stopped dd ? |
.dead dd ? |
.sizeof: |
} |
virtual at 0 |
UHCI UHCI |
end virtual |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
struc TD ;transfer descriptor |
{ |
.link dd ? |
.status dd ? |
.token dd ? |
.buffer dd ? |
.addr dd ? |
.frame dd ? |
.fd dd ? |
.bk dd ? |
.sizeof: |
} |
virtual at 0 |
TD TD |
end virtual |
public START |
public service_proc |
public version |
DEBUG equ 1 |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
STRIDE equ 4 ;size of row in devices table |
SRV_GETVERSION equ 0 |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .exit |
.entry: |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call init |
stdcall RegService, my_service, service_proc |
ret |
.fail: |
.exit: |
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 ebx, [ioctl] |
mov eax, [ebx+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [ebx+output] |
cmp [ebx+out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
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 detect |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall 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, STRIDE |
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 eax, UHCI.sizeof |
call Kmalloc |
test eax, eax |
jz .mem_fail |
mov ebx, [bus] |
mov [eax+UHCI.bus], ebx |
mov ecx, [devfn] |
mov [eax+UHCI.devfn], ecx |
ret |
.mem_fail: |
if DEBUG |
mov esi, msgMemFail |
call SysMsgBoardStr |
end if |
.err: |
xor eax, eax |
ret |
endp |
PCI_BASE equ 0x20 |
USB_LEGKEY equ 0xC0 |
align 4 |
proc init |
locals |
uhci dd ? |
endl |
call detect |
test eax, eax |
jz .fail |
mov [uhci], eax |
stdcall PciRead32, [eax+UHCI.bus], [eax+UHCI.devfn], PCI_BASE |
and eax, 0xFFC0 |
mov esi, [uhci] |
mov [esi+UHCI.io_base], eax |
stdcall uhci_reset, esi |
stdcall finish_reset, [uhci] |
.fail: |
if DEBUG |
mov esi, msgDevNotFound |
call SysMsgBoardStr |
end if |
ret |
endp |
UHCI_USBINTR equ 4 ; interrupt register |
UHCI_USBLEGSUP_RWC equ 0x8f00 ; the R/WC bits |
UHCI_USBLEGSUP_RO equ 0x5040 ; R/O and reserved bits |
UHCI_USBCMD_RUN equ 0x0001 ; RUN/STOP bit |
UHCI_USBCMD_HCRESET equ 0x0002 ; Host Controller reset |
UHCI_USBCMD_EGSM equ 0x0008 ; Global Suspend Mode |
UHCI_USBCMD_CONFIGURE equ 0x0040 ; Config Flag |
UHCI_USBINTR_RESUME equ 0x0002 ; Resume interrupt enable |
PORTSC0 equ 0x10 |
PORTSC1 equ 0x12 |
UHCI_RH_RESET equ 0 |
UHCI_RH_SUSPENDED equ 1 |
UHCI_RH_AUTO_STOPPED equ 2 |
UHCI_RH_RESUMING equ 3 |
; In this state the HC changes from running to halted |
; so it can legally appear either way. |
UHCI_RH_SUSPENDING equ 4 |
; In the following states it's an error if the HC is halted. |
; These two must come last. |
UHCI_RH_RUNNING equ 5 ; The normal state |
UHCI_RH_RUNNING_NODEVS equ 6 ; Running with no devices |
UHCI_IS_STOPPED equ 9999 |
align 4 |
proc uhci_reset stdcall, uhci:dword |
mov esi, [uhci] |
stdcall PciRead16, [esi+UHCI.bus], [esi+UHCI.devfn], USB_LEGKEY |
test eax, not (UHCI_USBLEGSUP_RO or UHCI_USBLEGSUP_RWC) |
jnz .reset |
mov edx, [esi+UHCI.io_base] |
in ax, dx |
test ax, UHCI_USBCMD_RUN |
jnz .reset |
test ax, UHCI_USBCMD_CONFIGURE |
jz .reset |
test ax, UHCI_USBCMD_EGSM |
jz .reset |
add edx, UHCI_USBINTR |
in ax, dx |
test ax, not UHCI_USBINTR_RESUME |
jnz .reset |
ret |
.reset: |
stdcall PciWrite16, [esi+UHCI.bus], [esi+UHCI.devfn], USB_LEGKEY, UHCI_USBLEGSUP_RWC |
mov edx, [esi+UHCI.io_base] |
mov ax, UHCI_USBCMD_HCRESET |
out dx, ax |
xor eax, eax |
out dx, ax |
add edx, UHCI_USBINTR |
out dx, ax |
ret |
endp |
proc finish_reset stdcall, uhci:dword |
mov esi, [uhci] |
mov edx, [esi+UHCI.io_base] |
add edx, PORTSC0 |
xor eax, eax |
out dx, ax |
add edx, (PORTSC1-PORTSC0) |
out dx, ax |
mov [esi+UHCI.port_c_suspend], eax |
mov [esi+UHCI.resuming_ports], eax |
mov [esi+UHCI.rh_state], UHCI_RH_RESET |
mov [esi+UHCI.rh_numports], 2 |
mov [esi+UHCI.is_stopped], UHCI_IS_STOPPED |
; mov [ uhci_to_hcd(uhci)->state = HC_STATE_HALT; |
; uhci_to_hcd(uhci)->poll_rh = 0; |
mov [esi+UHCI.dead], eax ; Full reset resurrects the controller |
ret |
endp |
proc insert_td stdcall, td:dword, frame:dword |
mov edi, [td] |
mov eax, [frame] |
and eax, -1024 |
mov [edi+TD.frame], eax |
mov ebx, [framelist] |
mov edx, [dma_framelist] |
shl eax, 5 |
mov ecx, [eax+ebx] |
test ecx, ecx |
jz .empty |
mov ecx, [ecx+TD.bk] ;last TD |
mov edx, [ecx+TD.fd] |
mov [edi+TD.fd], edx |
mov [edi+TD.bk], ecx |
mov [ecx+TD.fd], edi |
mov [edx+TD.bk], edi |
mov eax, [ecx+TD.link] |
mov [edi+TD.link], eax |
mov ebx, [edi+TD.addr] |
mov [ecx+TD.link], ebx |
ret |
.empty: |
mov ecx, [eax+edx] |
mov [edi+TD.link], ecx |
mov [ebx+eax], edi |
mov ecx, [edi+TD.addr] |
mov [eax+edx], ecx |
ret |
endp |
align 4 |
proc usb_get_descriptor stdcall, dev:dword, type:dword, index:dword,\ |
buf:dword, size:dword |
locals |
count dd ? |
endl |
mov esi, [buf] |
mov ecx, [size] |
xor eax, eax |
cld |
rep stosb |
mov [count], 3 |
@@: |
mov eax, [type] |
shl eax, 8 |
add eax, [index] |
stdcall usb_control_msg, [dev],pipe,USB_REQ_GET_DESCRIPTOR,\ |
USB_DIR_IN, eax,0,[buf], [size],\ |
USB_CTRL_GET_TIMEOUT |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
jmp. ok |
.next: |
dec [count] |
jnz @B |
mov eax, -1 |
.ok: |
ret |
endp |
DEVICE_ID equ 0x24D2 ; pci device id |
VENDOR_ID equ 0x8086 ; device vendor id |
QEMU_USB equ 0x7020 |
;all initialized data place here |
align 4 |
devices dd (DEVICE_ID shl 16)+VENDOR_ID |
dd (QEMU_USB shl 16)+VENDOR_ID |
dd 0 ;terminator |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
my_service db 'UHCI',0 ;max 16 chars include zero |
msgInit db 'detect hardware...',13,10,0 |
msgPCI db 'PCI accsess not supported',13,10,0 |
msgDevNotFound db 'device not found',13,10,0 |
msgMemFail db 'Kmalloc failed', 10,10,0 |
;msgFail db 'device not found',13,10,0 |
section '.data' data readable writable align 16 |
;all uninitialized data place here |
/kernel/branches/Kolibri-acpi/drivers/usb |
---|
Property changes: |
Added: svn:ignore |
+*.mnt |
+lang.inc |
+*.bat |
+out.txt |
+scin* |
+*.obj |
/kernel/branches/Kolibri-acpi/drivers/mix_mmx.inc |
---|
0,0 → 1,247 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. 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:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/drivers/mix_sse2.inc |
---|
0,0 → 1,145 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. 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:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/drivers/. |
---|
Property changes: |
Added: svn:ignore |
+*.mnt |
+lang.inc |
+*.bat |
+out.txt |
+scin* |
+*.obj |