/kernel/branches/gfx_kernel/drivers/ati2d.asm |
---|
0,0 → 1,1008 |
format MS COFF |
include 'proc32.inc' |
include 'imports.inc' |
DEBUG equ 1 |
VID_ATI equ 0x1002 |
LOAD_FROM_FILE equ 0 |
LOAD_FROM_MEM equ 1 |
LOAD_INDIRECT equ 2 |
LOAD_SYSTEM equ 3 |
VIDEO_FREE equ 2 |
struc BITMAPINFOHEADER { |
.biSize dd ? ; DWORD |
.biWidth dd ? ; LONG |
.biHeight dd ? ; LONG |
.biPlanes dw ? ; WORD |
.biBitCount dw ? ; WORD |
.biCompression dd ? ; DWORD |
.biSizeImage dd ? ; DWORD |
.biXPelsPerMeter dd ? ; LONG |
.biYPelsPerMeter dd ? ; LONG |
.biClrUsed dd ? ; DWORD |
.biClrImportant dd ? ; DWORD |
} |
virtual at 0 |
BI BITMAPINFOHEADER |
end virtual |
struc CURSOR |
{;common object header |
.magic dd ? ;'CURS' |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
;cursor data |
.base dd ? ;allocated memory |
.hot_x dd ? ;hotspot coords |
.hot_y dd ? |
} |
virtual at 0 |
CURSOR CURSOR |
end virtual |
CURSOR_SIZE equ 32 |
R8500 equ 0x514C ;R200 |
R9000 equ 0x4966 ;RV250 |
R9200 equ 0x5961 ;RV280 |
R9500 equ 0x4144 ;R300 |
R9500P equ 0x4E45 ;R300 |
R9550 equ 0x4153 ;RV350 |
R9600 equ 0x4150 ;RV350 |
R9600XT equ 0x4152 ;RV360 |
R9700P equ 0x4E44 ;R300 |
R9800 equ 0x4E49 ;R350 |
R9800P equ 0x4E48 ;R350 |
R9800XT equ 0x4E4A ;R360 |
OS_BASE equ 0 |
new_app_base equ 0x80000000 |
SLOT_BASE equ 0x0080000 |
PG_SW equ 0x003 |
PG_NOCACHE equ 0x018 |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
;MMIO equ 0F9000000h |
RD_RB3D_CNTL equ 1c3ch |
RD_MEM_CNTL equ 0140h |
RD_CRTC_GEN_CNTL equ 0050h |
RD_CRTC_CUR_EN equ 10000h |
RD_DISPLAY_BASE_ADDR equ 023ch |
RD_DEFAULT_OFFSET equ 16e0h |
CUR_HORZ_VERT_OFF equ 0268h |
CUR_HORZ_VERT_POSN equ 0264h |
CUR_OFFSET equ 0260h |
RD_RB3D_CNTL equ 1c3ch |
RD_RBBM_STATUS equ 0e40h |
RD_RBBM_FIFOCNT_MASK equ 007fh |
RD_RBBM_ACTIVE equ 80000000h |
RD_TIMEOUT equ 2000000 |
RD_DP_GUI_MASTER_CNTL equ 0146ch |
RD_DP_BRUSH_BKGD_CLR equ 01478h |
RD_DP_BRUSH_FRGD_CLR equ 0147ch |
RD_DP_SRC_BKGD_CLR equ 015dch |
RD_DP_SRC_FRGD_CLR equ 015d8h |
RD_DP_CNTL equ 016c0h |
RD_DP_DATATYPE equ 016c4h |
RD_DP_WRITE_MASK equ 016cch |
RD_DP_SRC_SOURCE_MEMORY equ (2 shl 24) |
RD_DP_SRC_SOURCE_HOST_DATA equ (3 shl 24) |
RD_DEFAULT_SC_BOTTOM_RIGHT equ 16e8h |
RD_GMC_BRUSH_SOLID_COLOR equ (13 shl 4) |
RD_DEFAULT_SC_RIGHT_MAX equ 1fffh |
RD_DEFAULT_SC_BOTTOM_MAX equ 1fff0000h |
RD_GMC_DST_DATATYPE_SHIFT equ 8 |
RD_ROP3_S equ 00cc0000h |
RD_ROP3_P equ 00f00000h |
RD_RB2D_DSTCACHE_MODE equ 03428h |
RD_RB2D_DSTCACHE_CTLSTAT equ 0342ch |
RD_RB2D_DC_FLUSH_ALL equ 000fh |
RD_RB2D_DC_BUSY equ 80000000h |
RD_GMC_BRUSH_SOLID_COLOR equ 000000D0h |
RD_GMC_SRC_DATATYPE_COLOR equ (3 shl 12) |
RD_GMC_CLR_CMP_CNTL_DIS equ (1 shl 28) |
RD_GMC_WR_MSK_DIS equ (1 shl 30) |
cmdSolidFill equ 73f036d0h |
RD_DST_PITCH_OFFSET equ 142ch |
RD_SRC_PITCH_OFFSET equ 1428h |
RD_DST_X_LEFT_TO_RIGHT equ 1 |
RD_DST_Y_TOP_TO_BOTTOM equ 2 |
RD_DST_Y_X equ 1438h |
RD_DST_WIDTH_HEIGHT equ 1598h |
RD_DST_LINE_START equ 1600h |
RD_DST_LINE_END equ 1604h |
R300_MEM_NUM_CHANNELS_MASK equ 0003h |
macro rdr op1, op2 |
{ |
mov edi, [ati_io] |
mov op1, [edi+op2] |
} |
macro wrr dest, src |
{ |
mov edi, [ati_io] |
mov dword [edi+dest], src |
} |
public START |
public service_proc |
public version |
CURSOR_IMAGE_OFFSET equ 0x00500000 |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .exit |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect_ati |
test eax, eax |
jz .fail |
call init_ati |
test eax, eax |
jz .fail |
or eax, -1 |
mov [cursor_map], eax |
mov [cursor_map+4], eax |
mov edx, cursor_map |
mov [cursor_start], edx |
add edx, 8 |
mov [cursor_end], edx |
stdcall RegService, sz_ati_srv, service_proc |
test eax, eax |
jz .fail |
mov dword [SetHwCursor], drvCursorPos ;enable hardware cursor |
mov dword [HwCursorRestore], drv_restore |
mov dword [HwCursorCreate], ati_cursor |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
.exit: |
xor eax, eax |
; mov ebx, SetHwCursor |
; mov dword [ebx], eax ;force disable hardware cursor |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov edi, [ioctl] |
mov ebx, [edi+io_code] |
cmp ebx, VIDEO_FREE |
jne .fail |
mov eax, [edi+input] |
call video_free |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc detect_ati |
locals |
last_bus dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, 4 |
jmp @B |
.next: |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
xor eax, eax |
inc eax |
ret |
.err: |
xor eax, eax |
ret |
endp |
align 4 |
proc init_ati |
stdcall AllocKernelSpace, dword 0x10000 |
test eax, eax |
jz .fail |
mov [ati_io], eax |
stdcall PciRead32, [bus], [devfn], dword 0x18 |
and eax, 0xFFFF0000 |
mov esi, eax |
mov edi, [ati_io] |
mov edx, 16 |
@@: |
stdcall MapPage,edi,esi,PG_SW+PG_NOCACHE |
add edi, 0x1000 |
add esi, 0x1000 |
dec edx |
jnz @B |
mov edi, [ati_io] |
mov dword [edi+RD_RB3D_CNTL], 0 |
call engRestore |
mov edi, [ati_io] |
mov eax, [edi+0x50] |
mov ebx,3 |
shl ebx,20 |
not ebx |
and eax,ebx |
mov ebx, 2 |
shl ebx,20 |
or eax, ebx |
mov [edi+0x50], eax |
call drvShowCursor |
xor eax, eax |
inc eax |
.fail: |
ret |
endp |
align 4 |
drv_restore: |
ret 8 |
align 4 |
drvShowCursor: |
mov edi, [ati_io] |
mov eax, [edi+RD_CRTC_GEN_CNTL] |
bts eax,16 |
mov [edi+RD_CRTC_GEN_CNTL], eax |
ret |
align 4 |
proc drvCursorPos stdcall, hcursor:dword, x:dword, y:dword |
pushfd |
cli |
xor eax, eax |
xor edx, edx |
mov esi, [hcursor] |
mov ebx, [x] |
mov ecx, [y] |
sub ebx, [esi+CURSOR.hot_x] |
jnc @F |
neg ebx |
mov eax, ebx |
shl eax, 16 |
xor ebx, ebx |
@@: |
sub ecx, [esi+CURSOR.hot_y] |
jnc @F |
neg ecx |
mov ax, cx |
mov edx, ecx |
xor ecx, ecx |
@@: |
or eax, 0x80000000 |
wrr CUR_HORZ_VERT_OFF, eax |
shl ebx, 16 |
mov bx, cx |
or ebx, 0x80000000 |
wrr CUR_HORZ_VERT_POSN, ebx |
shl edx, 8 |
add edx, [esi+CURSOR.base] |
sub edx, LFBAddress |
wrr CUR_OFFSET, edx |
popfd |
ret |
endp |
align 4 |
proc video_alloc |
pushfd |
cli |
mov ebx, [cursor_start] |
mov ecx, [cursor_end] |
.l1: |
bsf eax,[ebx]; |
jnz .found |
add ebx,4 |
cmp ebx, ecx |
jb .l1 |
popfd |
xor eax,eax |
ret |
.found: |
btr [ebx], eax |
popfd |
mov [cursor_start],ebx |
sub ebx, cursor_map |
lea eax,[eax+ebx*8] |
shl eax,14 |
add eax, LFBAddress+CURSOR_IMAGE_OFFSET |
ret |
endp |
align 4 |
video_free: |
pushfd |
cli |
sub eax, LFBAddress+CURSOR_IMAGE_OFFSET |
shr eax, 14 |
mov ebx, cursor_map |
bts [ebx], eax |
shr eax, 3 |
and eax, not 3 |
add eax, ebx |
cmp [cursor_start], eax |
ja @f |
popfd |
ret |
@@: |
mov [cursor_start], eax |
popfd |
ret |
; param |
; eax= pid |
; ebx= src |
; ecx= flags |
align 4 |
ati_cursor: |
.src equ esp |
.flags equ esp+4 |
.hcursor equ esp+8 |
sub esp, 4 ;space for .hcursor |
push ecx |
push ebx |
mov ebx, eax |
mov eax, CURSOR_SIZE |
call CreateObject |
test eax, eax |
jz .fail |
mov [.hcursor],eax |
xor ebx, ebx |
mov [eax+CURSOR.magic], 'CURS' |
mov [eax+CURSOR.destroy], destroy_cursor |
mov [eax+CURSOR.hot_x], ebx |
mov [eax+CURSOR.hot_y], ebx |
call video_alloc |
mov edi, [.hcursor] |
mov [edi+CURSOR.base], eax |
mov esi, [.src] |
mov ebx, [.flags] |
cmp bx, LOAD_INDIRECT |
je .indirect |
movzx ecx, word [esi+10] |
movzx edx, word [esi+12] |
mov [edi+CURSOR.hot_x], ecx |
mov [edi+CURSOR.hot_y], edx |
stdcall ati_init_cursor, eax, esi |
mov eax, [.hcursor] |
.fail: |
add esp, 12 |
ret |
.indirect: |
shr ebx, 16 |
movzx ecx, bh |
movzx edx, bl |
mov [edi+CURSOR.hot_x], ecx |
mov [edi+CURSOR.hot_y], edx |
mov edi, eax |
mov ebx, eax |
mov ecx, 64*64 |
xor eax,eax |
cld |
rep stosd |
mov edi, ebx |
mov esi, [.src] |
mov ebx, 32 |
cld |
@@: |
mov ecx, 32 |
rep movsd |
add edi, 128 |
dec ebx |
jnz @B |
mov eax, [.hcursor] |
add esp, 12 |
ret |
align 4 |
destroy_cursor: |
push eax |
mov eax, [eax+CURSOR.base] |
call video_free |
pop eax |
call DestroyObject |
ret |
align 4 |
proc ati_init_cursor stdcall, dst:dword, src:dword |
locals |
rBase dd ? |
pQuad dd ? |
pBits dd ? |
pAnd dd ? |
width dd ? |
height dd ? |
counter dd ? |
endl |
mov esi, [src] |
add esi,[esi+18] |
mov eax,esi |
cmp [esi+BI.biBitCount], 24 |
je .img_24 |
cmp [esi+BI.biBitCount], 8 |
je .img_8 |
cmp [esi+BI.biBitCount], 4 |
je .img_4 |
.img_2: |
add eax, [esi] |
mov [pQuad],eax |
add eax,8 |
mov [pBits],eax |
add eax, 128 |
mov [pAnd],eax |
mov eax,[esi+4] |
mov [width],eax |
mov ebx,[esi+8] |
shr ebx,1 |
mov [height],ebx |
mov edi, pCursor |
add edi, 32*31*4 |
mov [rBase],edi |
mov esi,[pQuad] |
.l21: |
mov ebx, [pBits] |
mov ebx, [ebx] |
bswap ebx |
mov eax, [pAnd] |
mov eax, [eax] |
bswap eax |
mov [counter], 32 |
@@: |
xor edx, edx |
shl eax,1 |
setc dl |
dec edx |
xor ecx, ecx |
shl ebx,1 |
setc cl |
mov ecx, [esi+ecx*4] |
and ecx, edx |
and edx, 0xFF000000 |
or edx, ecx |
mov [edi], edx |
add edi, 4 |
dec [counter] |
jnz @B |
add [pBits], 4 |
add [pAnd], 4 |
mov edi,[rBase] |
sub edi,128 |
mov [rBase],edi |
sub [height],1 |
jnz .l21 |
jmp .copy |
.img_4: |
add eax, [esi] |
mov [pQuad],eax |
add eax,64 |
mov [pBits],eax |
add eax, 0x200 |
mov [pAnd],eax |
mov eax,[esi+4] |
mov [width],eax |
mov ebx,[esi+8] |
shr ebx,1 |
mov [height],ebx |
mov edi, pCursor |
add edi, 32*31*4 |
mov [rBase],edi |
mov esi,[pQuad] |
mov ebx, [pBits] |
.l4: |
mov eax, [pAnd] |
mov eax, [eax] |
bswap eax |
mov [counter], 16 |
@@: |
xor edx, edx |
shl eax,1 |
setc dl |
dec edx |
movzx ecx, byte [ebx] |
and cl, 0xF0 |
shr ecx, 2 |
mov ecx, [esi+ecx] |
and ecx, edx |
and edx, 0xFF000000 |
or edx, ecx |
mov [edi], edx |
xor edx, edx |
shl eax,1 |
setc dl |
dec edx |
movzx ecx, byte [ebx] |
and cl, 0x0F |
mov ecx, [esi+ecx*4] |
and ecx, edx |
and edx, 0xFF000000 |
or edx, ecx |
mov [edi+4], edx |
inc ebx |
add edi, 8 |
dec [counter] |
jnz @B |
add [pAnd], 4 |
mov edi,[rBase] |
sub edi,128 |
mov [rBase],edi |
sub [height],1 |
jnz .l4 |
jmp .copy |
.img_8: |
add eax, [esi] |
mov [pQuad],eax |
add eax,1024 |
mov [pBits],eax |
add eax, 1024 |
mov [pAnd],eax |
mov eax,[esi+4] |
mov [width],eax |
mov ebx,[esi+8] |
shr ebx,1 |
mov [height],ebx |
mov edi, pCursor |
add edi, 32*31*4 |
mov [rBase],edi |
mov esi,[pQuad] |
mov ebx, [pBits] |
.l81: |
mov eax, [pAnd] |
mov eax, [eax] |
bswap eax |
mov [counter], 32 |
@@: |
xor edx, edx |
shl eax,1 |
setc dl |
dec edx |
movzx ecx, byte [ebx] |
mov ecx, [esi+ecx*4] |
and ecx, edx |
and edx, 0xFF000000 |
or edx, ecx |
mov [edi], edx |
inc ebx |
add edi, 4 |
dec [counter] |
jnz @B |
add [pAnd], 4 |
mov edi,[rBase] |
sub edi,128 |
mov [rBase],edi |
sub [height],1 |
jnz .l81 |
jmp .copy |
.img_24: |
add eax, [esi] |
mov [pQuad],eax |
add eax, 0xC00 |
mov [pAnd],eax |
mov eax,[esi+BI.biWidth] |
mov [width],eax |
mov ebx,[esi+BI.biHeight] |
shr ebx,1 |
mov [height],ebx |
mov edi, pCursor |
add edi, 32*31*4 |
mov [rBase],edi |
mov esi,[pAnd] |
mov ebx, [pQuad] |
.row_24: |
mov eax, [esi] |
bswap eax |
mov [counter], 32 |
@@: |
xor edx, edx |
shl eax,1 |
setc dl |
dec edx |
mov ecx, [ebx] |
and ecx, 0x00FFFFFF |
and ecx, edx |
and edx, 0xFF000000 |
or edx, ecx |
mov [edi], edx |
add ebx, 3 |
add edi, 4 |
dec [counter] |
jnz @B |
add esi, 4 |
mov edi,[rBase] |
sub edi,128 |
mov [rBase],edi |
sub [height],1 |
jnz .row_24 |
.copy: |
mov edi, [dst] |
mov ecx, 64*64 |
xor eax,eax |
rep stosd |
mov esi, pCursor |
mov edi, [dst] |
mov ebx, 32 |
cld |
@@: |
mov ecx, 32 |
rep movsd |
add edi, 128 |
dec ebx |
jnz @B |
ret |
endp |
align 4 |
proc engFlush |
mov edi, [ati_io] |
mov eax, [edi+RD_RB2D_DSTCACHE_CTLSTAT] |
or eax,RD_RB2D_DC_FLUSH_ALL |
mov [edi+RD_RB2D_DSTCACHE_CTLSTAT],eax |
mov ecx, RD_TIMEOUT |
@@: |
mov eax,[edi+RD_RB2D_DSTCACHE_CTLSTAT] |
and eax, RD_RB2D_DC_BUSY |
jz .exit |
sub ecx,1 |
jnz @B |
.exit: |
ret |
endp |
align 4 |
engWaitForFifo: |
cnt equ bp+8 |
push ebp |
mov ebp, esp |
mov edi, [ati_io] |
mov ecx, RD_TIMEOUT |
@@: |
mov eax, [edi+RD_RBBM_STATUS] |
and eax, RD_RBBM_FIFOCNT_MASK |
cmp eax, [ebp+8] |
jae .exit |
sub ecx,1 |
jmp @B |
.exit: |
leave |
ret 4 |
align 4 |
proc engWaitForIdle |
push dword 64 |
call engWaitForFifo |
mov edi, [ati_io] |
mov ecx ,RD_TIMEOUT |
@@: |
mov eax, [edi+RD_RBBM_STATUS] |
and eax,RD_RBBM_ACTIVE |
jz .exit |
sub ecx,1 |
jnz @B |
.exit: |
call engFlush |
ret |
endp |
align 4 |
proc engRestore |
; push dword 1 |
; call engWaitForFifo |
; mov dword [MMIO+RD_RB2D_DSTCACHE_MODE], 0 |
push dword 3 |
call engWaitForFifo |
mov edi, [ati_io] |
mov eax, [edi+RD_DISPLAY_BASE_ADDR] |
shr eax, 10d |
or eax,(64d shl 22d) |
mov [edi+RD_DEFAULT_OFFSET],eax |
mov [edi+RD_SRC_PITCH_OFFSET],eax |
mov [edi+RD_DST_PITCH_OFFSET],eax |
push dword 1 |
call engWaitForFifo |
mov edi, [ati_io] |
mov eax, [edi+RD_DP_DATATYPE] |
btr eax, 29d |
mov [edi+RD_DP_DATATYPE],eax |
push dword 1 |
call engWaitForFifo |
mov edi, [ati_io] |
mov dword [edi+RD_DEFAULT_SC_BOTTOM_RIGHT],\ |
(RD_DEFAULT_SC_RIGHT_MAX or RD_DEFAULT_SC_BOTTOM_MAX) |
push dword 1 |
call engWaitForFifo |
mov edi, [ati_io] |
mov dword [edi+RD_DP_GUI_MASTER_CNTL],\ |
(RD_GMC_BRUSH_SOLID_COLOR or \ |
RD_GMC_SRC_DATATYPE_COLOR or \ |
(6 shl RD_GMC_DST_DATATYPE_SHIFT) or \ |
RD_GMC_CLR_CMP_CNTL_DIS or \ |
RD_ROP3_P or \ |
RD_GMC_WR_MSK_DIS) |
push dword 7 |
call engWaitForFifo |
mov edi, [ati_io] |
mov dword [edi+RD_DST_LINE_START],0 |
mov dword [edi+RD_DST_LINE_END], 0 |
mov dword [edi+RD_DP_BRUSH_FRGD_CLR], 808000ffh |
mov dword [edi+RD_DP_BRUSH_BKGD_CLR], 002020ffh |
mov dword [edi+RD_DP_SRC_FRGD_CLR], 808000ffh |
mov dword [edi+RD_DP_SRC_BKGD_CLR], 004000ffh |
mov dword [edi+RD_DP_WRITE_MASK],0ffffffffh |
call engWaitForIdle |
ret |
endp |
align 4 |
engSetupSolidFill: |
push ebp |
mov ebp, esp |
push dword 3 |
call engWaitForFifo |
wrr RD_DP_GUI_MASTER_CNTL, cmdSolidFill |
mov eax, [ebp+8] |
wrr RD_DP_BRUSH_FRGD_CLR,eax |
mov edi, [ati_io] |
mov dword [edi+RD_DP_CNTL],(RD_DST_X_LEFT_TO_RIGHT or RD_DST_Y_TOP_TO_BOTTOM) |
leave |
ret 4 |
align 4 |
drvSolidFill: |
;x:word,y:word,w:word,h:word,color:dword |
push ebp |
mov ebp, esp |
x equ ebp+8 |
y equ ebp+12 |
w equ ebp+16 |
h equ ebp+20 |
color equ ebp+24 |
push dword [ebp+24] |
call engSetupSolidFill |
push dword 2 |
call engWaitForFifo |
mov edi, [ati_io] |
mov eax, [y] |
mov ebx, [x] |
shl eax,16 |
or eax, ebx |
mov ecx, [w] |
mov edx, [h] |
shl ecx,16 |
or ecx, edx |
mov [edi+RD_DST_Y_X], eax |
mov [edi+RD_DST_WIDTH_HEIGHT], ecx |
call engFlush |
leave |
ret 20 |
align 4 |
devices dd (R8500 shl 16)+VID_ATI |
dd (R9000 shl 16)+VID_ATI |
dd (R9200 shl 16)+VID_ATI |
dd (R9500 shl 16)+VID_ATI |
dd (R9500P shl 16)+VID_ATI |
dd (R9550 shl 16)+VID_ATI |
dd (R9600 shl 16)+VID_ATI |
dd (R9600XT shl 16)+VID_ATI |
dd (R9700P shl 16)+VID_ATI |
dd (R9800 shl 16)+VID_ATI |
dd (R9800P shl 16)+VID_ATI |
dd (R9800XT shl 16)+VID_ATI |
dd 0 ;terminator |
version dd 0x00040004 |
sz_ati_srv db 'HWCURSOR',0 |
msgInit db 'detect hardware...',13,10,0 |
msgPCI db 'PCI accsess not supported',13,10,0 |
msgFail db 'device not found',13,10,0 |
msg_neg db 'neg ecx',13,10,0 |
buff db 8 dup(0) |
db 13,10, 0 |
section '.data' data readable writable align 16 |
pCursor db 4096 dup(?) |
cursor_map rd 2 |
cursor_start rd 1 |
cursor_end rd 1 |
bus dd ? |
devfn dd ? |
ati_io dd ? |
/kernel/branches/gfx_kernel/drivers/codec.inc |
---|
0,0 → 1,220 |
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, 0x0B0B |
stdcall codec_write, dword CODEC_MASTER_VOL_REG |
mov ax, 0x08 |
stdcall codec_write, dword 0x0C |
mov ax, 0x0808 |
stdcall codec_write, dword CODEC_PCM_OUT_REG |
mov ax, 0x0808 |
stdcall codec_write, dword 0x10 |
mov ax, 0x0808 |
stdcall codec_write, dword 0x12 |
mov ax, 0x0808 |
stdcall codec_write, dword 0x16 |
stdcall codec_read, dword CODEC_EXT_AUDIO_CTRL_REG |
and eax, 0FFFFh - BIT1 ; clear DRA (BIT1) |
or eax, BIT0 ; set VRA (BIT0) |
stdcall codec_write, dword CODEC_EXT_AUDIO_CTRL_REG |
stdcall set_sample_rate, dword 48000 |
.init_error: |
xor eax, eax ; exit with error |
ret |
endp |
; param |
; eax= volume -10000 - 0 for both channels |
align 4 |
set_master_vol: |
cmp eax, 0 |
jl @F |
xor eax, eax |
jmp .set |
@@: |
cmp eax, -9450 |
jg .set |
mov eax, -9450 ;clamp into 6 bits |
.set: |
cdq |
mov ebx, -150 |
idiv ebx |
mov ah, al |
stdcall codec_write, dword CODEC_MASTER_VOL_REG |
xor eax, eax |
ret |
align 4 |
proc get_master_vol stdcall, pvol:dword |
stdcall codec_read, dword CODEC_MASTER_VOL_REG |
and eax, 0x3F |
imul eax, -150 |
mov ebx, [pvol] |
mov [ebx], eax |
xor eax, eax |
ret |
endp |
align 4 |
proc set_sample_rate stdcall, rate:dword |
mov eax, [rate] |
stdcall codec_write, dword CODEC_PCM_FRONT_DACRATE_REG |
ret |
endp |
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 |
/kernel/branches/gfx_kernel/drivers/ensoniq.asm |
---|
0,0 → 1,1381 |
;alpha version |
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 ? |
.devfn dd ? |
.vendor dd ? |
.dev_id dd ? |
.pci_cmd dd ? |
.pci_stat dd ? |
.codec_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_io_base dd ? |
.ctrl_mem_base dd ? |
.cfg_reg dd ? |
.int_line dd ? |
.vendor_ids dd ? ;vendor id string |
.ctrl_ids dd ? ;hub id string |
.buffer dd ? |
.notify_pos dd ? |
.notify_task dd ? |
.lvi_reg dd ? |
.ctrl_setup dd ? |
.user_callback dd ? |
.codec_read16 dd ? |
.codec_write16 dd ? |
.ctrl_read8 dd ? |
.ctrl_read16 dd ? |
.ctrl_read32 dd ? |
.ctrl_write8 dd ? |
.ctrl_write16 dd ? |
.ctrl_write32 dd ? |
} |
struc CODEC ;Audio Chip base class |
{ |
.chip_id dd ? |
.flags dd ? |
.status dd ? |
.ac_vendor_ids dd ? ;ac vendor id string |
.chip_ids dd ? ;chip model string |
.shadow_flag dd ? |
dd ? |
.regs dw ? ; codec registers |
.reg_master_vol dw ? ;0x02 |
.reg_aux_out_vol dw ? ;0x04 |
.reg_mone_vol dw ? ;0x06 |
.reg_master_tone dw ? ;0x08 |
.reg_beep_vol dw ? ;0x0A |
.reg_phone_vol dw ? ;0x0C |
.reg_mic_vol dw ? ;0x0E |
.reg_line_in_vol dw ? ;0x10 |
.reg_cd_vol dw ? ;0x12 |
.reg_video_vol dw ? ;0x14 |
.reg_aux_in_vol dw ? ;0x16 |
.reg_pcm_out_vol dw ? ;0x18 |
.reg_rec_select dw ? ;0x1A |
.reg_rec_gain dw ? ;0x1C |
.reg_rec_gain_mic dw ? ;0x1E |
.reg_gen dw ? ;0x20 |
.reg_3d_ctrl dw ? ;0X22 |
.reg_page dw ? ;0X24 |
.reg_powerdown dw ? ;0x26 |
.reg_ext_audio dw ? ;0x28 |
.reg_ext_st dw ? ;0x2a |
.reg_pcm_front_rate dw ? ;0x2c |
.reg_pcm_surr_rate dw ? ;0x2e |
.reg_lfe_rate dw ? ;0x30 |
.reg_pcm_in_rate dw ? ;0x32 |
dw ? ;0x34 |
.reg_cent_lfe_vol dw ? ;0x36 |
.reg_surr_vol dw ? ;0x38 |
.reg_spdif_ctrl dw ? ;0x3A |
dw ? ;0x3C |
dw ? ;0x3E |
dw ? ;0x40 |
dw ? ;0x42 |
dw ? ;0x44 |
dw ? ;0x46 |
dw ? ;0x48 |
dw ? ;0x4A |
dw ? ;0x4C |
dw ? ;0x4E |
dw ? ;0x50 |
dw ? ;0x52 |
dw ? ;0x54 |
dw ? ;0x56 |
dw ? ;0x58 |
dw ? ;0x5A |
dw ? ;0x5C |
dw ? ;0x5E |
.reg_page_0 dw ? ;0x60 |
.reg_page_1 dw ? ;0x62 |
.reg_page_2 dw ? ;0x64 |
.reg_page_3 dw ? ;0x66 |
.reg_page_4 dw ? ;0x68 |
.reg_page_5 dw ? ;0x6A |
.reg_page_6 dw ? ;0x6C |
.reg_page_7 dw ? ;0x6E |
dw ? ;0x70 |
dw ? ;0x72 |
dw ? ;0x74 |
dw ? ;0x76 |
dw ? ;0x78 |
dw ? ;0x7A |
.reg_vendor_id_1 dw ? ;0x7C |
.reg_vendor_id_2 dw ? ;0x7E |
.reset dd ? ;virual |
.set_master_vol dd ? |
} |
struc CTRL_INFO |
{ .pci_cmd dd ? |
.irq dd ? |
.glob_cntrl dd ? |
.glob_sta dd ? |
.codec_io_base dd ? |
.ctrl_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_mem_base dd ? |
.codec_id dd ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
OS_BASE equ 0; 0x80400000 |
new_app_base equ 0x60400000; 0x01000000 |
PROC_BASE equ OS_BASE+0x0080000 |
public START |
public STOP |
public service_proc |
extrn AttachIntHandler |
extrn SysMsgBoardStr |
extrn PciApi |
extrn PciRead32 |
extrn PciRead8 |
extrn PciWrite8 |
extrn AllocKernelSpace |
extrn MapPage |
extrn RegService |
extrn KernelAlloc |
extrn GetPgAddr |
extrn GetCurrentTask |
section '.flat' code readable 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 |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
STOP: |
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 .no_pci |
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 |
@@: |
cmp ebx, 0x1274 |
jne @F |
mov [ctrl.vendor_ids], msgEnsoniq |
ret |
@@: |
mov [ctrl.vendor_ids], 0 ;something wrong ? |
ret |
.no_pci: |
mov esi, msgPCI |
call SysMsgBoardStr |
.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 4 |
devices dd (CTRL_ICH shl 16)+VID_INTEL,msg_ICH, set_ICH |
dd (CTRL_ICH0 shl 16)+VID_INTEL,msg_ICH0,set_ICH |
dd (CTRL_ICH2 shl 16)+VID_INTEL,msg_ICH2,set_ICH |
dd (CTRL_ICH3 shl 16)+VID_INTEL,msg_ICH3,set_ICH |
dd (CTRL_ICH4 shl 16)+VID_INTEL,msg_ICH4,set_ICH4 |
dd (CTRL_ICH5 shl 16)+VID_INTEL,msg_ICH5,set_ICH4 |
dd (CTRL_ICH6 shl 16)+VID_INTEL,msg_ICH6,set_ICH4 |
dd (CTRL_ICH7 shl 16)+VID_INTEL,msg_ICH7,set_ICH4 |
dd (CTRL_NFORCE shl 16)+VID_NVIDIA,msg_NForce, set_ICH |
dd (CTRL_NFORCE2 shl 16)+VID_NVIDIA,msg_NForce2,set_ICH |
dd (CTRL_NFORCE3 shl 16)+VID_NVIDIA,msg_NForce3,set_ICH |
dd (0x5000 shl 16)+0x1274,msgEnsoniq,set_ICH |
dd 0 ;terminator |
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 |
msgEnsoniq db 'Ensonic 1371',0 |
szKernel db 'KERNEL', 0 |
sz_sound_srv db 'SOUND',0 |
msgInit db 'detect hardware...',13,10,0 |
msgPCI db 'PCI accsess not supported',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 |
section '.data' data readable writable align 16 |
pcmout_bdl rq 32 |
buff_list rd 32 |
codec CODEC |
ctrl AC_CNTRL |
lpc_bus rd 1 |
civ_val rd 1 |
/kernel/branches/gfx_kernel/drivers/imports.inc |
---|
0,0 → 1,136 |
; all exported kernel functions and data |
if used RegService |
extrn RegService |
end if |
if used GetService |
extrn GetService |
end if |
if used ServiceHandler |
extrn ServiceHandler |
end if |
if used AttachIntHandler |
extrn AttachIntHandler |
end if |
if used FpuSave |
extrn FpuSave |
end if |
if used FpuRestore |
extrn FpuRestore |
end if |
if used PciApi |
extrn PciApi |
end if |
if used PciRead32 |
extrn PciRead32 |
end if |
if used PciRead8 |
extrn PciRead8 |
end if |
if used PciWrite8 |
extrn PciWrite8 |
end if |
if used AllocPage |
extrn AllocPage |
end if |
if used AllocPages |
extrn AllocPages |
end if |
if used FreePage |
extrn FreePage |
end if |
if used MapPage |
extrn MapPage |
end if |
if used MapSpace |
extrn MapSpace |
end if |
if used GetPgAddr |
extrn GetPgAddr |
end if |
if used CommitPages |
extrn CommitPages |
end if |
if used ReleasePages |
extrn ReleasePages |
end if |
if used AllocKernelSpace |
extrn AllocKernelSpace |
end if |
if used FreeKernelSpace |
extrn FreeKernelSpace |
end if |
if used KernelAlloc |
extrn KernelAlloc |
end if |
if used KernelFree |
extrn KernelFree |
end if |
if used UserAlloc |
extrn UserAlloc |
end if |
if used UserFree |
extrn UserFree |
end if |
if used Kmalloc |
extrn Kmalloc |
end if |
if used Kfree |
extrn Kfree |
end if |
if used CreateObject |
extrn CreateObject |
end if |
if used DestroyObject |
extrn DestroyObject |
end if |
if used CreateEvent |
extrn CreateEvent |
end if |
if used RaiseEvent |
extrn RaiseEvent |
end if |
if used WaitEvent |
extrn WaitEvent |
end if |
if used DestroyEvent |
extrn DestroyEvent |
end if |
if used ClearEvent |
extrn ClearEvent |
end if |
if used LoadCursor |
extrn LoadCursor |
end if |
if used SetHwCursor |
extrn SetHwCursor |
end if |
if used HwCursorRestore |
extrn HwCursorRestore |
end if |
if used HwCursorCreate |
extrn HwCursorCreate |
end if |
if used SysMsgBoardStr |
extrn SysMsgBoardStr |
end if |
if used GetCurrentTask |
extrn GetCurrentTask |
end if |
if used LoadFile |
extrn LoadFile |
end if |
if used SendEvent |
extrn SendEvent |
end if |
if used LFBAddress |
extrn LFBAddress |
end if |
/kernel/branches/gfx_kernel/drivers/infinity.asm |
---|
0,0 → 1,1291 |
; |
; 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' |
include 'imports.inc' |
FORCE_MMX equ 0 ;set to 1 to force use mmx or |
FORCE_MMX_128 equ 0 ;integer sse2 extensions |
;and reduce driver size |
;USE_SSE equ 0 |
DEBUG equ 1 |
OS_BASE equ 0 |
new_app_base equ 0x80000000 |
SLOT_BASE equ OS_BASE+0x0080000 |
CAPS_SSE2 equ 26 |
PG_SW equ 0x003 |
public START |
public service_proc |
public version |
RT_INP_EMPTY equ 0xFF000001 |
RT_OUT_EMPTY equ 0xFF000002 |
RT_INP_FULL equ 0xFF000003 |
RT_OUT_FULL equ 0xFF000004 |
EVENT_WATCHED equ 0x10000000 |
EVENT_SIGNALED equ 0x20000000 |
MANUAL_RESET equ 0x40000000 |
MANUAL_DESTROY equ 0x80000000 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .exit |
stdcall GetService, szSound |
test eax, eax |
jz .fail |
mov [hSound], eax |
stdcall KernelAlloc, 16*512 |
test eax, eax |
jz .out_of_mem |
mov [mix_buff], eax |
mov eax, str.fd-FD_OFFSET |
mov [str.fd], eax |
mov [str.bk], eax |
if FORCE_MMX |
if FORCE_MMX_128 |
display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10 |
stop |
end if |
mov [mix_2_core], mmx_mix_2 |
mov [mix_3_core], mmx_mix_3 |
mov [mix_4_core], mmx_mix_4 |
end if |
if FORCE_MMX_128 |
if FORCE_MMX |
display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10 |
stop |
end if |
mov [mix_2_core], mmx128_mix_2 |
mov [mix_3_core], mmx128_mix_3 |
mov [mix_4_core], mmx128_mix_4 |
end if |
if 0 |
if ~(FORCE_MMX or FORCE_MMX_128) ;autodetect |
mov eax, 1 |
cpuid |
bt edx, CAPS_SSE2 |
jc .mmx128 |
;old 64-bit mmx |
mov [mix_2_core], mmx_mix_2 |
mov [mix_3_core], mmx_mix_3 |
mov [mix_4_core], mmx_mix_4 |
jmp @F |
.mmx128: ;128-bit integer sse2 extensions |
mov [mix_2_core], mmx128_mix_2 |
mov [mix_3_core], mmx128_mix_3 |
mov [mix_4_core], mmx128_mix_4 |
@@: |
end if |
end if |
stdcall set_handler, [hSound], new_mix |
mov [eng_state], SND_STOP |
stdcall RegService, szInfinity, service_proc |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
.exit: |
xor eax, eax |
ret |
.out_of_mem: |
if DEBUG |
mov esi, msgMem |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [edi+output] |
mov eax, [eax] |
mov [eax+new_app_base], dword SOUND_VERSION |
xor eax, eax |
ret |
@@: |
cmp eax, SND_CREATE_BUFF |
jne @F |
mov ebx, [edi+input] |
push edi |
stdcall CreateBuffer,[ebx],[ebx+4] |
pop edi |
mov ecx, [edi+output] |
mov ecx, [ecx] |
mov [ecx+new_app_base], ebx |
ret |
@@: |
mov ebx, [edi+input] |
mov edx, [ebx] |
cmp [edx+STREAM.magic], 'WAVE' |
jne .fail |
cmp [edx+STREAM.size], STREAM_SIZE |
jne .fail |
cmp eax, SND_DESTROY_BUFF |
jne @F |
mov eax, edx |
call DestroyBuffer ;edx= stream |
ret |
@@: |
cmp eax, SND_SETFORMAT |
jne @F |
stdcall SetFormat,[ebx],[ebx+4] |
ret |
@@: |
cmp eax, SND_GETFORMAT |
jne @F |
movzx eax, word [edx+STREAM.format] |
mov ecx, [edi+output] |
mov ecx, [ecx] |
mov [ecx+new_app_base], eax |
xor eax, eax |
ret |
@@: |
cmp eax, SND_RESET |
jne @F |
stdcall ResetBuffer,[ebx],[ebx+4] |
ret |
@@: |
cmp eax, SND_SETPOS |
jne @F |
stdcall SetBufferPos,[ebx],[ebx+4] |
ret |
@@: |
cmp eax, SND_GETPOS |
jne @F |
push edi |
stdcall GetBufferPos, [ebx] |
pop edi |
mov ecx, [edi+output] |
mov ecx, [ecx] |
mov [ecx+new_app_base], ebx |
ret |
@@: |
cmp eax, SND_SETBUFF |
jne @F |
mov eax, [ebx+4] |
add eax, new_app_base |
stdcall set_buffer, [ebx],eax,[ebx+8],[ebx+12] |
ret |
@@: |
cmp eax, SND_SETVOLUME |
jne @F |
stdcall SetBufferVol,[ebx],[ebx+4],[ebx+8] |
ret |
@@: |
cmp eax, SND_GETVOLUME |
jne @F |
mov eax, [edi+output] |
mov ecx, [eax] |
mov eax, [eax+4] |
add ecx, new_app_base |
add eax, new_app_base |
stdcall GetBufferVol,[ebx],ecx,eax |
ret |
@@: |
cmp eax, SND_SETPAN |
jne @F |
stdcall SetBufferPan,[ebx],[ebx+4] |
ret |
@@: |
cmp eax, SND_GETPAN |
jne @F |
mov eax, [edx+STREAM.pan] |
mov ebx, [edi+output] |
mov ebx, [ebx] |
mov [ebx+new_app_base], eax |
xor eax, eax |
ret |
@@: |
cmp eax, SND_OUT |
jne @F |
mov eax, [ebx+4] |
add eax, new_app_base |
stdcall wave_out, [ebx],eax,[ebx+8] |
ret |
@@: |
cmp eax, SND_PLAY |
jne @F |
stdcall play_buffer, [ebx],[ebx+4] |
ret |
@@: |
cmp eax, SND_STOP |
jne @F |
stdcall stop_buffer, [ebx] |
ret |
@@: |
cmp eax, SND_GETBUFFSIZE |
jne @F |
mov eax, [edx+STREAM.in_size] |
mov ecx, [edi+output] |
mov ecx, [ecx] |
mov [ecx+new_app_base], eax |
xor eax, eax |
ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
TASK_COUNT equ 0x0003004 |
CURRENT_TASK equ 0x0003000 |
align 4 |
proc CreateBuffer stdcall, format:dword, size:dword |
locals |
str dd ? |
ring_size dd ? |
ring_pages dd ? |
endl |
mov eax, [format] |
cmp ax, PCM_1_8_8 |
ja .fail |
test eax, PCM_OUT |
jnz .test_out |
test eax, PCM_RING |
jnz .test_ring |
;staic |
test eax, PCM_OUT+PCM_RING |
jnz .fail |
jmp .test_ok |
.test_out: |
test eax, PCM_RING+PCM_STATIC |
jnz .fail |
jmp .test_ok |
.test_ring: |
test eax, PCM_OUT+PCM_STATIC |
jnz .fail |
.test_ok: |
mov ebx, [CURRENT_TASK] ;hack: direct accsess |
shl ebx, 5 ;to kernel data |
mov ebx, [CURRENT_TASK+ebx+4] |
mov eax, STREAM_SIZE |
call CreateObject |
test eax, eax |
jz .fail |
mov [str], eax |
mov ebx, [format] |
mov [eax+STREAM.format], ebx |
xor ecx, ecx |
movzx ebx, bx |
cmp ebx, 19 |
jb @f |
mov ecx, 0x80808080 |
@@: |
mov [eax+STREAM.r_silence], ecx |
shl ebx, 2 |
lea ebx, [ebx+ebx*2] ;ebx*=12 |
mov ecx, [resampler_params+ebx] |
mov edx, [resampler_params+ebx+4] |
mov esi, [resampler_params+ebx+8] |
mov [eax+STREAM.r_size],ecx |
mov [eax+STREAM.r_dt], edx |
mov [eax+STREAM.resample], esi |
xor ecx, ecx |
mov [eax+STREAM.l_vol], ecx |
mov [eax+STREAM.r_vol], ecx |
mov dword [eax+STREAM.l_amp], 0x7FFF7FFF |
mov [eax+STREAM.pan], ecx |
test [format], PCM_STATIC |
jnz .static |
; ring and waveout |
mov eax, 0x10000 |
test [format], PCM_RING |
jz .waveout |
mov eax, [eax+STREAM.r_size] |
add eax, 4095 |
and eax, -4096 |
add eax, eax |
.waveout: |
mov [ring_size], eax |
mov ebx, eax |
shr ebx, 12 |
mov [ring_pages], ebx |
add eax, eax ;double ring size |
stdcall AllocKernelSpace, eax |
mov edi, [str] |
mov ecx, [ring_size] |
mov [edi+STREAM.in_base], eax |
mov [edi+STREAM.in_size], ecx |
add eax, 128 |
sub ecx, 128 |
mov [edi+STREAM.in_wp], eax |
mov [edi+STREAM.in_rp], eax |
mov [edi+STREAM.in_count], 0 |
mov [edi+STREAM.in_free], ecx |
add eax, ecx |
mov [edi+STREAM.in_top], eax |
mov ebx, [ring_pages] |
stdcall AllocPages, ebx |
mov edi, [str] |
mov ebx, [edi+STREAM.in_base] |
mov ecx, [ring_pages] |
or eax, PG_SW |
push eax |
push ebx |
call CommitPages ;eax, ebx, ecx |
mov ecx, [ring_pages] |
pop ebx |
pop eax |
add ebx, [ring_size] |
call CommitPages ;double mapped |
jmp .out_buff |
.static: |
mov ecx, [size] |
add ecx, 128 ;resampler required |
mov [eax+STREAM.in_size], ecx |
stdcall KernelAlloc, ecx |
mov edi, [str] |
mov [edi+STREAM.in_base], eax |
add eax, 128 |
mov [edi+STREAM.in_wp], eax |
mov [edi+STREAM.in_rp], eax |
mov ebx, [size] |
mov [edi+STREAM.in_count], ebx |
mov [edi+STREAM.in_free], ebx |
add eax, ebx |
mov [edi+STREAM.in_top], eax |
.out_buff: |
stdcall AllocKernelSpace, dword 128*1024 |
mov edi, [str] |
mov [edi+STREAM.out_base], eax |
mov [edi+STREAM.out_wp], eax |
mov [edi+STREAM.out_rp], eax |
mov [edi+STREAM.out_count], 0 |
add eax, 64*1024 |
mov [edi+STREAM.out_top], eax |
stdcall AllocPages, dword 64/4 |
mov edi, [str] |
mov ebx, [edi+STREAM.out_base] |
mov ecx, 16 |
or eax, PG_SW |
push eax |
push ebx |
call CommitPages ;eax, ebx, ecx |
mov ecx, 16 |
pop ebx |
pop eax |
add ebx, 64*1024 |
call CommitPages ;double mapped |
mov edi, [str] |
mov ecx, [edi+STREAM.in_top] |
mov edi, [edi+STREAM.in_base] |
sub ecx, edi |
xor eax, eax |
shr ecx, 2 |
cld |
rep stosd |
mov edi, [str] |
mov edi, [edi+STREAM.out_base] |
mov ecx, (64*1024)/4 |
rep stosd |
xor edx, edx |
mov ebx, MANUAL_DESTROY |
call CreateEvent |
mov ebx, [str] |
mov [ebx+STREAM.notify_event], eax |
mov [ebx+STREAM.notify_id], edx |
mov [ebx+STREAM.magic], 'WAVE' |
mov [ebx+STREAM.destroy], DestroyBuffer.destroy |
mov [ebx+STREAM.size], STREAM_SIZE |
mov [ebx+STREAM.flags], SND_STOP |
pushf |
cli |
mov eax, str.fd-FD_OFFSET |
mov edx, [eax+STREAM.str_fd] |
mov [ebx+STREAM.str_fd], edx |
mov [ebx+STREAM.str_bk], eax |
mov [eax+STREAM.str_fd], ebx |
mov [edx+STREAM.str_bk], ebx |
popf |
xor eax, eax |
ret |
.fail: |
xor ebx, ebx |
or eax, -1 |
ret |
endp |
;param |
; eax= buffer handle |
align 4 |
DestroyBuffer: |
.handle equ esp ;local |
mov [eax+STREAM.flags], SND_STOP |
.destroy: |
push eax |
pushfd |
cli |
mov ebx, [eax+STREAM.str_fd] |
mov ecx, [eax+STREAM.str_bk] |
mov [ebx+STREAM.str_bk], ecx |
mov [ecx+STREAM.str_fd], ebx |
popf |
stdcall KernelFree, [eax+STREAM.in_base] |
mov eax, [.handle] |
stdcall KernelFree, [eax+STREAM.out_base] |
pop eax ;restore stack |
call DestroyObject ;eax= stream |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
restore .handle |
align 4 |
proc SetFormat stdcall, str:dword, format:dword |
cmp word [format], PCM_1_8_8 |
ja .fail |
mov edx, [str] |
mov [edx+STREAM.flags], SND_STOP |
test [edx+STREAM.format], PCM_RING |
jnz .fail |
; mov eax,[edx+STREAM.out_base] |
; mov [edx+STREAM.out_wp], eax |
; mov [edx+STREAM.out_rp], eax |
; mov [edx+STREAM.out_count], 0 |
movzx eax, word [format] |
mov word [edx+STREAM.format], ax |
xor ebx, ebx |
cmp eax, 19 |
jb @f |
mov ebx, 0x80808080 |
@@: |
mov [edx+STREAM.r_silence], ebx |
shl eax, 2 |
lea eax, [eax+eax*2] ;eax*=12 |
mov edi, [resampler_params+eax] |
mov ecx, [resampler_params+eax+4] |
mov ebx, [resampler_params+eax+8] |
mov [edx+STREAM.r_size],edi |
mov [edx+STREAM.r_dt], ecx |
mov [edx+STREAM.resample], ebx |
mov edi, [edx+STREAM.in_base] |
mov ecx, 128/4 |
mov eax, [edx+STREAM.r_silence] |
cld |
rep stosd |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; for static buffers only |
; use waveout for streams |
align 4 |
proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword |
mov edx, [str] |
test [edx+STREAM.format], PCM_OUT |
jnz .fail |
mov esi, [src] |
mov edi, [offs] |
add edi, [edx+STREAM.in_base] |
add edi, 128 |
cmp edi, [edx+STREAM.in_top] |
jae .fail |
mov ecx, [size] |
lea ebx, [ecx+edi] |
sub ebx, [edx+STREAM.in_top] |
jb @F |
sub ecx, ebx |
@@: |
shr ecx, 2 |
cld |
rep movsd |
xor eax,eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; for stream buffers only |
align 4 |
proc wave_out stdcall, str:dword,src:dword,size:dword |
locals |
state_saved dd ? |
fpu_state rb 528 |
endl |
mov edx, [str] |
mov eax, [edx+STREAM.format] |
test eax, PCM_STATIC+PCM_RING |
jnz .fail |
cmp ax, PCM_ALL |
je .fail |
mov esi,[src] |
test esi, esi |
jz .fail |
cmp esi, new_app_base |
jb .fail |
mov [state_saved], 0 |
.main_loop: |
mov edx, [str] |
mov ebx, [size] |
test ebx, ebx |
jz .done |
cmp [edx+STREAM.flags], SND_STOP |
jne .fill |
mov edi, [edx+STREAM.in_base] |
mov ecx, 128/4 |
mov eax, [edx+STREAM.r_silence] |
cld |
rep stosd |
mov ecx, [edx+STREAM.in_size] |
sub ecx, 128 |
mov [edx+STREAM.in_wp], edi |
mov [edx+STREAM.in_rp], edi |
mov [edx+STREAM.in_count], 0 |
mov [edx+STREAM.in_free], ecx |
mov eax,[edx+STREAM.out_base] |
mov [edx+STREAM.out_wp], eax |
mov [edx+STREAM.out_rp], eax |
mov [edx+STREAM.out_count], 0 |
.fill: |
mov ecx, [edx+STREAM.in_free] |
test ecx, ecx |
jz .wait |
cmp ecx, ebx |
jbe @F |
mov ecx, ebx |
@@: |
sub [size], ecx |
add [edx+STREAM.in_count], ecx |
sub [edx+STREAM.in_free], ecx |
shr ecx, 2 |
mov edi, [edx+STREAM.in_wp] |
mov esi, [src] |
cld |
rep movsd |
mov [src], esi |
cmp edi, [edx+STREAM.in_top] |
jb @F |
sub edi, [edx+STREAM.in_size] |
@@: |
mov [edx+STREAM.in_wp], edi |
cmp [edx+STREAM.out_count], 32768 |
jae .skip |
cmp [state_saved], 0 |
jne @F |
lea eax, [fpu_state+15] |
and eax, -16 |
call FpuSave |
mov [state_saved], 1 |
@@: |
stdcall refill, edx |
.skip: |
mov ebx, [str] |
mov [ebx+STREAM.flags], SND_PLAY |
cmp [eng_state], SND_PLAY |
je .main_loop |
stdcall dev_play, [hSound] |
mov [eng_state], SND_PLAY |
jmp .main_loop |
.wait: |
mov edx, [str] |
mov eax, [edx+STREAM.notify_event] |
mov ebx, [edx+STREAM.notify_id] |
call WaitEvent ;eax ebx |
jmp .main_loop |
.done: |
cmp [state_saved], 1 |
jne @F |
lea eax, [fpu_state+15] |
and eax, -16 |
call FpuRestore |
@@: |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; both static and stream |
; reset all but not clear buffers |
; flags reserved |
; RESET_INPUT equ 1 ;reserved reset and clear input buffer |
; RESET_OUTPUT equ 2 ;reserved reset and clear output buffer |
; RESET_ALL equ 3 |
align 4 |
proc ResetBuffer stdcall, str:dword, flags:dword |
mov edx, [str] |
mov [edx+STREAM.flags], SND_STOP |
mov edi, [edx+STREAM.in_base] |
mov ecx, 128/4 |
mov eax, [edx+STREAM.r_silence] |
cld |
rep stosd |
mov [edx+STREAM.in_wp], edi |
mov [edx+STREAM.in_rp], edi |
mov [edx+STREAM.in_count], 0 |
mov eax, [edx+STREAM.in_size] |
sub eax, 128 |
mov [edx+STREAM.in_free], eax |
xor eax, eax |
mov ebx,[edx+STREAM.out_base] |
mov [edx+STREAM.out_wp], ebx |
mov [edx+STREAM.out_rp], ebx |
mov [edx+STREAM.out_count], eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; for static buffers only |
align 4 |
proc SetBufferPos stdcall, str:dword, pos:dword |
mov edx, [str] |
test [edx+STREAM.format], PCM_OUT+PCM_RING |
jnz .fail |
mov [edx+STREAM.flags], SND_STOP |
mov eax, [pos] |
add eax, [edx+STREAM.in_base] |
mov ebx, [edx+STREAM.in_top] |
add eax, 128 |
cmp eax, ebx |
jae .fail |
mov [edx+STREAM.in_rp], eax |
sub ebx, eax |
mov [edx+STREAM.in_count], ebx |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
align 4 |
proc GetBufferPos stdcall, str:dword |
mov edx, [str] |
test [edx+STREAM.format], PCM_OUT+PCM_RING |
jnz .fail |
mov ebx, [edx+STREAM.in_rp] |
xor eax, eax |
ret |
.fail: |
xor ebx,ebx |
or eax, -1 |
ret |
endp |
; both |
align 4 |
proc SetBufferVol stdcall, str:dword,l_vol:dword,r_vol:dword |
mov edx, [str] |
stdcall set_vol_param,[l_vol],[r_vol],[edx+STREAM.pan] |
ret |
endp |
proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword |
locals |
_600 dd ? |
_32767 dd ? |
state rb 108 |
endl |
mov [_600], 0x44160000 ;600.0 |
mov [_32767], 32767 |
lea ebx, [state] |
fnsave [ebx] |
movq mm0, qword [l_vol] |
pminsw mm0, qword [vol_max] |
pmaxsw mm0, qword [vol_min] |
movq qword [l_vol], mm0 |
movq qword [edx+STREAM.l_vol], mm0 |
movd mm1,[pan] |
pminsw mm1, qword [pan_max] |
pmaxsw mm1, qword [vol_min] |
movd [edx+STREAM.pan], mm1 |
cmp word [edx+STREAM.pan], 0 |
jl @F |
psubsw mm0,mm1 |
pminsw mm0, qword [vol_max] |
pmaxsw mm0, qword [vol_min] |
movd [l_vol],mm0 |
jmp .calc_amp |
@@: |
punpckhdq mm0,mm0 |
paddsw mm0,mm1 |
pminsw mm0, qword [vol_max] |
pmaxsw mm0, qword [vol_min] |
movd [r_vol], mm0 |
.calc_amp: |
emms |
fild word [l_vol] |
call .calc |
fistp word [edx+STREAM.l_amp] |
fstp st0 |
fild word [r_vol] |
call .calc |
fistp word [edx+STREAM.r_amp] |
fstp st0 |
fnclex |
lea ebx, [state] |
frstor [ebx] |
xor eax, eax |
inc eax |
ret |
.calc: |
fdiv dword [_600] |
fld st0 |
frndint |
fxch st1 |
fsub st, st1 |
f2xm1 |
fld1 |
faddp st1, st0 |
fscale |
fimul dword [_32767] |
ret 0 |
endp |
align 4 |
proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword |
mov edx, [str] |
mov eax, [p_lvol] |
movsx ecx, word [edx+STREAM.l_vol] |
mov [eax], ecx |
mov eax, [p_rvol] |
movsx ecx, word [edx+STREAM.r_vol] |
mov [eax], ecx |
xor eax, eax |
ret |
endp |
align 4 |
proc SetBufferPan stdcall, str:dword,pan:dword |
mov edx, [str] |
stdcall set_vol_param,[edx+STREAM.l_vol],\ |
[edx+STREAM.r_vol],[pan] |
ret |
endp |
; for static and ring buffers only |
align 4 |
proc play_buffer stdcall, str:dword, flags:dword |
locals |
fpu_state rb 528 |
endl |
mov ebx, [str] |
mov eax, [ebx+STREAM.format] |
test eax, PCM_OUT |
jnz .fail |
cmp ax, PCM_ALL |
je .fail |
mov [ebx+STREAM.flags], SND_PLAY |
cmp [eng_state], SND_PLAY |
je .done |
stdcall dev_play, [hSound] |
mov [eng_state], SND_PLAY |
.done: |
test [flags], PLAY_SYNC |
jz @F |
mov edx, [str] |
.wait: |
mov eax, [edx+STREAM.notify_event] |
mov ebx, [edx+STREAM.notify_id] |
call WaitEvent ;eax ebx |
mov edx, [str] |
cmp [edx+STREAM.flags], SND_STOP |
jne .wait |
@@: |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; for static buffers only |
align 4 |
proc stop_buffer stdcall, str:dword |
mov edx, [str] |
test [edx+STREAM.format], PCM_STATIC+PCM_RING |
jz .fail |
mov [edx+STREAM.flags], SND_STOP |
; stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0 |
mov eax, [edx+STREAM.notify_event] |
mov ebx, [edx+STREAM.notify_id] |
call ClearEvent ;eax ebx |
xor eax, eax |
ret |
.fail: |
or eax, -1 |
ret |
endp |
; parm |
; eax= mix_list |
align 4 |
do_mix_list: |
xor edx, edx |
mov esi, str.fd-FD_OFFSET |
mov ebx, [esi+STREAM.str_fd] |
@@: |
cmp ebx, esi |
je .done |
cmp [ebx+STREAM.magic], 'WAVE' |
jne .next |
cmp [ebx+STREAM.size], STREAM_SIZE |
jne .next |
cmp [ebx+STREAM.flags], SND_PLAY; |
jne .next |
mov ecx, [ebx+STREAM.out_count] |
test ecx, ecx |
jnz .l1 |
test [ebx+STREAM.format], PCM_RING |
jnz .next |
mov [ebx+STREAM.flags], SND_STOP |
jmp .next |
.l1: |
cmp ecx, 512 |
jae .add_buff |
mov edi, [ebx+STREAM.out_rp] |
add edi, ecx |
sub ecx, 512 |
neg ecx |
push eax |
xor eax, eax |
cld |
rep stosb |
pop eax |
mov [ebx+STREAM.out_count], 512 |
.add_buff: |
mov ecx, [ebx+STREAM.out_rp] |
mov [eax],ecx |
mov edi, dword [ebx+STREAM.l_amp] |
mov [eax+4], edi |
add [ebx+STREAM.out_rp], 512 |
sub [ebx+STREAM.out_count], 512 |
add eax, 8 |
inc edx |
.next: |
mov ebx, [ebx+STREAM.str_fd] |
jmp @B |
.done: |
mov eax, edx |
ret |
align 4 |
prepare_playlist: |
xor edx, edx |
mov [play_count], edx |
mov esi, str.fd-FD_OFFSET |
mov edi, [esi+STREAM.str_fd] |
@@: |
cmp edi, esi |
je .done |
cmp [edi+STREAM.magic], 'WAVE' |
jne .next |
cmp [edi+STREAM.size], STREAM_SIZE |
jne .next |
cmp [edi+STREAM.flags], SND_PLAY; |
jne .next |
mov [play_list+edx], edi |
inc [play_count] |
add edx, 4 |
.next: |
mov edi, [edi+STREAM.str_fd] |
jmp @B |
.done: |
ret |
align 4 |
proc set_handler stdcall, hsrv:dword, handler_proc:dword |
locals |
handler dd ? |
io_code dd ? |
input dd ? |
inp_size dd ? |
output dd ? |
out_size dd ? |
val dd ? |
endl |
mov eax, [hsrv] |
lea ecx, [handler_proc] |
xor ebx, ebx |
mov [handler], eax |
mov [io_code], DEV_CALLBACK |
mov [input], ecx |
mov [inp_size], 4 |
mov [output], ebx |
mov [out_size], 0 |
lea eax, [handler] |
stdcall ServiceHandler, eax |
ret |
endp |
align 4 |
proc dev_play stdcall, hsrv:dword |
locals |
handle dd ? |
io_code dd ? |
input dd ? |
inp_size dd ? |
output dd ? |
out_size dd ? |
val dd ? |
endl |
mov eax, [hsrv] |
xor ebx, ebx |
mov [handle], eax |
mov [io_code], DEV_PLAY |
mov [input], ebx |
mov [inp_size], ebx |
mov [output], ebx |
mov [out_size], ebx |
lea eax, [handle] |
stdcall ServiceHandler, eax |
ret |
endp |
if 0 |
align 4 |
dword2str: |
mov esi, hex_buff |
mov ecx, -8 |
@@: |
rol eax, 4 |
mov ebx, eax |
and ebx, 0x0F |
mov bl, [ebx+hexletters] |
mov [8+esi+ecx], bl |
inc ecx |
jnz @B |
ret |
hexletters db '0123456789ABCDEF' |
hex_buff db 8 dup(0),13,10,0 |
end if |
include 'mixer.asm' |
include 'mix_mmx.inc' |
include 'mix_sse2.inc' |
;if USE_SSE |
; include 'mix_sse.inc' |
;end if |
align 16 |
resampler_params: |
;r_size r_dt resampler_func |
dd 0,0,0 ; 0 PCM_ALL |
dd 16384, 0, copy_stream ; 1 PCM_2_16_48 |
dd 16384, 0, m16_stereo ; 2 PCM_1_16_48 |
dd 16384, 30109, resample_2 ; 3 PCM_2_16_44 |
dd 8192, 30109, resample_1 ; 4 PCM_1_16_44 |
dd 16384, 21846, resample_2 ; 5 PCM_2_16_32 |
dd 8192, 21846, resample_1 ; 6 PCM_1_16_32 |
dd 16384, 16384, resample_2 ; 7 PCM_2_16_24 |
dd 8192, 16384, resample_1 ; 8 PCM_1_16_24 |
dd 8192, 15052, resample_2 ; 9 PCM_2_16_22 |
dd 4096, 15052, resample_1 ;10 PCM_1_16_22 |
dd 8192, 10923, resample_2 ;11 PCM_2_16_16 |
dd 4096, 10923, resample_1 ;12 PCM_1_16_16 |
dd 8192, 8192, resample_2 ;13 PCM_2_16_12 |
dd 4096, 8192, resample_1 ;14 PCM_1_16_12 |
dd 4096, 7527, resample_2 ;15 PCM_2_16_11 |
dd 2048, 7527, resample_1 ;16 PCM_1_16_11 |
dd 4096, 5462, resample_2 ;17 PCM_2_16_8 |
dd 2048, 5462, resample_1 ;18 PCM_1_16_8 |
dd 16384, 0, s8_stereo ;19 PCM_2_8_48 |
dd 8192, 0, m8_stereo ;20 PCM_1_8_48 |
dd 8192, 30109, resample_28 ;21 PCM_2_8_44 |
dd 4096, 30109, resample_18 ;22 PCM_1_8_44 |
dd 8192, 21846, resample_28 ;23 PCM_2_8_32 |
dd 4096, 21846, resample_18 ;24 PCM_1_8_32 |
dd 8192, 16384, resample_28 ;25 PCM_2_8_24 |
dd 4096, 16384, resample_18 ;26 PCM_1_8_24 |
dd 4096, 15052, resample_28 ;27 PCM_2_8_22 |
dd 2048, 15052, resample_18 ;28 PCM_1_8_22 |
dd 4096, 10923, resample_28 ;29 PCM_2_8_16 |
dd 2048, 10923, resample_18 ;30 PCM_1_8_16 |
dd 4096, 8192, resample_28 ;31 PCM_2_8_12 |
dd 2048, 8192, resample_18 ;32 PCM_1_8_12 |
dd 2048, 7527, resample_28 ;33 PCM_2_8_11 |
dd 1024, 7527, resample_18 ;34 PCM_1_8_11 |
dd 2048, 5462, resample_28 ;35 PCM_2_8_8 |
dd 1024, 5462, resample_18 ;36 PCM_1_8_8 |
m7 dw 0x8000,0x8000,0x8000,0x8000 |
mm80 dq 0x8080808080808080 |
mm_mask dq 0xFF00FF00FF00FF00 |
vol_max dd 0x00000000,0x00000000 |
vol_min dd 0x0000D8F0,0x0000D8F0 |
pan_max dd 0x00002710,0x00002710 |
;stream_map dd 0xFFFF ; 16 |
version dd (4 shl 16) or (SOUND_VERSION and 0xFFFF) |
szInfinity db 'INFINITY',0 |
szSound db 'SOUND',0 |
if DEBUG |
msgFail db 'Sound service not loaded',13,10,0 |
msgPlay db 'Play buffer',13,10,0 |
msgStop db 'Stop',13,10,0 |
msgUser db 'User callback',13,10,0 |
msgMem db 'Not enough memory',13,10,0 |
msgDestroy db 'Destroy sound buffer', 13,10,0 |
msgWaveout db 'Play waveout', 13,10,0 |
msgSetVolume db 'Set volume',13,10,0 |
end if |
section '.data' data readable writable align 16 |
play_list rd 16 |
mix_input rd 16 |
play_count rd 1 |
hSound rd 1 |
eng_state rd 1 |
mix_buff rd 1 |
mix_buff_map rd 1 |
str.fd rd 1 |
str.bk rd 1 |
mix_2_core rd 1 |
mix_3_core rd 1 |
mix_4_core rd 1 |
/kernel/branches/gfx_kernel/drivers/main.inc |
---|
0,0 → 1,169 |
; |
; This file is part of the Infinity sound driver. |
; (C) copyright Serge 2006-2007 |
; 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. |
SOUND_VERSION equ 0x01000100 |
PLAY_SYNC equ 0x80000000 |
PCM_ALL equ 0 |
PCM_OUT equ 0x08000000 |
PCM_RING equ 0x10000000 |
PCM_STATIC equ 0x20000000 |
PCM_FLOAT equ 0x40000000 ;reserved |
PCM_FILTER equ 0x80000000 ;reserved |
PCM_2_16_48 equ 1 |
PCM_1_16_48 equ 2 |
PCM_2_16_44 equ 3 |
PCM_1_16_44 equ 4 |
PCM_2_16_32 equ 5 |
PCM_1_16_32 equ 6 |
PCM_2_16_24 equ 7 |
PCM_1_16_24 equ 8 |
PCM_2_16_22 equ 9 |
PCM_1_16_22 equ 10 |
PCM_2_16_16 equ 11 |
PCM_1_16_16 equ 12 |
PCM_2_16_12 equ 13 |
PCM_1_16_12 equ 14 |
PCM_2_16_11 equ 15 |
PCM_1_16_11 equ 16 |
PCM_2_16_8 equ 17 |
PCM_1_16_8 equ 18 |
PCM_2_8_48 equ 19 |
PCM_1_8_48 equ 20 |
PCM_2_8_44 equ 21 |
PCM_1_8_44 equ 22 |
PCM_2_8_32 equ 23 |
PCM_1_8_32 equ 24 |
PCM_2_8_24 equ 25 |
PCM_1_8_24 equ 26 |
PCM_2_8_22 equ 27 |
PCM_1_8_22 equ 28 |
PCM_2_8_16 equ 29 |
PCM_1_8_16 equ 30 |
PCM_2_8_12 equ 31 |
PCM_1_8_12 equ 32 |
PCM_2_8_11 equ 33 |
PCM_1_8_11 equ 34 |
PCM_2_8_8 equ 35 |
PCM_1_8_8 equ 36 |
SRV_GETVERSION equ 0 |
SND_CREATE_BUFF equ 1 |
SND_DESTROY_BUFF equ 2 |
SND_SETFORMAT equ 3 |
SND_GETFORMAT equ 4 |
SND_RESET equ 5 |
SND_SETPOS equ 6 |
SND_GETPOS equ 7 |
SND_SETBUFF equ 8 |
SND_OUT equ 9 |
SND_PLAY equ 10 |
SND_STOP equ 11 |
SND_SETVOLUME equ 12 |
SND_GETVOLUME equ 13 |
SND_SETPAN equ 14 |
SND_GETPAN equ 15 |
SND_GETBUFFSIZE equ 16 |
struc STREAM |
{ |
.magic dd ? ;'WAVE' |
.destroy dd ? ;internal destructor |
.fd dd ? ;next object in list |
.bk dd ? ;prev object in list |
.pid dd ? ;owner id |
.size dd ? |
.str_fd dd ? |
.str_bk dd ? |
.device dd ? |
.format dd ? |
.flags dd ? |
.out_base dd ? |
.out_wp dd ? |
.out_rp dd ? |
.out_count dd ? |
.out_top dd ? |
.r_size dd ? |
.r_dt dd ? |
.r_silence dd ? |
.resample dd ? |
.l_vol dd ? |
.r_vol dd ? |
.l_amp dw ? |
.r_amp dw ? |
.pan dd ? |
.in_base dd ? |
.in_size dd ? |
.in_wp dd ? |
.in_rp dd ? |
.in_count dd ? |
.in_free dd ? |
.in_top dd ? |
.notify_event dd ? |
.notify_id dd ? |
} |
STREAM_SIZE equ 34*4 |
FD_OFFSET equ 24 |
virtual at 0 |
STREAM STREAM |
end virtual |
struc WAVE_HEADER |
{ .riff_id dd ? |
.riff_size dd ? |
.riff_format dd ? |
.fmt_id dd ? |
.fmt_size dd ? |
.format_tag dw ? |
.channels dw ? |
.freq dd ? |
.bytes_sec dd ? |
.block_align dw ? |
.bits_sample dw ? |
.data_id dd ? |
.data_size dd ? |
} |
/kernel/branches/gfx_kernel/drivers/mix_mmx.inc |
---|
0,0 → 1,241 |
; params |
; edi= output |
; eax= input stream 1 |
; ebx= input stream 2 |
if used mmx_mix_2 |
align 4 |
mmx_mix_2: |
movq mm0, [eax] |
movq mm1, [eax+8] |
movq mm2, [eax+16] |
movq mm3, [eax+24] |
movq mm4, [eax+32] |
movq mm5, [eax+40] |
movq mm6, [eax+48] |
movq mm7, [eax+56] |
paddsw mm0, [ebx] |
movq [edi], mm0 |
paddsw mm1,[ebx+8] |
movq [edi+8], mm1 |
paddsw mm2, [ebx+16] |
movq [edi+16], mm2 |
paddsw mm3, [ebx+24] |
movq [edi+24], mm3 |
paddsw mm4, [ebx+32] |
movq [edi+32], mm4 |
paddsw mm5, [ebx+40] |
movq [edi+40], mm5 |
paddsw mm6, [ebx+48] |
movq [edi+48], mm6 |
paddsw mm7, [ebx+56] |
movq [edi+56], mm7 |
movq mm0, [eax+64] |
movq mm1, [eax+72] |
movq mm2, [eax+80] |
movq mm3, [eax+88] |
movq mm4, [eax+96] |
movq mm5, [eax+104] |
movq mm6, [eax+112] |
movq mm7, [eax+120] |
paddsw mm0, [ebx+64] |
movq [edi+64], mm0 |
paddsw mm1, [ebx+72] |
movq [edi+72], mm1 |
paddsw mm2, [ebx+80] |
movq [edi+80], mm2 |
paddsw mm3, [ebx+88] |
movq [edi+88], mm3 |
paddsw mm4, [ebx+96] |
movq [edi+96], mm4 |
paddsw mm5, [ecx+104] |
movq [edx+104], mm5 |
paddsw mm6, [ebx+112] |
movq [edi+112], mm6 |
paddsw mm7, [ebx+120] |
movq [edi+120], mm7 |
ret |
align 4 |
mmx_mix_3: |
movq mm0, [eax] |
movq mm1, [eax+8] |
movq mm2, [eax+16] |
movq mm3, [eax+24] |
movq mm4, [eax+32] |
movq mm5, [eax+40] |
movq mm6, [eax+48] |
movq mm7, [eax+56] |
paddsw mm0, [ebx] |
paddsw mm1, [ebx+8] |
paddsw mm2, [ebx+16] |
paddsw mm3, [ebx+24] |
paddsw mm4, [ebx+32] |
paddsw mm5, [ebx+40] |
paddsw mm6, [ebx+48] |
paddsw mm7, [ebx+56] |
paddsw mm0, [ecx] |
movq [edi], mm0 |
paddsw mm1,[ecx+8] |
movq [edi+8], mm1 |
paddsw mm2, [ecx+16] |
movq [edi+16], mm2 |
paddsw mm3, [ecx+24] |
movq [edi+24], mm3 |
paddsw mm4, [ecx+32] |
movq [edi+32], mm4 |
paddsw mm5, [ecx+40] |
movq [edi+40], mm5 |
paddsw mm6, [ecx+48] |
movq [edi+48], mm6 |
paddsw mm7, [ecx+56] |
movq [edi+56], mm7 |
movq mm0, [eax+64] |
movq mm1, [eax+72] |
movq mm2, [eax+80] |
movq mm3, [eax+88] |
movq mm4, [eax+96] |
movq mm5, [eax+104] |
movq mm6, [eax+112] |
movq mm7, [eax+120] |
paddsw mm0, [ebx+64] |
paddsw mm1, [ebx+72] |
paddsw mm2, [ebx+80] |
paddsw mm3, [ebx+88] |
paddsw mm4, [ebx+96] |
paddsw mm5, [ebx+104] |
paddsw mm6, [ebx+112] |
paddsw mm7, [ebx+120] |
paddsw mm0, [ecx+64] |
movq [edi+64], mm0 |
paddsw mm1, [ecx+72] |
movq [edi+72], mm1 |
paddsw mm2, [ecx+80] |
movq [edi+80], mm2 |
paddsw mm3, [ecx+88] |
movq [edi+88], mm3 |
paddsw mm4, [ecx+96] |
movq [edi+96], mm4 |
paddsw mm5, [ecx+104] |
movq [edi+104], mm5 |
paddsw mm6, [ecx+112] |
movq [edi+112], mm6 |
paddsw mm7, [ecx+120] |
movq [edi+120], mm7 |
ret |
align 4 |
mmx_mix_4: |
movq mm0, [eax] |
movq mm2, [eax+8] |
movq mm4, [eax+16] |
movq mm6, [eax+24] |
movq mm1, [ebx] |
movq mm3, [ebx+8] |
movq mm5, [ebx+16] |
movq mm7, [ebx+24] |
paddsw mm0, [ecx] |
paddsw mm2, [ecx+8] |
paddsw mm4, [ecx+16] |
paddsw mm6, [ecx+24] |
paddsw mm1, [edx] |
paddsw mm3, [edx+8] |
paddsw mm5, [edx+16] |
paddsw mm7, [edx+24] |
paddsw mm0, mm1 |
movq [edi], mm0 |
paddsw mm2, mm3 |
movq [edi+8], mm2 |
paddsw mm4, mm5 |
movq [edi+16], mm4 |
paddsw mm5, mm6 |
movq [edi+24], mm6 |
movq mm0, [eax+32] |
movq mm2, [eax+40] |
movq mm4, [eax+48] |
movq mm6, [eax+56] |
movq mm1, [ebx+32] |
movq mm3, [ebx+40] |
movq mm5, [ebx+48] |
movq mm7, [ebx+56] |
paddsw mm0, [ecx+32] |
paddsw mm2, [ecx+40] |
paddsw mm4, [ecx+48] |
paddsw mm6, [ecx+56] |
paddsw mm1, [edx+32] |
paddsw mm3, [edx+40] |
paddsw mm5, [edx+48] |
paddsw mm7, [edx+56] |
paddsw mm0, mm1 |
movq [edi+32], mm0 |
paddsw mm2, mm2 |
movq [edi+40], mm2 |
paddsw mm4, mm5 |
movq [edi+48], mm4 |
paddsw mm6, mm7 |
movq [edi+56], mm6 |
movq mm0, [eax+64] |
movq mm2, [eax+72] |
movq mm4, [eax+80] |
movq mm6, [eax+88] |
movq mm1, [ebx+64] |
movq mm3, [ebx+72] |
movq mm5, [ebx+80] |
movq mm7, [ebx+88] |
paddsw mm0, [ecx+64] |
paddsw mm2, [ecx+72] |
paddsw mm4, [ecx+80] |
paddsw mm6, [ecx+88] |
paddsw mm1, [edx+64] |
paddsw mm3, [edx+72] |
paddsw mm5, [edx+80] |
paddsw mm7, [edx+88] |
paddsw mm0, mm1 |
movq [edi+64], mm0 |
paddsw mm2, mm3 |
movq [edi+72], mm2 |
paddsw mm4, mm5 |
movq [edi+80], mm4 |
paddsw mm6, mm5 |
movq [edi+88], mm7 |
movq mm0, [eax+96] |
movq mm2, [eax+104] |
movq mm4, [eax+112] |
movq mm6, [eax+120] |
movq mm1, [ebx+96] |
movq mm3, [ebx+104] |
movq mm5, [ebx+112] |
movq mm7, [ebx+120] |
paddsw mm0, [ecx+96] |
paddsw mm2, [ecx+104] |
paddsw mm4, [ecx+112] |
paddsw mm6, [ecx+120] |
paddsw mm1, [edx+96] |
paddsw mm3, [edx+104] |
paddsw mm5, [edx+112] |
paddsw mm7, [edx+120] |
paddsw mm0, mm1 |
movq [eax+96], mm0 |
paddsw mm2, mm3 |
movq [edi+104], mm2 |
paddsw mm4, mm5 |
movq [edi+112], mm4 |
paddsw mm6, mm7 |
movq [edi+120], mm6 |
ret |
end if |
/kernel/branches/gfx_kernel/drivers/mix_sse2.inc |
---|
0,0 → 1,139 |
if used mmx128_mix_2 |
align 4 |
mmx128_mix_2: |
prefetcht1 [eax+128] |
prefetcht1 [ebx+128] |
movaps xmm0, [eax] |
movaps xmm1, [eax+16] |
movaps xmm2, [eax+32] |
movaps xmm3, [eax+48] |
movaps xmm4, [eax+64] |
movaps xmm5, [eax+80] |
movaps xmm6, [eax+96] |
movaps xmm7, [eax+112] |
paddsw xmm0, [ebx] |
movaps [edi], xmm0 |
paddsw xmm1,[ebx+16] |
movaps [edi+16], xmm1 |
paddsw xmm2, [ebx+32] |
movaps [edi+32], xmm2 |
paddsw xmm3, [ebx+48] |
movaps [edi+48], xmm3 |
paddsw xmm4, [ebx+64] |
movaps [edi+64], xmm4 |
paddsw xmm5, [ebx+80] |
movaps [edi+80], xmm5 |
paddsw xmm6, [ebx+96] |
movaps [edi+96], xmm6 |
paddsw xmm7, [ebx+112] |
movaps [edi+112], xmm7 |
ret |
align 4 |
mmx128_mix_3: |
prefetcht1 [eax+128] |
prefetcht1 [ebx+128] |
prefetcht1 [ecx+128] |
movaps xmm0, [eax] |
movaps xmm1, [eax+16] |
movaps xmm2, [eax+32] |
movaps xmm3, [eax+48] |
movaps xmm4, [eax+64] |
movaps xmm5, [eax+80] |
movaps xmm6, [eax+96] |
movaps xmm7, [eax+112] |
paddsw xmm0, [ebx] |
paddsw xmm1, [ebx+16] |
paddsw xmm2, [ebx+32] |
paddsw xmm3, [ebx+48] |
paddsw xmm4, [ebx+64] |
paddsw xmm5, [ebx+80] |
paddsw xmm6, [ebx+96] |
paddsw xmm7, [ebx+112] |
paddsw xmm0, [ecx] |
movaps [edi], xmm0 |
paddsw xmm1, [ecx+16] |
movaps [edi+16], xmm1 |
paddsw xmm2, [ecx+32] |
movaps [edi+32], xmm2 |
paddsw xmm3, [ecx+48] |
movaps [edi+48], xmm3 |
paddsw xmm4, [ecx+64] |
movaps [edi+64], xmm4 |
paddsw xmm5, [ecx+80] |
movaps [edi+80], xmm5 |
paddsw xmm6, [ecx+96] |
movaps [edi+96], xmm6 |
paddsw xmm7, [ecx+112] |
movaps [edi+112], xmm7 |
ret |
align 4 |
mmx128_mix_4: |
prefetcht1 [eax+128] |
prefetcht1 [ebx+128] |
prefetcht1 [ecx+128] |
prefetcht1 [edx+128] |
movaps xmm0, [eax] |
movaps xmm2, [eax+16] |
movaps xmm4, [eax+32] |
movaps xmm6, [eax+48] |
movaps xmm1, [ebx] |
movaps xmm3, [ebx+16] |
movaps xmm5, [ebx+32] |
movaps xmm7, [ebx+48] |
paddsw xmm0, [ecx] |
paddsw xmm2, [ecx+16] |
paddsw xmm4, [ecx+32] |
paddsw xmm6, [ecx+48] |
paddsw xmm1, [edx] |
paddsw xmm3, [edx+16] |
paddsw xmm5, [edx+32] |
paddsw xmm7, [edx+48] |
paddsw xmm0, xmm1 |
movaps [edi], xmm0 |
paddsw xmm2, xmm3 |
movaps [edi+16], xmm2 |
paddsw xmm4, xmm5 |
movaps [edi+32], xmm4 |
paddsw xmm6, xmm7 |
movaps [edi+48], xmm6 |
movaps xmm0, [eax+64] |
movaps xmm2, [eax+80] |
movaps xmm4, [eax+96] |
movaps xmm6, [eax+112] |
movaps xmm1, [ebx+64] |
movaps xmm3, [ebx+80] |
movaps xmm5, [ebx+96] |
movaps xmm7, [ebx+112] |
paddsw xmm0, [ecx+64] |
paddsw xmm2, [ecx+80] |
paddsw xmm4, [ecx+96] |
paddsw xmm6, [ecx+112] |
paddsw xmm1, [edx+64] |
paddsw xmm3, [edx+80] |
paddsw xmm5, [edx+96] |
paddsw xmm7, [edx+112] |
paddsw xmm0, xmm1 |
movaps [edi+64], xmm0 |
paddsw xmm2, xmm3 |
movaps [edi+80], xmm2 |
paddsw xmm4, xmm5 |
movaps [edi+96], xmm4 |
paddsw xmm6, xmm7 |
movaps [edi+112], xmm6 |
ret |
end if |
/kernel/branches/gfx_kernel/drivers/mixer.asm |
---|
0,0 → 1,1106 |
; |
; 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 |
mix_list rq 32 |
align 4 |
proc new_mix stdcall, output:dword |
locals |
main_count rd 1 |
fpu_state rb 528 ;512+16 |
endl |
mov [main_count], 32 |
call prepare_playlist |
cmp [play_count], 0 |
je .clear |
lea eax, [fpu_state+16] |
and eax, -16 ;must be 16b aligned |
call FpuSave |
call update_stream |
.mix: |
lea eax, [mix_list] |
call do_mix_list |
test eax, eax |
je .done |
; cmp eax, 1 |
; je .copy |
lea ebx, [mix_list] |
stdcall mix_all, [output], ebx, eax |
@@: |
add [output], 512 |
dec [main_count] |
jnz .mix |
.exit: |
lea eax, [fpu_state+16] |
and eax, -16 |
call FpuRestore |
ret |
.copy: |
lea eax, [mix_list] |
stdcall copy_mem, [output], [eax] |
jmp @B |
.done: |
mov ecx, [main_count] |
shl ecx, 7 ;ecx*= 512/4 |
mov edi, [output] |
xor eax, eax |
cld |
rep stosd |
jmp .exit |
.clear: |
mov edi, [output] |
mov ecx, 4096 |
xor eax, eax |
cld |
rep stosd |
ret |
endp |
align 4 |
proc update_stream |
locals |
stream_index dd ? |
ev_code dd ? ;EVENT |
ev_offs dd ? |
rd 4 |
endl |
mov [stream_index], 0 |
.l1: |
mov edx, [stream_index] |
mov esi, [play_list+edx*4] |
mov eax, [esi+STREAM.out_rp] |
cmp eax, [esi+STREAM.out_top] |
jb @f |
sub eax, 64*1024 |
@@: |
mov [esi+STREAM.out_rp], eax |
cmp word [esi+STREAM.format], PCM_2_16_48 |
je .copy |
cmp [esi+STREAM.out_count], 16384 |
ja .skip |
test [esi+STREAM.format], PCM_RING |
jnz .ring |
stdcall refill, esi |
.skip: |
inc [stream_index] |
dec [play_count] |
jnz .l1 |
ret |
.ring: |
stdcall refill_ring, esi |
jmp .skip |
.copy: |
mov ebx, esi |
mov edi, [ebx+STREAM.out_wp] |
cmp edi, [ebx+STREAM.out_top] |
jb @f |
sub edi, 64*1024 |
mov [ebx+STREAM.out_wp], edi |
@@: |
mov esi, [ebx+STREAM.in_rp] |
mov ecx, 16384/4 |
cld |
rep movsd |
mov [ebx+STREAM.out_wp], edi |
cmp esi, [ebx+STREAM.in_top] |
jb @f |
sub esi, 0x10000 |
@@: |
mov [ebx+STREAM.in_rp], esi |
test eax, eax |
jz .l_end |
mov eax, [ebx+STREAM.notify_event] |
mov ebx, [ebx+STREAM.notify_id] |
mov ecx, EVENT_WATCHED |
xor edx, edx |
call RaiseEvent ;eax, ebx, ecx, edx |
.l_end: |
inc [stream_index] |
dec [play_count] |
jnz .l1 |
ret |
endp |
align 4 |
proc refill stdcall, str:dword |
locals |
r_size rd 1 |
event rd 6 |
endl |
mov ebx, [str] |
mov edi, [ebx+STREAM.out_wp] |
cmp edi, [ebx+STREAM.out_top] |
jb @F |
sub edi, 0x10000 |
mov [ebx+STREAM.out_wp], edi |
@@: |
mov eax, [ebx+STREAM.in_count] |
test eax, eax |
jz .done |
mov ecx, [ebx+STREAM.r_size] |
cmp eax, ecx |
jle @F |
mov eax, ecx |
@@: |
mov ecx, eax |
cmp word [ebx+STREAM.format], PCM_1_16_8 |
ja @F |
shr eax, 1 ;two channles |
@@: |
test [ebx+STREAM.format], 1 ;even formats mono |
jz @F |
shr eax, 1 ;eax= samples |
@@: |
shl eax, 15 ;eax*=32768 =r_end |
mov [r_size], ecx |
mov esi, [ebx+STREAM.in_rp] |
mov edi, [ebx+STREAM.out_wp] |
stdcall [ebx+STREAM.resample], edi, esi, \ |
[ebx+STREAM.r_dt], ecx, eax |
mov ebx, [str] |
add [ebx+STREAM.out_count], eax; |
add [ebx+STREAM.out_wp], eax; |
mov eax, [ebx+STREAM.in_rp] |
mov ecx, [r_size] |
add eax, ecx |
add [ebx+STREAM.in_free], ecx |
sub [ebx+STREAM.in_count], ecx |
cmp eax, [ebx+STREAM.in_top] |
jb @f |
sub eax, [ebx+STREAM.in_size] |
@@: |
mov [ebx+STREAM.in_rp], eax |
.done: |
mov eax, [ebx+STREAM.notify_event] |
test eax, eax |
jz .exit |
mov ebx, [ebx+STREAM.notify_id] |
mov ecx, EVENT_WATCHED |
xor edx, edx |
call RaiseEvent ;eax, ebx, ecx, edx |
.exit: |
ret |
endp |
align 4 |
proc refill_ring stdcall, str:dword |
locals |
event rd 6 |
endl |
mov ebx, [str] |
mov edi, [ebx+STREAM.out_wp] |
cmp edi, [ebx+STREAM.out_top] |
jb @F |
sub edi, 0x10000 |
mov [ebx+STREAM.out_wp], edi |
@@: |
mov ecx, [ebx+STREAM.r_size] |
mov eax, ecx |
cmp word [ebx+STREAM.format], PCM_1_16_8 |
ja @F |
shr eax, 1 ;two channles |
@@: |
test [ebx+STREAM.format], 1 ;even formats mono |
jz @F |
shr eax, 1 ;eax= samples |
@@: |
shl eax, 15 ;eax*=32768 =r_end |
mov esi, [ebx+STREAM.in_rp] |
mov edi, [ebx+STREAM.out_wp] |
stdcall [ebx+STREAM.resample], edi, esi, \ |
[ebx+STREAM.r_dt], ecx, eax |
mov ebx, [str] |
add [ebx+STREAM.out_count], eax; |
add [ebx+STREAM.out_wp], eax; |
mov eax, [ebx+STREAM.in_rp] |
mov ecx, [ebx+STREAM.r_size] |
add eax, ecx |
add [ebx+STREAM.in_free], ecx |
sub [ebx+STREAM.in_count], ecx |
cmp eax, [ebx+STREAM.in_top] |
jb @f |
sub eax, [ebx+STREAM.in_size] |
@@: |
mov [ebx+STREAM.in_rp], eax |
sub eax, [ebx+STREAM.in_base] |
sub eax, 128 |
lea edx, [event] |
mov dword [edx], RT_INP_EMPTY |
mov dword [edx+4], 0 |
mov dword [edx+8], ebx |
mov dword [edx+12], eax |
mov eax, [ebx+STREAM.notify_event] |
test eax, eax |
jz .exit |
mov ebx, [ebx+STREAM.notify_id] |
xor ecx, ecx |
call RaiseEvent ;eax, ebx, ecx, edx |
.exit: |
ret |
endp |
align 4 |
proc mix_all stdcall, dest:dword, list:dword, count:dword |
mov edi, [dest] |
mov ebx, 64 |
.mix: |
mov edx, [list] |
mov ecx, [count] |
mov eax, [edx] |
movq mm0, [eax] |
movd mm1, [edx+4] |
punpckldq mm1,mm1 |
pmulhw mm0, mm1 |
psllw mm0, 1 |
.mix_loop: |
add dword [edx], 8 |
add edx, 8 |
dec ecx |
jz @F |
mov eax, [edx] |
movq mm1, [eax] |
movd mm2, [edx+4] |
punpckldq mm2,mm2 |
pmulhw mm1, mm2 |
psllw mm1, 1 |
paddsw mm0, mm1 |
jmp .mix_loop |
@@: |
movq [edi], mm0 |
add edi, 8 |
dec ebx |
jnz .mix |
ret |
endp |
align 4 |
proc resample_1 stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
; dest equ esp+8 |
; src equ esp+12 |
; r_dt equ esp+16 |
; r_size equ esp+20 |
; r_end equ esp+24 |
mov edi, [dest] |
mov edx, [src] |
sub edx, 32*2 |
mov eax, 16 |
align 4 |
.l1: |
mov ecx, eax |
mov esi, eax |
and ecx, 0x7FFF |
shr esi, 15 |
lea esi, [edx+esi*2] |
movsx ebp, word [esi] |
movsx esi, word [esi+2] |
mov ebx, 32768 |
imul esi, ecx |
sub ebx, ecx |
imul ebx, ebp |
lea ecx, [ebx+esi+16384] |
sar ecx, 15 |
cmp ecx, 32767 ; 00007fffH |
jle @f |
mov ecx, 32767 ; 00007fffH |
jmp .write |
@@: |
cmp ecx, -32768 ; ffff8000H |
jge .write |
mov ecx, -32768 ; ffff8000H |
.write: |
mov ebx, ecx |
shl ebx, 16 |
mov bx, cx |
mov [edi], ebx |
add edi, 4 |
add eax, [esp+16] |
cmp eax, [esp+24] |
jb .l1 |
mov ebp, esp |
sub edi, [dest] |
mov eax, edi |
ret |
endp |
align 4 |
proc resample_18 stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov edi, [dest] |
mov edx, [src] |
sub edx, 32 |
mov esi, 16 |
align 4 |
.l1: |
mov ecx, esi |
mov eax, esi |
and ecx, 0x7FFF |
shr eax, 15 |
lea eax, [edx+eax] |
mov bx, word [eax] |
sub bh, 0x80 |
sub bl, 0x80 |
movsx eax, bh |
shl eax,8 |
movsx ebp, bl |
shl ebp,8 |
mov ebx, 32768 |
imul eax, ecx |
sub ebx, ecx |
imul ebx, ebp |
lea ecx, [ebx+eax+16384] |
sar ecx, 15 |
cmp ecx, 32767 ; 00007fffH |
jle @f |
mov ecx, 32767 ; 00007fffH |
jmp .write |
@@: |
cmp ecx, -32768 ; ffff8000H |
jge .write |
mov ecx, -32768 ; ffff8000H |
.write: |
mov ebx, ecx |
shl ebx, 16 |
mov bx, cx |
mov [edi], ebx |
add edi, 4 |
add esi, [esp+16] |
cmp esi, [esp+24] |
jb .l1 |
mov ebp, esp |
sub edi, [dest] |
mov eax, edi |
ret |
endp |
align 4 |
proc copy_stream stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov ecx, [r_size] |
mov eax, ecx |
shr ecx, 2 |
mov esi, [src] |
mov edi, [dest] |
rep movsd |
mov eax, 16384 |
ret |
endp |
align 4 |
proc resample_2 stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov edx, [src] |
sub edx, 32*4 |
mov edi, [dest] |
mov ebx, [r_dt] |
mov eax, 16 |
emms |
align 4 |
.l1: |
mov ecx, eax |
mov esi, eax |
and ecx, 0x7FFF |
shr esi, 15 |
lea esi, [edx+esi*4] |
movq mm0, [esi] |
movq mm1, mm0 |
movd mm2, ecx |
punpcklwd mm2, mm2 |
movq mm3, qword [m7] ;0x8000 |
psubw mm3, mm2 ; ;0x8000 - iconst |
punpckldq mm3, mm2 |
pmulhw mm0, mm3 |
pmullw mm1, mm3 |
movq mm4, mm1 |
punpcklwd mm1, mm0 |
punpckhwd mm4, mm0 |
paddd mm1, mm4 |
psrad mm1, 15 |
packssdw mm1, mm1 |
movd [edi], mm1 |
add edi, 4 |
add eax, ebx |
cmp eax, [r_end] |
jb .l1 |
emms |
sub edi, [dest] |
mov eax, edi |
ret |
endp |
align 4 |
proc resample_28 stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov edx, [src] |
sub edx, 32*2 |
mov edi, [dest] |
mov ebx, [r_dt] |
mov eax, 16 |
emms |
movq mm7,[mm80] |
movq mm6,[mm_mask] |
align 4 |
.l1: |
mov ecx, eax |
mov esi, eax |
and ecx, 0x7FFF |
shr esi, 15 |
lea esi, [edx+esi*2] |
movq mm0, [esi] |
psubb mm0,mm7 |
punpcklbw mm0,mm0 |
pand mm0,mm6 |
movq mm1, mm0 |
movd mm2, ecx |
punpcklwd mm2, mm2 |
movq mm3, qword [m7] ; // 0x8000 |
psubw mm3, mm2 ; // 0x8000 - iconst |
punpckldq mm3, mm2 |
pmulhw mm0, mm3 |
pmullw mm1, mm3 |
movq mm4, mm1 |
punpcklwd mm1, mm0 |
punpckhwd mm4, mm0 |
paddd mm1, mm4 |
psrad mm1, 15 |
packssdw mm1, mm1 |
movd [edi], mm1 |
add edi, 4 |
add eax, ebx |
cmp eax, [r_end] |
jb .l1 |
emms |
sub edi, [dest] |
mov eax, edi |
ret |
endp |
proc m16_stereo stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov esi, [src] |
mov edi, [dest] |
mov ecx, [r_size] |
shr ecx,8 |
@@: |
call m16_s_mmx |
add edi, 128 |
add esi, 64 |
call m16_s_mmx |
add edi, 128 |
add esi, 64 |
call m16_s_mmx |
add edi, 128 |
add esi, 64 |
call m16_s_mmx |
add edi, 128 |
add esi, 64 |
dec ecx |
jnz @b |
mov eax, [r_size] |
add eax, eax |
ret |
endp |
align 4 |
proc s8_stereo stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov esi, [src] |
mov edi, [dest] |
mov ecx, [r_size] |
shr ecx, 7 |
movq mm7, [mm80] |
movq mm6, [mm_mask] |
@@: |
call s8_s_mmx |
add edi, 64 |
add esi, 32 |
call s8_s_mmx |
add edi, 64 |
add esi, 32 |
call s8_s_mmx |
add edi, 64 |
add esi, 32 |
call s8_s_mmx |
add edi, 64 |
add esi, 32 |
dec ecx |
jnz @b |
mov eax, [r_size] |
add eax, eax |
ret |
endp |
proc m8_stereo stdcall, dest:dword,src:dword,\ |
r_dt:dword, r_size:dword,r_end:dword |
mov esi, [src] |
mov edi, [dest] |
mov ecx, [r_size] |
shr ecx, 6 |
movq mm7, [mm80] |
movq mm6, [mm_mask] |
@@: |
call m8_s_mmx |
add edi, 64 |
add esi, 16 |
call m8_s_mmx |
add edi, 64 |
add esi, 16 |
call m8_s_mmx |
add edi, 64 |
add esi, 16 |
call m8_s_mmx |
add edi, 64 |
add esi, 16 |
dec ecx |
jnz @b |
mov eax, [r_size] |
add eax, eax |
add eax, eax |
ret |
endp |
align 4 |
proc alloc_mix_buff |
bsf eax, [mix_buff_map] |
jnz .find |
xor eax, eax |
ret |
.find: |
btr [mix_buff_map], eax |
shl eax, 9 |
add eax, [mix_buff] |
ret |
endp |
align 4 |
proc m16_s_mmx |
movq mm0, [esi] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi], mm0 |
movq [edi+8], mm1 |
movq mm0, [esi+8] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+16], mm0 |
movq [edi+24], mm1 |
movq mm0, [esi+16] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+32], mm0 |
movq [edi+40], mm1 |
movq mm0, [esi+24] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+48], mm0 |
movq [edi+56], mm1 |
movq mm0, [esi+32] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+64], mm0 |
movq [edi+72], mm1 |
movq mm0, [esi+40] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+80], mm0 |
movq [edi+88], mm1 |
movq mm0, [esi+48] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+96], mm0 |
movq [edi+104], mm1 |
movq mm0, [esi+56] |
movq mm1, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm1, mm1 |
movq [edi+112], mm0 |
movq [edi+120], mm1 |
ret |
endp |
align 4 |
proc s8_s_mmx |
movq mm0, [esi] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq [edi], mm0 |
movq [edi+8], mm1 |
movq mm0, [esi+8] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq [edi+16], mm0 |
movq [edi+24], mm1 |
movq mm0, [esi+16] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq [edi+32], mm0 |
movq [edi+40], mm1 |
movq mm0, [esi+24] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq [edi+48], mm0 |
movq [edi+56], mm1 |
ret |
endp |
align 4 |
proc m8_s_mmx |
movq mm0, [esi] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq mm2, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm2, mm2 |
movq mm3, mm1 |
punpcklwd mm1, mm1 |
punpckhwd mm3, mm3 |
movq [edi], mm0 |
movq [edi+8], mm2 |
movq [edi+16], mm1 |
movq [edi+24], mm3 |
movq mm0, [esi+8] |
psubb mm0, mm7 |
movq mm1, mm0 |
punpcklbw mm0, mm0 |
pand mm0, mm6 |
punpckhbw mm1, mm1 |
pand mm1, mm6 |
movq mm2, mm0 |
punpcklwd mm0, mm0 |
punpckhwd mm2, mm2 |
movq mm3, mm1 |
punpcklwd mm1, mm1 |
punpckhwd mm3, mm3 |
movq [edi+32], mm0 |
movq [edi+40], mm2 |
movq [edi+48], mm1 |
movq [edi+56], mm3 |
ret |
endp |
align 4 |
proc mix_2_1 stdcall, output:dword, str0:dword, str1:dword |
mov edi, [output] |
mov eax, [str0] |
mov ebx, [str1] |
mov esi, 128 |
call [mix_2_core] ;edi, eax, ebx |
add edi, esi |
add eax, esi |
add ebx, esi |
call [mix_2_core] ;edi, eax, ebx |
add edi, esi |
add eax, esi |
add ebx, esi |
call [mix_2_core] ;edi, eax, ebx |
add edi, esi |
add eax, esi |
add ebx, esi |
call [mix_2_core] ;edi, eax, ebx |
ret |
endp |
align 4 |
proc mix_3_1 stdcall, output:dword, str0:dword, str1:dword, str2:dword |
mov edi, [output] |
mov eax, [str0] |
mov ebx, [str1] |
mov ecx, [str2] |
mov esi, 128 |
call [mix_3_core] |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
call [mix_3_core] |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
call [mix_3_core] |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
call [mix_3_core] |
ret |
endp |
align 4 |
proc mix_4_1 stdcall, str0:dword, str1:dword,\ |
str2:dword, str3:dword |
local output:DWORD |
call alloc_mix_buff |
and eax, eax |
jz .err |
mov [output], eax |
mov edi, eax |
mov eax, [str0] |
mov ebx, [str1] |
mov ecx, [str2] |
mov edx, [str3] |
mov esi, 128 |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
mov eax, [output] |
ret |
.err: |
xor eax, eax |
ret |
endp |
align 4 |
proc final_mix stdcall, output:dword, str0:dword, str1:dword,\ |
str2:dword, str3:dword |
mov edi, [output] |
mov eax, [str0] |
mov ebx, [str1] |
mov ecx, [str2] |
mov edx, [str3] |
mov esi, 128 |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
add edi, esi |
add eax, esi |
add ebx, esi |
add ecx, esi |
add edx, esi |
call [mix_4_core] ;edi, eax, ebx, ecx, edx |
ret |
endp |
align 4 |
proc copy_mem stdcall, output:dword, input:dword |
mov edi, [output] |
mov esi, [input] |
mov ecx, 0x80 |
.l1: |
mov eax, [esi] |
mov [edi], eax |
add esi, 4 |
add edi, 4 |
loop .l1 |
ret |
endp |
proc memcpy |
@@: |
mov eax, [esi] |
mov [edi], eax |
add esi, 4 |
add edi, 4 |
dec ecx |
jnz @B |
ret |
endp |
if 0 |
align 4 |
proc new_mix stdcall, output:dword |
locals |
mixCounter dd ? |
mixIndex dd ? |
streamIndex dd ? |
inputCount dd ? |
main_count dd ? |
blockCount dd ? |
mix_out dd ? |
endl |
call prepare_playlist |
cmp [play_count], 0 |
je .exit |
call FpuSave |
mov [main_count], 32; |
.l00: |
mov [mix_buff_map], 0x0000FFFF; |
xor eax, eax |
mov [mixCounter], eax |
mov [mixIndex],eax |
mov [streamIndex], eax; |
mov ebx, [play_count] |
mov [inputCount], ebx |
.l0: |
mov ecx, 4 |
.l1: |
mov ebx, [streamIndex] |
mov esi, [play_list+ebx*4] |
mov eax, [esi+STREAM.work_read] |
add [esi+STREAM.work_read], 512 |
mov ebx, [mixIndex] |
mov [mix_input+ebx*4], eax |
inc [mixCounter] |
inc [mixIndex] |
inc [streamIndex] |
dec [inputCount] |
jz .m2 |
dec ecx |
jnz .l1 |
cmp [mixCounter], 4 |
jnz .m2 |
stdcall mix_4_1, [mix_input],[mix_input+4],[mix_input+8],[mix_input+12] |
sub [mixIndex],4 |
mov ebx, [mixIndex] |
mov [mix_input+ebx*4], eax |
inc [mixIndex] |
mov [mixCounter], 0 |
cmp [inputCount], 0 |
jnz .l0 |
.m2: |
cmp [mixIndex], 1 |
jne @f |
stdcall copy_mem, [output], [mix_input] |
jmp .m3 |
@@: |
cmp [mixIndex], 2 |
jne @f |
stdcall mix_2_1, [output], [mix_input], [mix_input+4] |
jmp .m3 |
@@: |
cmp [mixIndex], 3 |
jne @f |
stdcall mix_3_1, [output],[mix_input],[mix_input+4],[mix_input+8] |
jmp .m3 |
@@: |
stdcall final_mix, [output],[mix_input],[mix_input+4],[mix_input+8], [mix_input+12] |
.m3: |
add [output],512 |
dec [main_count] |
jnz .l00 |
call update_stream |
emms |
call FpuRestore |
ret |
.exit: |
mov edi, [output] |
mov ecx, 0x1000 |
xor eax, eax |
cld |
rep stosd |
ret |
endp |
end if |
/kernel/branches/gfx_kernel/drivers/proc32.inc |
---|
0,0 → 1,268 |
; Macroinstructions for defining and calling procedures |
macro stdcall proc,[arg] ; directly call STDCALL procedure |
{ common |
if ~ arg eq |
reverse |
pushd arg |
common |
end if |
call proc } |
macro invoke proc,[arg] ; indirectly call STDCALL procedure |
{ common |
if ~ arg eq |
reverse |
pushd arg |
common |
end if |
call [proc] } |
macro ccall proc,[arg] ; directly call CDECL procedure |
{ common |
size@ccall = 0 |
if ~ arg eq |
reverse |
pushd arg |
size@ccall = size@ccall+4 |
common |
end if |
call proc |
if size@ccall |
add esp,size@ccall |
end if } |
macro cinvoke proc,[arg] ; indirectly call CDECL procedure |
{ common |
size@ccall = 0 |
if ~ arg eq |
reverse |
pushd arg |
size@ccall = size@ccall+4 |
common |
end if |
call [proc] |
if size@ccall |
add esp,size@ccall |
end if } |
macro proc [args] ; define procedure |
{ common |
match name params, args> |
\{ define@proc name,<params \} } |
prologue@proc equ prologuedef |
macro prologuedef procname,flag,parmbytes,localbytes,reglist |
{ if parmbytes | localbytes |
push ebp |
mov ebp,esp |
if localbytes |
sub esp,localbytes |
end if |
end if |
irps reg, reglist \{ push reg \} } |
epilogue@proc equ epiloguedef |
macro epiloguedef procname,flag,parmbytes,localbytes,reglist |
{ irps reg, reglist \{ reverse pop reg \} |
if parmbytes | localbytes |
leave |
end if |
if (flag and 10000b) | (parmbytes=0) |
retn |
else |
retn parmbytes |
end if } |
macro define@proc name,statement |
{ local params,flag,regs,parmbytes,localbytes,current |
if used name |
name: |
match =stdcall args, statement \{ params equ args |
flag = 11b \} |
match =stdcall, statement \{ params equ |
flag = 11b \} |
match =c args, statement \{ params equ args |
flag = 10001b \} |
match =c, statement \{ params equ |
flag = 10001b \} |
match =params, params \{ params equ statement |
flag = 0 \} |
virtual at ebp+8 |
match =uses reglist=,args, params \{ regs equ reglist |
params equ args \} |
match =regs =uses reglist, regs params \{ regs equ reglist |
params equ \} |
match =regs, regs \{ regs equ \} |
match =,args, params \{ defargs@proc args \} |
match =args@proc args, args@proc params \{ defargs@proc args \} |
parmbytes = $ - (ebp+8) |
end virtual |
name # % = parmbytes/4 |
all@vars equ |
current = 0 |
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \} |
macro locals |
\{ virtual at ebp-localbytes+current |
macro label . \\{ deflocal@proc .,:, \\} |
struc db [val] \\{ \common deflocal@proc .,db,val \\} |
struc dw [val] \\{ \common deflocal@proc .,dw,val \\} |
struc dp [val] \\{ \common deflocal@proc .,dp,val \\} |
struc dd [val] \\{ \common deflocal@proc .,dd,val \\} |
struc dt [val] \\{ \common deflocal@proc .,dt,val \\} |
struc dq [val] \\{ \common deflocal@proc .,dq,val \\} |
struc rb cnt \\{ deflocal@proc .,rb cnt, \\} |
struc rw cnt \\{ deflocal@proc .,rw cnt, \\} |
struc rp cnt \\{ deflocal@proc .,rp cnt, \\} |
struc rd cnt \\{ deflocal@proc .,rd cnt, \\} |
struc rt cnt \\{ deflocal@proc .,rt cnt, \\} |
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \} |
macro endl |
\{ purge label |
restruc db,dw,dp,dd,dt,dq |
restruc rb,rw,rp,rd,rt,rq |
restruc byte,word,dword,pword,tword,qword |
current = $-(ebp-localbytes) |
end virtual \} |
macro ret operand |
\{ match any, operand \\{ retn operand \\} |
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs> |
\\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \} |
macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2 |
end if \} } |
macro defargs@proc [arg] |
{ common |
if ~ arg eq |
forward |
local ..arg,current@arg |
match argname:type, arg |
\{ current@arg equ argname |
label ..arg type |
argname equ ..arg |
if dqword eq type |
dd ?,?,?,? |
else if tbyte eq type |
dd ?,?,? |
else if qword eq type | pword eq type |
dd ?,? |
else |
dd ? |
end if \} |
match =current@arg,current@arg |
\{ current@arg equ arg |
arg equ ..arg |
..arg dd ? \} |
common |
args@proc equ current@arg |
forward |
restore current@arg |
common |
end if } |
macro deflocal@proc name,def,[val] |
{ common |
match vars, all@vars \{ all@vars equ all@vars, \} |
all@vars equ all@vars name |
forward |
local ..var,..tmp |
..var def val |
match =?, val \{ ..tmp equ \} |
match any =dup (=?), val \{ ..tmp equ \} |
match tmp : value, ..tmp : val |
\{ tmp: end virtual |
initlocal@proc ..var,def value |
virtual at tmp\} |
common |
match first rest, ..var, \{ name equ first \} } |
macro initlocal@proc name,def |
{ virtual at name |
def |
size@initlocal = $ - name |
end virtual |
position@initlocal = 0 |
while size@initlocal > position@initlocal |
virtual at name |
def |
if size@initlocal - position@initlocal < 2 |
current@initlocal = 1 |
load byte@initlocal byte from name+position@initlocal |
else if size@initlocal - position@initlocal < 4 |
current@initlocal = 2 |
load word@initlocal word from name+position@initlocal |
else |
current@initlocal = 4 |
load dword@initlocal dword from name+position@initlocal |
end if |
end virtual |
if current@initlocal = 1 |
mov byte [name+position@initlocal],byte@initlocal |
else if current@initlocal = 2 |
mov word [name+position@initlocal],word@initlocal |
else |
mov dword [name+position@initlocal],dword@initlocal |
end if |
position@initlocal = position@initlocal + current@initlocal |
end while } |
macro endp |
{ purge ret,locals,endl |
finish@proc |
purge finish@proc |
restore regs@proc |
match all,args@proc \{ restore all \} |
restore args@proc |
match all,all@vars \{ restore all \} } |
macro local [var] |
{ common |
locals |
forward done@local equ |
match varname[count]:vartype, var |
\{ match =BYTE, vartype \\{ varname rb count |
restore done@local \\} |
match =WORD, vartype \\{ varname rw count |
restore done@local \\} |
match =DWORD, vartype \\{ varname rd count |
restore done@local \\} |
match =PWORD, vartype \\{ varname rp count |
restore done@local \\} |
match =QWORD, vartype \\{ varname rq count |
restore done@local \\} |
match =TBYTE, vartype \\{ varname rt count |
restore done@local \\} |
match =DQWORD, vartype \\{ label varname dqword |
rq count+count |
restore done@local \\} |
match , done@local \\{ virtual |
varname vartype |
end virtual |
rb count*sizeof.\#vartype |
restore done@local \\} \} |
match :varname:vartype, done@local:var |
\{ match =BYTE, vartype \\{ varname db ? |
restore done@local \\} |
match =WORD, vartype \\{ varname dw ? |
restore done@local \\} |
match =DWORD, vartype \\{ varname dd ? |
restore done@local \\} |
match =PWORD, vartype \\{ varname dp ? |
restore done@local \\} |
match =QWORD, vartype \\{ varname dq ? |
restore done@local \\} |
match =TBYTE, vartype \\{ varname dt ? |
restore done@local \\} |
match =DQWORD, vartype \\{ label varname dqword |
dq ?,? |
restore done@local \\} |
match , done@local \\{ varname vartype |
restore done@local \\} \} |
match ,done@local |
\{ var |
restore done@local \} |
common |
endl } |
/kernel/branches/gfx_kernel/drivers/sceletone.asm |
---|
0,0 → 1,157 |
;driver sceletone |
format MS COFF |
include 'proc32.inc' |
include 'imports.inc' |
OS_BASE equ 0; |
new_app_base equ 0x60400000 |
PROC_BASE equ OS_BASE+0x0080000 |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
public START |
public service_proc |
public version |
DEBUG equ 1 |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
STRIDE equ 4 ;size of row in devices table |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .exit |
.entry: |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
stdcall RegService, my_service, service_proc |
ret |
.fail: |
.exit: |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
; mov edi, [ioctl] |
; mov eax, [edi+io_code] |
xor eax, eax |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc detect |
locals |
last_bus dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, STRIDE |
jmp @B |
.next: inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
xor eax, eax |
inc eax |
ret |
.err: |
xor eax, eax |
ret |
endp |
;DEVICE_ID equ ; pci device id |
;VENDOR_ID equ ; device vendor id |
;all initialized data place here |
align 4 |
devices dd (DEVICE_ID shl 16)+VENDOR_ID |
dd 0 ;terminator |
version dd 0x00030003 |
my_service db 'MY_SERVICE',0 ;max 16 chars include zero |
msgInit db 'detect hardware...',13,10,0 |
msgPCI db 'PCI accsess not supported',13,10,0 |
msgFail db 'device not found',13,10,0 |
section '.data' data readable writable align 16 |
;all uninitialized data place here |
/kernel/branches/gfx_kernel/drivers/sis.asm |
---|
0,0 → 1,1174 |
format MS COFF |
include 'proc32.inc' |
include 'imports.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 ? |
.devfn dd ? |
.vendor dd ? |
.dev_id dd ? |
.pci_cmd dd ? |
.pci_stat dd ? |
.codec_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_io_base dd ? |
.ctrl_mem_base dd ? |
.cfg_reg dd ? |
.int_line dd ? |
.vendor_ids dd ? ;vendor id string |
.ctrl_ids dd ? ;hub id string |
.buffer dd ? |
.notify_pos dd ? |
.notify_task dd ? |
.lvi_reg dd ? |
.ctrl_setup dd ? |
.user_callback dd ? |
.codec_read16 dd ? |
.codec_write16 dd ? |
.ctrl_read8 dd ? |
.ctrl_read16 dd ? |
.ctrl_read32 dd ? |
.ctrl_write8 dd ? |
.ctrl_write16 dd ? |
.ctrl_write32 dd ? |
} |
struc CODEC ;Audio Chip base class |
{ |
.chip_id dd ? |
.flags dd ? |
.status dd ? |
.ac_vendor_ids dd ? ;ac vendor id string |
.chip_ids dd ? ;chip model string |
.shadow_flag dd ? |
dd ? |
.regs dw ? ; codec registers |
.reg_master_vol dw ? ;0x02 |
.reg_aux_out_vol dw ? ;0x04 |
.reg_mone_vol dw ? ;0x06 |
.reg_master_tone dw ? ;0x08 |
.reg_beep_vol dw ? ;0x0A |
.reg_phone_vol dw ? ;0x0C |
.reg_mic_vol dw ? ;0x0E |
.reg_line_in_vol dw ? ;0x10 |
.reg_cd_vol dw ? ;0x12 |
.reg_video_vol dw ? ;0x14 |
.reg_aux_in_vol dw ? ;0x16 |
.reg_pcm_out_vol dw ? ;0x18 |
.reg_rec_select dw ? ;0x1A |
.reg_rec_gain dw ? ;0x1C |
.reg_rec_gain_mic dw ? ;0x1E |
.reg_gen dw ? ;0x20 |
.reg_3d_ctrl dw ? ;0X22 |
.reg_page dw ? ;0X24 |
.reg_powerdown dw ? ;0x26 |
.reg_ext_audio dw ? ;0x28 |
.reg_ext_st dw ? ;0x2a |
.reg_pcm_front_rate dw ? ;0x2c |
.reg_pcm_surr_rate dw ? ;0x2e |
.reg_lfe_rate dw ? ;0x30 |
.reg_pcm_in_rate dw ? ;0x32 |
dw ? ;0x34 |
.reg_cent_lfe_vol dw ? ;0x36 |
.reg_surr_vol dw ? ;0x38 |
.reg_spdif_ctrl dw ? ;0x3A |
dw ? ;0x3C |
dw ? ;0x3E |
dw ? ;0x40 |
dw ? ;0x42 |
dw ? ;0x44 |
dw ? ;0x46 |
dw ? ;0x48 |
dw ? ;0x4A |
dw ? ;0x4C |
dw ? ;0x4E |
dw ? ;0x50 |
dw ? ;0x52 |
dw ? ;0x54 |
dw ? ;0x56 |
dw ? ;0x58 |
dw ? ;0x5A |
dw ? ;0x5C |
dw ? ;0x5E |
.reg_page_0 dw ? ;0x60 |
.reg_page_1 dw ? ;0x62 |
.reg_page_2 dw ? ;0x64 |
.reg_page_3 dw ? ;0x66 |
.reg_page_4 dw ? ;0x68 |
.reg_page_5 dw ? ;0x6A |
.reg_page_6 dw ? ;0x6C |
.reg_page_7 dw ? ;0x6E |
dw ? ;0x70 |
dw ? ;0x72 |
dw ? ;0x74 |
dw ? ;0x76 |
dw ? ;0x78 |
dw ? ;0x7A |
.reg_vendor_id_1 dw ? ;0x7C |
.reg_vendor_id_2 dw ? ;0x7E |
.reset dd ? ;virual |
.set_master_vol dd ? |
} |
struc CTRL_INFO |
{ .pci_cmd dd ? |
.irq dd ? |
.glob_cntrl dd ? |
.glob_sta dd ? |
.codec_io_base dd ? |
.ctrl_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_mem_base dd ? |
.codec_id dd ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
OS_BASE equ 0; 0x80400000 |
SLOT_BASE equ OS_BASE+0x0080000 |
new_app_base equ 0x80000000 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi,[ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call SysMsgBoardStr |
end if |
call init_controller |
test eax, eax |
jz .fail |
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 |
.stop: |
call stop |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
cmp eax, DEV_PLAY |
jne @F |
if DEBUG |
mov esi, msgPlay |
call SysMsgBoardStr |
end if |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call SysMsgBoardStr |
end if |
call stop |
ret |
@@: |
cmp eax, DEV_CALLBACK |
jne @F |
mov ebx, [edi+input] |
stdcall set_callback, [ebx] |
ret |
@@: |
cmp eax, DEV_SET_MASTERVOL |
jne @F |
mov eax, [edi+input] |
mov eax, [eax] |
call set_master_vol ;eax= vol |
ret |
@@: |
cmp eax, DEV_GET_MASTERVOL |
jne @F |
mov ebx, [edi+output] |
add ebx, new_app_base |
stdcall get_master_vol, ebx |
ret |
@@: |
cmp eax, DEV_GET_INFO |
jne @F |
mov ebx, [edi+output] |
stdcall get_dev_info, ebx |
ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc ac97_irq |
; if DEBUG |
; mov esi, msgIRQ |
; call SysMsgBoardStr |
; end if |
mov edx, PCM_OUT_CR_REG |
mov al, 0x10 |
call [ctrl.ctrl_write8] |
mov ax, 0x1c |
mov edx, PCM_OUT_SR_REG |
call [ctrl.ctrl_write16] |
mov edx, PCM_OUT_CIV_REG |
call [ctrl.ctrl_read8] |
and eax, 0x1F |
cmp eax, [civ_val] |
je .skip |
mov [civ_val], eax |
dec eax |
and eax, 0x1F |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x11 |
call [ctrl.ctrl_write8] |
mov eax, [civ_val] |
add eax, 1 |
and eax, 31 |
mov ebx, dword [buff_list+eax*4] |
cmp [ctrl.user_callback], 0 |
je @f |
stdcall [ctrl.user_callback], ebx |
@@: |
ret |
.skip: |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x11 |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc create_primary_buff |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call GetPgAddr |
mov ebx, 0xC0004000 |
mov ecx, 4 |
mov edi, pcmout_bdl |
@@: |
mov [edi], eax |
mov [edi+4], ebx |
mov [edi+32], eax |
mov [edi+4+32], ebx |
mov [edi+64], eax |
mov [edi+4+64], ebx |
mov [edi+96], eax |
mov [edi+4+96], ebx |
mov [edi+128], eax |
mov [edi+4+128], ebx |
mov [edi+160], eax |
mov [edi+4+160], ebx |
mov [edi+192], eax |
mov [edi+4+192], ebx |
mov [edi+224], eax |
mov [edi+4+224], ebx |
add eax, 0x4000 |
add edi, 8 |
loop @B |
mov edi, buff_list |
mov eax, [ctrl.buffer] |
mov ecx, 4 |
@@: |
mov [edi], eax |
mov [edi+16], eax |
mov [edi+32], eax |
mov [edi+48], eax |
mov [edi+64], eax |
mov [edi+80], eax |
mov [edi+96], eax |
mov [edi+112], eax |
add eax, 0x4000 |
add edi, 4 |
loop @B |
mov eax, pcmout_bdl |
mov ebx, eax |
call GetPgAddr ;eax |
and ebx, 0xFFF |
add eax, ebx |
mov edx, PCM_OUT_BDL |
call [ctrl.ctrl_write32] |
mov eax, 16 |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
and eax, not 0x000000C0 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
ret |
endp |
align 4 |
proc detect_controller |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, 12 |
jmp @B |
.next: |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
mov ebx, [bus] |
mov [ctrl.bus], ebx |
mov ecx, [devfn] |
mov [ctrl.devfn], ecx |
mov edx, eax |
and edx, 0xFFFF |
mov [ctrl.vendor], edx |
shr eax, 16 |
mov [ctrl.dev_id], eax |
mov ebx, [edi+4] |
mov [ctrl.ctrl_ids], ebx |
mov [ctrl.vendor_ids], msg_SIS |
mov esi, [edi+8] |
mov [ctrl.ctrl_setup], esi |
ret |
.err: |
xor eax, eax |
ret |
endp |
align 4 |
proc init_controller |
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 |
mov ebx, eax |
and eax, 0xFFFF |
mov [ctrl.pci_cmd], eax |
shr ebx, 16 |
mov [ctrl.pci_stat], ebx |
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 |
mov esi, msgControl |
call SysMsgBoardStr |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
test eax, CTRL_ST_CREADY |
jnz .ready |
call reset_codec |
and eax, eax |
jz .err |
xor edx, edx ;ac_reg_0 |
call [ctrl.codec_write16] |
xor eax, eax |
mov edx, CODEC_REG_POWERDOWN |
call [ctrl.codec_write16] |
mov [counter], 200 ; total 200*5 ms = 1s |
.wait: |
mov edx, CODEC_REG_POWERDOWN |
call [ctrl.codec_read16] |
and eax, 0x0F |
cmp eax, 0x0F |
je .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 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
and eax, not 0x08 |
or eax, 0x02 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
if DEBUG |
mov esi, msgCold |
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, msgCRFail |
call SysMsgBoardStr |
end if |
.fail: |
stc |
ret |
.ok: |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
and eax, CTRL_ST_CREADY |
jz .fail |
clc |
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, 0x0 |
call [ctrl.ctrl_write8] |
mov ax, 0x1c |
mov edx, PCM_OUT_SR_REG |
call [ctrl.ctrl_write16] |
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 |
js @B |
pop eax |
pop ebx |
pop edx |
pop ecx |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; CONTROLLER IO functions |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
proc codec_io_r16 |
add edx, [ctrl.codec_io_base] |
in ax, dx |
ret |
endp |
align 4 |
proc codec_io_w16 |
add edx, [ctrl.codec_io_base] |
out dx, ax |
ret |
endp |
align 4 |
proc ctrl_io_r8 |
add edx, [ctrl.ctrl_io_base] |
in al, dx |
ret |
endp |
align 4 |
proc ctrl_io_r16 |
add edx, [ctrl.ctrl_io_base] |
in ax, dx |
ret |
endp |
align 4 |
proc ctrl_io_r32 |
add edx, [ctrl.ctrl_io_base] |
in eax, dx |
ret |
endp |
align 4 |
proc ctrl_io_w8 |
add edx, [ctrl.ctrl_io_base] |
out dx, al |
ret |
endp |
align 4 |
proc ctrl_io_w16 |
add edx, [ctrl.ctrl_io_base] |
out dx, ax |
ret |
endp |
align 4 |
proc ctrl_io_w32 |
add edx, [ctrl.ctrl_io_base] |
out dx, eax |
ret |
endp |
align 4 |
dword2str: |
mov esi, hex_buff |
mov ecx, -8 |
@@: |
rol eax, 4 |
mov ebx, eax |
and ebx, 0x0F |
mov bl, [ebx+hexletters] |
mov [8+esi+ecx], bl |
inc ecx |
jnz @B |
ret |
include "codec.inc" |
align 4 |
devices dd (CTRL_SIS shl 16)+VID_SIS,msg_AC, set_SIS |
dd 0 |
version dd 0x00040004 |
msg_AC db '7012 AC97 controller',13,10, 0 |
msg_SIS db 'Silicon Integrated Systems',13,10, 0 |
sz_sound_srv db 'SOUND',0 |
msgInit db 'detect hardware...',13,10,0 |
msgFail db 'device not found',13,10,0 |
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 |
msgStatus db 'global status ',0 |
msgControl db 'global control ',0 |
hexletters db '0123456789ABCDEF' |
hex_buff db 8 dup(0),13,10,0 |
section '.data' data readable writable align 16 |
pcmout_bdl rq 32 |
buff_list rd 32 |
codec CODEC |
ctrl AC_CNTRL |
lpc_bus rd 1 |
civ_val rd 1 |
/kernel/branches/gfx_kernel/drivers/sound.asm |
---|
0,0 → 1,1413 |
format MS COFF |
include 'proc32.inc' |
include 'imports.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 |
CTRL_MCP04 equ 0x003A |
CTRL_CK804 equ 0x0059 |
CTRL_CK8 equ 0x008A |
CTRL_CK8S equ 0x00EA |
CTRL_MCP51 equ 0x026B |
PCM_OUT_BDL equ 0x10 ; PCM out buffer descriptors list |
PCM_OUT_CR_REG equ 0x1b ; PCM out Control Register |
PCM_OUT_LVI_REG equ 0x15 ; PCM last valid index |
PCM_OUT_SR_REG equ 0x16 ; PCM out Status register |
PCM_OUT_PIV_REG equ 0x1a |
PCM_OUT_CIV_REG equ 0x14 ; PCM out current index |
PCM_IN_CR_REG equ 0x0b ; PCM in Control Register |
MC_IN_CR_REG equ 0x2b ; MIC in Control Register |
RR equ BIT1 ; reset registers. Nukes all regs |
CODEC_MASTER_VOL_REG equ 0x02 |
CODEC_AUX_VOL equ 0x04 ; |
CODEC_PCM_OUT_REG equ 18h ; PCM output volume |
CODEC_EXT_AUDIO_REG equ 28h ; extended audio |
CODEC_EXT_AUDIO_CTRL_REG equ 2ah ; extended audio control |
CODEC_PCM_FRONT_DACRATE_REG equ 2ch ; PCM out sample rate |
CODEC_PCM_SURND_DACRATE_REG equ 2eh ; surround sound sample rate |
CODEC_PCM_LFE_DACRATE_REG equ 30h ; LFE sample rate |
GLOB_CTRL equ 0x2C ; Global Control |
CTRL_STAT equ 0x30 ; Global Status |
CTRL_CAS equ 0x34 ; Codec Access Semiphore |
CAS_FLAG equ 0x01 ; Codec Access Semiphore Bit |
CTRL_ST_CREADY equ BIT8+BIT9+BIT28 ; Primary Codec Ready |
CTRL_ST_RCS equ 0x00008000 ; Read Completion Status |
CTRL_CNT_CRIE equ BIT4+BIT5+BIT6 ; Codecs Resume Interrupt Enable |
CTRL_CNT_AC_OFF equ 0x00000008 ; ACLINK Off |
CTRL_CNT_WARM equ 0x00000004 ; AC97 Warm Reset |
CTRL_CNT_COLD equ 0x00000002 ; AC97 Cold Reset |
CTRL_CNT_GIE equ 0x00000001 ; GPI Interrupt Enable |
CODEC_REG_POWERDOWN equ 0x26 |
CODEC_REG_ST equ 0x26 |
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
DEV_SET_BUFF equ 4 |
DEV_NOTIFY equ 5 |
DEV_SET_MASTERVOL equ 6 |
DEV_GET_MASTERVOL equ 7 |
DEV_GET_INFO equ 8 |
struc AC_CNTRL ;AC controller base class |
{ .bus dd ? |
.devfn dd ? |
.vendor dd ? |
.dev_id dd ? |
.pci_cmd dd ? |
.pci_stat dd ? |
.codec_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_io_base dd ? |
.ctrl_mem_base dd ? |
.cfg_reg dd ? |
.int_line dd ? |
.vendor_ids dd ? ;vendor id string |
.ctrl_ids dd ? ;hub id string |
.buffer dd ? |
.notify_pos dd ? |
.notify_task dd ? |
.lvi_reg dd ? |
.ctrl_setup dd ? |
.user_callback dd ? |
.codec_read16 dd ? |
.codec_write16 dd ? |
.ctrl_read8 dd ? |
.ctrl_read16 dd ? |
.ctrl_read32 dd ? |
.ctrl_write8 dd ? |
.ctrl_write16 dd ? |
.ctrl_write32 dd ? |
} |
struc CODEC ;Audio Chip base class |
{ |
.chip_id dd ? |
.flags dd ? |
.status dd ? |
.ac_vendor_ids dd ? ;ac vendor id string |
.chip_ids dd ? ;chip model string |
.shadow_flag dd ? |
dd ? |
.regs dw ? ; codec registers |
.reg_master_vol dw ? ;0x02 |
.reg_aux_out_vol dw ? ;0x04 |
.reg_mone_vol dw ? ;0x06 |
.reg_master_tone dw ? ;0x08 |
.reg_beep_vol dw ? ;0x0A |
.reg_phone_vol dw ? ;0x0C |
.reg_mic_vol dw ? ;0x0E |
.reg_line_in_vol dw ? ;0x10 |
.reg_cd_vol dw ? ;0x12 |
.reg_video_vol dw ? ;0x14 |
.reg_aux_in_vol dw ? ;0x16 |
.reg_pcm_out_vol dw ? ;0x18 |
.reg_rec_select dw ? ;0x1A |
.reg_rec_gain dw ? ;0x1C |
.reg_rec_gain_mic dw ? ;0x1E |
.reg_gen dw ? ;0x20 |
.reg_3d_ctrl dw ? ;0X22 |
.reg_page dw ? ;0X24 |
.reg_powerdown dw ? ;0x26 |
.reg_ext_audio dw ? ;0x28 |
.reg_ext_st dw ? ;0x2a |
.reg_pcm_front_rate dw ? ;0x2c |
.reg_pcm_surr_rate dw ? ;0x2e |
.reg_lfe_rate dw ? ;0x30 |
.reg_pcm_in_rate dw ? ;0x32 |
dw ? ;0x34 |
.reg_cent_lfe_vol dw ? ;0x36 |
.reg_surr_vol dw ? ;0x38 |
.reg_spdif_ctrl dw ? ;0x3A |
dw ? ;0x3C |
dw ? ;0x3E |
dw ? ;0x40 |
dw ? ;0x42 |
dw ? ;0x44 |
dw ? ;0x46 |
dw ? ;0x48 |
dw ? ;0x4A |
dw ? ;0x4C |
dw ? ;0x4E |
dw ? ;0x50 |
dw ? ;0x52 |
dw ? ;0x54 |
dw ? ;0x56 |
dw ? ;0x58 |
dw ? ;0x5A |
dw ? ;0x5C |
dw ? ;0x5E |
.reg_page_0 dw ? ;0x60 |
.reg_page_1 dw ? ;0x62 |
.reg_page_2 dw ? ;0x64 |
.reg_page_3 dw ? ;0x66 |
.reg_page_4 dw ? ;0x68 |
.reg_page_5 dw ? ;0x6A |
.reg_page_6 dw ? ;0x6C |
.reg_page_7 dw ? ;0x6E |
dw ? ;0x70 |
dw ? ;0x72 |
dw ? ;0x74 |
dw ? ;0x76 |
dw ? ;0x78 |
dw ? ;0x7A |
.reg_vendor_id_1 dw ? ;0x7C |
.reg_vendor_id_2 dw ? ;0x7E |
.reset dd ? ;virual |
.set_master_vol dd ? |
} |
struc CTRL_INFO |
{ .pci_cmd dd ? |
.irq dd ? |
.glob_cntrl dd ? |
.glob_sta dd ? |
.codec_io_base dd ? |
.ctrl_io_base dd ? |
.codec_mem_base dd ? |
.ctrl_mem_base dd ? |
.codec_id dd ? |
} |
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
EVENT_NOTIFY equ 0x00000200 |
OS_BASE equ 0; |
SLOT_BASE equ OS_BASE+0x0080000 |
new_app_base equ 0x80000000 |
public START |
public service_proc |
public version |
section '.flat' code readable align 16 |
proc START stdcall, state:dword |
cmp [state], 1 |
jne .stop |
if DEBUG |
mov esi, msgInit |
call SysMsgBoardStr |
end if |
call detect_controller |
test eax, eax |
jz .fail |
if DEBUG |
mov esi,[ctrl.vendor_ids] |
call SysMsgBoardStr |
mov esi, [ctrl.ctrl_ids] |
call SysMsgBoardStr |
end if |
call init_controller |
test eax, eax |
jz .fail |
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 |
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call SysMsgBoardStr |
end if |
xor eax, eax |
ret |
.stop: |
call stop |
xor eax, eax |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc service_proc stdcall, ioctl:dword |
mov edi, [ioctl] |
mov eax, [edi+io_code] |
cmp eax, DEV_PLAY |
jne @F |
if DEBUG |
mov esi, msgPlay |
call SysMsgBoardStr |
end if |
call play |
ret |
@@: |
cmp eax, DEV_STOP |
jne @F |
if DEBUG |
mov esi, msgStop |
call SysMsgBoardStr |
end if |
call stop |
ret |
@@: |
cmp eax, DEV_CALLBACK |
jne @F |
mov ebx, [edi+input] |
stdcall set_callback, [ebx] |
ret |
@@: |
cmp eax, DEV_SET_MASTERVOL |
jne @F |
mov eax, [edi+input] |
mov eax, [eax] |
call set_master_vol ;eax= vol |
ret |
@@: |
cmp eax, DEV_GET_MASTERVOL |
jne @F |
mov ebx, [edi+output] |
add ebx, new_app_base |
stdcall get_master_vol, ebx |
ret |
;@@: |
; cmp eax, DEV_GET_INFO |
; jne @F |
; mov ebx, [edi+output] |
; stdcall get_dev_info, ebx |
; ret |
@@: |
.fail: |
or eax, -1 |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc 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, 0x10; 0x10 |
call [ctrl.ctrl_write8] |
mov ax, 0x1c |
mov edx, PCM_OUT_SR_REG |
call [ctrl.ctrl_write16] |
mov edx, PCM_OUT_CIV_REG |
call [ctrl.ctrl_read8] |
and eax, 0x1F |
cmp eax, [civ_val] |
je .skip |
mov [civ_val], eax |
dec eax |
and eax, 0x1F |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x11 ;0x1D |
call [ctrl.ctrl_write8] |
mov eax, [civ_val] |
add eax, 1 |
and eax, 31 |
mov ebx, dword [buff_list+eax*4] |
cmp [ctrl.user_callback], 0 |
je @f |
stdcall [ctrl.user_callback], ebx |
@@: |
ret |
.skip: |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x11 ;0x1D |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc create_primary_buff |
stdcall KernelAlloc, 0x10000 |
mov [ctrl.buffer], eax |
mov edi, eax |
mov ecx, 0x10000/4 |
xor eax, eax |
cld |
rep stosd |
mov eax, [ctrl.buffer] |
call GetPgAddr |
mov ebx, 0xC0002000 |
mov ecx, 4 |
mov edi, pcmout_bdl |
@@: |
mov [edi], eax |
mov [edi+4], ebx |
mov [edi+32], eax |
mov [edi+4+32], ebx |
mov [edi+64], eax |
mov [edi+4+64], ebx |
mov [edi+96], eax |
mov [edi+4+96], ebx |
mov [edi+128], eax |
mov [edi+4+128], ebx |
mov [edi+160], eax |
mov [edi+4+160], ebx |
mov [edi+192], eax |
mov [edi+4+192], ebx |
mov [edi+224], eax |
mov [edi+4+224], ebx |
add eax, 0x4000 |
add edi, 8 |
loop @B |
mov edi, buff_list |
mov eax, [ctrl.buffer] |
mov ecx, 4 |
@@: |
mov [edi], eax |
mov [edi+16], eax |
mov [edi+32], eax |
mov [edi+48], eax |
mov [edi+64], eax |
mov [edi+80], eax |
mov [edi+96], eax |
mov [edi+112], eax |
add eax, 0x4000 |
add edi, 4 |
loop @B |
mov eax, pcmout_bdl |
mov ebx, eax |
call GetPgAddr ;eax |
and ebx, 0xFFF |
add eax, ebx |
mov edx, PCM_OUT_BDL |
call [ctrl.ctrl_write32] |
mov eax, 16 |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
ret |
endp |
align 4 |
proc detect_controller |
locals |
last_bus dd ? |
bus dd ? |
devfn dd ? |
endl |
xor eax, eax |
mov [bus], eax |
inc eax |
call PciApi |
cmp eax, -1 |
je .err |
mov [last_bus], eax |
.next_bus: |
and [devfn], 0 |
.next_dev: |
stdcall PciRead32, [bus], [devfn], dword 0 |
test eax, eax |
jz .next |
cmp eax, -1 |
je .next |
mov edi, devices |
@@: |
mov ebx, [edi] |
test ebx, ebx |
jz .next |
cmp eax, ebx |
je .found |
add edi, 12 |
jmp @B |
.next: |
inc [devfn] |
cmp [devfn], 256 |
jb .next_dev |
mov eax, [bus] |
inc eax |
mov [bus], eax |
cmp eax, [last_bus] |
jna .next_bus |
xor eax, eax |
ret |
.found: |
mov ebx, [bus] |
mov [ctrl.bus], ebx |
mov ecx, [devfn] |
mov [ctrl.devfn], ecx |
mov edx, eax |
and edx, 0xFFFF |
mov [ctrl.vendor], edx |
shr eax, 16 |
mov [ctrl.dev_id], eax |
mov ebx, [edi+4] |
mov [ctrl.ctrl_ids], ebx |
mov esi, [edi+8] |
mov [ctrl.ctrl_setup], esi |
cmp 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 |
mov esi, msgControl |
call SysMsgBoardStr |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
mov esi, msgStatus |
call SysMsgBoardStr |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
call dword2str |
call SysMsgBoardStr |
test eax, CTRL_ST_CREADY |
jnz .ready |
call reset_codec |
and eax, eax |
jz .err |
xor edx, edx ;ac_reg_0 |
call [ctrl.codec_write16] |
xor eax, eax |
mov edx, CODEC_REG_POWERDOWN |
call [ctrl.codec_write16] |
mov [counter], 200 ; total 200*5 ms = 1s |
.wait: |
mov edx, CODEC_REG_POWERDOWN |
call [ctrl.codec_read16] |
and eax, 0x0F |
cmp eax, 0x0F |
jz .ready |
mov eax, 5000 ; wait 5 ms |
call StallExec |
sub [counter] , 1 |
jnz .wait |
.err: |
xor eax, eax ; timeout error |
ret |
.ready: |
call detect_codec |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc reset_codec |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
test eax, 0x02 |
jz .cold |
call warm_reset |
jnc .ok |
.cold: |
call cold_reset |
jnc .ok |
if DEBUG |
mov esi, msgCFail |
call SysMsgBoardStr |
end if |
xor eax, eax ; timeout error |
ret |
.ok: |
if DEBUG |
mov esi, msgResetOk |
call SysMsgBoardStr |
end if |
xor eax, eax |
inc eax |
ret |
endp |
align 4 |
proc warm_reset |
locals |
counter dd ? |
endl |
mov eax, 0x06 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
if DEBUG |
mov esi, msgWarm |
call SysMsgBoardStr |
end if |
mov [counter], 10 ; total 10*100 ms = 1s |
.wait: |
mov eax, 100000 ; wait 100 ms |
call StallExec |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
test eax, 4 |
jz .ok |
sub [counter], 1 |
jnz .wait |
if DEBUG |
mov esi, msgWRFail |
call SysMsgBoardStr |
end if |
stc |
ret |
.ok: |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
and eax, CTRL_ST_CREADY |
jz .fail |
clc |
ret |
.fail: |
stc |
ret |
endp |
align 4 |
proc cold_reset |
locals |
counter dd ? |
endl |
xor eax, eax |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
if DEBUG |
mov esi, msgCold |
call SysMsgBoardStr |
end if |
mov eax, 1000000 ; wait 1 s |
call StallExec |
mov eax, 2 |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_write32] |
mov [counter], 10 ; total 10*100 ms = 1s |
.wait: |
mov eax, 100000 ; wait 100 ms |
call StallExec |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
test eax, 4 |
jz .ok |
sub [counter], 1 |
jnz .wait |
if DEBUG |
mov esi, msgCRFail |
call SysMsgBoardStr |
end if |
stc |
ret |
.ok: |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
and eax, CTRL_ST_CREADY |
jz .fail |
clc |
ret |
.fail: |
stc |
ret |
endp |
align 4 |
play: |
mov eax, 16 |
mov [ctrl.lvi_reg], eax |
mov edx, PCM_OUT_LVI_REG |
call [ctrl.ctrl_write8] |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x1D |
call [ctrl.ctrl_write8] |
xor eax, eax |
ret |
align 4 |
stop: |
mov edx, PCM_OUT_CR_REG |
mov ax, 0x0 |
call [ctrl.ctrl_write8] |
mov ax, 0x1c |
mov edx, PCM_OUT_SR_REG |
call [ctrl.ctrl_write16] |
xor eax, eax |
ret |
align 4 |
proc get_dev_info stdcall, p_info:dword |
virtual at esi |
CTRL_INFO CTRL_INFO |
end virtual |
mov esi, [p_info] |
mov eax, [ctrl.int_line] |
mov ebx, [ctrl.codec_io_base] |
mov ecx, [ctrl.ctrl_io_base] |
mov edx, [ctrl.codec_mem_base] |
mov edi, [ctrl.ctrl_mem_base] |
mov [CTRL_INFO.irq], eax |
mov [CTRL_INFO.codec_io_base], ebx |
mov [CTRL_INFO.ctrl_io_base], ecx |
mov [CTRL_INFO.codec_mem_base], edx |
mov [CTRL_INFO.ctrl_mem_base], edi |
mov eax, [codec.chip_id] |
mov [CTRL_INFO.codec_id], eax |
mov edx, GLOB_CTRL |
call [ctrl.ctrl_read32] |
mov [CTRL_INFO.glob_cntrl], eax |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
mov [CTRL_INFO.glob_sta], eax |
mov ebx, [ctrl.pci_cmd] |
mov [CTRL_INFO.pci_cmd], ebx |
ret |
endp |
align 4 |
proc set_callback stdcall, handler:dword |
mov eax, [handler] |
mov [ctrl.user_callback], eax |
ret |
endp |
align 4 |
proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax |
mov edx, [ac_reg] |
mov ebx, edx |
shr ebx, 1 |
bt [codec.shadow_flag], ebx |
jc .use_shadow |
call [ctrl.codec_read16] ;change edx !!! |
mov ecx, eax |
mov edx, CTRL_STAT |
call [ctrl.ctrl_read32] |
test eax, CTRL_ST_RCS |
jz .read_ok |
mov edx, CTRL_STAT |
call [ctrl.ctrl_write32] |
xor eax,eax |
not eax ;timeout |
ret |
.read_ok: |
mov edx, [ac_reg] |
mov [codec.regs+edx], cx |
bts [codec.shadow_flag], ebx |
mov eax, ecx |
ret |
.use_shadow: |
movzx eax, word [codec.regs+edx] |
ret |
endp |
align 4 |
proc codec_write stdcall, ac_reg:dword |
push eax |
call check_semafore |
and eax, eax |
jz .err |
pop eax |
mov esi, [ac_reg] |
mov edx, esi |
call [ctrl.codec_write16] |
mov [codec.regs+esi], ax |
shr esi, 1 |
bts [codec.shadow_flag], esi |
ret |
.err: |
pop eax |
ret |
endp |
align 4 |
proc codec_check_ready |
mov edx, CTRL_ST |
call [ctrl.ctrl_read32] |
and eax, CTRL_ST_CREADY |
jz .not_ready |
xor eax, wax |
inc eax |
ret |
.not_ready: |
xor eax, eax |
ret |
endp |
align 4 |
proc check_semafore |
local counter:DWORD |
mov [counter], 100 |
.l1: |
mov edx, CTRL_CAS |
call [ctrl.ctrl_read8] |
and eax, CAS_FLAG |
jz .ok |
mov eax, 1 |
call StallExec |
sub [counter], 1 |
jnz .l1 |
xor eax, eax |
ret |
align 4 |
.ok: |
xor eax,eax |
inc eax |
ret |
endp |
align 4 |
proc StallExec |
push ecx |
push edx |
push ebx |
push eax |
mov ecx, CPU_FREQ |
mul ecx |
mov ebx, eax ;low |
mov ecx, edx ;high |
rdtsc |
add ebx, eax |
adc ecx,edx |
@@: |
rdtsc |
sub eax, ebx |
sbb edx, ecx |
js @B |
pop eax |
pop ebx |
pop edx |
pop ecx |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; CONTROLLER IO functions |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
proc codec_io_r16 |
add edx, [ctrl.codec_io_base] |
in ax, dx |
ret |
endp |
align 4 |
proc codec_io_w16 |
add edx, [ctrl.codec_io_base] |
out dx, ax |
ret |
endp |
align 4 |
proc ctrl_io_r8 |
add edx, [ctrl.ctrl_io_base] |
in al, dx |
ret |
endp |
align 4 |
proc ctrl_io_r16 |
add edx, [ctrl.ctrl_io_base] |
in ax, dx |
ret |
endp |
align 4 |
proc ctrl_io_r32 |
add edx, [ctrl.ctrl_io_base] |
in eax, dx |
ret |
endp |
align 4 |
proc ctrl_io_w8 |
add edx, [ctrl.ctrl_io_base] |
out dx, al |
ret |
endp |
align 4 |
proc ctrl_io_w16 |
add edx, [ctrl.ctrl_io_base] |
out dx, ax |
ret |
endp |
align 4 |
proc ctrl_io_w32 |
add edx, [ctrl.ctrl_io_base] |
out dx, eax |
ret |
endp |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; MEMORY MAPPED IO (os depended) |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
proc codec_mem_r16 |
add edx, [ctrl.codec_mem_base] |
mov ax, word [edx] |
ret |
endp |
align 4 |
proc codec_mem_w16 |
add edx, [ctrl.codec_mem_base] |
mov word [edx], ax |
ret |
endp |
align 4 |
proc ctrl_mem_r8 |
add edx, [ctrl.ctrl_mem_base] |
mov al, [edx] |
ret |
endp |
align 4 |
proc ctrl_mem_r16 |
add edx, [ctrl.ctrl_mem_base] |
mov ax, [edx] |
ret |
endp |
align 4 |
proc ctrl_mem_r32 |
add edx, [ctrl.ctrl_mem_base] |
mov eax, [edx] |
ret |
endp |
align 4 |
proc ctrl_mem_w8 |
add edx, [ctrl.ctrl_mem_base] |
mov [edx], al |
ret |
endp |
align 4 |
proc ctrl_mem_w16 |
add edx, [ctrl.ctrl_mem_base] |
mov [edx], ax |
ret |
endp |
align 4 |
proc ctrl_mem_w32 |
add edx, [ctrl.ctrl_mem_base] |
mov [edx], eax |
ret |
endp |
align 4 |
dword2str: |
mov esi, hex_buff |
mov ecx, -8 |
@@: |
rol eax, 4 |
mov ebx, eax |
and ebx, 0x0F |
mov bl, [ebx+hexletters] |
mov [8+esi+ecx], bl |
inc ecx |
jnz @B |
ret |
hexletters db '0123456789ABCDEF' |
hex_buff db 8 dup(0),13,10,0 |
include "codec.inc" |
align 4 |
devices dd (CTRL_ICH shl 16)+VID_INTEL,msg_ICH, set_ICH |
dd (CTRL_ICH0 shl 16)+VID_INTEL,msg_ICH0,set_ICH |
dd (CTRL_ICH2 shl 16)+VID_INTEL,msg_ICH2,set_ICH |
dd (CTRL_ICH3 shl 16)+VID_INTEL,msg_ICH3,set_ICH |
dd (CTRL_ICH4 shl 16)+VID_INTEL,msg_ICH4,set_ICH4 |
dd (CTRL_ICH5 shl 16)+VID_INTEL,msg_ICH5,set_ICH4 |
dd (CTRL_ICH6 shl 16)+VID_INTEL,msg_ICH6,set_ICH4 |
dd (CTRL_ICH7 shl 16)+VID_INTEL,msg_ICH7,set_ICH4 |
dd (CTRL_NFORCE shl 16)+VID_NVIDIA,msg_NForce, set_ICH |
dd (CTRL_NFORCE2 shl 16)+VID_NVIDIA,msg_NForce2,set_ICH |
dd (CTRL_NFORCE3 shl 16)+VID_NVIDIA,msg_NForce3,set_ICH |
dd (CTRL_MCP04 shl 16)+VID_NVIDIA,msg_MCP04,set_ICH |
dd (CTRL_CK804 shl 16)+VID_NVIDIA,msg_CK804,set_ICH |
dd (CTRL_CK8 shl 16)+VID_NVIDIA,msg_CK8,set_ICH |
dd (CTRL_CK8S shl 16)+VID_NVIDIA,msg_CK8S,set_ICH |
dd (CTRL_MCP51 shl 16)+VID_NVIDIA,msg_MCP51,set_ICH |
dd 0 ;terminator |
version dd 0x00040004 |
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_MCP04 db 'NForce MCP04',13,10, 0 |
msg_CK804 db 'NForce CK804',13,10, 0 |
msg_CK8 db 'NForce CK8', 13,10, 0 |
msg_CK8S db 'NForce CK8S', 13,10, 0 |
msg_MCP51 db 'NForce MCP51',13,10, 0 |
msg_NVidia db 'NVidia', 0 |
szKernel db 'KERNEL', 0 |
sz_sound_srv db 'SOUND',0 |
msgInit db 'detect hardware...',13,10,0 |
msgFail db 'device not found',13,10,0 |
msgAttchIRQ db 'IRQ line not supported', 13,10, 0 |
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 |
msgPlay db 'start play', 13,10,0 |
msgStop db 'stop play', 13,10,0 |
msgNotify db 'call notify',13,10,0 |
msgIRQ db 'AC97 IRQ', 13,10,0 |
msgInitCtrl db 'init controller',13,10,0 |
msgInitCodec db 'init codec',13,10,0 |
msgPrimBuff db 'create primary buffer',13,10,0 |
msgReg db 'set service handler',13,10,0 |
msgOk db 'service installed',13,10,0 |
msgCold db 'cold reset',13,10,0 |
msgWarm db 'warm reset',13,10,0 |
msgWRFail db 'warm reset failed',13,10,0 |
msgCRFail db 'cold reset failed',13,10,0 |
msgCFail db 'codec not ready',13,10,0 |
msgResetOk db 'reset complete',13,10,0 |
msgStatus db 'global status ',0 |
msgControl db 'global control ',0 |
section '.data' data readable writable align 16 |
pcmout_bdl rq 32 |
buff_list rd 32 |
codec CODEC |
ctrl AC_CNTRL |
lpc_bus rd 1 |
civ_val rd 1 |