From 233c3e64354411bf10529d83c6078e4369d3a5ba Mon Sep 17 00:00:00 2001 From: "Sergey Semyonov (Serge)" Date: Sat, 7 Oct 2006 09:47:03 +0000 Subject: [PATCH] complete SSE support. user-level SSE & FPU exceptions handling git-svn-id: svn://kolibrios.org@168 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/trunk/const.inc | 28 + kernel/trunk/core/except.inc | 67 +- kernel/trunk/core/memory.inc | 20 +- kernel/trunk/core/sys32.inc | 6 +- kernel/trunk/drivers/codec.inc | 223 +++++ kernel/trunk/drivers/infinity.asm | 795 ++++++++++++++++ kernel/trunk/drivers/main.inc | 133 +++ kernel/trunk/drivers/mixer.asm | 1290 ++++++++++++++++++++++++++ kernel/trunk/drivers/proc32.inc | 268 ++++++ kernel/trunk/drivers/sis.asm | 1177 ++++++++++++++++++++++++ kernel/trunk/drivers/unisound.asm | 1394 +++++++++++++++++++++++++++++ kernel/trunk/kernel.asm | 43 +- kernel/trunk/proc32.inc | 268 ++++++ 13 files changed, 5687 insertions(+), 25 deletions(-) create mode 100644 kernel/trunk/drivers/codec.inc create mode 100644 kernel/trunk/drivers/infinity.asm create mode 100644 kernel/trunk/drivers/main.inc create mode 100644 kernel/trunk/drivers/mixer.asm create mode 100644 kernel/trunk/drivers/proc32.inc create mode 100644 kernel/trunk/drivers/sis.asm create mode 100644 kernel/trunk/drivers/unisound.asm create mode 100644 kernel/trunk/proc32.inc diff --git a/kernel/trunk/const.inc b/kernel/trunk/const.inc index 59636a7220..b8d55c1d19 100644 --- a/kernel/trunk/const.inc +++ b/kernel/trunk/const.inc @@ -86,6 +86,19 @@ CAPS_SVM equ 73 ;secure virual machine CAPS_ALTMOVCR8 equ 74 ; +CR0_PE equ 0x00000001 ;protected mode +CR0_MP equ 0x00000002 ;monitor fpu +CR0_EM equ 0x00000004 ;fpu emulation +CR0_TS equ 0x00000008 ;task switch +CR0_ET equ 0x00000010 ;extension type hardcoded to 1 +CR0_NE equ 0x00000020 ;numeric error +CR0_WP equ 0x00010000 ;write protect +CR0_AM equ 0x00040000 ;alignment check +CR0_NW equ 0x20000000 ;not write-through +CR0_CD equ 0x40000000 ;cache disable +CR0_PG equ 0x80000000 ;paging + + CR4_VME equ 0x0001 CR4_PVI equ 0x0002 CR4_TSD equ 0x0004 @@ -98,7 +111,22 @@ CR4_PCE equ 0x0100 CR4_OSFXSR equ 0x0200 CR4_OSXMMEXPT equ 0x0400 +SSE_IE equ 0x0001 +SSE_DE equ 0x0002 +SSE_ZE equ 0x0004 +SSE_OE equ 0x0008 +SSE_UE equ 0x0010 +SSE_PE equ 0x0020 +SSE_DAZ equ 0x0040 +SSE_IM equ 0x0080 +SSE_DM equ 0x0100 +SSE_ZM equ 0x0200 +SSE_OM equ 0x0400 +SSE_UM equ 0x0800 +SSE_PM equ 0x1000 +SSE_FZ equ 0x8000 +SSE_INIT equ (SSE_IM+SSE_DM+SSE_ZM+SSE_OM+SSE_UM+SSE_PM) OS_BASE equ 0; 0x80400000 diff --git a/kernel/trunk/core/except.inc b/kernel/trunk/core/except.inc index 08b724ff55..05992ea1ab 100644 --- a/kernel/trunk/core/except.inc +++ b/kernel/trunk/core/except.inc @@ -5,13 +5,13 @@ reg_cs equ ebp+8 reg_eflags equ ebp+12 reg_esp equ ebp+16 reg_ss equ ebp+20 -fpu_ctrl equ ebp-28 +;fpu_ctrl equ ebp-28 align 4 except_16: push ebp mov ebp, esp - sub esp, 28 +; sub esp, 28 push eax push ebx @@ -41,11 +41,53 @@ except_16: iretd .default: + pop edx + pop ecx + pop ebx + pop eax + leave - fnstenv [fpu_ctrl] - fnclex - or word [fpu_ctrl], 0111111b - fldenv [fpu_ctrl] + save_ring3_context ;debugger support + + mov bl, 16 + jmp exc_c + +; fnstenv [fpu_ctrl] +; fnclex +; or word [fpu_ctrl], 0111111b +; fldenv [fpu_ctrl] + +; pop edx +; pop ecx +; pop ebx +; pop eax + +; leave +; iretd + +align 16 +except_19: + push ebp + mov ebp, esp + + push eax + push ebx + push ecx + push edx + + mov ebx, [ss:CURRENT_TASK] + shl ebx, 8 + + mov eax, [ss:ebx+PROC_BASE+APPDATA.sse_handler] + test eax, eax + jz .default + + mov ecx, [reg_eip] + mov edx, [reg_esp] + sub edx, 4 + mov [ss:edx+new_app_base], ecx + mov [reg_esp], edx + mov dword [reg_eip], eax pop edx pop ecx @@ -55,10 +97,21 @@ except_16: leave iretd +.default: + pop edx + pop ecx + pop ebx + pop eax + leave + + save_ring3_context ;debugger support + + mov bl, 19 + jmp exc_c restore reg_eip restore reg_cs restore reg_eflags restore reg_esp restore reg_ss -restore fpu_ctrl +;restore fpu_ctrl diff --git a/kernel/trunk/core/memory.inc b/kernel/trunk/core/memory.inc index 1b01815238..6768e64f28 100644 --- a/kernel/trunk/core/memory.inc +++ b/kernel/trunk/core/memory.inc @@ -4,9 +4,9 @@ tmp_page_tab equ 0x01000000 align 4 proc mem_test mov eax, cr0 - or eax, 0x60000000 ;disable caching + or eax, (CR0_CD+CR0_NW);disable caching mov cr0, eax - wbinvd ;invalidate cache + wbinvd ;invalidate cache xor edi, edi mov ebx, 'TEST' @@ -17,7 +17,7 @@ proc mem_test xchg ebx, dword [edi] je @b - and eax, 0x21 + and eax, not (CR0_CD+CR0_NW) mov cr0, eax mov eax, edi ret @@ -40,7 +40,10 @@ proc init_memEx jnc @F or eax, PG_GLOBAL or ebx, CR4_PGE + @@: + mov cr4, ebx + mov dword [sys_pgdir], eax add eax, 0x00400000 mov dword [sys_pgdir+4], eax @@ -52,8 +55,6 @@ proc init_memEx mov dword [sys_pgdir+0x600], sys_master_tab+PG_SW mov dword [sys_master_tab+0x600], sys_master_tab+PG_SW - mov cr4, ebx - mov ecx, [pg_data.kernel_tables] sub ecx, 4 mov eax, tmp_page_tab+PG_SW @@ -1102,6 +1103,15 @@ new_services: stdcall srv_handlerEx, ebx mov [esp+36], eax ret +@@: + cmp eax, 18 + ja @f + mov ecx, [CURRENT_TASK] + shl ecx, 8 + mov eax, [ecx+PROC_BASE+APPDATA.sse_handler] + mov [ecx+PROC_BASE+APPDATA.sse_handler], ebx + mov [esp+36], eax + ret @@: .fail: diff --git a/kernel/trunk/core/sys32.inc b/kernel/trunk/core/sys32.inc index 673a9b8dc0..7a25a724b4 100644 --- a/kernel/trunk/core/sys32.inc +++ b/kernel/trunk/core/sys32.inc @@ -172,8 +172,8 @@ iglobal dd e8,e9,e10,e11 dd e12,e13,page_fault_handler,e15 - dd except_16, e17 - times 14 dd unknown_interrupt + dd except_16, e17,e18, except_19 + times 12 dd unknown_interrupt dd irq0 , irq_serv.irq_1, p_irq2 ,irq_serv.irq_3 dd p_irq4 ,irq_serv.irq_5,p_irq6,irq_serv.irq_7 @@ -219,7 +219,7 @@ macro exc_w_code [num] jmp exc_c } -exc_wo_code 0, 1, 2, 3, 4, 5, 6, 9, 15 ; 18, 19 +exc_wo_code 0, 1, 2, 3, 4, 5, 6, 9, 15, 18 exc_w_code 8, 10, 11, 12, 13, 14, 17 exc_c: diff --git a/kernel/trunk/drivers/codec.inc b/kernel/trunk/drivers/codec.inc new file mode 100644 index 0000000000..ae222dca5e --- /dev/null +++ b/kernel/trunk/drivers/codec.inc @@ -0,0 +1,223 @@ + +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 + 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 + 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] + test ebx, ebx + jz .unknown + + cmp eax,ebx + jne .next + mov eax, [edi+4] + mov [codec.chip_ids], eax + ret +.next: + add edi, 8 + jmp @b +.unknown: + mov [codec.chip_ids], chip_unknown + ret +endp + +align 4 +proc setup_codec + + xor eax, eax + stdcall codec_write, dword CODEC_AUX_VOL + + mov eax, 0x1010 + 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 + +align 4 +proc set_master_vol stdcall, vol:dword + + mov ebx, 63 + mov ecx, 20644 + mov eax, [vol] + cmp eax, 90 + jna @f + mov eax, 90 +@@: + mul ecx + shr eax, 15 + sub ebx, eax + mov ah, bl + mov al, bl + stdcall codec_write, dword CODEC_MASTER_VOL_REG + ret +endp + +align 4 +proc get_master_vol stdcall, pvol:dword + + stdcall codec_read, dword CODEC_MASTER_VOL_REG + and eax, 0x3F + mov ebx, 63 + mov ecx, 20644 + + xchg eax, ebx + sub eax, ebx + shl eax, 15 + xor edx, edx + div ecx + mov ebx, [pvol] + mov [ebx], 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 + +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 +chip_unknown db 'unknown chip', 13,10,0 + +CHIP_ANALOG equ 0x41445300 +CHIP_REALTEK equ 0x414C4700 +CHIP_CMEDIA equ 0x434D4900 + +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 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 0x75, chip_AD1985 + dd 0 + +chips_Realtek 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 0 + +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 0 + +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_AD1985 db 'AD1985 ',0dh,0ah,00h + +;Realtek +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 + diff --git a/kernel/trunk/drivers/infinity.asm b/kernel/trunk/drivers/infinity.asm new file mode 100644 index 0000000000..af2317ca88 --- /dev/null +++ b/kernel/trunk/drivers/infinity.asm @@ -0,0 +1,795 @@ +; +; This file is part of the Infinity sound library. +; (C) copyright Serge 2006 +; email: infinity_sound@mail.ru +; +; This program is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. + +format MS COFF + +include 'proc32.inc' +include 'main.inc' + +DEBUG equ 1 + +EVENT_NOTIFY equ 0x00000200 + +OS_BASE equ 0; 0x80400000 +new_app_base equ 0x60400000; 0x01000000 +PROC_BASE equ OS_BASE+0x0080000 + +public service_proc +public START +public IMPORTS + +SND_CREATE_BUFF equ 2 +SND_PLAY equ 3 +SND_STOP equ 4 +SND_SETBUFF equ 5 +SND_DESTROY_BUFF equ 6 + +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' align 16 + +START: + 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 edi, stream_list + mov ecx, 17 + xor eax, eax + cld + rep stosd + + mov edi, stream + mov ecx, 4*STREAM_SIZE + rep stosd + + stdcall set_handler, [hSound], new_mix + + stdcall [RegService], szInfinity, service_proc + mov [stream_count],0 + + ret +.fail: + if DEBUG + mov esi, msgFail + call [SysMsgBoardStr] + end if + xor eax, eax + ret + +.out_of_mem: + if DEBUG + mov esi, msgMem + call [SysMsgBoardStr] + end if + xor eax, eax + ret + +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, SND_CREATE_BUFF + jne @F + mov ebx, [edi+input] + stdcall CreateBuffer,[ebx] + ret +@@: + cmp eax, SND_PLAY + jne @F + + mov ebx, [edi+input] + stdcall play_buffer, [ebx] + ret +@@: + cmp eax, SND_STOP + jne @F + +; if DEBUG +; mov esi, msgStop +; call [SysMsgBoardStr] +; end if + + mov ebx, [edi+input] + stdcall stop_buffer, [ebx] + ret +@@: + cmp eax, SND_SETBUFF + jne @F + + mov ebx, [edi+input] + mov eax, [ebx+4] + add eax, new_app_base + stdcall set_buffer, [ebx],eax,[ebx+8],[ebx+12] + ret +@@: + cmp eax, SND_DESTROY_BUFF + jne @F + + mov ebx, [edi+input] + stdcall DestroyBuffer, [ebx] + ret +@@: + xor eax, eax + ret +endp + +restore handle +restore io_code +restore input +restore inp_size +restore output +restore out_size + +TASK_COUNT equ 0x0003004 +CURRENT_TASK equ 0x0003000 + + +align 8 +proc CreateBuffer stdcall, format:dword + locals + str dd ? + endl + + call alloc_stream + and eax, eax + jz .fail + mov [str], eax + mov edi, eax + + mov edx, [stream_count] + mov [stream_list+edx*4], eax + inc [stream_count] + + mov [edi+STREAM.magic], 'WAVE' + mov [edi+STREAM.size], STREAM_SIZE + + stdcall [KernelAlloc], 180*1024 + + mov edi, [str] + mov [edi+STREAM.base], eax + mov [edi+STREAM.curr_seg], eax + mov [edi+STREAM.notify_off1], eax + add eax, 0x8000 + mov [edi+STREAM.notify_off2], eax + add eax, 0x7FFF + mov [edi+STREAM.limit], eax + + inc eax + + mov [edi+STREAM.work_buff], eax + mov [edi+STREAM.work_read], eax + mov [edi+STREAM.work_write], eax + mov [edi+STREAM.work_count], 0 + add eax, 0x10000 + mov [edi+STREAM.work_top], eax + add eax, 1024*32 + mov [edi+STREAM.r_buff], eax + + mov ebx, [CURRENT_TASK] + shl ebx, 5 + mov eax, [0x3000+ebx+4] + + mov [edi+STREAM.notify_task], eax + + mov eax, [format] + mov [edi+STREAM.format], eax + mov [edi+STREAM.flags], SND_STOP + + xor ebx, ebx + cmp eax, 19 + jb @f + mov ebx, 0x80808080 +@@: + mov [edi+STREAM.r_silence], ebx + + shl eax, 4 + mov ebx, [resampler_params+eax] + mov ecx, [resampler_params+eax+4] + mov edx, [resampler_params+eax+8] + + mov [edi+STREAM.r_size],ebx + mov [edi+STREAM.r_end], ecx + mov [edi+STREAM.r_dt], edx + + mov ebx, [resampler_params+eax+12] + mov [edi+STREAM.resample], ebx + + mov edi, [edi+STREAM.base] + mov ecx, 180*1024/4 + xor eax, eax + rep stosd + + mov eax, [str] + ret + +.fail: + xor eax, eax + ret +endp + +align 4 +pid_to_slot: + + push ebx + push ecx + mov ebx,[TASK_COUNT] + shl ebx,5 + mov ecx,2*32 +.loop: + cmp byte [CURRENT_TASK+ecx+0xa],9 + jz .endloop ;skip empty slots + cmp [CURRENT_TASK+ecx+0x4],eax ;check PID + jz .pid_found +.endloop: + add ecx,32 + cmp ecx,ebx + jle .loop + pop ecx + pop ebx + xor eax,eax + ret + +.pid_found: + shr ecx,5 + mov eax,ecx + pop ecx + pop ebx + ret + + + +align 4 +proc DestroyBuffer stdcall, str:dword + + mov esi, [str] + + cmp [esi+STREAM.magic], 'WAVE' + jne .fail + + cmp [esi+STREAM.size], STREAM_SIZE + jne .fail + + stdcall [KernelFree], [esi+STREAM.base] + + mov eax, [str] + call free_stream + + mov edi, [str] + mov ecx, STREAM_SIZE/4 + xor eax, eax + cld + rep stosd + + mov eax, [str] + mov esi, stream_list + mov ecx, 16 +@@: + cmp [esi], eax + je .remove + add esi, 4 + dec ecx + jnz @B + xor eax, eax + inc eax + ret +.remove: + mov edi, esi + add esi, 4 + cld + rep movsd + dec [stream_count] + xor eax, eax + inc eax + ret +.fail: + xor eax, eax + ret +endp + +align 4 +proc play_buffer stdcall, str:dword + + mov ebx, [str] + + cmp [ebx+STREAM.magic], 'WAVE' + jne .fail + + cmp [ebx+STREAM.size], STREAM_SIZE + jne .fail + + mov [ebx+STREAM.flags], SND_PLAY + + mov eax,[ebx+STREAM.work_buff] + mov [ebx+STREAM.work_read], eax + mov [ebx+STREAM.work_write], eax + mov [ebx+STREAM.work_count], 0 + + mov eax, [ebx+STREAM.base] + mov [ebx+STREAM.curr_seg], eax + + mov esi, [ebx+STREAM.curr_seg] + mov edi, [ebx+STREAM.work_write] + mov edx, [ebx+STREAM.r_buff] + + mov ecx, 32 + mov eax, [ebx+STREAM.r_silence] +@@: + mov [edx], eax + add edx, 4 + dec ecx + jnz @B + + mov edx, [ebx+STREAM.r_buff] + + stdcall [ebx+STREAM.resample], edi, esi, edx,\ + [ebx+STREAM.r_dt],[ebx+STREAM.r_size],[ebx+STREAM.r_end] + + mov ebx, [str] + + add [ebx+STREAM.work_count], eax; + add [ebx+STREAM.work_write], eax; + + mov eax, [ebx+STREAM.r_size] + add [ebx+STREAM.curr_seg], eax + +; if DEBUG +; mov esi, msgPlay +; call [SysMsgBoardStr] +; end if + + stdcall dev_play, [hSound] + + xor eax, eax + inc eax + ret + +.fail: + xor eax, eax + ret + +endp + + +align 4 +proc stop_buffer stdcall, str:dword + + mov edi, [str] + + cmp [edi+STREAM.magic], 'WAVE' + jne .fail + + cmp [edi+STREAM.size], STREAM_SIZE + jne .fail + + mov [edi+STREAM.flags], SND_STOP + +; stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0 + + xor eax, eax + inc eax + ret + +.fail: + xor eax, eax + ret + +endp + +align 4 +proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword + + mov edx, [str] + test edx, edx + jz .fail + + cmp [edx+STREAM.magic], 'WAVE' + jne .fail + + cmp [edx+STREAM.size], STREAM_SIZE + jne .fail + + mov esi,[src] + test esi, esi + jz .fail + + cmp esi, new_app_base + jb .fail + + mov ecx, [size] + test ecx, ecx + jz .fail + + mov eax, [edx+STREAM.base] + add eax, [offs] + + cmp eax, [edx+STREAM.base] + jb .fail + + mov edi, eax + add eax, ecx + sub eax, 1 + + cmp eax, [edx+STREAM.limit] + ja .fail + + shr ecx, 2 + cld + rep movsd + + xor eax, eax + inc eax + ret +.fail: + xor eax, eax + ret +endp + +align 4 +proc alloc_stream + + mov esi, stream_map + + pushf + cli + + bsf eax, [esi] + jnz .find + popf + xor eax, eax + ret + +.find: btr [esi], eax + popf + mov ebx, STREAM_SIZE + mul ebx + add eax, stream + ret +endp + +align 4 +proc free_stream + sub eax, stream + mov ebx, STREAM_SIZE + xor edx, edx + div ebx + + and edx, edx + jnz .err + + bts [stream_map], eax + + ret +.err: + xor eax, eax + ret +endp + +align 4 +proc check_stream + + xor edx, edx + mov ecx, [play_count] +.l1: + mov esi, [play_list+edx] + + mov eax, [esi+STR.curr_seg] + cmp eax, [esi+STR.limit] + jb .next + +.m1: mov eax,[esi+STR.base] + mov [esi+STR.curr_seg], eax +.next: + add edx, 4 + loop .l1 + ret +endp + + +align 4 +proc prepare_playlist + +.restart: + xor ebx, ebx + xor edx, edx + mov [play_count], 0 + mov ecx, [stream_count] + jcxz .exit +.l1: + mov esi, [stream_list+ebx] + test esi, esi + jz .next + + cmp [esi+STREAM.magic], 'WAVE' + jne .next + + cmp [esi+STREAM.size], STREAM_SIZE + jne .next + + mov eax,[esi+STREAM.notify_task] + cmp eax, -1 + je .fail + + call pid_to_slot + test eax, eax + jz .fail + + cmp [esi+STREAM.flags], SND_PLAY; + jne .next + cmp [esi+STREAM.work_count], 16384 + jb .next + + mov [play_list+edx], esi + inc [play_count] + add edx, 4 +.next: + add ebx, 4 + loop .l1 +.exit: + ret + +.fail: + stdcall DestroyBuffer, esi + jmp .restart +endp + +align 4 +proc prepare_updatelist + + xor ebx, ebx + xor edx, edx + mov [play_count], 0 + mov ecx, [stream_count] + jcxz .exit +.l1: + mov eax, [stream_list+ebx] + test eax, eax + jz .next + cmp [eax+STREAM.flags], SND_PLAY + jne .next + + mov [play_list+edx], eax + inc [play_count] + add edx, 4 +.next: + add ebx, 4 + loop .l1 +.exit: + ret +endp + + +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 + +include 'mixer.asm' + +align 16 +play_list dd 16 dup(0) +stream_list dd 17 dup(0) + +align 16 +resampler_params: + ;r_size r_end r_dt resampler_func + dd 0,0,0,0 ; 0 PCM_ALL + dd 16384, 0, 0, copy_stream ; 1 PCM_2_16_48 + dd 16384, 0, 0, m16_stereo ; 2 PCM_1_16_48 + + dd 16384, 0x08000000, 30109, resample_2 ; 3 PCM_2_16_44 + dd 8192, 0x08000000, 30109, resample_1 ; 4 PCM_1_16_44 + + dd 16384, 0x08000000, 21846, resample_2 ; 5 PCM_2_16_32 + dd 8192, 0x08000000, 21846, resample_1 ; 6 PCM_1_16_32 + + dd 16384, 0x08000000, 16384, resample_2 ; 7 PCM_2_16_24 + dd 8192, 0x08000000, 16384, resample_1 ; 8 PCM_1_16_24 + + dd 8192, 0x04000000, 15052, resample_2 ; 9 PCM_2_16_22 + dd 4096, 0x04000000, 15052, resample_1 ;10 PCM_1_16_22 + + dd 8192, 0x04000000, 10923, resample_2 ;11 PCM_2_16_16 + dd 4096, 0x04000000, 10923, resample_1 ;12 PCM_1_16_16 + + dd 8192, 0x04000000, 8192, resample_2 ;13 PCM_2_16_12 + dd 4096, 0x04000000, 8192, resample_1 ;14 PCM_1_16_12 + + dd 4096, 0x02000000, 7527, resample_2 ;15 PCM_2_16_11 + dd 2048, 0x02000000, 7527, resample_1 ;16 PCM_1_16_11 + + dd 4096, 0x02000000, 5462, resample_2 ;17 PCM_2_16_8 + dd 2048, 0x02000000, 5462, resample_1 ;18 PCM_1_16_8 + + dd 16384, 0, 0, s8_stereo ;19 PCM_2_8_48 + dd 8192, 0, 0, m8_stereo ;20 PCM_1_8_48 + + dd 8192, 0x08000000, 30109, resample_28 ;21 PCM_2_8_44 + dd 4096, 0x08000000, 30109, resample_18 ;22 PCM_1_8_44 + + dd 8192, 0x08000000, 21846, resample_28 ;23 PCM_2_8_32 + dd 4096, 0x08000000, 21846, resample_18 ;24 PCM_1_8_32 + + dd 8192, 0x08000000, 16384, resample_28 ;25 PCM_2_8_24 + dd 4096, 0x08000000, 16384, resample_18 ;26 PCM_1_8_24 + + dd 4096, 0x04000000, 15052, resample_28 ;27 PCM_2_8_22 + dd 2048, 0x04000000, 15052, resample_18 ;28 PCM_1_8_22 + + dd 4096, 0x04000000, 10923, resample_28 ;29 PCM_2_8_16 + dd 2048, 0x04000000, 10923, resample_18 ;30 PCM_1_8_16 + + dd 4096, 0x04000000, 8192, resample_28 ;31 PCM_2_8_12 + dd 2048, 0x04000000, 8192, resample_18 ;32 PCM_1_8_12 + + dd 2048, 0x02000000, 7527, resample_28 ;33 PCM_2_8_11 + dd 1024, 0x02000000, 7527, resample_18 ;34 PCM_1_8_11 + + dd 2048, 0x02000000, 5462, resample_28 ;35 PCM_2_8_8 + dd 1024, 0x02000000, 5462, resample_18 ;36 PCM_1_8_8 + + +play_count dd 0 + +stream_count dd 0 + +align 8 +hSound dd 0 + +m7 dw 0x8000,0x8000,0x8000,0x8000 +mm80 dq 0x8080808080808080 +mm_mask dq 0xFF00FF00FF00FF00 + +mix_input dd 16 dup(0) + +align 16 +;fpu_state db 512 dup(0) + +align 16 +stream db STREAM_SIZE*16 dup(0) +stream_map dd 0xFFFF ; 16 +mix_buff dd 0 +mix_buff_map dd 0 + +align 16 +IMPORTS: + +AttachIntHandler dd szAttachIntHandler +SysMsgBoardStr dd szSysMsgBoardStr +PciApi dd szPciApi +PciRead32 dd szPciRead32 +PciRead8 dd szPciRead8 +AllocKernelSpace dd szAllocKernelSpace +MapPage dd szMapPage +KernelAlloc dd szKernelAlloc +KernelFree dd szKernelFree +GetPgAddr dd szGetPgAddr +RegService dd szRegService +GetCurrentTask dd szGetCurrentTask +GetService dd szGetService +ServiceHandler dd szServiceHandler +FpuSave dd szFpuSave +FpuRestore dd szFpuRestore + dd 0 + +szKernel db 'KERNEL', 0 +szAttachIntHandler db 'AttachIntHandler',0 +szSysMsgBoardStr db 'SysMsgBoardStr', 0 +szPciApi db 'PciApi', 0 +szPciRead32 db 'PciRead32', 0 +szPciRead8 db 'PciRead8', 0 +szAllocKernelSpace db 'AllocKernelSpace',0 +szMapPage db 'MapPage',0 +szRegService db 'RegService',0 +szKernelAlloc db 'KernelAlloc',0 +szGetPgAddr db 'GetPgAddr',0 +szGetCurrentTask db 'GetCurrentTask ',0 +szGetService db 'GetService',0 +szServiceHandler db 'ServiceHandler',0 +szKernelFree db 'KernelFree',0 +szFpuSave db 'FpuSave',0 +szFpuRestore db 'FpuRestore',0 + + +szInfinity db 'INFINITY',0 +szSound db 'SOUND',0 + +if DEBUG +msgFail db 'Sound service not found',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 +end if diff --git a/kernel/trunk/drivers/main.inc b/kernel/trunk/drivers/main.inc new file mode 100644 index 0000000000..1a4c5e8a55 --- /dev/null +++ b/kernel/trunk/drivers/main.inc @@ -0,0 +1,133 @@ +; +; This file is part of the Infinity sound AC97 driver. +; (C) copyright Serge 2006 +; email: infinity_sound@mail.ru +; +; This program is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. + +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_8_48 equ 17 +PCM_1_8_48 equ 18 + +PCM_2_8_44 equ 19 +PCM_1_8_44 equ 20 + +PCM_2_8_32 equ 21 +PCM_1_8_32 equ 22 + +PCM_2_8_24 equ 23 +PCM_1_8_24 equ 24 + +PCM_2_8_22 equ 25 +PCM_1_8_22 equ 26 + +PCM_2_8_16 equ 27 +PCM_1_8_16 equ 28 + +PCM_2_8_12 equ 29 +PCM_1_8_12 equ 30 + +PCM_2_8_11 equ 31 +PCM_1_8_11 equ 32 + +SND_PLAY equ 1 +SND_STOP equ 2 + +; struc SND_DEV +;{ .magic dd 0 +; .size dd 0 +; .count dd 0 +; dd 0 +; .snd_buff dd 16 dup (0) +;} + +;virtual at 0 +; SND_DEV SND_DEV +;end virtual + +;SND_DEV_SIZE equ 80 + + +struc STREAM +{ .magic dd 0 + .size dd 0 + .device dd 0 + .format dd 0 + .flags dd 0 + + .work_buff dd 0 + .work_read dd 0 + .work_write dd 0 + .work_count dd 0 + .work_top dd 0 + .r_buff dd 0 + .r_size dd 0 + .r_end dd 0 + .r_dt dd 0 + .r_silence dd 0 + + .base dd 0 + .curr_seg dd 0 + .limit dd 0 + .buff_size dd 0 + .notify_off1 dd 0 + .notify_off2 dd 0 + .notify_task dd 0 + .resample dd 0 +} + +STREAM_SIZE equ 23*4 + +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 ? +} + diff --git a/kernel/trunk/drivers/mixer.asm b/kernel/trunk/drivers/mixer.asm new file mode 100644 index 0000000000..72d90deb68 --- /dev/null +++ b/kernel/trunk/drivers/mixer.asm @@ -0,0 +1,1290 @@ +; +; This file is part of the Infinity sound library. +; (C) copyright Serge 2006 +; email: infinity_sound@mail.ru +; +; This program is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. + +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 +; mov eax, fpu_state +; fnsave [eax] + call [FpuSave] + emms + 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 + + sub [main_count], 1 + jnz .l00 + + call update_stream + call [FpuRestore] + ret +.exit: + mov edi, [output] + mov ecx, 0x1000 + xor eax, eax + cld + rep stosd + ret +endp + + +align 4 +proc update_stream + locals + stream_index dd 0 + endl + + mov [stream_index], 0 +.l1: + mov edx, [stream_index] + mov esi, [play_list+edx*4] + + mov eax, [esi+STREAM.work_read] + cmp eax, [esi+STREAM.work_top] + jb @f + mov eax, [esi+STREAM.work_buff] +@@: + mov [esi+STREAM.work_read], eax + + cmp [esi+STREAM.format], PCM_2_16_48 + je .copy + + sub [esi+STREAM.work_count], 16384 + + cmp [esi+STREAM.work_count], 32768 + ja @f + + stdcall refill, esi +@@: + inc [stream_index] + dec [play_count] + jnz .l1 + + ret +.copy: + mov ebx, esi + mov edi, [ebx+STREAM.work_write] + cmp edi, [ebx+STREAM.work_top] + jb @f + mov edi, [ebx+STREAM.work_buff] + mov [ebx+STREAM.work_write], edi +@@: + mov esi, [ebx+STREAM.curr_seg] + mov ecx, 16384/4 + cld + rep movsd + + mov [ebx+STREAM.work_write], edi + + cmp esi, [ebx+STREAM.limit] + jb @f + + mov esi, [ebx+STREAM.base] +@@: + mov [ebx+STREAM.curr_seg], esi + + xor ecx, ecx + cmp esi, [ebx+STREAM.notify_off2] + je @f + + mov ecx,0x8000 + cmp esi, [ebx+STREAM.notify_off1] + je @f + + inc [stream_index] + dec [play_count] + jnz .l1 + + ret +@@: + mov eax, [ebx+STREAM.notify_task] + call pid_to_slot + test eax, eax + jnz @f + not eax + mov [ebx+STREAM.notify_task], eax ;-1 + jmp .l_end +@@: + shl eax, 8 + mov [eax+PROC_BASE+32],ecx + or dword [eax+PROC_BASE+0xA8],EVENT_NOTIFY +.l_end: + inc [stream_index] + dec [play_count] + jnz .l1 + ret +endp + +align 4 +proc refill stdcall, str:dword + +; if DEBUG +; mov esi, msgUser +; call [SysMsgBoardStr] +; end if + + mov ebx, [str] + + mov ecx, [ebx+STREAM.work_write] + cmp ecx, [ebx+STREAM.work_top] + jbe .m2 + mov esi, [ebx+STREAM.work_top] + sub ecx, esi + mov edi, [ebx+STREAM.work_buff] + shr ecx, 2 + rep movsd ;call memcpy + + mov [ebx+STREAM.work_write], edi +.m2: + mov esi, [ebx+STREAM.curr_seg] + mov edi, [ebx+STREAM.work_write] + mov edx, [ebx+STREAM.r_buff] + + stdcall [ebx+STREAM.resample], edi, esi, edx,\ + [ebx+STREAM.r_dt],[ebx+STREAM.r_size],[ebx+STREAM.r_end] + + mov ebx, [str] + + add [ebx+STREAM.work_count], eax; + add [ebx+STREAM.work_write], eax; + + mov eax, [ebx+STREAM.curr_seg] + add eax, [ebx+STREAM.r_size] + cmp eax, [ebx+STREAM.limit] + jb @f + mov eax, [ebx+STREAM.base] +@@: + mov [ebx+STREAM.curr_seg], eax + + xor ecx, ecx + cmp eax, [ebx+STREAM.notify_off2] + je @f + + mov ecx,0x8000 + cmp eax, [ebx+STREAM.notify_off1] + je @f + + ret +@@: + mov eax, [ebx+STREAM.notify_task] + call pid_to_slot + test eax, eax + jnz @f + not eax + mov [ebx+STREAM.notify_task], eax ;-1 + ret +@@: + shl eax, 8 + mov [eax+PROC_BASE+32],ecx + or dword [eax+PROC_BASE+0xA8],EVENT_NOTIFY + ret +endp + +align 4 +proc resample_1 stdcall, dest:dword,src:dword,r_buff:dword,\ + r_dt:dword, r_size:dword,r_end:dword + + mov edi, [r_buff] + add edi, 32*2 + mov esi, [src] + mov ecx, [r_size] + shr ecx, 2 + rep movsd + + mov edi, [dest] + mov edx, [r_buff] + mov eax, 16 + +align 16 +.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+20] ;rdt + cmp eax, [esp+28] ;r_end + jb .l1 + + mov ebp, esp + + mov esi, [src] + add esi, [r_size] + sub esi, 32*2 + mov edx, [r_buff] + mov ecx, 16 +@@: + mov ebx, [esi] + mov [edx], ebx + add esi, 4 + add edx, 4 + dec ecx + jnz @B + + sub edi, [dest] + mov eax, edi + ret +endp + +align 4 +proc resample_18 stdcall, dest:dword,src:dword,r_buff:dword,\ + r_dt:dword, r_size:dword,r_end:dword + + mov edi, [r_buff] + add edi, 32 + mov esi, [src] + mov ecx, [r_size] + shr ecx, 2 + rep movsd + + mov edi, [dest] + mov edx, [r_buff] + mov esi, 16 + +align 16 +.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+20] ;rdt + cmp esi, [esp+28] ;r_end + jb .l1 + + mov ebp, esp + + mov esi, [src] + add esi, [r_size] + sub esi, 32 + mov edx, [r_buff] + mov ecx, 8 +@@: + mov ebx, [esi] + mov [edx], ebx + add esi, 4 + add edx, 4 + dec ecx + jnz @B + + sub edi, [dest] + mov eax, edi + ret +endp + +align 4 +proc copy_stream stdcall, dest:dword,src:dword,r_buff: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] + rep movsd + mov eax, 16384 + ret +endp + +align 4 +proc resample_2 stdcall, dest:dword,src:dword,r_buff:dword,\ + r_dt:dword, r_size:dword,r_end:dword + + mov edi, [r_buff] + add edi, 32*4 + mov esi, [src] + mov ecx, [r_size] + shr ecx, 2 + rep movsd ;call memcpy + + mov edx, [r_buff] + mov edi, [dest] + mov ebx, [r_dt] + mov eax, 16 + emms + +align 16 +.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 + + mov esi, [src] + add esi, [r_size] + sub esi, 32*4 + mov edx, [r_buff] + mov ecx, 32 +@@: + mov ebx, [esi] + mov [edx], ebx + add esi, 4 + add edx, 4 + dec ecx + jnz @B + + sub edi, [dest] + mov eax, edi + ret +endp + +align 4 +proc resample_28 stdcall, dest:dword,src:dword,r_buff:dword,\ + r_dt:dword, r_size:dword,r_end:dword + + mov edi, [r_buff] + add edi, 32*2 + mov esi, [src] + mov ecx, [r_size] + shr ecx, 2 + rep movsd ;call memcpy + + mov edx, [r_buff] + mov edi, [dest] + mov ebx, [r_dt] + mov eax, 16 + emms + movq mm7,[mm80] + movq mm6,[mm_mask] + +align 16 +.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 + + mov esi, [src] + add esi, [r_size] + sub esi, 32*2 + mov edx, [r_buff] + mov ecx, 16 +@@: + mov ebx, [esi] + mov [edx], ebx + add esi, 4 + add edx, 4 + dec ecx + jnz @B + + sub edi, [dest] + mov eax, edi + ret +endp + + +proc m16_stereo stdcall, dest:dword,src:dword,r_buff: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_buff: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_buff: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 + +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] + + stdcall mix_2_1_mmx, edi, [str0],[str1] + add edi, 128 + add [str0], 128 + add [str1], 128 + stdcall mix_2_1_mmx, edi, [str0],[str1] + add edi, 128 + add [str0], 128 + add [str1], 128 + stdcall mix_2_1_mmx, edi, [str0],[str1] + add edi, 128 + add [str0], 128 + add [str1], 128 + stdcall mix_2_1_mmx, edi, [str0],[str1] + + ret +endp + + +align 4 +proc mix_3_1 stdcall, output:dword, str0:dword, str1:dword, str2:dword + + mov edi, [output] + + stdcall mix_3_1_mmx, edi, [str0],[str1],[str2] + add edi, 128 + add [str0], 128 + add [str1], 128 + add [str2], 128 + stdcall mix_3_1_mmx, edi, [str0],[str1],[str2] + add edi, 128 + add [str0], 128 + add [str1], 128 + add [str2], 128 + stdcall mix_3_1_mmx, edi, [str0],[str1],[str2] + add edi, 128 + add [str0], 128 + add [str1], 128 + add [str2], 128 + stdcall mix_3_1_mmx, edi, [str0],[str1],[str2] + + 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 + + stdcall mix_4_1_mmx, edi, [str0],[str1],[str2],[str3] + add edi, 128 + add [str0], 128 + add [str1], 128 + add [str2], 128 + add [str3], 128 + stdcall mix_4_1_mmx, edi, [str0],[str1],[str2],[str3] + add edi, 128 + add [str0], 128 + add [str1], 128 + add [str2], 128 + add [str3], 128 + stdcall mix_4_1_mmx, edi, [str0],[str1],[str2],[str3] + add edi, 128 + add [str0], 128 + add [str1], 128 + add [str2], 128 + add [str3], 128 + stdcall mix_4_1_mmx, edi, [str0],[str1],[str2],[str3] + 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] + + stdcall mix_4_1_mmx, edi, [str0],[str1],[str2],[str3] + add edi, 128 + add [str0], 128 + add [str1], 128 + add [str2], 128 + add [str3], 128 + stdcall mix_4_1_mmx, edi, [str0],[str1],[str2],[str3] + add edi, 128 + add [str0], 128 + add [str1], 128 + add [str2], 128 + add [str3], 128 + stdcall mix_4_1_mmx, edi, [str0],[str1],[str2],[str3] + add edi, 128 + add [str0], 128 + add [str1], 128 + add [str2], 128 + add [str3], 128 + stdcall mix_4_1_mmx, edi, [str0],[str1],[str2],[str3] + + ret +endp + +align 4 +proc mix_2_1_mmx stdcall, output:dword, str0:dword, str1:dword + + mov edx, [output] + mov eax, [str0] + mov ecx, [str1] + + movq mm0, [eax] + paddsw mm0, [ecx] + ; psraw mm0, 1 + movq [edx], mm0 + + movq mm1, [eax+8] + paddsw mm1,[ecx+8] + ; psraw mm1, 1 + movq [edx+8], mm1 + + movq mm2, [eax+16] + paddsw mm2, [ecx+16] + ; psraw mm2, 1 + movq [edx+16], mm2 + + movq mm3, [eax+24] + paddsw mm3, [ecx+24] + ; psraw mm3, 1 + movq [edx+24], mm3 + + movq mm0, [eax+32] + paddsw mm0, [ecx+32] + ; psraw mm0, 1 + movq [edx+32], mm0 + + movq mm1, [eax+40] + paddsw mm1, [ecx+40] + ; psraw mm1, 1 + movq [edx+40], mm1 + + movq mm2, [eax+48] + paddsw mm2, [ecx+48] + ; psraw mm2, 1 + movq [edx+48], mm2 + + movq mm3, [eax+56] + paddsw mm3, [ecx+56] + ; psraw mm3, 1 + movq [edx+56], mm3 + + movq mm0, [eax+64] + paddsw mm0, [ecx+64] + ; psraw mm0, 1 + movq [edx+64], mm0 + + movq mm1, [eax+72] + paddsw mm1, [ecx+72] + ; psraw mm1, 1 + movq [edx+72], mm1 + + movq mm2, [eax+80] + paddsw mm2, [ecx+80] + ; psraw mm2, 1 + movq [edx+80], mm2 + + movq mm3, [eax+88] + paddsw mm3, [ecx+88] + ; psraw mm3, 1 + + movq [edx+88], mm3 + + movq mm0, [eax+96] + paddsw mm0, [ecx+96] + ; psraw mm0, 1 + + movq [edx+96], mm0 + + movq mm1, [eax+104] + paddsw mm1, [ecx+104] + ; psraw mm1, 1 + + movq [edx+104], mm1 + + movq mm2, [eax+112] + paddsw mm2, [ecx+112] + ; psraw mm2, 1 + + movq [edx+112], mm2 + + movq mm3, [eax+120] + paddsw mm3, [ecx+120] + ; psraw mm3, 1 + + movq [edx+120], mm3 + + ret +endp + +align 4 +proc mix_3_1_mmx stdcall, output:dword, str0:dword, str1:dword, str2:dword + + mov edx, [output] + mov eax, [str0] + mov ebx, [str1] + mov ecx, [str2] + + movq mm0, [eax] + paddsw mm0, [ebx] + paddsw mm0, [ecx] + movq [edx], mm0 + + movq mm1, [eax+8] + paddsw mm1,[ebx+8] + paddsw mm1,[ecx+8] + movq [edx+8], mm1 + + movq mm2, [eax+16] + paddsw mm2, [ebx+16] + paddsw mm2, [ecx+16] + movq [edx+16], mm2 + + movq mm3, [eax+24] + paddsw mm3, [ebx+24] + paddsw mm3, [ecx+24] + movq [edx+24], mm3 + + movq mm0, [eax+32] + paddsw mm0, [ebx+32] + paddsw mm0, [ecx+32] + movq [edx+32], mm0 + + movq mm1, [eax+40] + paddsw mm1, [ebx+40] + paddsw mm1, [ecx+40] + movq [edx+40], mm1 + + movq mm2, [eax+48] + paddsw mm2, [ebx+48] + paddsw mm2, [ecx+48] + movq [edx+48], mm2 + + movq mm3, [eax+56] + paddsw mm3, [ebx+56] + paddsw mm3, [ecx+56] + movq [edx+56], mm3 + + movq mm0, [eax+64] + paddsw mm0, [ebx+64] + paddsw mm0, [ecx+64] + movq [edx+64], mm0 + + movq mm1, [eax+72] + paddsw mm1, [ebx+72] + paddsw mm1, [ecx+72] + movq [edx+72], mm1 + + movq mm2, [eax+80] + paddsw mm2, [ebx+80] + paddsw mm2, [ecx+80] + movq [edx+80], mm2 + + movq mm3, [eax+88] + paddsw mm3, [ebx+88] + paddsw mm3, [ecx+88] + movq [edx+88], mm3 + + movq mm0, [eax+96] + paddsw mm0, [ebx+96] + paddsw mm0, [ecx+96] + movq [edx+96], mm0 + + movq mm1, [eax+104] + paddsw mm1, [ebx+104] + paddsw mm1, [ecx+104] + movq [edx+104], mm1 + + movq mm2, [eax+112] + paddsw mm2, [ebx+112] + paddsw mm2, [ecx+112] + movq [edx+112], mm2 + + movq mm3, [eax+120] + paddsw mm3, [ebx+120] + paddsw mm3, [ecx+120] + movq [edx+120], mm3 + + ret +endp + +align 4 +proc mix_4_1_mmx stdcall, output:dword, str0:dword, str1:dword,\ + str2:dword, str3:dword + + mov edx, [output] + mov esi, [str0] + mov eax, [str1] + mov ebx, [str2] + mov ecx, [str3] + + movq mm0, [esi] + movq mm1, [eax] + paddsw mm0, [ebx] + paddsw mm1, [ecx] + paddsw mm0, mm1 + movq [edx], mm0 + + movq mm2, [esi+8] + movq mm3, [eax+8] + paddsw mm2, [ebx+8] + paddsw mm3, [ecx+8] + paddsw mm2, mm3 + movq [edx+8], mm2 + + movq mm0, [esi+16] + movq mm1, [eax+16] + paddsw mm0, [ebx+16] + paddsw mm1, [ecx+16] + paddsw mm0, mm1 + movq [edx+16], mm0 + + movq mm2, [esi+24] + movq mm3, [eax+24] + paddsw mm2, [ebx+24] + paddsw mm3, [ecx+24] + paddsw mm2, mm3 + movq [edx+24], mm2 + + movq mm0, [esi+32] + movq mm1, [eax+32] + paddsw mm0, [ebx+32] + paddsw mm1, [ecx+32] + paddsw mm0, mm1 + movq [edx+32], mm0 + + movq mm2, [esi+40] + movq mm3, [eax+40] + paddsw mm2, [ebx+40] + paddsw mm3, [ecx+40] + paddsw mm2, mm3 + movq [edx+40], mm2 + + movq mm0, [esi+48] + movq mm1, [eax+48] + paddsw mm0, [ebx+48] + paddsw mm1, [ecx+48] + paddsw mm0, mm1 + movq [edx+48], mm0 + + movq mm2, [esi+56] + movq mm3, [eax+56] + paddsw mm2, [ebx+56] + paddsw mm3, [ecx+56] + paddsw mm2, mm3 + movq [edx+56], mm2 + + movq mm0, [esi+64] + movq mm1, [eax+64] + paddsw mm0, [ebx+64] + paddsw mm1, [ecx+64] + paddsw mm0, mm1 + movq [edx+64], mm0 + + movq mm2, [esi+72] + movq mm3, [eax+72] + paddsw mm2, [ebx+72] + paddsw mm3, [ecx+72] + paddsw mm2, mm3 + movq [edx+72], mm2 + + movq mm2, [esi+80] + movq mm3, [eax+80] + paddsw mm2, [ebx+80] + paddsw mm3, [ecx+80] + paddsw mm2, mm3 + movq [edx+80], mm2 + + movq mm2, [esi+88] + movq mm3, [eax+88] + paddsw mm2, [ebx+88] + paddsw mm3, [ecx+88] + paddsw mm2, mm3 + movq [edx+88], mm2 + + movq mm2, [esi+96] + movq mm3, [eax+96] + paddsw mm2, [ebx+96] + paddsw mm3, [ecx+96] + paddsw mm2, mm3 + movq [edx+96], mm2 + + movq mm2, [esi+104] + movq mm3, [eax+104] + paddsw mm2, [ebx+104] + paddsw mm3, [ecx+104] + paddsw mm2, mm3 + movq [edx+104], mm2 + + movq mm2, [esi+112] + movq mm3, [eax+112] + paddsw mm2, [ebx+112] + paddsw mm3, [ecx+112] + paddsw mm2, mm3 + movq [edx+112], mm2 + + movq mm2, [esi+120] + movq mm3, [eax+120] + paddsw mm2, [ebx+120] + paddsw mm3, [ecx+120] + paddsw mm2, mm3 + movq [edx+120], mm2 + + 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 + + + diff --git a/kernel/trunk/drivers/proc32.inc b/kernel/trunk/drivers/proc32.inc new file mode 100644 index 0000000000..23c56b03c1 --- /dev/null +++ b/kernel/trunk/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, \{ 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: + \\\{ 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 } diff --git a/kernel/trunk/drivers/sis.asm b/kernel/trunk/drivers/sis.asm new file mode 100644 index 0000000000..9fe34d73b0 --- /dev/null +++ b/kernel/trunk/drivers/sis.asm @@ -0,0 +1,1177 @@ + +format MS COFF + + +include 'proc32.inc' + +DEBUG equ 1 + +CPU_FREQ equ 2000d ;cpu freq in MHz + +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 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 0 + .devfn dd 0 + + .vendor dd 0 + .dev_id dd 0 + .pci_cmd dd 0 + .pci_stat dd 0 + + .codec_io_base dd 0 + .codec_mem_base dd 0 + + .ctrl_io_base dd 0 + .ctrl_mem_base dd 0 + .cfg_reg dd 0 + .int_line dd 0 + + .vendor_ids dd 0 ;vendor id string + .ctrl_ids dd 0 ;hub id string + + .buffer dd 0 + + .notify_pos dd 0 + .notify_task dd 0 + + .lvi_reg dd 0 + .ctrl_setup dd 0 + .user_callback dd 0 + .codec_read16 dd 0 + .codec_write16 dd 0 + + .ctrl_read8 dd 0 + .ctrl_read16 dd 0 + .ctrl_read32 dd 0 + + .ctrl_write8 dd 0 + .ctrl_write16 dd 0 + .ctrl_write32 dd 0 +} + +struc CODEC ;Audio Chip base class +{ + .chip_id dd 0 + .flags dd 0 + .status dd 0 + + .ac_vendor_ids dd 0 ;ac vendor id string + .chip_ids dd 0 ;chip model string + + .shadow_flag dd 0 + dd 0 + + .regs dw 0 ; codec registers + .reg_master_vol dw 0 ;0x02 + .reg_aux_out_vol dw 0 ;0x04 + .reg_mone_vol dw 0 ;0x06 + .reg_master_tone dw 0 ;0x08 + .reg_beep_vol dw 0 ;0x0A + .reg_phone_vol dw 0 ;0x0C + .reg_mic_vol dw 0 ;0x0E + .reg_line_in_vol dw 0 ;0x10 + .reg_cd_vol dw 0 ;0x12 + .reg_video_vol dw 0 ;0x14 + .reg_aux_in_vol dw 0 ;0x16 + .reg_pcm_out_vol dw 0 ;0x18 + .reg_rec_select dw 0 ;0x1A + .reg_rec_gain dw 0 ;0x1C + .reg_rec_gain_mic dw 0 ;0x1E + .reg_gen dw 0 ;0x20 + .reg_3d_ctrl dw 0 ;0X22 + .reg_page dw 0 ;0X24 + .reg_powerdown dw 0 ;0x26 + .reg_ext_audio dw 0 ;0x28 + .reg_ext_st dw 0 ;0x2a + .reg_pcm_front_rate dw 0 ;0x2c + .reg_pcm_surr_rate dw 0 ;0x2e + .reg_lfe_rate dw 0 ;0x30 + .reg_pcm_in_rate dw 0 ;0x32 + dw 0 ;0x34 + .reg_cent_lfe_vol dw 0 ;0x36 + .reg_surr_vol dw 0 ;0x38 + .reg_spdif_ctrl dw 0 ;0x3A + dw 0 ;0x3C + dw 0 ;0x3E + dw 0 ;0x40 + dw 0 ;0x42 + dw 0 ;0x44 + dw 0 ;0x46 + dw 0 ;0x48 + dw 0 ;0x4A + dw 0 ;0x4C + dw 0 ;0x4E + dw 0 ;0x50 + dw 0 ;0x52 + dw 0 ;0x54 + dw 0 ;0x56 + dw 0 ;0x58 + dw 0 ;0x5A + dw 0 ;0x5C + dw 0 ;0x5E + .reg_page_0 dw 0 ;0x60 + .reg_page_1 dw 0 ;0x62 + .reg_page_2 dw 0 ;0x64 + .reg_page_3 dw 0 ;0x66 + .reg_page_4 dw 0 ;0x68 + .reg_page_5 dw 0 ;0x6A + .reg_page_6 dw 0 ;0x6C + .reg_page_7 dw 0 ;0x6E + dw 0 ;0x70 + dw 0 ;0x72 + dw 0 ;0x74 + dw 0 ;0x76 + dw 0 ;0x78 + dw 0 ;0x7A + .reg_vendor_id_1 dw 0 ;0x7C + .reg_vendor_id_2 dw 0 ;0x7E + + + .reset dd 0 ;virual + .set_master_vol dd 0 +} + +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 0; 0x80400000 +new_app_base equ 0x60400000; 0x01000000 +PROC_BASE equ OS_BASE+0x0080000 + + +public service_proc +public START +public IMPORTS + +section '.flat' align 16 + +START: + 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 + + 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 + + stdcall [AttachIntHandler], [ctrl.int_line], ac97_irq + + stdcall [RegService], sz_sound_srv, service_proc + + mov esi, msgOk + call [SysMsgBoardStr] + + ret + +.fail: + if DEBUG + mov esi, msgFail + call [SysMsgBoardStr] + end if + + xor eax, eax + ret + +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 ebx, [edi+input] + stdcall set_master_vol, [ebx] + ret +@@: + cmp eax, DEV_GET_MASTERVOL + jne @F + mov ebx, [edi+output] + test ebx, ebx + jz .fail + + stdcall get_master_vol, ebx + ret +@@: + cmp eax, DEV_GET_INFO + jne @F + mov ebx, [edi+output] + stdcall get_dev_info, ebx + ret +@@: +.fail: + xor eax, eax + 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 + + mov edx, PCM_OUT_CR_REG + mov al, 0x14 + 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, 0x1D + call [ctrl.ctrl_write8] + + mov eax, [civ_val] + add eax, 2 + 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, 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 + rep stosd + + stdcall [GetPgAddr], [ctrl.buffer] + + 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 ecx, pcmout_bdl + stdcall [GetPgAddr], ecx + and ecx, 0xFFF + add eax, ecx + + 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 + + stdcall [PciRead32], [ctrl.bus], [ctrl.devfn], dword 0x10 + and eax,0xFFFE + mov [ctrl.codec_io_base], eax + + stdcall [PciRead32], [ctrl.bus], [ctrl.devfn], dword 0x14 + and eax, 0xFFC0 + mov [ctrl.ctrl_io_base], eax + + stdcall [PciRead32], [ctrl.bus], [ctrl.devfn], dword 0x18 + mov [ctrl.codec_mem_base], eax + + stdcall [PciRead32], [ctrl.bus], [ctrl.devfn], dword 0x1C + mov [ctrl.ctrl_mem_base], eax + + 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 + + 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: + 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 +proc 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] + ret +endp + +align 4 +proc stop + mov edx, PCM_OUT_CR_REG + mov ax, 0x14 + call [ctrl.ctrl_write8] + + mov eax, 16 + mov [ctrl.lvi_reg], eax + mov edx, PCM_OUT_LVI_REG + call [ctrl.ctrl_write8] + + ret +endp + +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 + +align 4 +.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 + jb @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 + +include "codec.inc" + + +align 16 +pcmout_bdl dq 32 dup(0) +buff_list dd 32 dup(0) + +align 16 +ctrl AC_CNTRL + +align 16 +codec CODEC + +civ_val dd 0 + +align 16 +devices dd (CTRL_SIS shl 16)+VID_SIS,msg_AC, set_SIS + dd 0 + +align 16 +imp_table: +IMPORTS: + +AttachIntHandler dd szAttachIntHandler +SysMsgBoardStr dd szSysMsgBoardStr +PciApi dd szPciApi +PciRead32 dd szPciRead32 +PciRead8 dd szPciRead8 +PciWrite8 dd szPciWrite8 +AllocKernelSpace dd szAllocKernelSpace +MapPage dd szMapPage +KernelAlloc dd szKernelAlloc +GetPgAddr dd szGetPgAddr +RegService dd szRegService +GetCurrentTask dd szGetCurrentTask + dd 0 + +msg_AC db '7012 AC97 controller',13,10, 0 +msg_SIS db 'Silicon Integrated Systems',13,10, 0 + +szKernel db 'KERNEL', 0 +szAttachIntHandler db 'AttachIntHandler',0 +szSysMsgBoardStr db 'SysMsgBoardStr', 0 +szPciApi db 'PciApi', 0 +szPciRead32 db 'PciRead32', 0 +szPciRead8 db 'PciRead8', 0 +szPciWrite8 db 'PciWrite8',0 +szAllocKernelSpace db 'AllocKernelSpace',0 +szMapPage db 'MapPage',0 +szRegService db 'RegService',0 +szKernelAlloc db 'KernelAlloc',0 +szGetPgAddr db 'GetPgAddr',0 +szGetCurrentTask db 'GetCurrentTask ',0 + +sz_sound_srv db 'SOUND',0 + +msgInit db 'detect hardware...',13,10,0 +msgFail db 'device not found',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 resret',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 diff --git a/kernel/trunk/drivers/unisound.asm b/kernel/trunk/drivers/unisound.asm new file mode 100644 index 0000000000..b2828d5f16 --- /dev/null +++ b/kernel/trunk/drivers/unisound.asm @@ -0,0 +1,1394 @@ + +format MS COFF + + +include 'proc32.inc' + +DEBUG equ 1 + +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 + +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 + + +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 0 + .devfn dd 0 + + .vendor dd 0 + .dev_id dd 0 + .pci_cmd dd 0 + .pci_stat dd 0 + + .codec_io_base dd 0 + .codec_mem_base dd 0 + + .ctrl_io_base dd 0 + .ctrl_mem_base dd 0 + .cfg_reg dd 0 + .int_line dd 0 + + .vendor_ids dd 0 ;vendor id string + .ctrl_ids dd 0 ;hub id string + + .buffer dd 0 + + .notify_pos dd 0 + .notify_task dd 0 + + .lvi_reg dd 0 + .ctrl_setup dd 0 + .user_callback dd 0 + .codec_read16 dd 0 + .codec_write16 dd 0 + + .ctrl_read8 dd 0 + .ctrl_read16 dd 0 + .ctrl_read32 dd 0 + + .ctrl_write8 dd 0 + .ctrl_write16 dd 0 + .ctrl_write32 dd 0 +} + +struc CODEC ;Audio Chip base class +{ + .chip_id dd 0 + .flags dd 0 + .status dd 0 + + .ac_vendor_ids dd 0 ;ac vendor id string + .chip_ids dd 0 ;chip model string + + .shadow_flag dd 0 + dd 0 + + .regs dw 0 ; codec registers + .reg_master_vol dw 0 ;0x02 + .reg_aux_out_vol dw 0 ;0x04 + .reg_mone_vol dw 0 ;0x06 + .reg_master_tone dw 0 ;0x08 + .reg_beep_vol dw 0 ;0x0A + .reg_phone_vol dw 0 ;0x0C + .reg_mic_vol dw 0 ;0x0E + .reg_line_in_vol dw 0 ;0x10 + .reg_cd_vol dw 0 ;0x12 + .reg_video_vol dw 0 ;0x14 + .reg_aux_in_vol dw 0 ;0x16 + .reg_pcm_out_vol dw 0 ;0x18 + .reg_rec_select dw 0 ;0x1A + .reg_rec_gain dw 0 ;0x1C + .reg_rec_gain_mic dw 0 ;0x1E + .reg_gen dw 0 ;0x20 + .reg_3d_ctrl dw 0 ;0X22 + .reg_page dw 0 ;0X24 + .reg_powerdown dw 0 ;0x26 + .reg_ext_audio dw 0 ;0x28 + .reg_ext_st dw 0 ;0x2a + .reg_pcm_front_rate dw 0 ;0x2c + .reg_pcm_surr_rate dw 0 ;0x2e + .reg_lfe_rate dw 0 ;0x30 + .reg_pcm_in_rate dw 0 ;0x32 + dw 0 ;0x34 + .reg_cent_lfe_vol dw 0 ;0x36 + .reg_surr_vol dw 0 ;0x38 + .reg_spdif_ctrl dw 0 ;0x3A + dw 0 ;0x3C + dw 0 ;0x3E + dw 0 ;0x40 + dw 0 ;0x42 + dw 0 ;0x44 + dw 0 ;0x46 + dw 0 ;0x48 + dw 0 ;0x4A + dw 0 ;0x4C + dw 0 ;0x4E + dw 0 ;0x50 + dw 0 ;0x52 + dw 0 ;0x54 + dw 0 ;0x56 + dw 0 ;0x58 + dw 0 ;0x5A + dw 0 ;0x5C + dw 0 ;0x5E + .reg_page_0 dw 0 ;0x60 + .reg_page_1 dw 0 ;0x62 + .reg_page_2 dw 0 ;0x64 + .reg_page_3 dw 0 ;0x66 + .reg_page_4 dw 0 ;0x68 + .reg_page_5 dw 0 ;0x6A + .reg_page_6 dw 0 ;0x6C + .reg_page_7 dw 0 ;0x6E + dw 0 ;0x70 + dw 0 ;0x72 + dw 0 ;0x74 + dw 0 ;0x76 + dw 0 ;0x78 + dw 0 ;0x7A + .reg_vendor_id_1 dw 0 ;0x7C + .reg_vendor_id_2 dw 0 ;0x7E + + + .reset dd 0 ;virual + .set_master_vol dd 0 +} + +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 0; 0x80400000 +new_app_base equ 0x60400000; 0x01000000 +PROC_BASE equ OS_BASE+0x0080000 + +public service_proc +public START +public IMPORTS + +section '.flat' align 16 + +START: + 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 + + 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 + +; if REMAP_IRQ + +; call get_LPC_bus +; cmp eax, -1 +; jz .fail + +; mov [lpc_bus], 0 ;eax +; call remap_irq +; end if + + 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 + + stdcall [RegService], sz_sound_srv, service_proc + + mov esi, msgOk + call [SysMsgBoardStr] + + ret + +.fail: + if DEBUG + mov esi, msgFail + call [SysMsgBoardStr] + end if + + xor eax, eax + ret + +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 ebx, [edi+input] + stdcall set_master_vol, [ebx] + ret +@@: + cmp eax, DEV_GET_MASTERVOL + jne @F + mov ebx, [edi+output] + test ebx, ebx + jz .fail + + stdcall get_master_vol, ebx + ret +@@: + cmp eax, DEV_GET_INFO + jne @F + mov ebx, [edi+output] + stdcall get_dev_info, ebx + ret +@@: +.fail: + xor eax, eax + ret +endp + +restore handle +restore io_code +restore input +restore inp_size +restore output +restore out_size + + +align 4 +proc remap_irq ;for Intel chipsets ONLY !!! + mov eax, VALID_IRQ + bt eax, IRQ_LINE + jnc .exit + + mov edx, 0x4D0 + in ax,dx + bts ax, IRQ_LINE + out dx, aX + + stdcall [PciWrite8], dword 0, dword 0xF8, dword 0x61, dword IRQ_LINE + mov [ctrl.int_line], IRQ_LINE + +.exit: + ret +endp + +align 4 +proc ac97_irq + +; if DEBUG +; mov esi, msgIRQ +; call [SysMsgBoardStr] +; end if + + mov edx, PCM_OUT_CR_REG + mov al, 0x14 + 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, 0x1D + call [ctrl.ctrl_write8] + + mov eax, [civ_val] + add eax, 2 + 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, 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 + + stdcall [GetPgAddr], [ctrl.buffer] + + 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 ecx, pcmout_bdl + stdcall [GetPgAddr], ecx + and ecx, 0xFFF + add eax, ecx + + 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, VID_INTEL + jne @F + mov [ctrl.vendor_ids], msg_Intel + ret +@@: + cmp ebx, VID_NVIDIA + jne @F + mov [ctrl.vendor_ids], msg_NVidia +@@: + mov [ctrl.vendor_ids], 0 ;something wrong ? + ret +.err: + xor eax, eax + ret +endp + +align 4 +proc get_LPC_bus ;for Intel chipsets ONLY !!! + locals + last_bus dd ? + bus dd ? + endl + + xor eax, eax + mov [bus], eax + inc eax + call [PciApi] + cmp eax, -1 + je .err + + mov [last_bus], eax +.next_bus: + stdcall [PciRead32], [bus], dword 0xF8, dword 0 + test eax, eax + jz .next + cmp eax, -1 + je .next + + cmp eax, 0x24D08086 + je .found +.next: + mov eax, [bus] + inc eax + cmp eax, [last_bus] + mov [bus], eax + jna .next_bus +.err: + xor eax, eax + dec eax + ret +.found: + mov eax, [bus] + 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 + + stdcall [PciRead32], [ctrl.bus], [ctrl.devfn], dword 0x10 + and eax,0xFFFE + mov [ctrl.codec_io_base], eax + + stdcall [PciRead32], [ctrl.bus], [ctrl.devfn], dword 0x14 + and eax, 0xFFC0 + mov [ctrl.ctrl_io_base], eax + + stdcall [PciRead32], [ctrl.bus], [ctrl.devfn], dword 0x18 + mov [ctrl.codec_mem_base], eax + + stdcall [PciRead32], [ctrl.bus], [ctrl.devfn], dword 0x1C + mov [ctrl.ctrl_mem_base], eax + + 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 [AllocKernelSpace], dword 0x2000 + mov edi, eax + stdcall [MapPage], edi,[ctrl.codec_mem_base],PG_SW+PG_NOCACHE + mov [ctrl.codec_mem_base], edi + add edi, 0x1000 + stdcall [MapPage], edi, [ctrl.ctrl_mem_base],PG_SW+PG_NOCACHE + mov [ctrl.ctrl_mem_base], edi + + 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 + + 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 +proc 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] + ret +endp + +align 4 +proc stop + mov edx, PCM_OUT_CR_REG + mov ax, 0x14 + call [ctrl.ctrl_write8] + + mov eax, 16 + mov [ctrl.lvi_reg], eax + mov edx, PCM_OUT_LVI_REG + call [ctrl.ctrl_write8] + + ret +endp + +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 + +align 4 +.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 + jb @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 + + +include "codec.inc" + + +align 16 +pcmout_bdl dq 32 dup(0) +buff_list dd 32 dup(0) + +align 16 +ctrl AC_CNTRL + +align 16 +codec CODEC + +lpc_bus dd 0 +civ_val dd 0 + +align 16 +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 0 ;terminator + +align 16 +imp_table: +IMPORTS: + +AttachIntHandler dd szAttachIntHandler +SysMsgBoardStr dd szSysMsgBoardStr +PciApi dd szPciApi +PciRead32 dd szPciRead32 +PciRead8 dd szPciRead8 +PciWrite8 dd szPciWrite8 +AllocKernelSpace dd szAllocKernelSpace +MapPage dd szMapPage +KernelAlloc dd szKernelAlloc +GetPgAddr dd szGetPgAddr +RegService dd szRegService +GetCurrentTask dd szGetCurrentTask + dd 0 + +msg_ICH db 'Intel ICH', 13,10, 0 +msg_ICH0 db 'Intel ICH0', 13,10, 0 +msg_ICH2 db 'Intel ICH2', 13,10, 0 +msg_ICH3 db 'Intel ICH3', 13,10, 0 +msg_ICH4 db 'Intel ICH4', 13,10, 0 +msg_ICH5 db 'Intel ICH5', 13,10, 0 +msg_ICH6 db 'Intel ICH6', 13,10, 0 +msg_ICH7 db 'Intel ICH7', 13,10, 0 +msg_Intel db 'Intel Corp. ', 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_NVidia db 'NVidea', 0 + + +szKernel db 'KERNEL', 0 +szAttachIntHandler db 'AttachIntHandler',0 +szSysMsgBoardStr db 'SysMsgBoardStr', 0 +szPciApi db 'PciApi', 0 +szPciRead32 db 'PciRead32', 0 +szPciRead8 db 'PciRead8', 0 +szPciWrite8 db 'PciWrite8',0 +szAllocKernelSpace db 'AllocKernelSpace',0 +szMapPage db 'MapPage',0 +szRegService db 'RegService',0 +szKernelAlloc db 'KernelAlloc',0 +szGetPgAddr db 'GetPgAddr',0 +szGetCurrentTask db 'GetCurrentTask ',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',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 + diff --git a/kernel/trunk/kernel.asm b/kernel/trunk/kernel.asm index 728bd84917..322b8715d6 100644 --- a/kernel/trunk/kernel.asm +++ b/kernel/trunk/kernel.asm @@ -120,7 +120,7 @@ app_data equ 3+app_data_l-gdts ; CR0 Flags - Protected mode and Paging - mov ecx, 0x00000021 + mov ecx, CR0_PE ; Enabling 32 bit protected mode @@ -399,9 +399,9 @@ include 'detect/disks.inc' mov eax, sys_pgdir ;+PG_NOCACHE mov cr3, eax - mov eax,cr0 - or eax,0x80000000 - mov cr0,eax + mov eax,cr0 + or eax,CR0_PG + mov cr0,eax call init_kernel_heap call init_LFB @@ -447,25 +447,48 @@ include 'detect/disks.inc' mov ecx, 16 rep movsb + clts + fninit + bt [cpu_caps], CAPS_FXSR jnc .no_FXSR stdcall kernel_alloc, 512*256 mov [fpu_data], eax + mov ebx, cr4 - or ebx, CR4_OSFXSR + mov ecx, cr0 + or ebx, CR4_OSFXSR+CR4_OSXMMEXPT mov cr4, ebx - jmp .clts + + and ecx, not (CR0_MP+CR0_EM) + or ecx, CR0_NE + mov cr0, ecx + + mov dword [esp-4], SSE_INIT + ldmxcsr [esp-4] + + xorps xmm0, xmm0 + xorps xmm1, xmm1 + xorps xmm2, xmm2 + xorps xmm3, xmm3 + xorps xmm4, xmm4 + xorps xmm5, xmm5 + xorps xmm6, xmm6 + xorps xmm7, xmm7 + + jmp .set_cr .no_FXSR: stdcall kernel_alloc, 112*256 mov [fpu_data], eax mov ebx, cr4 + mov ecx, cr0 and ebx, not (CR4_OSFXSR+CR4_OSXMMEXPT) + and ecx, not CR0_EM + or ecx, CR0_MP+CR0_NE + mov cr0, ecx mov cr4, ebx -.clts: - clts - fninit - +.set_cr: mov edi, irq_tab xor eax, eax mov ecx, 16 diff --git a/kernel/trunk/proc32.inc b/kernel/trunk/proc32.inc new file mode 100644 index 0000000000..23c56b03c1 --- /dev/null +++ b/kernel/trunk/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, \{ 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: + \\\{ 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 }