Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 383 → Rev 384

/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