Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 2987 → Rev 3232

/kernel/branches/Kolibri-acpi/drivers/infinity.asm
875,8 → 875,8
 
 
; flags reserved
; RESET_INPUT equ 1 ;reserved reset and clear input buffer
; RESET_OUTPUT equ 2 ;reserved reset and clear output buffer
; RESET_INPUT equ 1 ;reset and clear input buffer
; RESET_OUTPUT equ 2 ;reset and clear output buffer
; RESET_ALL equ 3
 
 
913,6 → 913,33
mov [edx+STREAM.out_wp], ebx
mov [edx+STREAM.out_rp], ebx
mov [edx+STREAM.out_count], eax
 
mov dword [edx+STREAM.time_base], eax
mov dword [edx+STREAM.time_base+4], eax
 
mov dword [edx+STREAM.time_stamp], eax
mov dword [edx+STREAM.time_stamp+4], eax
mov dword [edx+STREAM.last_ts], eax
 
 
mov eax, [edx+STREAM.r_silence]
test [flags], 1
jz @F
 
mov ecx, [edx+STREAM.in_top]
mov edi, [edx+STREAM.in_base]
sub ecx, edi
shr ecx, 2
cld
rep stosd
@@:
test [flags], 2
jz @F
 
mov edi, [edx+STREAM.out_base]
mov ecx, (64*1024)/4
rep stosd
@@:
ret
.fail:
or eax, -1
1153,8 → 1180,6
 
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
/kernel/branches/Kolibri-acpi/drivers/intelac97.asm
0,0 → 1,1507
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
DEBUG equ 1
 
include 'proc32.inc'
include 'imports.inc'
 
API_VERSION equ 0x01000100
 
DEBUG_IRQ equ 0
 
USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices
IRQ_REMAP equ 0
IRQ_LINE equ 0
 
 
;irq 0,1,2,8,12,13 íåäîñòóïíû
; FEDCBA9876543210
VALID_IRQ equ 1100111011111000b
ATTCH_IRQ equ 0000111010100000b
 
if USE_COM_IRQ
ATTCH_IRQ equ 0000111010111000b
end if
 
CPU_FREQ equ 2600d
 
BIT0 EQU 0x00000001
BIT1 EQU 0x00000002
BIT2 EQU 0x00000004
BIT3 EQU 0x00000008
BIT4 EQU 0x00000010
BIT5 EQU 0x00000020
BIT6 EQU 0x00000040
BIT7 EQU 0x00000080
BIT8 EQU 0x00000100
BIT9 EQU 0x00000200
BIT10 EQU 0x00000400
BIT11 EQU 0x00000800
BIT12 EQU 0x00001000
BIT13 EQU 0x00002000
BIT14 EQU 0x00004000
BIT15 EQU 0x00008000
BIT16 EQU 0x00010000
BIT17 EQU 0x00020000
BIT18 EQU 0x00040000
BIT19 EQU 0x00080000
BIT20 EQU 0x00100000
BIT21 EQU 0x00200000
BIT22 EQU 0x00400000
BIT23 EQU 0x00800000
BIT24 EQU 0x00100000
BIT25 EQU 0x02000000
BIT26 EQU 0x04000000
BIT27 EQU 0x08000000
BIT28 EQU 0x10000000
BIT29 EQU 0x20000000
BIT30 EQU 0x40000000
BIT31 EQU 0x80000000
 
PCM_4 equ BIT20
PCM_6 equ BIT21
 
VID_INTEL equ 0x8086
VID_NVIDIA equ 0x10DE
 
CTRL_ICH equ 0x2415
CTRL_ICH0 equ 0x2425
CTRL_ICH2 equ 0x2435
CTRL_ICH3 equ 0x2445
CTRL_ICH4 equ 0x24C5
CTRL_ICH5 equ 0x24D5
CTRL_ICH6 equ 0x266E
CTRL_ICH7 equ 0x27DE
 
CTRL_NFORCE equ 0x01B1
CTRL_NFORCE2 equ 0x006A
CTRL_NFORCE3 equ 0x00DA
CTRL_MCP04 equ 0x003A
CTRL_CK804 equ 0x0059
CTRL_CK8 equ 0x008A
CTRL_CK8S equ 0x00EA
CTRL_MCP51 equ 0x026B
 
 
PCM_OUT_BDL equ 0x10 ; PCM out buffer descriptors list
PCM_OUT_CR_REG equ 0x1b ; PCM out Control Register
PCM_OUT_LVI_REG equ 0x15 ; PCM last valid index
PCM_OUT_SR_REG equ 0x16 ; PCM out Status register
PCM_OUT_PIV_REG equ 0x1a
PCM_OUT_CIV_REG equ 0x14 ; PCM out current index
 
PCM_IN_CR_REG equ 0x0b ; PCM in Control Register
MC_IN_CR_REG equ 0x2b ; MIC in Control Register
RR equ BIT1 ; reset registers. Nukes all regs
 
CODEC_MASTER_VOL_REG equ 0x02
CODEC_AUX_VOL equ 0x04 ;
CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume
CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio
CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control
CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate
CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate
CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate
 
GLOB_CTRL equ 0x2C ; Global Control
CTRL_STAT equ 0x30 ; Global Status
CTRL_CAS equ 0x34 ; Codec Access Semiphore
 
CAS_FLAG equ 0x01 ; Codec Access Semiphore Bit
 
CTRL_ST_CREADY equ BIT8+BIT9+BIT28 ; Primary Codec Ready
 
CTRL_ST_RCS equ 0x00008000 ; Read Completion Status
 
CTRL_CNT_CRIE equ BIT4+BIT5+BIT6 ; Codecs Resume Interrupt Enable
CTRL_CNT_AC_OFF equ 0x00000008 ; ACLINK Off
CTRL_CNT_WARM equ 0x00000004 ; AC97 Warm Reset
CTRL_CNT_COLD equ 0x00000002 ; AC97 Cold Reset
CTRL_CNT_GIE equ 0x00000001 ; GPI Interrupt Enable
 
CODEC_REG_POWERDOWN equ 0x26
CODEC_REG_ST equ 0x26
 
SRV_GETVERSION equ 0
DEV_PLAY equ 1
DEV_STOP equ 2
DEV_CALLBACK equ 3
DEV_SET_BUFF equ 4
DEV_NOTIFY equ 5
DEV_SET_MASTERVOL equ 6
DEV_GET_MASTERVOL equ 7
DEV_GET_INFO equ 8
DEV_GET_POS equ 9
 
struc AC_CNTRL ;AC controller base class
{ .bus dd ?
.devfn dd ?
 
.vendor dd ?
.dev_id dd ?
.pci_cmd dd ?
.pci_stat dd ?
 
.codec_io_base dd ?
.codec_mem_base dd ?
 
.ctrl_io_base dd ?
.ctrl_mem_base dd ?
.cfg_reg dd ?
.int_line dd ?
 
.vendor_ids dd ? ;vendor id string
.ctrl_ids dd ? ;hub id string
 
.buffer dd ?
 
.notify_pos dd ?
.notify_task dd ?
 
.lvi_reg dd ?
.ctrl_setup dd ?
.user_callback dd ?
.codec_read16 dd ?
.codec_write16 dd ?
 
.ctrl_read8 dd ?
.ctrl_read16 dd ?
.ctrl_read32 dd ?
 
.ctrl_write8 dd ?
.ctrl_write16 dd ?
.ctrl_write32 dd ?
}
 
struc CODEC ;Audio Chip base class
{
.chip_id dd ?
.flags dd ?
.status dd ?
 
.ac_vendor_ids dd ? ;ac vendor id string
.chip_ids dd ? ;chip model string
 
.shadow_flag dd ?
dd ?
 
.regs dw ? ; codec registers
.reg_master_vol dw ? ;0x02
.reg_aux_out_vol dw ? ;0x04
.reg_mone_vol dw ? ;0x06
.reg_master_tone dw ? ;0x08
.reg_beep_vol dw ? ;0x0A
.reg_phone_vol dw ? ;0x0C
.reg_mic_vol dw ? ;0x0E
.reg_line_in_vol dw ? ;0x10
.reg_cd_vol dw ? ;0x12
.reg_video_vol dw ? ;0x14
.reg_aux_in_vol dw ? ;0x16
.reg_pcm_out_vol dw ? ;0x18
.reg_rec_select dw ? ;0x1A
.reg_rec_gain dw ? ;0x1C
.reg_rec_gain_mic dw ? ;0x1E
.reg_gen dw ? ;0x20
.reg_3d_ctrl dw ? ;0X22
.reg_page dw ? ;0X24
.reg_powerdown dw ? ;0x26
.reg_ext_audio dw ? ;0x28
.reg_ext_st dw ? ;0x2a
.reg_pcm_front_rate dw ? ;0x2c
.reg_pcm_surr_rate dw ? ;0x2e
.reg_lfe_rate dw ? ;0x30
.reg_pcm_in_rate dw ? ;0x32
dw ? ;0x34
.reg_cent_lfe_vol dw ? ;0x36
.reg_surr_vol dw ? ;0x38
.reg_spdif_ctrl dw ? ;0x3A
dw ? ;0x3C
dw ? ;0x3E
dw ? ;0x40
dw ? ;0x42
dw ? ;0x44
dw ? ;0x46
dw ? ;0x48
dw ? ;0x4A
dw ? ;0x4C
dw ? ;0x4E
dw ? ;0x50
dw ? ;0x52
dw ? ;0x54
dw ? ;0x56
dw ? ;0x58
dw ? ;0x5A
dw ? ;0x5C
dw ? ;0x5E
.reg_page_0 dw ? ;0x60
.reg_page_1 dw ? ;0x62
.reg_page_2 dw ? ;0x64
.reg_page_3 dw ? ;0x66
.reg_page_4 dw ? ;0x68
.reg_page_5 dw ? ;0x6A
.reg_page_6 dw ? ;0x6C
.reg_page_7 dw ? ;0x6E
dw ? ;0x70
dw ? ;0x72
dw ? ;0x74
dw ? ;0x76
dw ? ;0x78
dw ? ;0x7A
.reg_vendor_id_1 dw ? ;0x7C
.reg_vendor_id_2 dw ? ;0x7E
 
 
.reset dd ? ;virual
.set_master_vol dd ?
}
 
struc CTRL_INFO
{ .pci_cmd dd ?
.irq dd ?
.glob_cntrl dd ?
.glob_sta dd ?
.codec_io_base dd ?
.ctrl_io_base dd ?
.codec_mem_base dd ?
.ctrl_mem_base dd ?
.codec_id dd ?
}
 
struc IOCTL
{ .handle dd ?
.io_code dd ?
.input dd ?
.inp_size dd ?
.output dd ?
.out_size dd ?
}
 
virtual at 0
IOCTL IOCTL
end virtual
 
EVENT_NOTIFY equ 0x00000200
 
public START
public service_proc
public version
 
section '.flat' code readable align 16
 
proc START stdcall, state:dword
 
cmp [state], 1
jne .stop
 
if DEBUG
mov esi, msgInit
call SysMsgBoardStr
end if
 
call detect_controller
test eax, eax
jz .fail
 
if DEBUG
mov esi, [ctrl.vendor_ids]
call SysMsgBoardStr
mov esi, [ctrl.ctrl_ids]
call SysMsgBoardStr
 
end if
 
call init_controller
test eax, eax
jz .fail
 
call init_codec
test eax, eax
jz .fail
 
call reset_controller
call setup_codec
 
mov esi, msgPrimBuff
call SysMsgBoardStr
call create_primary_buff
mov esi, msgDone
call SysMsgBoardStr
 
if IRQ_REMAP
pushf
cli
 
mov ebx, [ctrl.int_line]
in al, 0xA1
mov ah, al
in al, 0x21
test ebx, ebx
jz .skip
bts ax, bx ;mask old line
.skip
bts ax, IRQ_LINE ;mask new ine
out 0x21, al
mov al, ah
out 0xA1, al
;remap IRQ
stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE
 
mov dx, 0x4d0 ;8259 ELCR1
in al, dx
bts ax, IRQ_LINE
out dx, al ;set level-triggered mode
mov [ctrl.int_line], IRQ_LINE
popf
mov esi, msgRemap
call SysMsgBoardStr
end if
 
mov ebx, [ctrl.int_line]
stdcall AttachIntHandler, ebx, ac97_irq, dword 0
.reg:
stdcall RegService, sz_sound_srv, service_proc
ret
.fail:
if DEBUG
mov esi, msgFail
call SysMsgBoardStr
end if
xor eax, eax
ret
.fail_msg:
call SysMsgBoardStr
xor eax, eax
ret
.stop:
call stop
xor eax, eax
ret
endp
 
handle equ IOCTL.handle
io_code equ IOCTL.io_code
input equ IOCTL.input
inp_size equ IOCTL.inp_size
output equ IOCTL.output
out_size equ IOCTL.out_size
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edi, [ioctl]
mov eax, [edi+io_code]
 
cmp eax, SRV_GETVERSION
jne @F
 
mov eax, [edi+output]
cmp [edi+out_size], 4
jne .fail
 
mov [eax], dword API_VERSION
xor eax, eax
ret
@@:
cmp eax, DEV_PLAY
jne @F
if DEBUG
mov esi, msgPlay
call SysMsgBoardStr
end if
call play
ret
@@:
cmp eax, DEV_STOP
jne @F
if DEBUG
mov esi, msgStop
call SysMsgBoardStr
end if
call stop
ret
@@:
cmp eax, DEV_CALLBACK
jne @F
mov ebx, [edi+input]
stdcall set_callback, [ebx]
ret
@@:
cmp eax, DEV_SET_MASTERVOL
jne @F
mov eax, [edi+input]
mov eax, [eax]
call set_master_vol ;eax= vol
ret
@@:
cmp eax, DEV_GET_MASTERVOL
jne @F
mov ebx, [edi+output]
stdcall get_master_vol, ebx
ret
 
@@:
cmp eax, DEV_GET_POS
jne @F
 
mov ebx, 8192
mov edx, 0x18
xor eax, eax
call [ctrl.ctrl_read16]
sub ebx, eax
shr ebx, 1
mov edx, [edi+output]
mov [edx], ebx
xor eax, eax
ret
;@@:
; cmp eax, DEV_GET_INFO
; jne @F
; mov ebx, [edi+output]
; stdcall get_dev_info, ebx
; ret
@@:
.fail:
or eax, -1
ret
endp
 
restore handle
restore io_code
restore input
restore inp_size
restore output
restore out_size
 
align 4
proc ac97_irq
 
if DEBUG_IRQ
mov esi, msgIRQ
call SysMsgBoardStr
end if
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
 
cmp eax, 0xffffffff
je .exit
 
test eax, 0x40
jnz .do_intr
 
test eax, eax
jz .exit
 
mov edx, CTRL_STAT
call [ctrl.ctrl_write32]
.exit:
xor eax, eax
ret
 
.do_intr:
push eax
 
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 .done
 
stdcall [ctrl.user_callback], ebx
.done:
pop eax
and eax, 0x40
mov edx, CTRL_STAT
call [ctrl.ctrl_write32]
or eax, 1
ret
.skip:
mov edx, PCM_OUT_CR_REG
mov ax, 0x11 ;0x1D
call [ctrl.ctrl_write8]
jmp .done
endp
 
align 4
proc create_primary_buff
 
stdcall KernelAlloc, 0x10000
mov [ctrl.buffer], eax
 
mov edi, eax
mov ecx, 0x10000/4
xor eax, eax
cld
rep stosd
 
mov eax, [ctrl.buffer]
call GetPgAddr
 
mov ebx, 0xC0002000
mov ecx, 4
mov edi, pcmout_bdl
@@:
mov [edi], eax
mov [edi+4], ebx
 
mov [edi+32], eax
mov [edi+4+32], ebx
 
mov [edi+64], eax
mov [edi+4+64], ebx
 
mov [edi+96], eax
mov [edi+4+96], ebx
 
mov [edi+128], eax
mov [edi+4+128], ebx
 
mov [edi+160], eax
mov [edi+4+160], ebx
 
mov [edi+192], eax
mov [edi+4+192], ebx
 
mov [edi+224], eax
mov [edi+4+224], ebx
 
add eax, 0x4000
add edi, 8
loop @B
 
mov edi, buff_list
mov eax, [ctrl.buffer]
mov ecx, 4
@@:
mov [edi], eax
mov [edi+16], eax
mov [edi+32], eax
mov [edi+48], eax
mov [edi+64], eax
mov [edi+80], eax
mov [edi+96], eax
mov [edi+112], eax
 
add eax, 0x4000
add edi, 4
loop @B
 
mov eax, pcmout_bdl
mov ebx, eax
call GetPgAddr ;eax
and ebx, 0xFFF
add eax, ebx
 
mov edx, PCM_OUT_BDL
call [ctrl.ctrl_write32]
 
mov eax, 16
mov [ctrl.lvi_reg], eax
mov edx, PCM_OUT_LVI_REG
call [ctrl.ctrl_write8]
ret
endp
 
align 4
proc detect_controller
locals
last_bus dd ?
bus dd ?
devfn dd ?
endl
 
xor eax, eax
mov [bus], eax
inc eax
call PciApi
cmp eax, -1
je .err
 
mov [last_bus], eax
 
.next_bus:
and [devfn], 0
.next_dev:
stdcall PciRead32, [bus], [devfn], dword 0
test eax, eax
jz .next
cmp eax, -1
je .next
 
mov edi, devices
@@:
mov ebx, [edi]
test ebx, ebx
jz .next
 
cmp eax, ebx
je .found
add edi, 12
jmp @B
.next:
inc [devfn]
cmp [devfn], 256
jb .next_dev
mov eax, [bus]
inc eax
mov [bus], eax
cmp eax, [last_bus]
jna .next_bus
xor eax, eax
ret
.found:
mov ebx, [bus]
mov [ctrl.bus], ebx
 
mov ecx, [devfn]
mov [ctrl.devfn], ecx
 
mov edx, eax
and edx, 0xFFFF
mov [ctrl.vendor], edx
shr eax, 16
mov [ctrl.dev_id], eax
 
mov ebx, [edi+4]
mov [ctrl.ctrl_ids], ebx
mov esi, [edi+8]
mov [ctrl.ctrl_setup], esi
 
cmp edx, VID_INTEL
jne @F
mov [ctrl.vendor_ids], msg_Intel
ret
@@:
cmp edx, VID_NVIDIA
jne @F
mov [ctrl.vendor_ids], msg_NVidia
ret
@@:
.err:
xor eax, eax
mov [ctrl.vendor_ids], eax ;something wrong ?
ret
endp
 
align 4
proc init_controller
 
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4
mov ebx, eax
and eax, 0xFFFF
mov [ctrl.pci_cmd], eax
shr ebx, 16
mov [ctrl.pci_stat], ebx
 
mov esi, msgPciCmd
call SysMsgBoardStr
call dword2str
call SysMsgBoardStr
 
mov esi, msgPciStat
call SysMsgBoardStr
mov eax, [ctrl.pci_stat]
call dword2str
call SysMsgBoardStr
 
mov esi, msgMixIsaIo
call SysMsgBoardStr
 
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10
 
call dword2str
call SysMsgBoardStr
 
and eax, 0xFFFE
mov [ctrl.codec_io_base], eax
 
mov esi, msgCtrlIsaIo
call SysMsgBoardStr
 
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x14
 
call dword2str
call SysMsgBoardStr
 
and eax, 0xFFC0
mov [ctrl.ctrl_io_base], eax
 
mov esi, msgMixMMIo
call SysMsgBoardStr
 
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x18
mov [ctrl.codec_mem_base], eax
 
call dword2str
call SysMsgBoardStr
 
mov esi, msgCtrlMMIo
call SysMsgBoardStr
 
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x1C
mov [ctrl.ctrl_mem_base], eax
 
call dword2str
call SysMsgBoardStr
 
if 0
 
;;patch for some ugly BIOS ICH-ICH5 compatible
cmp [ctrl.vendor], VID_INTEL
jne .default
 
mov esi, msgIrqMap
call SysMsgBoardStr
stdcall PciRead8, 0, 0xF8, 0x61
and eax, 0xFF
call dword2str
call SysMsgBoardStr
btr eax, 7 ;when bit 7 set remap disabled
jnc @F
xor eax, eax
jmp @F
end if
 
.default:
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C
and eax, 0xFF
@@:
mov [ctrl.int_line], eax
 
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword 0x41
and eax, 0xFF
mov [ctrl.cfg_reg], eax
 
mov [ctrl.user_callback], 0
 
call [ctrl.ctrl_setup]
xor eax, eax
inc eax
ret
endp
 
align 4
proc set_ICH
mov [ctrl.codec_read16], codec_io_r16 ;virtual
mov [ctrl.codec_write16], codec_io_w16 ;virtual
 
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual
 
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual
ret
endp
 
PG_SW equ 0x003
PG_NOCACHE equ 0x018
 
align 4
proc set_ICH4
 
stdcall MapIoMem, [ctrl.codec_mem_base], 0x1000, PG_SW+PG_NOCACHE
mov [ctrl.codec_mem_base], eax
 
stdcall MapIoMem, [ctrl.ctrl_mem_base], 0x1000, PG_SW+PG_NOCACHE
mov [ctrl.ctrl_mem_base], eax
 
mov [ctrl.codec_read16], codec_mem_r16 ;virtual
mov [ctrl.codec_write16], codec_mem_w16 ;virtual
 
mov [ctrl.ctrl_read8 ], ctrl_mem_r8 ;virtual
mov [ctrl.ctrl_read16], ctrl_mem_r16 ;virtual
mov [ctrl.ctrl_read32], ctrl_mem_r32 ;virtual
 
mov [ctrl.ctrl_write8 ], ctrl_mem_w8 ;virtual
mov [ctrl.ctrl_write16], ctrl_mem_w16 ;virtual
mov [ctrl.ctrl_write32], ctrl_mem_w32 ;virtual
ret
endp
 
align 4
proc reset_controller
 
xor eax, eax
mov edx, PCM_IN_CR_REG
call [ctrl.ctrl_write8]
 
mov edx, PCM_OUT_CR_REG
call [ctrl.ctrl_write8]
 
mov edx, MC_IN_CR_REG
call [ctrl.ctrl_write8]
 
mov eax, RR
mov edx, PCM_IN_CR_REG
call [ctrl.ctrl_write8]
 
mov edx, PCM_OUT_CR_REG
call [ctrl.ctrl_write8]
 
mov edx, MC_IN_CR_REG
call [ctrl.ctrl_write8]
ret
endp
 
align 4
proc init_codec
locals
counter dd ?
endl
 
mov esi, msgControl
call SysMsgBoardStr
 
mov edx, GLOB_CTRL
call [ctrl.ctrl_read32]
call dword2str
call SysMsgBoardStr
 
mov esi, msgStatus
call SysMsgBoardStr
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
push eax
call dword2str
call SysMsgBoardStr
pop eax
cmp eax, 0xFFFFFFFF
je .err
 
test eax, CTRL_ST_CREADY
jnz .ready
 
call reset_codec
test eax, eax
jz .err
 
.ready:
xor edx, edx ;ac_reg_0
call [ctrl.codec_write16]
 
xor eax, eax
mov edx, CODEC_REG_POWERDOWN
call [ctrl.codec_write16]
 
mov [counter], 200 ; total 200*5 ms = 1s
.wait:
mov eax, 5000 ; wait 5 ms
call StallExec
 
mov edx, CODEC_REG_POWERDOWN
call [ctrl.codec_read16]
and eax, 0x0F
cmp eax, 0x0F
jz .done
 
sub [counter] , 1
jnz .wait
.err:
xor eax, eax ; timeout error
ret
.done:
mov eax, 2 ;force set 16-bit 2-channel PCM
mov edx, GLOB_CTRL
call [ctrl.ctrl_write32]
mov eax, 5000 ; wait 5 ms
call StallExec
 
call detect_codec
 
xor eax, eax
inc eax
ret
endp
 
align 4
proc reset_codec
mov edx, GLOB_CTRL
call [ctrl.ctrl_read32]
 
test eax, 0x02
jz .cold
 
call warm_reset
jnc .ok
.cold:
call cold_reset
jnc .ok
 
if DEBUG
mov esi, msgCFail
call SysMsgBoardStr
end if
xor eax, eax ; timeout error
ret
.ok:
if DEBUG
mov esi, msgResetOk
call SysMsgBoardStr
end if
 
xor eax, eax
inc eax
ret
endp
 
align 4
proc warm_reset
locals
counter dd ?
endl
 
mov eax, 0x06
mov edx, GLOB_CTRL
call [ctrl.ctrl_write32]
 
if DEBUG
mov esi, msgWarm
call SysMsgBoardStr
end if
 
mov [counter], 10 ; total 10*100 ms = 1s
.wait:
mov eax, 100000 ; wait 100 ms
call StallExec
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
test eax, CTRL_ST_CREADY
jnz .ok
 
dec [counter]
jnz .wait
 
if DEBUG
mov esi, msgWRFail
call SysMsgBoardStr
end if
.fail:
stc
ret
.ok:
clc
ret
endp
 
align 4
proc cold_reset
locals
counter dd ?
endl
 
mov eax, 0x02
mov edx, GLOB_CTRL
call [ctrl.ctrl_write32]
 
if DEBUG
mov esi, msgCold
call SysMsgBoardStr
end if
 
mov eax, 400000 ; wait 400 ms
call StallExec
 
mov [counter], 16 ; total 20*100 ms = 2s
.wait:
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
test eax, CTRL_ST_CREADY
jnz .ok
 
mov eax, 100000 ; wait 100 ms
call StallExec
 
dec [counter]
jnz .wait
 
if DEBUG
mov esi, msgCRFail
call SysMsgBoardStr
end if
 
.fail:
stc
ret
.ok:
mov esi, msgControl
call SysMsgBoardStr
 
mov edx, GLOB_CTRL
call [ctrl.ctrl_read32]
call dword2str
call SysMsgBoardStr
 
mov esi, msgStatus
call SysMsgBoardStr
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
push eax
call dword2str
call SysMsgBoardStr
pop eax
 
test eax, CTRL_ST_CREADY
jz .fail
clc
ret
endp
 
align 4
play:
mov eax, 16
mov [ctrl.lvi_reg], eax
mov edx, PCM_OUT_LVI_REG
call [ctrl.ctrl_write8]
 
mov edx, PCM_OUT_CR_REG
mov ax, 0x1D
call [ctrl.ctrl_write8]
xor eax, eax
ret
 
align 4
stop:
mov edx, PCM_OUT_CR_REG
mov ax, 0x0
call [ctrl.ctrl_write8]
 
mov ax, 0x1c
mov edx, PCM_OUT_SR_REG
call [ctrl.ctrl_write16]
xor eax, eax
ret
 
align 4
proc get_dev_info stdcall, p_info:dword
virtual at esi
CTRL_INFO CTRL_INFO
end virtual
 
mov esi, [p_info]
mov eax, [ctrl.int_line]
mov ebx, [ctrl.codec_io_base]
mov ecx, [ctrl.ctrl_io_base]
mov edx, [ctrl.codec_mem_base]
mov edi, [ctrl.ctrl_mem_base]
 
mov [CTRL_INFO.irq], eax
mov [CTRL_INFO.codec_io_base], ebx
mov [CTRL_INFO.ctrl_io_base], ecx
mov [CTRL_INFO.codec_mem_base], edx
mov [CTRL_INFO.ctrl_mem_base], edi
 
mov eax, [codec.chip_id]
mov [CTRL_INFO.codec_id], eax
 
mov edx, GLOB_CTRL
call [ctrl.ctrl_read32]
mov [CTRL_INFO.glob_cntrl], eax
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
mov [CTRL_INFO.glob_sta], eax
 
mov ebx, [ctrl.pci_cmd]
mov [CTRL_INFO.pci_cmd], ebx
ret
endp
 
align 4
proc set_callback stdcall, handler:dword
mov eax, [handler]
mov [ctrl.user_callback], eax
ret
endp
 
align 4
proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax
 
mov edx, [ac_reg]
 
mov ebx, edx
shr ebx, 1
bt [codec.shadow_flag], ebx
jc .use_shadow
 
call [ctrl.codec_read16] ;change edx !!!
mov ecx, eax
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
test eax, CTRL_ST_RCS
jz .read_ok
 
mov edx, CTRL_STAT
call [ctrl.ctrl_write32]
xor eax, eax
not eax ;timeout
ret
.read_ok:
mov edx, [ac_reg]
mov [codec.regs+edx], cx
bts [codec.shadow_flag], ebx
mov eax, ecx
ret
.use_shadow:
movzx eax, word [codec.regs+edx]
ret
endp
 
align 4
proc codec_write stdcall, ac_reg:dword
push eax
call check_semafore
and eax, eax
jz .err
pop eax
 
mov esi, [ac_reg]
mov edx, esi
call [ctrl.codec_write16]
mov [codec.regs+esi], ax
shr esi, 1
bts [codec.shadow_flag], esi
ret
.err:
pop eax
ret
endp
 
align 4
proc codec_check_ready
 
mov edx, CTRL_ST
call [ctrl.ctrl_read32]
and eax, CTRL_ST_CREADY
jz .not_ready
 
xor eax, wax
inc eax
ret
.not_ready:
xor eax, eax
ret
endp
 
align 4
proc check_semafore
local counter:DWORD
 
mov [counter], 100
.l1:
mov edx, CTRL_CAS
call [ctrl.ctrl_read8]
and eax, CAS_FLAG
jz .ok
 
mov eax, 1
call StallExec
sub [counter], 1
jnz .l1
xor eax, eax
ret
align 4
.ok:
xor eax, eax
inc eax
ret
endp
 
align 4
proc StallExec
push ecx
push edx
push ebx
push eax
 
mov ecx, CPU_FREQ
mul ecx
mov ebx, eax ;low
mov ecx, edx ;high
rdtsc
add ebx, eax
adc ecx, edx
@@:
rdtsc
sub eax, ebx
sbb edx, ecx
js @B
 
pop eax
pop ebx
pop edx
pop ecx
ret
endp
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; CONTROLLER IO functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc codec_io_r16
add edx, [ctrl.codec_io_base]
in ax, dx
ret
endp
 
align 4
proc codec_io_w16
add edx, [ctrl.codec_io_base]
out dx, ax
ret
endp
 
align 4
proc ctrl_io_r8
add edx, [ctrl.ctrl_io_base]
in al, dx
ret
endp
 
align 4
proc ctrl_io_r16
add edx, [ctrl.ctrl_io_base]
in ax, dx
ret
endp
 
align 4
proc ctrl_io_r32
add edx, [ctrl.ctrl_io_base]
in eax, dx
ret
endp
 
align 4
proc ctrl_io_w8
add edx, [ctrl.ctrl_io_base]
out dx, al
ret
endp
 
align 4
proc ctrl_io_w16
add edx, [ctrl.ctrl_io_base]
out dx, ax
ret
endp
 
align 4
proc ctrl_io_w32
add edx, [ctrl.ctrl_io_base]
out dx, eax
ret
endp
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; MEMORY MAPPED IO (os depended)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc codec_mem_r16
add edx, [ctrl.codec_mem_base]
mov ax, word [edx]
ret
endp
 
align 4
proc codec_mem_w16
add edx, [ctrl.codec_mem_base]
mov word [edx], ax
ret
endp
 
align 4
proc ctrl_mem_r8
add edx, [ctrl.ctrl_mem_base]
mov al, [edx]
ret
endp
 
align 4
proc ctrl_mem_r16
add edx, [ctrl.ctrl_mem_base]
mov ax, [edx]
ret
endp
 
align 4
proc ctrl_mem_r32
add edx, [ctrl.ctrl_mem_base]
mov eax, [edx]
ret
endp
 
align 4
proc ctrl_mem_w8
add edx, [ctrl.ctrl_mem_base]
mov [edx], al
ret
endp
 
align 4
proc ctrl_mem_w16
add edx, [ctrl.ctrl_mem_base]
mov [edx], ax
ret
endp
 
align 4
proc ctrl_mem_w32
add edx, [ctrl.ctrl_mem_base]
mov [edx], eax
ret
endp
 
align 4
dword2str:
mov esi, hex_buff
mov ecx, -8
@@:
rol eax, 4
mov ebx, eax
and ebx, 0x0F
mov bl, [ebx+hexletters]
mov [8+esi+ecx], bl
inc ecx
jnz @B
ret
 
hexletters db '0123456789ABCDEF'
hex_buff db 8 dup(0),13,10,0
 
 
include "codec.inc"
 
align 4
devices dd (CTRL_ICH shl 16)+VID_INTEL,msg_ICH, set_ICH
dd (CTRL_ICH0 shl 16)+VID_INTEL,msg_ICH0,set_ICH
dd (CTRL_ICH2 shl 16)+VID_INTEL,msg_ICH2,set_ICH
dd (CTRL_ICH3 shl 16)+VID_INTEL,msg_ICH3,set_ICH
dd (CTRL_ICH4 shl 16)+VID_INTEL,msg_ICH4,set_ICH4
dd (CTRL_ICH5 shl 16)+VID_INTEL,msg_ICH5,set_ICH4
dd (CTRL_ICH6 shl 16)+VID_INTEL,msg_ICH6,set_ICH4
dd (CTRL_ICH7 shl 16)+VID_INTEL,msg_ICH7,set_ICH4
 
dd (CTRL_NFORCE shl 16)+VID_NVIDIA,msg_NForce, set_ICH
dd (CTRL_NFORCE2 shl 16)+VID_NVIDIA,msg_NForce2,set_ICH
dd (CTRL_NFORCE3 shl 16)+VID_NVIDIA,msg_NForce3,set_ICH
dd (CTRL_MCP04 shl 16)+VID_NVIDIA,msg_MCP04,set_ICH
dd (CTRL_CK804 shl 16)+VID_NVIDIA,msg_CK804,set_ICH
dd (CTRL_CK8 shl 16)+VID_NVIDIA,msg_CK8,set_ICH
dd (CTRL_CK8S shl 16)+VID_NVIDIA,msg_CK8S,set_ICH
dd (CTRL_MCP51 shl 16)+VID_NVIDIA,msg_MCP51,set_ICH
 
dd 0 ;terminator
 
 
version dd (5 shl 16) or (API_VERSION and 0xFFFF)
 
msg_ICH db '802801AA (ICH)', 13,10, 0
msg_ICH0 db '802801AB (ICH0)', 13,10, 0
msg_ICH2 db '802801BA (ICH2)', 13,10, 0
msg_ICH3 db '802801CA (ICH3)', 13,10, 0
msg_ICH4 db '802801DB (ICH4)', 13,10, 0
msg_ICH5 db '802801EB (ICH5)', 13,10, 0
msg_ICH6 db '802801FB (ICH6)', 13,10, 0
msg_ICH7 db '802801GB (ICH7)', 13,10, 0
msg_Intel db 'Intel ', 0
 
msg_NForce db 'NForce', 13,10, 0
msg_NForce2 db 'NForce 2', 13,10, 0
msg_NForce3 db 'NForce 3', 13,10, 0
msg_MCP04 db 'NForce MCP04',13,10, 0
msg_CK804 db 'NForce CK804',13,10, 0
msg_CK8 db 'NForce CK8', 13,10, 0
msg_CK8S db 'NForce CK8S', 13,10, 0
msg_MCP51 db 'NForce MCP51',13,10, 0
 
msg_NVidia db 'NVidia', 0
 
szKernel db 'KERNEL', 0
sz_sound_srv db 'SOUND',0
 
msgInit db 'detect hardware...',13,10,0
msgFail db 'device not found',13,10,0
msgAttchIRQ db 'IRQ line not supported', 13,10, 0
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0
msgPlay db 'start play', 13,10,0
msgStop db 'stop play', 13,10,0
;msgNotify db 'call notify',13,10,0
msgIRQ db 'AC97 IRQ', 13,10,0
msgInitCtrl db 'init controller',13,10,0
;msgInitCodec db 'init codec',13,10,0
msgPrimBuff db 'create primary buffer ...',0
msgDone db 'done',13,10,0
msgRemap db 'Remap IRQ',13,10,0
;msgReg db 'set service handler',13,10,0
msgOk db 'service installed',13,10,0
msgCold db 'cold reset',13,10,0
msgWarm db 'warm reset',13,10,0
msgWRFail db 'warm reset failed',13,10,0
msgCRFail db 'cold reset failed',13,10,0
msgCFail db 'codec not ready',13,10,0
msgResetOk db 'reset complete',13,10,0
msgStatus db 'global status ',0
msgControl db 'global control ',0
msgPciCmd db 'PCI command ',0
msgPciStat db 'PCI status ',0
msgCtrlIsaIo db 'controller io base ',0
msgMixIsaIo db 'codec io base ',0
msgCtrlMMIo db 'controller mmio base ',0
msgMixMMIo db 'codec mmio base ',0
msgIrqMap db 'AC97 irq map as ',0
 
section '.data' data readable writable align 16
 
pcmout_bdl rq 32
buff_list rd 32
 
codec CODEC
ctrl AC_CNTRL
 
lpc_bus rd 1
civ_val rd 1
/kernel/branches/Kolibri-acpi/drivers/sound.asm
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7,288 → 7,144
 
format MS COFF
 
DEBUG equ 1
DEBUG = 1
 
include 'proc32.inc'
include 'imports.inc'
 
API_VERSION equ 0x01000100
VID_INTEL = 0x8086
VID_NVIDIA = 0x10DE
VID_VIA = 0x1106
VID_SIS = 0x1039
VID_FM801 = 0x1319
VID_CREATIVE = 0x1102
VID_ATI = 0x1002
VID_AMD = 0x1022
VID_ULI = 0x10B9
VID_TERA = 0x6549
VID_RDC = 0x17F3
VID_VMWARE = 0x15AD
 
DEBUG_IRQ equ 0
CTRL_ICH = 0x2415
CTRL_ICH0 = 0x2425
CTRL_ICH2 = 0x2435
CTRL_ICH3 = 0x2445
CTRL_ICH4 = 0x24C5
CTRL_ICH5 = 0x24D5
CTRL_ICH6 = 0x266E
CTRL_ICH7 = 0x27DE
 
USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices
IRQ_REMAP equ 0
IRQ_LINE equ 0
CTRL_NFORCE = 0x01B1
CTRL_NFORCE2 = 0x006A
CTRL_NFORCE3 = 0x00DA
CTRL_MCP04 = 0x003A
CTRL_CK804 = 0x0059
CTRL_CK8 = 0x008A
CTRL_CK8S = 0x00EA
CTRL_MCP51 = 0x026B
 
CTRL_VT82C686 = 0x3058
CTRL_VT8233_5 = 0x3059
 
;irq 0,1,2,8,12,13 íåäîñòóïíû
; FEDCBA9876543210
VALID_IRQ equ 1100111011111000b
ATTCH_IRQ equ 0000111010100000b
CTRL_SIS = 0x7012
 
if USE_COM_IRQ
ATTCH_IRQ equ 0000111010111000b
end if
CTRL_FM801 = 0x0801
 
CPU_FREQ equ 2600d
CTRL_CT0200 = 0x0006 ; Dell OEM version (EMU10K1X)
 
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
CTRL_INTEL_SCH2 = 0x080a
CTRL_INTEL_HPT = 0x0c0c
CTRL_INTEL_CPT = 0x1c20
CTRL_INTEL_PGB = 0x1d20
CTRL_INTEL_PPT1 = 0x1e20
CTRL_INTEL_82801F = 0x2668
CTRL_INTEL_63XXESB = 0x269a
CTRL_INTEL_82801G = 0x27d8
CTRL_INTEL_82801H = 0x284b
CTRL_INTEL_82801_UNK1 = 0x2911
CTRL_INTEL_82801I = 0x293e
CTRL_INTEL_82801_UNK2 = 0x293f
CTRL_INTEL_82801JI = 0x3a3e
CTRL_INTEL_82801JD = 0x3a6e
CTRL_INTEL_PCH = 0x3b56
CTRL_INTEL_PCH2 = 0x3b57
CTRL_INTEL_SCH = 0x811b
CTRL_INTEL_LPT = 0x8c20
 
PCM_4 equ BIT20
PCM_6 equ BIT21
CTRL_NVIDIA_MCP51 = 0x026c
CTRL_NVIDIA_MCP55 = 0x0371
CTRL_NVIDIA_MCP61_1 = 0x03e4
CTRL_NVIDIA_MCP61_2 = 0x03f0
CTRL_NVIDIA_MCP65_1 = 0x044a
CTRL_NVIDIA_MCP65_2 = 0x044b
CTRL_NVIDIA_MCP67_1 = 0x055c
CTRL_NVIDIA_MCP67_2 = 0x055d
CTRL_NVIDIA_MCP78_1 = 0x0774
CTRL_NVIDIA_MCP78_2 = 0x0775
CTRL_NVIDIA_MCP78_3 = 0x0776
CTRL_NVIDIA_MCP78_4 = 0x0777
CTRL_NVIDIA_MCP73_1 = 0x07fc
CTRL_NVIDIA_MCP73_2 = 0x07fd
CTRL_NVIDIA_MCP79_1 = 0x0ac0
CTRL_NVIDIA_MCP79_2 = 0x0ac1
CTRL_NVIDIA_MCP79_3 = 0x0ac2
CTRL_NVIDIA_MCP79_4 = 0x0ac3
CTRL_NVIDIA_0BE2 = 0x0be2
CTRL_NVIDIA_0BE3 = 0x0be3
CTRL_NVIDIA_0BE4 = 0x0be4
CTRL_NVIDIA_GT100 = 0x0be5
CTRL_NVIDIA_GT106 = 0x0be9
CTRL_NVIDIA_GT108 = 0x0bea
CTRL_NVIDIA_GT104 = 0x0beb
CTRL_NVIDIA_GT116 = 0x0bee
CTRL_NVIDIA_MCP89_1 = 0x0d94
CTRL_NVIDIA_MCP89_2 = 0x0d95
CTRL_NVIDIA_MCP89_3 = 0x0d96
CTRL_NVIDIA_MCP89_4 = 0x0d97
CTRL_NVIDIA_GF119 = 0x0e08
CTRL_NVIDIA_GF110_1 = 0x0e09
CTRL_NVIDIA_GF110_2 = 0x0e0c
 
VID_INTEL equ 0x8086
VID_NVIDIA equ 0x10DE
CTRL_ATI_SB450 = 0x437b
CTRL_ATI_SB600 = 0x4383
 
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_ATI_RS600 = 0x793b
CTRL_ATI_RS690 = 0x7919
CTRL_ATI_RS780 = 0x960f
CTRL_ATI_RS_UNK1 = 0x970f
CTRL_ATI_R600 = 0xaa00
CTRL_ATI_RV630 = 0xaa08
CTRL_ATI_RV610 = 0xaa10
CTRL_ATI_RV670 = 0xaa18
CTRL_ATI_RV635 = 0xaa20
CTRL_ATI_RV620 = 0xaa28
CTRL_ATI_RV770 = 0xaa30
CTRL_ATI_RV730 = 0xaa38
CTRL_ATI_RV710 = 0xaa40
CTRL_ATI_RV740 = 0xaa48
 
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
CTRL_AMD_HUDSON = 0x780d
 
CTRL_VIA_VT82XX = 0x3288
CTRL_VIA_VT61XX = 0x9140
CTRL_VIA_VT71XX = 0x9170
 
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
CTRL_SIS_966 = 0x7502
 
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
CTRL_ULI_M5461 = 0x5461
 
CODEC_MASTER_VOL_REG equ 0x02
CODEC_AUX_VOL equ 0x04 ;
CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume
CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio
CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control
CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate
CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate
CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate
CTRL_CREATIVE_CA0110_IBG = 0x0009
CTRL_CREATIVE_SOUND_CORE3D_1 = 0x0010
CTRL_CREATIVE_SOUND_CORE3D_2 = 0x0012
 
GLOB_CTRL equ 0x2C ; Global Control
CTRL_STAT equ 0x30 ; Global Status
CTRL_CAS equ 0x34 ; Codec Access Semiphore
CTRL_TERA_UNK1 = 0x1200
 
CAS_FLAG equ 0x01 ; Codec Access Semiphore Bit
CTRL_RDC_R3010 = 0x3010
 
CTRL_ST_CREADY equ BIT8+BIT9+BIT28 ; Primary Codec Ready
CTRL_VMWARE_UNK1 = 0x1977
 
CTRL_ST_RCS equ 0x00008000 ; Read Completion Status
API_VERSION = 0x01000100
 
CTRL_CNT_CRIE equ BIT4+BIT5+BIT6 ; Codecs Resume Interrupt Enable
CTRL_CNT_AC_OFF equ 0x00000008 ; ACLINK Off
CTRL_CNT_WARM equ 0x00000004 ; AC97 Warm Reset
CTRL_CNT_COLD equ 0x00000002 ; AC97 Cold Reset
CTRL_CNT_GIE equ 0x00000001 ; GPI Interrupt Enable
 
CODEC_REG_POWERDOWN equ 0x26
CODEC_REG_ST equ 0x26
 
SRV_GETVERSION equ 0
DEV_PLAY equ 1
DEV_STOP equ 2
DEV_CALLBACK equ 3
DEV_SET_BUFF equ 4
DEV_NOTIFY equ 5
DEV_SET_MASTERVOL equ 6
DEV_GET_MASTERVOL equ 7
DEV_GET_INFO equ 8
DEV_GET_POS equ 9
 
struc AC_CNTRL ;AC controller base class
{ .bus dd ?
.devfn dd ?
 
.vendor dd ?
.dev_id dd ?
.pci_cmd dd ?
.pci_stat dd ?
 
.codec_io_base dd ?
.codec_mem_base dd ?
 
.ctrl_io_base dd ?
.ctrl_mem_base dd ?
.cfg_reg dd ?
.int_line dd ?
 
.vendor_ids dd ? ;vendor id string
.ctrl_ids dd ? ;hub id string
 
.buffer dd ?
 
.notify_pos dd ?
.notify_task dd ?
 
.lvi_reg dd ?
.ctrl_setup dd ?
.user_callback dd ?
.codec_read16 dd ?
.codec_write16 dd ?
 
.ctrl_read8 dd ?
.ctrl_read16 dd ?
.ctrl_read32 dd ?
 
.ctrl_write8 dd ?
.ctrl_write16 dd ?
.ctrl_write32 dd ?
}
 
struc CODEC ;Audio Chip base class
{
.chip_id dd ?
.flags dd ?
.status dd ?
 
.ac_vendor_ids dd ? ;ac vendor id string
.chip_ids dd ? ;chip model string
 
.shadow_flag dd ?
dd ?
 
.regs dw ? ; codec registers
.reg_master_vol dw ? ;0x02
.reg_aux_out_vol dw ? ;0x04
.reg_mone_vol dw ? ;0x06
.reg_master_tone dw ? ;0x08
.reg_beep_vol dw ? ;0x0A
.reg_phone_vol dw ? ;0x0C
.reg_mic_vol dw ? ;0x0E
.reg_line_in_vol dw ? ;0x10
.reg_cd_vol dw ? ;0x12
.reg_video_vol dw ? ;0x14
.reg_aux_in_vol dw ? ;0x16
.reg_pcm_out_vol dw ? ;0x18
.reg_rec_select dw ? ;0x1A
.reg_rec_gain dw ? ;0x1C
.reg_rec_gain_mic dw ? ;0x1E
.reg_gen dw ? ;0x20
.reg_3d_ctrl dw ? ;0X22
.reg_page dw ? ;0X24
.reg_powerdown dw ? ;0x26
.reg_ext_audio dw ? ;0x28
.reg_ext_st dw ? ;0x2a
.reg_pcm_front_rate dw ? ;0x2c
.reg_pcm_surr_rate dw ? ;0x2e
.reg_lfe_rate dw ? ;0x30
.reg_pcm_in_rate dw ? ;0x32
dw ? ;0x34
.reg_cent_lfe_vol dw ? ;0x36
.reg_surr_vol dw ? ;0x38
.reg_spdif_ctrl dw ? ;0x3A
dw ? ;0x3C
dw ? ;0x3E
dw ? ;0x40
dw ? ;0x42
dw ? ;0x44
dw ? ;0x46
dw ? ;0x48
dw ? ;0x4A
dw ? ;0x4C
dw ? ;0x4E
dw ? ;0x50
dw ? ;0x52
dw ? ;0x54
dw ? ;0x56
dw ? ;0x58
dw ? ;0x5A
dw ? ;0x5C
dw ? ;0x5E
.reg_page_0 dw ? ;0x60
.reg_page_1 dw ? ;0x62
.reg_page_2 dw ? ;0x64
.reg_page_3 dw ? ;0x66
.reg_page_4 dw ? ;0x68
.reg_page_5 dw ? ;0x6A
.reg_page_6 dw ? ;0x6C
.reg_page_7 dw ? ;0x6E
dw ? ;0x70
dw ? ;0x72
dw ? ;0x74
dw ? ;0x76
dw ? ;0x78
dw ? ;0x7A
.reg_vendor_id_1 dw ? ;0x7C
.reg_vendor_id_2 dw ? ;0x7E
 
 
.reset dd ? ;virual
.set_master_vol dd ?
}
 
struc CTRL_INFO
{ .pci_cmd dd ?
.irq dd ?
.glob_cntrl dd ?
.glob_sta dd ?
.codec_io_base dd ?
.ctrl_io_base dd ?
.codec_mem_base dd ?
.ctrl_mem_base dd ?
.codec_id dd ?
}
 
struc IOCTL
{ .handle dd ?
.io_code dd ?
.input dd ?
.inp_size dd ?
.output dd ?
.out_size dd ?
}
 
virtual at 0
IOCTL IOCTL
end virtual
 
EVENT_NOTIFY equ 0x00000200
 
public START
public service_proc
public version
306,340 → 162,22
end if
 
call detect_controller
test eax, eax
jz .fail
 
if DEBUG
mov esi, [ctrl.vendor_ids]
call SysMsgBoardStr
mov esi, [ctrl.ctrl_ids]
call SysMsgBoardStr
 
end if
 
call init_controller
test eax, eax
jz .fail
 
call init_codec
test eax, eax
jz .fail
 
call reset_controller
call setup_codec
 
mov esi, msgPrimBuff
call SysMsgBoardStr
call create_primary_buff
mov esi, msgDone
call SysMsgBoardStr
 
if IRQ_REMAP
pushf
cli
 
mov ebx, [ctrl.int_line]
in al, 0xA1
mov ah, al
in al, 0x21
test ebx, ebx
jz .skip
bts ax, bx ;mask old line
.skip
bts ax, IRQ_LINE ;mask new ine
out 0x21, al
mov al, ah
out 0xA1, al
;remap IRQ
stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE
 
mov dx, 0x4d0 ;8259 ELCR1
in al, dx
bts ax, IRQ_LINE
out dx, al ;set level-triggered mode
mov [ctrl.int_line], IRQ_LINE
popf
mov esi, msgRemap
call SysMsgBoardStr
end if
 
mov ebx, [ctrl.int_line]
stdcall AttachIntHandler, ebx, ac97_irq, dword 0
.reg:
stdcall RegService, sz_sound_srv, service_proc
ret
.fail:
if DEBUG
mov esi, msgFail
call SysMsgBoardStr
end if
xor eax, eax
ret
.fail_msg:
call SysMsgBoardStr
xor eax, eax
ret
.stop:
call stop
xor eax, eax
ret
endp
 
handle equ IOCTL.handle
io_code equ IOCTL.io_code
input equ IOCTL.input
inp_size equ IOCTL.inp_size
output equ IOCTL.output
out_size equ IOCTL.out_size
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edi, [ioctl]
mov eax, [edi+io_code]
 
cmp eax, SRV_GETVERSION
jne @F
 
mov eax, [edi+output]
cmp [edi+out_size], 4
jne .fail
 
mov [eax], dword API_VERSION
xor eax, eax
ret
@@:
cmp eax, DEV_PLAY
jne @F
if DEBUG
mov esi, msgPlay
call SysMsgBoardStr
end if
call play
ret
@@:
cmp eax, DEV_STOP
jne @F
if DEBUG
mov esi, msgStop
call SysMsgBoardStr
end if
call stop
ret
@@:
cmp eax, DEV_CALLBACK
jne @F
mov ebx, [edi+input]
stdcall set_callback, [ebx]
ret
@@:
cmp eax, DEV_SET_MASTERVOL
jne @F
mov eax, [edi+input]
mov eax, [eax]
call set_master_vol ;eax= vol
ret
@@:
cmp eax, DEV_GET_MASTERVOL
jne @F
mov ebx, [edi+output]
stdcall get_master_vol, ebx
ret
 
@@:
cmp eax, DEV_GET_POS
jne @F
 
mov ebx, 8192
mov edx, 0x18
xor eax, eax
call [ctrl.ctrl_read16]
sub ebx, eax
shr ebx, 1
mov edx, [edi+output]
mov [edx], ebx
xor eax, eax
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
proc detect_controller
 
if DEBUG_IRQ
mov esi, msgIRQ
call SysMsgBoardStr
end if
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
 
cmp eax, 0xffffffff
je .exit
 
test eax, 0x40
jnz .do_intr
 
test eax, eax
jz .exit
 
mov edx, CTRL_STAT
call [ctrl.ctrl_write32]
.exit:
xor eax, eax
ret
 
.do_intr:
push eax
 
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 .done
 
stdcall [ctrl.user_callback], ebx
.done:
pop eax
and eax, 0x40
mov edx, CTRL_STAT
call [ctrl.ctrl_write32]
or eax, 1
ret
.skip:
mov edx, PCM_OUT_CR_REG
mov ax, 0x11 ;0x1D
call [ctrl.ctrl_write8]
jmp .done
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 ?
672,7 → 210,7
 
cmp eax, ebx
je .found
add edi, 12
add edi, 8
jmp @B
.next:
inc [devfn]
686,822 → 224,170
xor eax, eax
ret
.found:
mov ebx, [bus]
mov [ctrl.bus], ebx
 
mov ecx, [devfn]
mov [ctrl.devfn], ecx
 
mov edx, eax
and edx, 0xFFFF
mov [ctrl.vendor], edx
shr eax, 16
mov [ctrl.dev_id], eax
 
mov ebx, [edi+4]
mov [ctrl.ctrl_ids], ebx
mov esi, [edi+8]
mov [ctrl.ctrl_setup], esi
 
cmp edx, VID_INTEL
jne @F
mov [ctrl.vendor_ids], msg_Intel
ret
@@:
cmp edx, VID_NVIDIA
jne @F
mov [ctrl.vendor_ids], msg_NVidia
ret
@@:
.err:
xor eax, eax
mov [ctrl.vendor_ids], eax ;something wrong ?
ret
endp
 
align 4
proc init_controller
 
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4
mov ebx, eax
and eax, 0xFFFF
mov [ctrl.pci_cmd], eax
shr ebx, 16
mov [ctrl.pci_stat], ebx
 
mov esi, msgPciCmd
if DEBUG
mov esi, msgLoading
call SysMsgBoardStr
call dword2str
call SysMsgBoardStr
 
mov esi, msgPciStat
mov esi, dword[edi+4]
call SysMsgBoardStr
mov eax, [ctrl.pci_stat]
call dword2str
call SysMsgBoardStr
 
mov esi, msgMixIsaIo
mov esi, msgNewline
call SysMsgBoardStr
 
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10
 
call dword2str
call SysMsgBoardStr
 
and eax, 0xFFFE
mov [ctrl.codec_io_base], eax
 
mov esi, msgCtrlIsaIo
call SysMsgBoardStr
 
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x14
 
call dword2str
call SysMsgBoardStr
 
and eax, 0xFFC0
mov [ctrl.ctrl_io_base], eax
 
mov esi, msgMixMMIo
call SysMsgBoardStr
 
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x18
mov [ctrl.codec_mem_base], eax
 
call dword2str
call SysMsgBoardStr
 
mov esi, msgCtrlMMIo
call SysMsgBoardStr
 
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x1C
mov [ctrl.ctrl_mem_base], eax
 
call dword2str
call SysMsgBoardStr
 
if 0
 
;;patch for some ugly BIOS ICH-ICH5 compatible
cmp [ctrl.vendor], VID_INTEL
jne .default
 
mov esi, msgIrqMap
call SysMsgBoardStr
stdcall PciRead8, 0, 0xF8, 0x61
and eax, 0xFF
call dword2str
call SysMsgBoardStr
btr eax, 7 ;when bit 7 set remap disabled
jnc @F
xor eax, eax
jmp @F
end if
 
.default:
stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C
and eax, 0xFF
@@:
mov [ctrl.int_line], eax
stdcall GetService, dword[edi+4]
 
stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword 0x41
and eax, 0xFF
mov [ctrl.cfg_reg], eax
 
mov [ctrl.user_callback], 0
 
call [ctrl.ctrl_setup]
xor eax, eax
inc eax
ret
endp
 
align 4
proc set_ICH
mov [ctrl.codec_read16], codec_io_r16 ;virtual
mov [ctrl.codec_write16], codec_io_w16 ;virtual
 
mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual
mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual
mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual
 
mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual
mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual
mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual
ret
endp
 
PG_SW equ 0x003
PG_NOCACHE equ 0x018
 
align 4
proc set_ICH4
 
stdcall MapIoMem, [ctrl.codec_mem_base], 0x1000, PG_SW+PG_NOCACHE
mov [ctrl.codec_mem_base], eax
 
stdcall MapIoMem, [ctrl.ctrl_mem_base], 0x1000, PG_SW+PG_NOCACHE
mov [ctrl.ctrl_mem_base], eax
 
mov [ctrl.codec_read16], codec_mem_r16 ;virtual
mov [ctrl.codec_write16], codec_mem_w16 ;virtual
 
mov [ctrl.ctrl_read8 ], ctrl_mem_r8 ;virtual
mov [ctrl.ctrl_read16], ctrl_mem_r16 ;virtual
mov [ctrl.ctrl_read32], ctrl_mem_r32 ;virtual
 
mov [ctrl.ctrl_write8 ], ctrl_mem_w8 ;virtual
mov [ctrl.ctrl_write16], ctrl_mem_w16 ;virtual
mov [ctrl.ctrl_write32], ctrl_mem_w32 ;virtual
ret
endp
 
align 4
proc reset_controller
 
xor eax, eax
mov edx, PCM_IN_CR_REG
call [ctrl.ctrl_write8]
 
mov edx, PCM_OUT_CR_REG
call [ctrl.ctrl_write8]
 
mov edx, MC_IN_CR_REG
call [ctrl.ctrl_write8]
 
mov eax, RR
mov edx, PCM_IN_CR_REG
call [ctrl.ctrl_write8]
 
mov edx, PCM_OUT_CR_REG
call [ctrl.ctrl_write8]
 
mov edx, MC_IN_CR_REG
call [ctrl.ctrl_write8]
ret
endp
 
align 4
proc init_codec
locals
counter dd ?
endl
 
mov esi, msgControl
call SysMsgBoardStr
 
mov edx, GLOB_CTRL
call [ctrl.ctrl_read32]
call dword2str
call SysMsgBoardStr
 
mov esi, msgStatus
call SysMsgBoardStr
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
push eax
call dword2str
call SysMsgBoardStr
pop eax
cmp eax, 0xFFFFFFFF
je .err
 
test eax, CTRL_ST_CREADY
jnz .ready
 
call reset_codec
test eax, eax
jz .err
 
.ready:
xor edx, edx ;ac_reg_0
call [ctrl.codec_write16]
 
xor eax, eax
mov edx, CODEC_REG_POWERDOWN
call [ctrl.codec_write16]
 
mov [counter], 200 ; total 200*5 ms = 1s
.wait:
mov eax, 5000 ; wait 5 ms
call StallExec
 
mov edx, CODEC_REG_POWERDOWN
call [ctrl.codec_read16]
and eax, 0x0F
cmp eax, 0x0F
jz .done
 
sub [counter] , 1
jnz .wait
.err:
xor eax, eax ; timeout error
ret
.done:
mov eax, 2 ;force set 16-bit 2-channel PCM
mov edx, GLOB_CTRL
call [ctrl.ctrl_write32]
mov eax, 5000 ; wait 5 ms
call StallExec
 
call detect_codec
 
xor eax, eax
inc eax
ret
endp
 
align 4
proc reset_codec
mov edx, GLOB_CTRL
call [ctrl.ctrl_read32]
 
test eax, 0x02
jz .cold
 
call warm_reset
jnc .ok
.cold:
call cold_reset
jnc .ok
 
if DEBUG
mov esi, msgCFail
mov esi, msgFail
call SysMsgBoardStr
end if
xor eax, eax ; timeout error
ret
.ok:
if DEBUG
mov esi, msgResetOk
call SysMsgBoardStr
end if
 
xor eax, eax
inc eax
ret
endp
 
align 4
proc warm_reset
locals
counter dd ?
endl
 
mov eax, 0x06
mov edx, GLOB_CTRL
call [ctrl.ctrl_write32]
 
if DEBUG
mov esi, msgWarm
call SysMsgBoardStr
end if
 
mov [counter], 10 ; total 10*100 ms = 1s
.wait:
mov eax, 100000 ; wait 100 ms
call StallExec
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
test eax, CTRL_ST_CREADY
jnz .ok
 
dec [counter]
jnz .wait
 
if DEBUG
mov esi, msgWRFail
call SysMsgBoardStr
end if
.fail:
stc
ret
.ok:
clc
ret
endp
 
align 4
proc cold_reset
locals
counter dd ?
endl
devices dd (CTRL_ICH shl 16)+VID_INTEL, intelac97
dd (CTRL_ICH0 shl 16)+VID_INTEL, intelac97
dd (CTRL_ICH2 shl 16)+VID_INTEL, intelac97
dd (CTRL_ICH3 shl 16)+VID_INTEL, intelac97
dd (CTRL_ICH4 shl 16)+VID_INTEL, intelac97
dd (CTRL_ICH5 shl 16)+VID_INTEL, intelac97
dd (CTRL_ICH6 shl 16)+VID_INTEL, intelac97
dd (CTRL_ICH7 shl 16)+VID_INTEL, intelac97
 
mov eax, 0x02
mov edx, GLOB_CTRL
call [ctrl.ctrl_write32]
dd (CTRL_NFORCE shl 16)+VID_NVIDIA, intelac97
dd (CTRL_NFORCE2 shl 16)+VID_NVIDIA, intelac97
dd (CTRL_NFORCE3 shl 16)+VID_NVIDIA, intelac97
dd (CTRL_MCP04 shl 16)+VID_NVIDIA, intelac97
dd (CTRL_CK804 shl 16)+VID_NVIDIA, intelac97
dd (CTRL_CK8 shl 16)+VID_NVIDIA, intelac97
dd (CTRL_CK8S shl 16)+VID_NVIDIA, intelac97
dd (CTRL_MCP51 shl 16)+VID_NVIDIA, intelac97
 
if DEBUG
mov esi, msgCold
call SysMsgBoardStr
end if
dd (CTRL_VT82C686 shl 16)+VID_VIA, vt823x
dd (CTRL_VT8233_5 shl 16)+VID_VIA, vt823x
 
mov eax, 400000 ; wait 400 ms
call StallExec
dd (CTRL_SIS shl 16)+VID_SIS, sis
 
mov [counter], 16 ; total 20*100 ms = 2s
.wait:
dd (CTRL_FM801 shl 16)+VID_FM801, fm801
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
test eax, CTRL_ST_CREADY
jnz .ok
dd (0x5000 shl 16)+0x1274, ensoniq
dd (0x5880 shl 16)+0x1274, ensoniq
 
mov eax, 100000 ; wait 100 ms
call StallExec
dd (CTRL_CT0200 shl 16)+VID_CREATIVE, emu10k1x
; Intel
dd (CTRL_INTEL_SCH2 shl 16)+VID_INTEL, intelhda
dd (CTRL_INTEL_HPT shl 16)+VID_INTEL, intelhda
dd (CTRL_INTEL_CPT shl 16)+VID_INTEL, intelhda
dd (CTRL_INTEL_PGB shl 16)+VID_INTEL, intelhda
dd (CTRL_INTEL_PPT1 shl 16)+VID_INTEL, intelhda
dd (CTRL_INTEL_82801F shl 16)+VID_INTEL, intelhda
dd (CTRL_INTEL_63XXESB shl 16)+VID_INTEL, intelhda
dd (CTRL_INTEL_82801G shl 16)+VID_INTEL, intelhda
dd (CTRL_INTEL_82801H shl 16)+VID_INTEL, intelhda
dd (CTRL_INTEL_82801_UNK1 shl 16)+VID_INTEL, intelhda
dd (CTRL_INTEL_82801I shl 16)+VID_INTEL, intelhda
dd (CTRL_INTEL_82801_UNK2 shl 16)+VID_INTEL, intelhda
dd (CTRL_INTEL_82801JI shl 16)+VID_INTEL, intelhda
dd (CTRL_INTEL_82801JD shl 16)+VID_INTEL, intelhda
dd (CTRL_INTEL_PCH shl 16)+VID_INTEL, intelhda
dd (CTRL_INTEL_PCH2 shl 16)+VID_INTEL, intelhda
dd (CTRL_INTEL_SCH shl 16)+VID_INTEL, intelhda
dd (CTRL_INTEL_LPT shl 16)+VID_INTEL, intelhda
; Nvidia
dd (CTRL_NVIDIA_MCP51 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP55 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP61_1 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP61_2 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP65_1 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP65_2 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP67_1 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP67_2 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP73_1 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP73_2 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP78_1 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP78_2 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP78_3 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP78_4 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP79_1 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP79_2 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP79_3 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP79_4 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_0BE2 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_0BE3 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_0BE4 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_GT100 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_GT106 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_GT108 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_GT104 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_GT116 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP89_1 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP89_2 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP89_3 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_MCP89_4 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_GF119 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_GF110_1 shl 16)+VID_NVIDIA, intelhda
dd (CTRL_NVIDIA_GF110_2 shl 16)+VID_NVIDIA, intelhda
; ATI
dd (CTRL_ATI_SB450 shl 16)+VID_ATI, intelhda
dd (CTRL_ATI_SB600 shl 16)+VID_ATI, intelhda
dd (CTRL_ATI_RS600 shl 16)+VID_ATI, intelhda
dd (CTRL_ATI_RS690 shl 16)+VID_ATI, intelhda
dd (CTRL_ATI_RS780 shl 16)+VID_ATI, intelhda
dd (CTRL_ATI_RS_UNK1 shl 16)+VID_ATI, intelhda
dd (CTRL_ATI_R600 shl 16)+VID_ATI, intelhda
dd (CTRL_ATI_RV610 shl 16)+VID_ATI, intelhda
dd (CTRL_ATI_RV620 shl 16)+VID_ATI, intelhda
dd (CTRL_ATI_RV630 shl 16)+VID_ATI, intelhda
dd (CTRL_ATI_RV635 shl 16)+VID_ATI, intelhda
dd (CTRL_ATI_RV670 shl 16)+VID_ATI, intelhda
dd (CTRL_ATI_RV710 shl 16)+VID_ATI, intelhda
dd (CTRL_ATI_RV730 shl 16)+VID_ATI, intelhda
dd (CTRL_ATI_RV740 shl 16)+VID_ATI, intelhda
dd (CTRL_ATI_RV770 shl 16)+VID_ATI, intelhda
; AMD
dd (CTRL_AMD_HUDSON shl 16)+VID_AMD, intelhda
; VIA
dd (CTRL_VIA_VT82XX shl 16)+VID_VIA, intelhda
dd (CTRL_VIA_VT61XX shl 16)+VID_VIA, intelhda
dd (CTRL_VIA_VT71XX shl 16)+VID_VIA, intelhda
; SiS
dd (CTRL_SIS_966 shl 16)+VID_SIS, intelhda
; ULI
dd (CTRL_ULI_M5461 shl 16)+VID_ULI, intelhda
; Teradici
dd (CTRL_TERA_UNK1 shl 16)+VID_ULI, intelhda
; Creative
dd (CTRL_CREATIVE_CA0110_IBG shl 16)+VID_CREATIVE, intelhda
dd (CTRL_CREATIVE_SOUND_CORE3D_1 shl 16)+VID_CREATIVE, intelhda
dd (CTRL_CREATIVE_SOUND_CORE3D_2 shl 16)+VID_CREATIVE, intelhda
; RDC Semiconductor
dd (CTRL_RDC_R3010 shl 16)+VID_RDC, intelhda
; VMware
dd (CTRL_VMWARE_UNK1 shl 16)+VID_VMWARE, intelhda
 
dec [counter]
jnz .wait
 
if DEBUG
mov esi, msgCRFail
call SysMsgBoardStr
end if
 
.fail:
stc
ret
.ok:
mov esi, msgControl
call SysMsgBoardStr
 
mov edx, GLOB_CTRL
call [ctrl.ctrl_read32]
call dword2str
call SysMsgBoardStr
 
mov esi, msgStatus
call SysMsgBoardStr
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
push eax
call dword2str
call SysMsgBoardStr
pop eax
 
test eax, CTRL_ST_CREADY
jz .fail
clc
ret
endp
 
align 4
play:
mov eax, 16
mov [ctrl.lvi_reg], eax
mov edx, PCM_OUT_LVI_REG
call [ctrl.ctrl_write8]
 
mov edx, PCM_OUT_CR_REG
mov ax, 0x1D
call [ctrl.ctrl_write8]
xor eax, eax
ret
 
align 4
stop:
mov edx, PCM_OUT_CR_REG
mov ax, 0x0
call [ctrl.ctrl_write8]
 
mov ax, 0x1c
mov edx, PCM_OUT_SR_REG
call [ctrl.ctrl_write16]
xor eax, eax
ret
 
align 4
proc get_dev_info stdcall, p_info:dword
virtual at esi
CTRL_INFO CTRL_INFO
end virtual
 
mov esi, [p_info]
mov eax, [ctrl.int_line]
mov ebx, [ctrl.codec_io_base]
mov ecx, [ctrl.ctrl_io_base]
mov edx, [ctrl.codec_mem_base]
mov edi, [ctrl.ctrl_mem_base]
 
mov [CTRL_INFO.irq], eax
mov [CTRL_INFO.codec_io_base], ebx
mov [CTRL_INFO.ctrl_io_base], ecx
mov [CTRL_INFO.codec_mem_base], edx
mov [CTRL_INFO.ctrl_mem_base], edi
 
mov eax, [codec.chip_id]
mov [CTRL_INFO.codec_id], eax
 
mov edx, GLOB_CTRL
call [ctrl.ctrl_read32]
mov [CTRL_INFO.glob_cntrl], eax
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
mov [CTRL_INFO.glob_sta], eax
 
mov ebx, [ctrl.pci_cmd]
mov [CTRL_INFO.pci_cmd], ebx
ret
endp
 
align 4
proc set_callback stdcall, handler:dword
mov eax, [handler]
mov [ctrl.user_callback], eax
ret
endp
 
align 4
proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax
 
mov edx, [ac_reg]
 
mov ebx, edx
shr ebx, 1
bt [codec.shadow_flag], ebx
jc .use_shadow
 
call [ctrl.codec_read16] ;change edx !!!
mov ecx, eax
 
mov edx, CTRL_STAT
call [ctrl.ctrl_read32]
test eax, CTRL_ST_RCS
jz .read_ok
 
mov edx, CTRL_STAT
call [ctrl.ctrl_write32]
xor eax, eax
not eax ;timeout
ret
.read_ok:
mov edx, [ac_reg]
mov [codec.regs+edx], cx
bts [codec.shadow_flag], ebx
mov eax, ecx
ret
.use_shadow:
movzx eax, word [codec.regs+edx]
ret
endp
 
align 4
proc codec_write stdcall, ac_reg:dword
push eax
call check_semafore
and eax, eax
jz .err
pop eax
 
mov esi, [ac_reg]
mov edx, esi
call [ctrl.codec_write16]
mov [codec.regs+esi], ax
shr esi, 1
bts [codec.shadow_flag], esi
ret
.err:
pop eax
ret
endp
 
align 4
proc codec_check_ready
 
mov edx, CTRL_ST
call [ctrl.ctrl_read32]
and eax, CTRL_ST_CREADY
jz .not_ready
 
xor eax, wax
inc eax
ret
.not_ready:
xor eax, eax
ret
endp
 
align 4
proc check_semafore
local counter:DWORD
 
mov [counter], 100
.l1:
mov edx, CTRL_CAS
call [ctrl.ctrl_read8]
and eax, CAS_FLAG
jz .ok
 
mov eax, 1
call StallExec
sub [counter], 1
jnz .l1
xor eax, eax
ret
align 4
.ok:
xor eax, eax
inc eax
ret
endp
 
align 4
proc StallExec
push ecx
push edx
push ebx
push eax
 
mov ecx, CPU_FREQ
mul ecx
mov ebx, eax ;low
mov ecx, edx ;high
rdtsc
add ebx, eax
adc ecx, edx
@@:
rdtsc
sub eax, ebx
sbb edx, ecx
js @B
 
pop eax
pop ebx
pop edx
pop ecx
ret
endp
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; CONTROLLER IO functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc codec_io_r16
add edx, [ctrl.codec_io_base]
in ax, dx
ret
endp
 
align 4
proc codec_io_w16
add edx, [ctrl.codec_io_base]
out dx, ax
ret
endp
 
align 4
proc ctrl_io_r8
add edx, [ctrl.ctrl_io_base]
in al, dx
ret
endp
 
align 4
proc ctrl_io_r16
add edx, [ctrl.ctrl_io_base]
in ax, dx
ret
endp
 
align 4
proc ctrl_io_r32
add edx, [ctrl.ctrl_io_base]
in eax, dx
ret
endp
 
align 4
proc ctrl_io_w8
add edx, [ctrl.ctrl_io_base]
out dx, al
ret
endp
 
align 4
proc ctrl_io_w16
add edx, [ctrl.ctrl_io_base]
out dx, ax
ret
endp
 
align 4
proc ctrl_io_w32
add edx, [ctrl.ctrl_io_base]
out dx, eax
ret
endp
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; MEMORY MAPPED IO (os depended)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc codec_mem_r16
add edx, [ctrl.codec_mem_base]
mov ax, word [edx]
ret
endp
 
align 4
proc codec_mem_w16
add edx, [ctrl.codec_mem_base]
mov word [edx], ax
ret
endp
 
align 4
proc ctrl_mem_r8
add edx, [ctrl.ctrl_mem_base]
mov al, [edx]
ret
endp
 
align 4
proc ctrl_mem_r16
add edx, [ctrl.ctrl_mem_base]
mov ax, [edx]
ret
endp
 
align 4
proc ctrl_mem_r32
add edx, [ctrl.ctrl_mem_base]
mov eax, [edx]
ret
endp
 
align 4
proc ctrl_mem_w8
add edx, [ctrl.ctrl_mem_base]
mov [edx], al
ret
endp
 
align 4
proc ctrl_mem_w16
add edx, [ctrl.ctrl_mem_base]
mov [edx], ax
ret
endp
 
align 4
proc ctrl_mem_w32
add edx, [ctrl.ctrl_mem_base]
mov [edx], eax
ret
endp
 
align 4
dword2str:
mov esi, hex_buff
mov ecx, -8
@@:
rol eax, 4
mov ebx, eax
and ebx, 0x0F
mov bl, [ebx+hexletters]
mov [8+esi+ecx], bl
inc ecx
jnz @B
ret
 
hexletters db '0123456789ABCDEF'
hex_buff db 8 dup(0),13,10,0
 
 
include "codec.inc"
 
align 4
devices dd (CTRL_ICH shl 16)+VID_INTEL,msg_ICH, set_ICH
dd (CTRL_ICH0 shl 16)+VID_INTEL,msg_ICH0,set_ICH
dd (CTRL_ICH2 shl 16)+VID_INTEL,msg_ICH2,set_ICH
dd (CTRL_ICH3 shl 16)+VID_INTEL,msg_ICH3,set_ICH
dd (CTRL_ICH4 shl 16)+VID_INTEL,msg_ICH4,set_ICH4
dd (CTRL_ICH5 shl 16)+VID_INTEL,msg_ICH5,set_ICH4
dd (CTRL_ICH6 shl 16)+VID_INTEL,msg_ICH6,set_ICH4
dd (CTRL_ICH7 shl 16)+VID_INTEL,msg_ICH7,set_ICH4
 
dd (CTRL_NFORCE shl 16)+VID_NVIDIA,msg_NForce, set_ICH
dd (CTRL_NFORCE2 shl 16)+VID_NVIDIA,msg_NForce2,set_ICH
dd (CTRL_NFORCE3 shl 16)+VID_NVIDIA,msg_NForce3,set_ICH
dd (CTRL_MCP04 shl 16)+VID_NVIDIA,msg_MCP04,set_ICH
dd (CTRL_CK804 shl 16)+VID_NVIDIA,msg_CK804,set_ICH
dd (CTRL_CK8 shl 16)+VID_NVIDIA,msg_CK8,set_ICH
dd (CTRL_CK8S shl 16)+VID_NVIDIA,msg_CK8S,set_ICH
dd (CTRL_MCP51 shl 16)+VID_NVIDIA,msg_MCP51,set_ICH
 
dd 0 ;terminator
 
 
version dd (5 shl 16) or (API_VERSION and 0xFFFF)
 
msg_ICH db '802801AA (ICH)', 13,10, 0
msg_ICH0 db '802801AB (ICH0)', 13,10, 0
msg_ICH2 db '802801BA (ICH2)', 13,10, 0
msg_ICH3 db '802801CA (ICH3)', 13,10, 0
msg_ICH4 db '802801DB (ICH4)', 13,10, 0
msg_ICH5 db '802801EB (ICH5)', 13,10, 0
msg_ICH6 db '802801FB (ICH6)', 13,10, 0
msg_ICH7 db '802801GB (ICH7)', 13,10, 0
msg_Intel db 'Intel ', 0
intelac97 db 'INTELAC97', 0
vt823x db 'VT823X', 0
sis db 'SIS', 0
fm801 db 'FM801', 0
ensoniq db 'ENSONIQ', 0
emu10k1x db 'EMU10K1X', 0
intelhda db 'INTEL_HDA', 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
msgInit db 'Detecting hardware...',13,10,0
msgFail db 'No compatible soundcard found!',13,10,0
msgLoading db 'Loading ',0
msgNewline db 13,10,0
 
msg_NVidia db 'NVidia', 0
 
szKernel db 'KERNEL', 0
sz_sound_srv db 'SOUND',0
 
msgInit db 'detect hardware...',13,10,0
msgFail db 'device not found',13,10,0
msgAttchIRQ db 'IRQ line not supported', 13,10, 0
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0
msgPlay db 'start play', 13,10,0
msgStop db 'stop play', 13,10,0
;msgNotify db 'call notify',13,10,0
msgIRQ db 'AC97 IRQ', 13,10,0
msgInitCtrl db 'init controller',13,10,0
;msgInitCodec db 'init codec',13,10,0
msgPrimBuff db 'create primary buffer ...',0
msgDone db 'done',13,10,0
msgRemap db 'Remap IRQ',13,10,0
;msgReg db 'set service handler',13,10,0
msgOk db 'service installed',13,10,0
msgCold db 'cold reset',13,10,0
msgWarm db 'warm reset',13,10,0
msgWRFail db 'warm reset failed',13,10,0
msgCRFail db 'cold reset failed',13,10,0
msgCFail db 'codec not ready',13,10,0
msgResetOk db 'reset complete',13,10,0
msgStatus db 'global status ',0
msgControl db 'global control ',0
msgPciCmd db 'PCI command ',0
msgPciStat db 'PCI status ',0
msgCtrlIsaIo db 'controller io base ',0
msgMixIsaIo db 'codec io base ',0
msgCtrlMMIo db 'controller mmio base ',0
msgMixMMIo db 'codec mmio base ',0
msgIrqMap db 'AC97 irq map as ',0
 
section '.data' data readable writable align 16
 
pcmout_bdl rq 32
buff_list rd 32
 
codec CODEC
ctrl AC_CNTRL
 
lpc_bus rd 1
civ_val rd 1
/kernel/branches/Kolibri-acpi/drivers/tmpdisk.asm
0,0 → 1,295
; Disk driver to create FAT16/FAT32 memory-based temporary disk aka RAM disk.
; (c) CleverMouse
 
; Note: in the ideal world, a disk driver should not care about a file system
; on it. In the current world, however, there is no way to format a disk in
; FAT, so this part of file-system-specific operations is included in the
; driver.
 
; When this driver is loading, it registers itself in the system and does
; nothing more. When loaded, this driver controls pseudo-disk devices
; named /tmp#/, where # is a digit from 0 to 9. The driver does not create
; any device by itself, waiting for instructions from an application.
; The driver responds to the following IOCTLs from a control application:
SRV_GETVERSION equ 0 ; input ignored,
; output = dword API_VERSION
DEV_ADD_DISK equ 1 ; input = structure add_disk_struc,
; no output
DEV_DEL_DISK equ 2 ; input = structure del_disk_struc,
; no output
; For all IOCTLs the driver returns one of the following error codes:
NO_ERROR equ 0
ERROR_INVALID_IOCTL equ 1 ; unknown IOCTL code, wrong input/output size...
ERROR_INVALID_ID equ 2 ; .DiskId must be from 0 to 9
ERROR_SIZE_TOO_LARGE equ 3 ; .DiskSize is too large
ERROR_SIZE_TOO_SMALL equ 4 ; .DiskSize is too small
ERROR_NO_MEMORY equ 5 ; memory allocation failed
 
 
API_VERSION equ 1
; Input structures:
struc add_disk_struc
{
.DiskSize dd ? ; disk size in sectors, 1 sector = 512 bytes
; Note: .DiskSize is the full size, including FAT service data.
; Size for useful data is slightly less than this number.
.DiskId db ? ; from 0 to 9
.sizeof:
}
virtual at 0
add_disk_struc add_disk_struc
end virtual
struc del_disk_struc
{
.DiskId db ? ; from 0 to 9
.sizeof:
}
virtual at 0
del_disk_struc del_disk_struc
end virtual
 
max_num_disks equ 10
 
; standard driver stuff
format MS COFF
 
DEBUG equ 0
include 'proc32.inc'
include 'imports.inc'
 
public START
public version
 
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
; the start procedure (see the description above)
proc START
; This procedure is called in two situations:
; when the driver is loading and when the system is shutting down.
; 1. Check that the driver is loading; do nothing unless so.
xor eax, eax ; set return value in case we will do nothing
cmp dword [esp+4], 1
jne .nothing
; 2. Register the driver in the system.
stdcall RegService, my_service, service_proc
; 3. Return the value returned by RegService back to the system.
.nothing:
retn 4
endp
 
; Service procedure for the driver - handle all IOCTL requests for the driver.
; The description of handled IOCTLs is located in the start of this file.
proc service_proc
; 1. Save used registers to be stdcall.
; Note: this shifts esp, so the first parameter [esp+4] becomes [esp+16].
; Note: edi is used not by this procedure itself, but by worker procedures.
push ebx esi edi
; 2. Get parameter from the stack: [esp+16] is the first parameter,
; pointer to IOCTL structure.
mov edx, [esp+16] ; edx -> IOCTL
; 3. Set the return value to 'invalid IOCTL'.
; Now, if one of conditions for IOCTL does not met, the code
; can simply return the value already loaded.
mov al, ERROR_INVALID_IOCTL
; 4. Get request code and select a handler for the code.
mov ecx, [edx+IOCTL.io_code]
test ecx, ecx ; check for SRV_GETVERSION
jnz .no.srv_getversion
; 4. This is SRV_GETVERSION request, no input, 4 bytes output, API_VERSION.
; 4a. Output size must be at least 4 bytes.
cmp [edx+IOCTL.out_size], 4
jl .return
; 4b. Write result to the output buffer.
mov eax, [edx+IOCTL.output]
mov dword [eax], API_VERSION
; 4c. Return success.
xor eax, eax
jmp .return
.no.srv_getversion:
dec ecx ; check for DEV_ADD_DISK
jnz .no.dev_add_disk
; 5. This is DEV_ADD_DISK request, input is add_disk_struc, output is 1 byte
; 5a. Input size must be exactly add_disk_struc.sizeof bytes.
cmp [edx+IOCTL.inp_size], add_disk_struc.sizeof
jnz .return
; 5b. Load input parameters and call the worker procedure.
mov eax, [edx+IOCTL.input]
movzx ebx, [eax+add_disk_struc.DiskId]
mov esi, [eax+add_disk_struc.DiskSize]
call add_disk
; 5c. Return back to the caller the value from the worker procedure.
jmp .return
.no.dev_add_disk:
dec ecx ; check for DEV_DEL_DISK
jnz .return
; 6. This is DEV_DEL_DISK request, input is del_disk_struc
; 6a. Input size must be exactly del_disk_struc.sizeof bytes.
cmp [edx+IOCTL.inp_size], del_disk_struc.sizeof
jnz .return
; 6b. Load input parameters and call the worker procedure.
mov eax, [edx+IOCTL.input]
movzx ebx, [eax+del_disk_struc.DiskId]
call del_disk
; 6c. Return back to the caller the value from the worker procedure.
.return:
; 7. Exit.
; 7a. The code above returns a value in al for efficiency,
; propagate it to eax.
movzx eax, al
; 7b. Restore used registers to be stdcall.
pop edi esi ebx
; 7c. Return, popping one argument.
retn 4
endp
 
; The worker procedure for DEV_ADD_DISK request.
; Creates a memory-based disk of given size and formats it in FAT16/32.
; Called with ebx = disk id, esi = disk size,
; returns error code in al.
proc add_disk
; 1. Check that disk id is correct and free.
; Otherwise, return the corresponding error code.
mov al, ERROR_INVALID_ID
cmp ebx, max_num_disks
jae .return
cmp [disk_pointers+ebx*4], 0
jnz .return
; 2. Check that the size is reasonable.
; Otherwise, return the corresponding error code.
mov al, ERROR_SIZE_TOO_LARGE
cmp esi, MAX_SIZE
ja .return
mov al, ERROR_SIZE_TOO_SMALL
cmp esi, MIN_FAT16_SIZE
jb .return
; 3. Allocate memory for the disk, store the pointer in edi.
; If failed, return the corresponding error code.
mov eax, esi
shl eax, 9
stdcall KernelAlloc, eax
mov edi, eax
test eax, eax
mov al, ERROR_NO_MEMORY
jz .return
; 4. Store the pointer and the size in the global variables.
; It is possible, though very unlikely, that two threads
; have called this function in parallel with the same id,
; so [disk_pointers+ebx*4] could be filled by another thread.
; Play extra safe and store new value only if old value is zero.
xor eax, eax
lock cmpxchg [disk_pointers+ebx*4], edi
jz @f
; Otherwise, free the allocated memory and return the corresponding error code.
stdcall KernelFree, edi
mov al, ERROR_INVALID_ID
jmp .return
@@:
mov [disk_sizes+ebx*4], esi
; 5. Call the worker procedure for formatting this disk.
; It should not fail.
call format_disk
; 6. Register the disk in the system.
; 6a. Generate name as /tmp#, where # = ebx + '0'. Use two dwords in the stack.
push 0
push 'tmp'
mov eax, esp ; eax points to 'tmp' + zero byte + zero dword
lea ecx, [ebx+'0'] ; ecx = digit
mov [eax+3], cl ; eax points to 'tmp#' + zero dword
; 6b. Call the kernel API. Use disk id as 'userdata' parameter for callbacks.
stdcall DiskAdd, disk_functions, eax, ebx, 0
; 6c. Restore the stack after 6a.
pop ecx ecx
; 6c. Check the result. If DiskAdd has failed, cleanup and return
; ERROR_NO_MEMORY, this is the most probable or even the only reason to fail.
test eax, eax
jnz @f
mov [disk_sizes+ebx*4], 0
mov [disk_pointers+ebx*4], 0
stdcall KernelFree, edi
mov al, ERROR_NO_MEMORY
jmp .return
@@:
push eax
; 6d. Notify the kernel that media is inserted.
stdcall DiskMediaChanged, eax, 1
; 6e. Disk is fully configured; store its handle in the global variable
; and return success.
pop [disk_handles+ebx*4]
xor eax, eax
; 7. Return.
.return:
retn
endp
 
; The worker procedure for DEV_DEL_DISK request.
; Deletes a previously created memory-based disk.
; Called with ebx = disk id,
; returns error code in al.
proc del_disk
; 1. Check that disk id is correct.
; Otherwise, return the corresponding error code.
mov al, ERROR_INVALID_ID
cmp ebx, max_num_disks
jae .return
; 2. Get the disk handle, simultaneously clearing the global variable.
xor edx, edx
xchg edx, [disk_handles+ebx*4]
; 3. Check that the handle is non-zero.
; Otherwise, return the corresponding error code.
test edx, edx
jz .return
; 4. Delete the disk from the system.
stdcall DiskDel, edx
; 5. Return success.
; Note that we can't free memory yet; it will be done in tmpdisk_close.
xor eax, eax
.return:
retn
endp
 
; Include implementation of tmpdisk_* callbacks.
include 'tmpdisk_work.inc'
; Include FAT-specific code.
include 'tmpdisk_fat.inc'
 
; initialized data
align 4
disk_functions:
dd disk_functions_end - disk_functions
dd tmpdisk_close
dd 0 ; no need in .closemedia
dd tmpdisk_querymedia
dd tmpdisk_read
dd tmpdisk_write
dd 0 ; no need in .flush
dd tmpdisk_adjust_cache_size
disk_functions_end:
; disk_handles = array of values for Disk* kernel functions
label disk_handles dword
times max_num_disks dd 0
; disk_pointers = array of pointers to disk data
label disk_pointers dword
times max_num_disks dd 0
; disk_sizes = array of disk sizes
label disk_sizes dword
times max_num_disks dd 0
 
version dd 0x00060006
my_service db 'tmpdisk',0
 
; uninitialized data
; actually, not used here
;section '.data' data readable writable align 16 ; standard driver stuff
/kernel/branches/Kolibri-acpi/drivers/tmpdisk_fat.inc
0,0 → 1,327
; FAT-specific code for tmpdisk.asm.
; Formats a disk to FAT16 or FAT32, depending on size.
; Note: formatting is adjusted for memory-based disks. Although the resulting
; image is a valid FAT32 volume, it has no "spare" sectors, e.g. second copy
; of FAT or place for second sector of MS FAT32 bootloader.
 
; Some constants
FAT16_ROOTDIR_SECTORS = 16 ; can be changed, but why not?
; FAT16:
; 1 bootsector,
; min 0xFF5 sectors for data,
; min (0xFF5*2/512) = 16 sectors per FAT, we use only one copy,
; FAT16_ROOTDIR_SECTORS for root directory
MIN_FAT16_SIZE = 1 + 16 + FAT16_ROOTDIR_SECTORS + 0xFF5
; FAT32:
; 1 bootsector,
; 1 sector for fsinfo,
; min 0xFFF5 sectors for data,
; min (0xFFF5*4/512) = 512 sectors per FAT, we use only one copy
MIN_FAT32_SIZE = 1 + 1 + 512 + 0xFFF5
MAX_SIZE = 1 shl (30 - 9) ; 1G in 512-byte sectors
 
; Initializes FATxx structures on the disk.
; Called with edi = pointer to disk data, esi = size of disk.
proc format_disk
; Determine FAT type and jump to the corresponding handler.
cmp esi, MIN_FAT32_SIZE
jae format_disk_fat32
; Fall through to format_disk_fat16.
endp
 
; Structure of FAT16 bootsector. Field names are from MS spec.
struc FAT16BOOT
{
.BS_jmpBoot rb 3
.BS_OEMName rb 8
.BPB_BytsPerSec dw ?
.BPB_SecsPerClus db ?
.BPB_RsvdSecCnt dw ?
.BPB_NumFATs db ?
.BPB_RootEntCnt dw ?
.BPB_TotSec16 dw ?
.BPB_Media db ?
.BPB_FATSz16 dw ?
.BPB_SecPerTrk dw ?
.BPB_NumHeads dw ?
.BPB_HiddSec dd ?
.BPB_TotSec32 dd ?
.BS_DrvNum db ?
.BS_Reserved1 db ?
.BS_BootSig db ?
.BS_VolID dd ?
.BS_VolLab rb 11
.BS_FilSysType rb 8
}
virtual at 0
FAT16BOOT FAT16BOOT
end virtual
 
; Initializes FAT16 structures on the disk.
; Called with edi = pointer to disk data, esi = size of disk.
format_disk_fat16:
; 1. Calculate number of clusters.
; 1a. There are fixed-sized areas and there are data+FAT;
; every cluster uses 512 bytes in data area and 2 bytes in FAT area.
lea eax, [esi-1-FAT16_ROOTDIR_SECTORS]
; two following lines are equivalent to edx = floor(eax*512/514)
mov ecx, 0xFF00FF01
mul ecx ; edx = number of clusters
; 1b. Force the number be less than 0xfff5.
mov eax, 0xFFF4
cmp edx, eax
jb @f
mov edx, eax
@@:
; 2. Zero all system areas on the disk.
lea ecx, [256*(1+FAT16_ROOTDIR_SECTORS)/2+edx+255]
and ecx, not 255
shr ecx, 1
xor eax, eax
push edi
rep stosd
pop edi
; 3. Generate the bootsector.
; 3a. Copy static stub.
push esi edi
mov esi, fat16bootsector_stub
mov ecx, fat16bootsector_stub_size
rep movsb
pop edi esi
mov word [edi+510], 0xAA55
; 3b. Set fields which depend on size.
cmp esi, 0x10000
jae .size_is_32bit
mov [edi+FAT16BOOT.BPB_TotSec16], si
jmp .size_written
.size_is_32bit:
mov [edi+FAT16BOOT.BPB_TotSec32], esi
.size_written:
lea eax, [edx+255]
shr eax, 8
mov [edi+FAT16BOOT.BPB_FATSz16], ax
; 3c. Generate volume ID.
call generate_volume_id
mov [edi+FAT16BOOT.BS_VolID], eax
; 4. Initialize FAT.
mov dword [edi+512], 0xFFFFFFF8
; 5. Return.
ret
 
; Structure of FAT32 bootsector. Field names are from MS spec.
struc FAT32BOOT
{
.BS_jmpBoot rb 3
.BS_OEMName rb 8
.BPB_BytsPerSec dw ?
.BPB_SecsPerClus db ?
.BPB_RsvdSecCnt dw ?
.BPB_NumFATs db ?
.BPB_RootEntCnt dw ?
.BPB_TotSec16 dw ?
.BPB_Media db ?
.BPB_FATSz16 dw ?
.BPB_SecPerTrk dw ?
.BPB_NumHeads dw ?
.BPB_HiddSec dd ?
.BPB_TotSec32 dd ?
.BPB_FATSz32 dd ?
.BPB_ExtFlags dw ?
.BPB_FSVer dw ?
.BPB_RootClus dd ?
.BPB_FSInfo dw ?
.BPB_BkBootSec dw ?
.BPB_Reserved rb 12
.BS_DrvNum db ?
.BS_Reserved1 db ?
.BS_BootSig db ?
.BS_VolID dd ?
.BS_VolLab rb 11
.BS_FilSysType rb 8
}
virtual at 0
FAT32BOOT FAT32BOOT
end virtual
 
; Initializes FAT32 structures on the disk.
; Called with edi = pointer to disk data, esi = size of disk.
format_disk_fat32:
; 1. Calculate number of clusters.
; 1a. There is fixed-sized area and there are data+FAT;
; every cluster uses 512 bytes in data area and 4 bytes in FAT area.
lea eax, [esi-1-1]
; two following lines are equivalent to edx=floor(eax*512/516) if eax<10000000h
mov ecx, 0xFE03F810
mul ecx ; edx = number of clusters
; 2. Zero all system areas on the disk and first cluster of data,
; used for root directory.
lea ecx, [128*(1+1+1)+edx+127]
and ecx, not 127
xor eax, eax
push edi
rep stosd
pop edi
; 3. Generate the bootsector.
; 3a. Copy static stub.
push esi edi
mov esi, fat32bootsector_stub
mov ecx, fat32bootsector_stub_size
rep movsb
pop edi esi
mov word [edi+510], 0xAA55
; 3b. Set fields which depend on size.
mov [edi+FAT32BOOT.BPB_TotSec32], esi
lea eax, [edx+127]
shr eax, 7
mov [edi+FAT32BOOT.BPB_FATSz32], eax
; 3c. Generate volume ID.
call generate_volume_id
mov [edi+FAT32BOOT.BS_VolID], eax
; 4. Initialize fsinfo sector.
mov dword [edi+512], 'RRaA'
mov dword [edi+512+484], 'rrAa'
dec edx ; one cluster is occupied by root dir
mov dword [edi+512+488], edx ; free count
mov byte [edi+512+492], 3 ; first free cluster
mov word [edi+512+510], 0xAA55
; 5. Initialize FAT.
mov dword [edi+512*2], 0x0FFFFFF8
mov dword [edi+512*2+4], 0x0FFFFFFF
mov dword [edi+512*2+8], 0x0FFFFFFF
; 6. Return.
ret
 
; Generate volume serial number, which should try to be unique for each volume.
; Use CMOS date+time, copy-pasted from fat32.inc.
generate_volume_id:
call get_time_for_file
mov cx, ax
call get_date_for_file
shl eax, 16
mov ax, cx
ret
 
; Three following procedures are copy-pasted from fat32.inc.
bcd2bin:
;----------------------------------
; input : AL=BCD number (eg. 0x11)
; output : AH=0
; AL=decimal number (eg. 11)
;----------------------------------
xor ah, ah
shl ax, 4
shr al, 4
aad
ret
 
get_date_for_file:
;-----------------------------------------------------
; Get date from CMOS and pack day,month,year in AX
; DATE bits 0..4 : day of month 0..31
; 5..8 : month of year 1..12
; 9..15 : count of years from 1980
;-----------------------------------------------------
mov al, 0x7 ;day
out 0x70, al
in al, 0x71
call bcd2bin
ror eax, 5
 
mov al, 0x8 ;month
out 0x70, al
in al, 0x71
call bcd2bin
ror eax, 4
 
mov al, 0x9 ;year
out 0x70, al
in al, 0x71
call bcd2bin
add ax, 20 ;because CMOS return only the two last
;digit (eg. 2000 -> 00 , 2001 -> 01) and we
rol eax, 9 ;need the difference with 1980 (eg. 2001-1980)
ret
 
 
get_time_for_file:
;-----------------------------------------------------
; Get time from CMOS and pack hour,minute,second in AX
; TIME bits 0..4 : second (the low bit is lost)
; 5..10 : minute 0..59
; 11..15 : hour 0..23
;-----------------------------------------------------
mov al, 0x0 ;second
out 0x70, al
in al, 0x71
call bcd2bin
ror eax, 6
 
mov al, 0x2 ;minute
out 0x70, al
in al, 0x71
call bcd2bin
ror eax, 6
 
mov al, 0x4 ;hour
out 0x70, al
in al, 0x71
call bcd2bin
rol eax, 11
ret
 
; some data
fat16bootsector_stub:
db 0EBh, 3Ch, 90h ; BS_jmpBoot
db 'KOLIBRI ' ; BS_OEMName
dw 512 ; BPB_BytsPerSec
db 1 ; BPB_SecsPerClus
dw 1 ; BPB_RsvdSecCnt
db 1 ; BPB_NumFATs
dw FAT16_ROOTDIR_SECTORS*16 ; BPB_RootEntCnt
dw 0 ; BPB_TotSec16, filled in format_disk_fat16
db 0F8h ; BPB_Media
dw 0 ; BPB_FATSz16, filled in format_disk_fat16
dw 32 ; BPB_SecPerTrk
dw 128 ; BPB_NumHeads
dd 0 ; BPB_HiddSec
dd 0 ; BPB_TotSec32, filled in format_disk_fat16
db 80h ; BS_DrvNum
db 0 ; BS_Reserved1
db 29h ; BS_BootSig
dd 0 ; BS_VolID, filled in format_disk_fat16
db 'NO NAME ' ; BS_VolLab
db 'FAT16 ' ; BS_FilSysType
; just in case add some meaningful bytes if someone tries to boot
db 0CDh, 19h, 0EBh, 0FEh ; int 19h, jmp $
fat16bootsector_stub_size = $ - fat16bootsector_stub
fat32bootsector_stub:
db 0EBh, 58h, 90h ; BS_jmpBoot
db 'KOLIBRI ' ; BS_OEMName
dw 512 ; BPB_BytsPerSec
db 1 ; BPB_SecsPerClus
dw 1 ; BPB_RsvdSecCnt
db 1 ; BPB_NumFATs
dw 0 ; BPB_RootEntCnt
dw 0 ; BPB_TotSec16
db 0F8h ; BPB_Media
dw 0 ; BPB_FATSz16
dw 32 ; BPB_SecPerTrk
dw 128 ; BPB_NumHeads
dd 0 ; BPB_HiddSec
dd 0 ; BPB_TotSec32, filled in format_disk_fat32
dd 0 ; BPB_FATSz32, filled in format_disk_fat32
dw 0 ; BPB_ExtFlags
dw 0 ; BPB_FSVer
dd 2 ; BPB_RootClus
dw 1 ; BPB_FSInfo
dw 0 ; BPB_BkBootSec
rb 12 ; BPB_Reserved
db 80h ; BS_DrvNum
db 0 ; BS_Reserved1
db 29h ; BS_BootSig
dd 0 ; BS_VolID, filled in format_disk_fat32
db 'NO NAME ' ; BS_VolLab
db 'FAT32 ' ; BS_FilSysType
; same bytes as in fat16bootsector_stub
db 0CDh, 19h, 0EBh, 0FEh ; int 19h, jmp $
fat32bootsector_stub_size = $ - fat32bootsector_stub
/kernel/branches/Kolibri-acpi/drivers/tmpdisk_work.inc
0,0 → 1,144
; Callbacks which implement tmpdisk-specific disk functions for tmpdisk.asm.
 
; The first argument of every callback is .userdata = userdata arg of AddDisk.
; For tmpdisk, .userdata is the disk id, one of 0,...,max_num_disks-1.
 
DISK_STATUS_OK = 0 ; success
DISK_STATUS_GENERAL_ERROR = -1; if no other code is suitable
DISK_STATUS_INVALID_CALL = 1 ; invalid input parameters
DISK_STATUS_NO_MEDIA = 2 ; no media present
DISK_STATUS_END_OF_MEDIA = 3 ; end of media while reading/writing data
 
; The last function that is called for the given disk. The kernel calls it when
; the kernel has finished all operations with the disk and it is safe to free
; all driver-specific data identified by 'userdata'.
proc tmpdisk_close
virtual at esp+4
.userdata dd ?
end virtual
; Free the memory for disk and zero global variables.
mov edx, [.userdata]
mov [disk_sizes+edx*4], 0
xor eax, eax
xchg eax, [disk_pointers+edx*4]
stdcall KernelFree, eax
retn 4
endp
 
struc DISKMEDIAINFO
{
.flags dd ?
DISK_MEDIA_READONLY = 1
.sectorsize dd ?
.capacity dq ?
}
virtual at 0
DISKMEDIAINFO DISKMEDIAINFO
end virtual
 
; Returns information about disk media.
proc tmpdisk_querymedia
virtual at esp+4
.userdata dd ?
.info dd ?
end virtual
; Media is always present, sector size is always 512 bytes,
; the size of disk in sectors is stored in a global variable.
mov edx, [.userdata]
mov ecx, [.info]
mov [ecx+DISKMEDIAINFO.flags], 0
mov [ecx+DISKMEDIAINFO.sectorsize], 512
mov eax, [disk_sizes+edx*4]
mov dword [ecx+DISKMEDIAINFO.capacity], eax
mov dword [ecx+DISKMEDIAINFO.capacity+4], 0
; Return zero as an indicator of success.
xor eax, eax
retn 8
endp
 
; Reads one or more sectors from the device.
tmpdisk_read:
xor edx, edx ; 0 = reading
jmp tmpdisk_readwrite
 
; Writes one or more sectors to the device.
tmpdisk_write:
mov dl, 1 ; 1 = writing
; Fall through to tmpdisk_readwrite.
 
; Common procedure for reading and writing.
; dl = 0 for reading, dl = 1 for writing.
; Arguments of tmpdisk_read and tmpdisk_write are the same,
; they continue to be stack arguments of this procedure.
proc tmpdisk_readwrite \
userdata:dword, \
buffer:dword, \
start_sector:qword, \
numsectors_ptr:dword
; 1. Save used registers to be stdcall.
push esi edi
mov esi, [userdata]
mov edi, [numsectors_ptr]
; 1. Determine number of sectors to be transferred.
; This is either the requested number of sectors or number of sectors
; up to the disk boundary, depending of what is less.
xor ecx, ecx
; 1a. Test whether [start_sector] is less than [disk_sizes] for selected disk.
; If so, calculate number of sectors between [start_sector] and [disk_sizes].
; Otherwise, the actual number of sectors is zero.
cmp dword [start_sector+4], ecx
jnz .got_number
mov eax, [disk_sizes+esi*4]
sub eax, dword [start_sector]
jbe .got_number
; 1b. Get the requested number of sectors.
mov ecx, [edi]
; 1c. If it is greater than number of sectors calculated in 1a, use the value
; from 1a.
cmp ecx, eax
jb .got_number
mov ecx, eax
.got_number:
; 2. Compare the actual number of sectors with requested. If they are
; equal, set eax (it will be the returned value) to zero. Otherwise,
; use DISK_STATUS_END_OF_MEDIA.
xor eax, eax
cmp ecx, [edi]
jz @f
mov al, DISK_STATUS_END_OF_MEDIA
@@:
; 3. Store the actual number of sectors.
mov [edi], ecx
; 4. Calculate source and destination addresses.
mov edi, dword [start_sector]
shl edi, 9
add edi, [disk_pointers+esi*4]
mov esi, [buffer]
; 5. Calculate number of dwords to be transferred.
shl ecx, 9-2
; 6. Now esi = [buffer], edi = pointer inside disk.
; This is normal for write operations;
; exchange esi and edi for read operations.
test dl, dl
jnz @f
xchg esi, edi
@@:
; 7. Copy data.
rep movsd
; 8. Restore used registers to be stdcall and return.
; The value in eax was calculated in step 2.
pop edi esi
ret
endp
 
; The kernel calls this function when initializing cache subsystem for
; the media. This call allows the driver to adjust the cache size.
proc tmpdisk_adjust_cache_size
virtual at esp+4
.userdata dd ?
.suggested_size dd ?
end virtual
; Since tmpdisk does not need cache, just return 0.
xor eax, eax
retn 8
endp