/kernel/branches/Kolibri-acpi/blkdev/disk.inc |
---|
349,10 → 349,8 |
inc eax |
cmp byte [ebx+eax-1], 0 |
jnz @b |
; 2b. Call the heap manager. Note that it can change ebx. |
push ebx |
; 2b. Call the heap manager. |
call malloc |
pop ebx |
; 2c. Check the result. If allocation failed, go to 7. |
pop esi ; restore allocated pointer to DISK |
test eax, eax |
/kernel/branches/Kolibri-acpi/blkdev/hd_drv.inc |
---|
11,7 → 11,8 |
; Low-level driver for HDD access |
; DMA support by Mario79 |
; Access through BIOS by diamond |
; LBA48 support by Mario79 |
;----------------------------------------------------------------------------- |
align 4 |
hd_read: |
;----------------------------------------------------------- |
21,8 → 22,6 |
and [hd_error], 0 |
push ecx esi edi ; scan cache |
; mov ecx,cache_max ; entries in cache |
; mov esi,HD_CACHE+8 |
call calculate_cache |
add esi, 8 |
29,7 → 28,6 |
mov edi, 1 |
hdreadcache: |
cmp dword [esi+4], 0; empty |
je nohdcache |
37,7 → 35,6 |
je yeshdcache |
nohdcache: |
add esi, 8 |
inc edi |
dec ecx |
49,12 → 46,6 |
; Read through BIOS? |
cmp [hdpos], 0x80 |
jae .bios |
; hd_read_{dma,pio} use old ATA with 28 bit for sector number |
cmp eax, 0x10000000 |
jb @f |
inc [hd_error] |
jmp return_01 |
@@: |
; DMA read is permitted if [allow_dma_access]=1 or 2 |
cmp [allow_dma_access], 2 |
ja .nodma |
70,20 → 61,17 |
@@: |
cmp [hd_error], 0 |
jne return_01 |
; lea esi,[edi*8+HD_CACHE] |
; push eax |
call calculate_cache_1 |
lea esi, [edi*8+esi] |
; pop eax |
mov [esi], eax ; sector number |
mov dword [esi+4], 1; hd read - mark as same as in hd |
yeshdcache: |
mov esi, edi |
shl esi, 9 |
; add esi,HD_CACHE+65536 |
push eax |
call calculate_cache_2 |
add esi, eax |
93,18 → 81,33 |
mov ecx, 512/4 |
cld |
rep movsd ; move data |
return_01: |
pop edi esi ecx |
ret |
;----------------------------------------------------------------------------- |
align 4 |
hd_read_pio: |
push eax edx |
; Select the desired drive |
mov edx, [hdbase] |
add edx, 6 ;адрес регистра головок |
mov al, byte [hdid] |
add al, 128+64+32 |
out dx, al; номер головки/номер диска |
call wait_for_hd_idle |
cmp [hd_error], 0 |
jne hd_read_error |
; ATA with 28 or 48 bit for sector number? |
mov eax, [esp+4] |
cmp eax, 0x10000000 |
jae .lba48 |
;-------------------------------------- |
.lba28: |
pushfd |
cli |
xor eax, eax |
mov edx, [hdbase] |
112,36 → 115,78 |
out dx, al; ATAFeatures регистр "особенностей" |
inc edx |
inc eax |
out dx, al; ATASectorCount счётчик секторов |
out dx, al ; ATA Sector Counter счётчик секторов |
inc edx |
mov eax, [esp+4] |
out dx, al; ATASectorNumber регистр номера сектора |
mov eax, [esp+4+4] |
out dx, al ; LBA Low LBA (7:0) |
shr eax, 8 |
inc edx |
out dx, al; ATACylinder номер цилиндра (младший байт) |
out dx, al ; LBA Mid LBA (15:8) |
shr eax, 8 |
inc edx |
out dx, al; номер цилиндра (старший байт) |
out dx, al ; LBA High LBA (23:16) |
shr eax, 8 |
inc edx |
and al, 1+2+4+8 |
and al, 1+2+4+8 ; LBA (27:24) |
add al, byte [hdid] |
add al, 128+64+32 |
out dx, al; номер головки/номер диска |
inc edx |
mov al, 20h |
mov al, 20h ; READ SECTOR(S) |
out dx, al; ATACommand регистр команд |
sti |
popfd |
jmp .continue |
;-------------------------------------- |
.lba48: |
pushfd |
cli |
xor eax, eax |
mov edx, [hdbase] |
inc edx |
out dx, al ; Features Previous Reserved |
out dx, al ; Features Current Reserved |
inc edx |
out dx, al ; Sector Count Previous Sector count (15:8) |
inc eax |
out dx, al ; Sector Count Current Sector count (7:0) |
inc edx |
mov eax, [esp+4+4] |
rol eax, 8 |
out dx, al ; LBA Low Previous LBA (31:24) |
xor eax, eax ; because only 32 bit cache |
inc edx |
out dx, al ; LBA Mid Previous LBA (39:32) |
inc edx |
out dx, al ; LBA High Previous LBA (47:40) |
sub edx, 2 |
mov eax, [esp+4+4] |
out dx, al ; LBA Low Current LBA (7:0) |
shr eax, 8 |
inc edx |
out dx, al ; LBA Mid Current LBA (15:8) |
shr eax, 8 |
inc edx |
out dx, al ; LBA High Current LBA (23:16) |
inc edx |
mov al, byte [hdid] |
add al, 128+64+32 |
out dx, al ; номер головки/номер диска |
inc edx |
mov al, 24h ; READ SECTOR(S) EXT |
out dx, al ; ATACommand регистр команд |
popfd |
;-------------------------------------- |
.continue: |
call wait_for_sector_buffer |
cmp [hd_error], 0 |
jne hd_read_error |
pushfd |
cli |
push edi |
shl edi, 9 |
; add edi,HD_CACHE+65536 |
push eax |
call calculate_cache_2 |
add edi, eax |
152,27 → 197,11 |
cld |
rep insw |
pop edi |
sti |
popfd |
pop edx eax |
ret |
disable_ide_int: |
; mov edx,[hdbase] |
; add edx,0x206 |
; mov al,2 |
; out dx,al |
cli |
ret |
enable_ide_int: |
; mov edx,[hdbase] |
; add edx,0x206 |
; mov al,0 |
; out dx,al |
sti |
ret |
;----------------------------------------------------------------------------- |
align 4 |
hd_write: |
;----------------------------------------------------------- |
182,16 → 211,11 |
push ecx esi edi |
; check if the cache already has the sector and overwrite it |
; mov ecx,cache_max |
; mov esi,HD_CACHE+8 |
call calculate_cache |
add esi, 8 |
mov edi, 1 |
hdwritecache: |
cmp dword [esi+4], 0; if cache slot is empty |
je not_in_cache_write |
199,7 → 223,6 |
je yes_in_cache_write |
not_in_cache_write: |
add esi, 8 |
inc edi |
dec ecx |
207,25 → 230,19 |
; sector not found in cache |
; write the block to a new location |
call find_empty_slot ; ret in edi |
cmp [hd_error], 0 |
jne hd_write_access_denied |
; lea esi,[edi*8+HD_CACHE] |
; push eax |
call calculate_cache_1 |
lea esi, [edi*8+esi] |
; pop eax |
mov [esi], eax ; sector number |
yes_in_cache_write: |
mov dword [esi+4], 2; write - differs from hd |
shl edi, 9 |
; add edi,HD_CACHE+65536 |
push eax |
call calculate_cache_2 |
add edi, eax |
235,48 → 252,100 |
mov ecx, 512/4 |
cld |
rep movsd ; move data |
hd_write_access_denied: |
pop edi esi ecx |
ret |
;----------------------------------------------------------------------------- |
align 4 |
cache_write_pio: |
cmp dword[esi], 0x10000000 |
jae .bad |
; call disable_ide_int |
; Select the desired drive |
mov edx, [hdbase] |
add edx, 6 ;адрес регистра головок |
mov al, byte [hdid] |
add al, 128+64+32 |
out dx, al ; номер головки/номер диска |
call wait_for_hd_idle |
cmp [hd_error], 0 |
jne hd_write_error |
; ATA with 28 or 48 bit for sector number? |
mov eax, [esi] |
cmp eax, 0x10000000 |
jae .lba48 |
;-------------------------------------- |
.lba28: |
pushfd |
cli |
xor eax, eax |
mov edx, [hdbase] |
inc edx |
out dx, al |
out dx, al ; ATA Features регистр "особенностей" |
inc edx |
inc eax |
out dx, al |
out dx, al ; ATA Sector Counter счётчик секторов |
inc edx |
mov eax, [esi] ; eax = sector to write |
out dx, al |
out dx, al ; LBA Low LBA (7:0) |
shr eax, 8 |
inc edx |
out dx, al |
out dx, al ; LBA Mid LBA (15:8) |
shr eax, 8 |
inc edx |
out dx, al |
out dx, al ; LBA High LBA (23:16) |
shr eax, 8 |
inc edx |
and al, 1+2+4+8 |
and al, 1+2+4+8 ; LBA (27:24) |
add al, byte [hdid] |
add al, 128+64+32 |
out dx, al |
out dx, al ; номер головки/номер диска |
inc edx |
mov al, 30h |
out dx, al |
sti |
mov al, 30h ; WRITE SECTOR(S) |
out dx, al ; ATACommand регистр команд |
popfd |
jmp .continue |
;-------------------------------------- |
.lba48: |
pushfd |
cli |
xor eax, eax |
mov edx, [hdbase] |
inc edx |
out dx, al ; Features Previous Reserved |
out dx, al ; Features Current Reserved |
inc edx |
out dx, al ; Sector Count Previous Sector count (15:8) |
inc eax |
out dx, al ; Sector Count Current Sector count (7:0) |
inc edx |
mov eax, [esi] |
rol eax, 8 |
out dx, al ; LBA Low Previous LBA (31:24) |
xor eax, eax ; because only 32 bit cache |
inc edx |
out dx, al ; LBA Mid Previous LBA (39:32) |
inc edx |
out dx, al ; LBA High Previous LBA (47:40) |
sub edx, 2 |
mov eax, [esi] |
out dx, al ; LBA Low Current LBA (7:0) |
shr eax, 8 |
inc edx |
out dx, al ; LBA Mid Current LBA (15:8) |
shr eax, 8 |
inc edx |
out dx, al ; LBA High Current LBA (23:16) |
inc edx |
mov al, byte [hdid] |
add al, 128+64+32 |
out dx, al ; номер головки/номер диска |
inc edx |
mov al, 34h ; WRITE SECTOR(S) EXT |
out dx, al ; ATACommand регистр команд |
popfd |
;-------------------------------------- |
.continue: |
call wait_for_sector_buffer |
cmp [hd_error], 0 |
284,10 → 353,11 |
push ecx esi |
pushfd |
cli |
mov esi, edi |
shl esi, 9 |
; add esi,HD_CACHE+65536 ; esi = from memory position |
push eax |
call calculate_cache_2 |
add esi, eax |
297,18 → 367,13 |
mov edx, [hdbase] |
cld |
rep outsw |
sti |
popfd |
; call enable_ide_int |
pop esi ecx |
ret |
.bad: |
inc [hd_error] |
ret |
;----------------------------------------------------------------------------- |
align 4 |
save_hd_wait_timeout: |
push eax |
mov eax, [timer_ticks] |
add eax, 300 ; 3 sec timeout |
315,47 → 380,29 |
mov [hd_wait_timeout], eax |
pop eax |
ret |
;----------------------------------------------------------------------------- |
align 4 |
check_hd_wait_timeout: |
push eax |
mov eax, [hd_wait_timeout] |
cmp [timer_ticks], eax |
jg hd_timeout_error |
pop eax |
mov [hd_error], 0 |
ret |
;iglobal |
; hd_timeout_str db 'K : FS - HD timeout',0 |
; hd_read_str db 'K : FS - HD read error',0 |
; hd_write_str db 'K : FS - HD write error',0 |
; hd_lba_str db 'K : FS - HD LBA error',0 |
;endg |
;----------------------------------------------------------------------------- |
hd_timeout_error: |
; call clear_hd_cache |
; call clear_application_table_status |
; mov esi,hd_timeout_str |
; call sys_msg_board_str |
if lang eq sp |
DEBUGF 1,"K : FS - HD tiempo de espera agotado\n" |
else |
DEBUGF 1,"K : FS - HD timeout\n" |
end if |
mov [hd_error], 1 |
pop eax |
ret |
;----------------------------------------------------------------------------- |
hd_read_error: |
; call clear_hd_cache |
; call clear_application_table_status |
; mov esi,hd_read_str |
; call sys_msg_board_str |
if lang eq sp |
DEBUGF 1,"K : FS - HD error de lectura\n" |
else |
363,13 → 410,10 |
end if |
pop edx eax |
ret |
;----------------------------------------------------------------------------- |
hd_write_error_dma: |
pop esi |
hd_write_error: |
; call clear_hd_cache |
; call clear_application_table_status |
; mov esi,hd_write_str |
; call sys_msg_board_str |
if lang eq sp |
DEBUGF 1,"K : FS - HD error de escritura\n" |
else |
376,25 → 420,8 |
DEBUGF 1,"K : FS - HD write error\n" |
end if |
ret |
hd_write_error_dma: |
; call clear_hd_cache |
; call clear_application_table_status |
; mov esi, hd_write_str |
; call sys_msg_board_str |
if lang eq sp |
DEBUGF 1,"K : FS - HD error de escritura\n" |
else |
DEBUGF 1,"K : FS - HD write error\n" |
end if |
pop esi |
ret |
;----------------------------------------------------------------------------- |
hd_lba_error: |
; call clear_hd_cache |
; call clear_application_table_status |
; mov esi,hd_lba_str |
; call sys_msg_board_str |
if lang eq sp |
DEBUGF 1,"K : FS - HD error en LBA\n" |
else |
401,11 → 428,9 |
DEBUGF 1,"K : FS - HD LBA error\n" |
end if |
jmp LBA_read_ret |
;----------------------------------------------------------------------------- |
align 4 |
wait_for_hd_idle: |
push eax edx |
call save_hd_wait_timeout |
412,9 → 437,9 |
mov edx, [hdbase] |
add edx, 0x7 |
;-------------------------------------- |
align 4 |
wfhil1: |
call check_hd_wait_timeout |
cmp [hd_error], 0 |
jne @f |
424,14 → 449,11 |
jnz wfhil1 |
@@: |
pop edx eax |
ret |
;----------------------------------------------------------------------------- |
align 4 |
wait_for_sector_buffer: |
push eax edx |
mov edx, [hdbase] |
438,9 → 460,9 |
add edx, 0x7 |
call save_hd_wait_timeout |
;-------------------------------------- |
align 4 |
hdwait_sbuf: ; wait for sector buffer to be ready |
call check_hd_wait_timeout |
cmp [hd_error], 0 |
jne @f |
460,16 → 482,16 |
mov [hd_error], 1 |
buf_wait_ok: |
pop edx eax |
ret |
; \begin{Mario79} |
;----------------------------------------------------------------------------- |
align 4 |
wait_for_sector_dma_ide0: |
push eax |
push edx |
call save_hd_wait_timeout |
;-------------------------------------- |
align 4 |
.wait: |
call change_task |
cmp [irq14_func], hdd_irq14 |
485,12 → 507,14 |
pop edx |
pop eax |
ret |
;----------------------------------------------------------------------------- |
align 4 |
wait_for_sector_dma_ide1: |
push eax |
push edx |
call save_hd_wait_timeout |
;-------------------------------------- |
align 4 |
.wait: |
call change_task |
cmp [irq15_func], hdd_irq15 |
507,7 → 531,7 |
pop edx |
pop eax |
ret |
;----------------------------------------------------------------------------- |
iglobal |
align 4 |
; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary |
521,7 → 545,7 |
irq14_func dd hdd_irq_null |
irq15_func dd hdd_irq_null |
endg |
;----------------------------------------------------------------------------- |
uglobal |
; all uglobals are zeroed at boot |
dma_process dd 0 |
534,7 → 558,7 |
dma_hdd db 0 |
allow_dma_access db 0 |
endg |
;----------------------------------------------------------------------------- |
align 4 |
hdd_irq14: |
pushfd |
544,27 → 568,12 |
mov dx, [IDEContrRegsBaseAddr] |
mov al, 0 |
out dx, al |
; call update_counters |
; mov ebx, [dma_process] |
; cmp [CURRENT_TASK], ebx |
; jz .noswitch |
; mov [dma_task_switched], 1 |
; mov edi, [dma_slot_ptr] |
; mov eax, [CURRENT_TASK] |
; mov [dma_process], eax |
; mov eax, [TASK_BASE] |
; mov [dma_slot_ptr], eax |
; mov [CURRENT_TASK], ebx |
; mov [TASK_BASE], edi |
; mov byte [DONT_SWITCH], 1 |
; call do_change_task |
.noswitch: |
popad |
popfd |
align 4 |
hdd_irq_null: |
ret |
;----------------------------------------------------------------------------- |
align 4 |
hdd_irq15: |
pushfd |
575,25 → 584,10 |
add dx, 8 |
mov al, 0 |
out dx, al |
; call update_counters |
; mov ebx, [dma_process] |
; cmp [CURRENT_TASK], ebx |
; jz .noswitch |
; mov [dma_task_switched], 1 |
; mov edi, [dma_slot_ptr] |
; mov eax, [CURRENT_TASK] |
; mov [dma_process], eax |
; mov eax, [TASK_BASE] |
; mov [dma_slot_ptr], eax |
; mov [CURRENT_TASK], ebx |
; mov [TASK_BASE], edi |
; mov byte [DONT_SWITCH], 1 |
; call do_change_task |
.noswitch: |
popad |
popfd |
ret |
;----------------------------------------------------------------------------- |
align 4 |
hd_read_dma: |
push eax |
614,7 → 608,7 |
push ecx esi edi |
mov esi, eax |
shl edi, 9 |
; add edi, HD_CACHE+0x10000 |
push eax |
call calculate_cache_2 |
add edi, eax |
646,37 → 640,97 |
add edx, 2 |
mov al, 6 |
out dx, al |
; Select the desired drive |
mov edx, [hdbase] |
add edx, 6 ; адрес регистра головок |
mov al, byte [hdid] |
add al, 128+64+32 |
out dx, al ; номер головки/номер диска |
call wait_for_hd_idle |
cmp [hd_error], 0 |
jnz hd_read_error |
call disable_ide_int |
; ATA with 28 or 48 bit for sector number? |
mov eax, [esp+4] |
; -10h because the PreCache hits the boundary between lba28 and lba48 |
; 10h = 16 - size of PreCache |
cmp eax, 0x10000000-10h |
jae .lba48 |
;-------------------------------------- |
.lba28: |
pushfd |
cli |
xor eax, eax |
mov edx, [hdbase] |
inc edx |
out dx, al |
out dx, al ; ATA Features регистр "особенностей" |
inc edx |
mov eax, 10h |
out dx, al |
mov eax, 10h ; Sector Counter = 16 ; PreCache |
out dx, al ; ATA Sector Counter счётчик секторов |
inc edx |
mov eax, [esp+4] |
out dx, al |
mov eax, [esp+4+4] |
out dx, al ; LBA Low LBA (7:0) |
shr eax, 8 |
inc edx |
out dx, al |
out dx, al ; LBA Mid LBA (15:8) |
shr eax, 8 |
inc edx |
out dx, al |
out dx, al ; LBA High LBA (23:16) |
shr eax, 8 |
inc edx |
and al, 0xF |
and al, 0xF ; LBA (27:24) |
add al, byte [hdid] |
add al, 11100000b |
out dx, al |
out dx, al ; номер головки/номер диска |
inc edx |
mov al, 0xC8 |
out dx, al |
mov al, 0xC8 ; READ DMA |
out dx, al ; ATACommand регистр команд |
jmp .continue |
;-------------------------------------- |
.lba48: |
pushfd |
cli |
xor eax, eax |
mov edx, [hdbase] |
inc edx |
out dx, al ; Features Previous Reserved |
out dx, al ; Features Current Reserved |
inc edx |
out dx, al ; Sector Count Previous Sector count (15:8) |
mov eax, 10h ; Sector Counter = 16 PreCache |
out dx, al ; Sector Count Current Sector count (7:0) |
inc edx |
mov eax, [esp+4+4] |
rol eax, 8 |
out dx, al ; LBA Low Previous LBA (31:24) |
xor eax, eax ; because only 32 bit cache |
inc edx |
out dx, al ; LBA Mid Previous LBA (39:32) |
inc edx |
out dx, al ; LBA High Previous LBA (47:40) |
sub edx, 2 |
mov eax, [esp+4+4] |
out dx, al ; LBA Low Current LBA (7:0) |
shr eax, 8 |
inc edx |
out dx, al ; LBA Mid Current LBA (15:8) |
shr eax, 8 |
inc edx |
out dx, al ; LBA High Current LBA (23:16) |
inc edx |
mov al, byte [hdid] |
add al, 128+64+32 |
out dx, al ; номер головки/номер диска |
inc edx |
mov al, 25h ; READ DMA EXT |
out dx, al ; ATACommand регистр команд |
;-------------------------------------- |
.continue: |
mov dx, [IDEContrRegsBaseAddr] |
cmp [hdbase], 0x1F0 |
mov eax, [hd_address_table] |
cmp [hdbase], eax ; 0x1F0 |
jz @f |
add dx, 8 |
@@: |
686,7 → 740,8 |
mov [dma_process], eax |
mov eax, [TASK_BASE] |
mov [dma_slot_ptr], eax |
cmp [hdbase], 0x1F0 |
mov eax, [hd_address_table] |
cmp [hdbase], eax ; 0x1F0 |
jnz .ide1 |
mov [irq14_func], hdd_irq14 |
jmp @f |
693,8 → 748,9 |
.ide1: |
mov [irq15_func], hdd_irq15 |
@@: |
call enable_ide_int |
cmp [hdbase], 0x1F0 |
popfd |
mov eax, [hd_address_table] |
cmp [hdbase], eax ; 0x1F0 |
jnz .wait_ide1 |
call wait_for_sector_dma_ide0 |
jmp @f |
709,17 → 765,17 |
pop eax |
mov [dma_cur_sector], eax |
jmp hd_read_dma |
;----------------------------------------------------------------------------- |
align 4 |
write_cache_sector: |
mov [cache_chain_size], 1 |
mov [cache_chain_pos], edi |
;-------------------------------------- |
align 4 |
write_cache_chain: |
cmp [hdpos], 0x80 |
jae bd_write_cache_chain |
mov eax, [cache_chain_ptr] |
cmp dword[eax], 0x10000000 |
jae .bad |
push esi |
mov eax, IDE_descriptor_table |
mov edx, eax |
752,38 → 808,98 |
add edx, 2 |
mov al, 6 |
out dx, al |
; Select the desired drive |
mov edx, [hdbase] |
add edx, 6 ; адрес регистра головок |
mov al, byte [hdid] |
add al, 128+64+32 |
out dx, al ; номер головки/номер диска |
call wait_for_hd_idle |
cmp [hd_error], 0 |
jnz hd_write_error_dma |
call disable_ide_int |
; ATA with 28 or 48 bit for sector number? |
mov esi, [cache_chain_ptr] |
mov eax, [esi] |
; -40h because the PreCache hits the boundary between lba28 and lba48 |
; 40h = 64 - the maximum number of sectors to be written for one command |
cmp eax, 0x10000000-40h |
jae .lba48 |
;-------------------------------------- |
.lba28: |
pushfd |
cli |
xor eax, eax |
mov edx, [hdbase] |
inc edx |
out dx, al |
out dx, al ; ATA Features регистр "особенностей" |
inc edx |
mov al, [cache_chain_size] |
out dx, al |
mov al, [cache_chain_size] ; Sector Counter |
out dx, al ; ATA Sector Counter счётчик секторов |
inc edx |
mov esi, [cache_chain_ptr] |
mov eax, [esi] |
out dx, al |
out dx, al ; LBA Low LBA (7:0) |
shr eax, 8 |
inc edx |
out dx, al |
out dx, al ; LBA Mid LBA (15:8) |
shr eax, 8 |
inc edx |
out dx, al |
out dx, al ; LBA High LBA (23:16) |
shr eax, 8 |
inc edx |
and al, 0xF |
and al, 0xF ; LBA (27:24) |
add al, byte [hdid] |
add al, 11100000b |
out dx, al |
out dx, al ; номер головки/номер диска |
inc edx |
mov al, 0xCA |
out dx, al |
mov al, 0xCA ; WRITE DMA |
out dx, al ; ATACommand регистр команд |
jmp .continue |
;-------------------------------------- |
.lba48: |
pushfd |
cli |
xor eax, eax |
mov edx, [hdbase] |
inc edx |
out dx, al ; Features Previous Reserved |
out dx, al ; Features Current Reserved |
inc edx |
out dx, al ; Sector Count Previous Sector count (15:8) |
mov al, [cache_chain_size] ; Sector Counter |
out dx, al ; Sector Count Current Sector count (7:0) |
inc edx |
mov eax, [esi] |
rol eax, 8 |
out dx, al ; LBA Low Previous LBA (31:24) |
xor eax, eax ; because only 32 bit cache |
inc edx |
out dx, al ; LBA Mid Previous LBA (39:32) |
inc edx |
out dx, al ; LBA High Previous LBA (47:40) |
sub edx, 2 |
mov eax, [esi] |
out dx, al ; LBA Low Current LBA (7:0) |
shr eax, 8 |
inc edx |
out dx, al ; LBA Mid Current LBA (15:8) |
shr eax, 8 |
inc edx |
out dx, al ; LBA High Current LBA (23:16) |
inc edx |
mov al, byte [hdid] |
add al, 128+64+32 |
out dx, al ; номер головки/номер диска |
inc edx |
mov al, 35h ; WRITE DMA EXT |
out dx, al ; ATACommand регистр команд |
;-------------------------------------- |
.continue: |
mov dx, [IDEContrRegsBaseAddr] |
cmp [hdbase], 0x1F0 |
mov eax, [hd_address_table] |
cmp [hdbase], eax ; 0x1F0 |
jz @f |
add dx, 8 |
@@: |
793,7 → 909,8 |
mov [dma_process], eax |
mov eax, [TASK_BASE] |
mov [dma_slot_ptr], eax |
cmp [hdbase], 0x1F0 |
mov eax, [hd_address_table] |
cmp [hdbase], eax ; 0x1F0 |
jnz .ide1 |
mov [irq14_func], hdd_irq14 |
jmp @f |
800,9 → 917,10 |
.ide1: |
mov [irq15_func], hdd_irq15 |
@@: |
call enable_ide_int |
popfd |
mov [dma_cur_sector], not 0x40 |
cmp [hdbase], 0x1F0 |
mov eax, [hd_address_table] |
cmp [hdbase], eax ; 0x1F0 |
jnz .wait_ide1 |
call wait_for_sector_dma_ide0 |
jmp @f |
813,15 → 931,16 |
jnz hd_write_error_dma |
pop esi |
ret |
.bad: |
inc [hd_error] |
ret |
;----------------------------------------------------------------------------- |
uglobal |
IDEContrRegsBaseAddr dw ? |
IDEContrProgrammingInterface dw ? |
IDE_BAR0_val dw ? |
IDE_BAR1_val dw ? |
IDE_BAR2_val dw ? |
IDE_BAR3_val dw ? |
endg |
; \end{Mario79} |
;----------------------------------------------------------------------------- |
; \begin{diamond} |
uglobal |
bios_hdpos dd 0 ; 0 is invalid value for [hdpos] |
828,6 → 947,8 |
bios_cur_sector dd ? |
bios_read_len dd ? |
endg |
;----------------------------------------------------------------------------- |
align 4 |
bd_read: |
push eax |
push edx |
847,7 → 968,7 |
push ecx esi edi |
mov esi, eax |
shl edi, 9 |
; add edi, HD_CACHE+0x10000 |
push eax |
call calculate_cache_2 |
add edi, eax |
881,7 → 1002,8 |
.v86err: |
mov [hd_error], 1 |
jmp hd_read_error |
;----------------------------------------------------------------------------- |
align 4 |
bd_write_cache_chain: |
pusha |
mov esi, [cache_chain_pos] |
909,12 → 1031,13 |
popa |
mov [hd_error], 1 |
jmp hd_write_error |
;----------------------------------------------------------------------------- |
uglobal |
int13_regs_in rb sizeof.v86_regs |
int13_regs_out rb sizeof.v86_regs |
endg |
;----------------------------------------------------------------------------- |
align 4 |
int13_call: |
; Because this code uses fixed addresses, |
; it can not be run simultaniously by many threads. |
965,9 → 1088,9 |
@@: |
ret |
; \end{diamond} |
;----------------------------------------------------------------------------- |
align 4 |
reserve_hd1: |
cli |
cmp [hd1_status], 0 |
je reserve_ok1 |
977,7 → 1100,6 |
jmp reserve_hd1 |
reserve_ok1: |
push eax |
mov eax, [CURRENT_TASK] |
shl eax, 5 |
986,12 → 1108,12 |
pop eax |
sti |
ret |
;******************************************** |
;----------------------------------------------------------------------------- |
uglobal |
hd_in_cache db ? |
endg |
;----------------------------------------------------------------------------- |
align 4 |
reserve_hd_channel: |
; BIOS disk accesses are protected with common mutex hd1_status |
; This must be modified when hd1_status will not be valid! |
1030,7 → 1152,7 |
sti |
.ret: |
ret |
;----------------------------------------------------------------------------- |
free_hd_channel: |
; see comment at reserve_hd_channel |
cmp [hdpos], 0x80 |
1044,4 → 1166,4 |
.IDE_Channel_2: |
mov [IDE_Channel_2], 0 |
ret |
;******************************************** |
;----------------------------------------------------------------------------- |
/kernel/branches/Kolibri-acpi/blkdev/ide_cache.inc |
---|
136,14 → 136,7 |
ret |
;-------------------------------------------------------------------- |
align 4 |
clear_hd_cache: |
ret |
;-------------------------------------------------------------------- |
align 4 |
calculate_cache: |
; mov ecx,cache_max ; entries in cache |
; mov esi,HD_CACHE+8 |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [hdpos], 1 |
221,7 → 214,6 |
;-------------------------------------------------------------------- |
align 4 |
calculate_cache_1: |
; lea esi,[edi*8+HD_CACHE] |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [hdpos], 1 |
290,7 → 282,6 |
;-------------------------------------------------------------------- |
align 4 |
calculate_cache_2: |
; add esi,HD_CACHE+65536 |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [hdpos], 1 |
644,9 → 635,6 |
;-------------------------------------------------------------------- |
align 4 |
cd_calculate_cache: |
; mov ecx,cache_max ; entries in cache |
; mov esi,HD_CACHE+8 |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [cdpos], 1 |
697,7 → 685,6 |
;-------------------------------------------------------------------- |
align 4 |
cd_calculate_cache_1: |
; lea esi,[edi*8+HD_CACHE] |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [cdpos], 1 |
740,7 → 727,6 |
;-------------------------------------------------------------------- |
align 4 |
cd_calculate_cache_2: |
; add esi,HD_CACHE+65536 |
; 1 - IDE0 ... 4 - IDE3 |
.ide0: |
cmp [cdpos], 1 |
/kernel/branches/Kolibri-acpi/boot/bootcode.inc |
---|
387,7 → 387,12 |
push 0 |
pop es |
and word [es:BOOT_IDE_BASE_ADDR], 0 |
xor ax, ax |
and word [es:BOOT_IDE_BASE_ADDR], ax ;0 |
and word [es:BOOT_IDE_BAR0_16], ax ;0 |
and word [es:BOOT_IDE_BAR1_16], ax ;0 |
and word [es:BOOT_IDE_BAR2_16], ax ;0 |
and word [es:BOOT_IDE_BAR3_16], ax ;0 |
; \begin{Mario79} |
; find HDD IDE DMA PCI device |
; check for PCI BIOS |
400,14 → 405,17 |
; class 1 = mass storage |
; subclass 1 = IDE controller |
; a) class 1, subclass 1, programming interface 0x80 |
; This is a Parallel IDE Controller which uses IRQs 14 and 15. |
mov ax, 0xB103 |
mov ecx, 1*10000h + 1*100h + 0x80 |
mov [es:BOOT_IDE_PI_16], cx |
xor si, si ; device index = 0 |
int 0x1A |
jnc .found |
; b) class 1, subclass 1, programming interface 0x8A |
jnc .found_1 ; Parallel IDE Controller |
; b) class 1, subclass 1, programming interface 0x8f |
mov ax, 0xB103 |
mov ecx, 1*10000h + 1*100h + 0x8A |
mov ecx, 1*10000h + 1*100h + 0x8f |
mov [es:BOOT_IDE_PI_16], cx |
xor si, si ; device index = 0 |
int 0x1A |
jnc .found |
414,17 → 422,68 |
; c) class 1, subclass 1, programming interface 0x85 |
mov ax, 0xB103 |
mov ecx, 1*10000h + 1*100h + 0x85 |
xor si, si |
mov [es:BOOT_IDE_PI_16], cx |
xor si, si ; device index = 0 |
int 0x1A |
jc .nopci |
.found: |
; get memory base |
jnc .found |
; d) class 1, subclass 1, programming interface 0x8A |
; This is a Parallel IDE Controller which uses IRQs 14 and 15. |
mov ax, 0xB103 |
mov ecx, 1*10000h + 1*100h + 0x8A |
mov [es:BOOT_IDE_PI_16], cx |
xor si, si ; device index = 0 |
int 0x1A |
jnc .found_1 ; Parallel IDE Controller |
jmp .nopci |
.found_1: |
; get memory base BAR4 |
mov ax, 0xB10A |
mov di, 0x20 ; memory base is config register at 0x20 |
push cx |
int 0x1A |
jc .nopci |
jc .no_BAR4 ;.nopci |
and cx, 0xFFF0 ; clear address decode type |
mov [es:BOOT_IDE_BASE_ADDR], cx |
.no_BAR4: |
pop cx |
.found: |
; get memory base BAR0 |
mov ax, 0xB10A |
mov di, 0x10 ; memory base is config register at 0x10 |
push cx |
int 0x1A |
jc .no_BAR0 ;.nopci |
mov [es:BOOT_IDE_BAR0_16], cx |
.no_BAR0: |
pop cx |
; get memory base BAR1 |
mov ax, 0xB10A |
mov di, 0x14 ; memory base is config register at 0x14 |
push cx |
int 0x1A |
jc .no_BAR1 ;.nopci |
mov [es:BOOT_IDE_BAR1_16], cx |
.no_BAR1: |
pop cx |
; get memory base BAR2 |
mov ax, 0xB10A |
mov di, 0x18 ; memory base is config register at 0x18 |
push cx |
int 0x1A |
jc .no_BAR2 ;.nopci |
mov [es:BOOT_IDE_BAR2_16], cx |
.no_BAR2: |
pop cx |
; get memory base BAR3 |
mov ax, 0xB10A |
mov di, 0x1C ; memory base is config register at 0x1c |
push cx |
int 0x1A |
jc .no_BAR3 ;.nopci |
mov [es:BOOT_IDE_BAR3_16], cx |
.no_BAR3: |
pop cx |
.nopci: |
; \end{Mario79} |
550,8 → 609,8 |
; following 4 lines set variables to 1 if its current value is 0 |
cmp byte [di+preboot_dma-preboot_device], 1 |
adc byte [di+preboot_dma-preboot_device], 0 |
cmp byte [di+preboot_biosdisk-preboot_device], 1 |
adc byte [di+preboot_biosdisk-preboot_device], 0 |
; cmp byte [di+preboot_biosdisk-preboot_device], 1 |
; adc byte [di+preboot_biosdisk-preboot_device], 0 |
;; default value for VRR is OFF |
; cmp byte [di+preboot_vrrm-preboot_device], 0 |
; jnz @f |
/kernel/branches/Kolibri-acpi/bus/usb/ehci.inc |
---|
81,27 → 81,21 |
; * The hardware requires 32-bytes alignment of the hardware part, so |
; the entire descriptor must be 32-bytes aligned. Since the allocator |
; (usb_allocate_common) allocates memory sequentially from page start |
; (aligned on 0x1000 bytes), size of the structure must be divisible by 32. |
; (aligned on 0x1000 bytes), block size for the allocator must be divisible |
; by 32; ehci_alloc_td ensures this. |
; * The hardware also requires that the hardware part must not cross page |
; boundary; the allocator satisfies this automatically. |
struct ehci_gtd ehci_hardware_td |
Flags dd ? |
; Copy of flags from the call to usb_*_transfer_async. |
SoftwarePart rd sizeof.usb_gtd/4 |
; Software part, common for all controllers. |
rd 3 ; padding |
ends |
if sizeof.ehci_gtd mod 32 |
.err ehci_gtd must be 32-bytes aligned |
end if |
; EHCI-specific part of a pipe descriptor. |
; * This structure corresponds to the Queue Head from the EHCI specification. |
; * The hardware requires 32-bytes alignment of the hardware part. |
; Since the allocator (usb_allocate_common) allocates memory sequentially |
; from page start (aligned on 0x1000 bytes), size of the structure must be |
; divisible by 32. |
; from page start (aligned on 0x1000 bytes), block size for the allocator |
; must be divisible by 32; ehci_alloc_pipe ensures this. |
; * The hardware requires also that the hardware part must not cross page |
; boundary; the allocator satisfies this automatically. |
struct ehci_pipe |
154,15 → 148,8 |
; from the new TD, if any. |
BaseList dd ? |
; Pointer to head of the corresponding pipe list. |
SoftwarePart rd sizeof.usb_pipe/4 |
; Software part, common for all controllers. |
rd 2 ; padding |
ends |
if sizeof.ehci_pipe mod 32 |
.err ehci_pipe must be 32-bytes aligned |
end if |
; This structure describes the static head of every list of pipes. |
; The hardware requires 32-bytes alignment of this structure. |
; All instances of this structure are located sequentially in ehci_controller, |
764,7 → 751,7 |
; and stores USB device address in the ehci_pipe structure. |
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address |
proc ehci_set_device_address |
mov byte [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart], cl |
mov byte [ebx+ehci_pipe.Token-sizeof.ehci_pipe], cl |
call usb_subscribe_control |
ret |
endp |
773,7 → 760,7 |
; in: esi -> usb_controller, ebx -> usb_pipe |
; out: eax = endpoint address |
proc ehci_get_device_address |
mov eax, [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart] |
mov eax, [ebx+ehci_pipe.Token-sizeof.ehci_pipe] |
and eax, 7Fh |
ret |
endp |
793,11 → 780,11 |
; stores the packet size in ehci_pipe structure. |
; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size |
proc ehci_set_endpoint_packet_size |
mov eax, [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart] |
mov eax, [ebx+ehci_pipe.Token-sizeof.ehci_pipe] |
and eax, not (0x7FF shl 16) |
shl ecx, 16 |
or eax, ecx |
mov [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart], eax |
mov [ebx+ehci_pipe.Token-sizeof.ehci_pipe], eax |
; Wait until hardware cache is evicted. |
call usb_subscribe_control |
ret |
818,10 → 805,10 |
proc ehci_alloc_pipe |
push ebx |
mov ebx, ehci_ep_mutex |
stdcall usb_allocate_common, sizeof.ehci_pipe |
stdcall usb_allocate_common, (sizeof.ehci_pipe + sizeof.usb_pipe + 1Fh) and not 1Fh |
test eax, eax |
jz @f |
add eax, ehci_pipe.SoftwarePart |
add eax, sizeof.ehci_pipe |
@@: |
pop ebx |
ret |
834,7 → 821,7 |
dd ? ; return address |
.ptr dd ? |
end virtual |
sub [.ptr], ehci_pipe.SoftwarePart |
sub [.ptr], sizeof.ehci_pipe |
jmp usb_free_common |
endp |
853,9 → 840,9 |
end virtual |
; 1. Zero all fields in the hardware part. |
push eax ecx |
sub edi, ehci_pipe.SoftwarePart |
sub edi, sizeof.ehci_pipe |
xor eax, eax |
movi ecx, ehci_pipe.SoftwarePart/4 |
movi ecx, sizeof.ehci_pipe/4 |
rep stosd |
pop ecx eax |
; 2. Setup PID in the first TD and make sure that the it is not active. |
862,16 → 849,16 |
xor edx, edx |
test byte [.endpoint], 80h |
setnz dh |
mov [eax+ehci_gtd.Token-ehci_gtd.SoftwarePart], edx |
mov [eax+ehci_gtd.NextTD-ehci_gtd.SoftwarePart], 1 |
mov [eax+ehci_gtd.AlternateNextTD-ehci_gtd.SoftwarePart], 1 |
mov [eax+ehci_gtd.Token-sizeof.ehci_gtd], edx |
mov [eax+ehci_gtd.NextTD-sizeof.ehci_gtd], 1 |
mov [eax+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], 1 |
; 3. Store physical address of the first TD. |
sub eax, ehci_gtd.SoftwarePart |
sub eax, sizeof.ehci_gtd |
call get_phys_addr |
mov [edi+ehci_pipe.Overlay.NextTD-ehci_pipe.SoftwarePart], eax |
mov [edi+ehci_pipe.Overlay.NextTD-sizeof.ehci_pipe], eax |
; 4. Fill ehci_pipe.Flags except for S- and C-masks. |
; Copy location from the config pipe. |
mov eax, [ecx+ehci_pipe.Flags-ehci_pipe.SoftwarePart] |
mov eax, [ecx+ehci_pipe.Flags-sizeof.ehci_pipe] |
and eax, 3FFF0000h |
; Use 1 requests per microframe for control/bulk endpoints, |
; use value from the endpoint descriptor for periodic endpoints |
884,9 → 871,9 |
@@: |
shl edx, 30 |
or eax, edx |
mov [edi+ehci_pipe.Flags-ehci_pipe.SoftwarePart], eax |
mov [edi+ehci_pipe.Flags-sizeof.ehci_pipe], eax |
; 5. Fill ehci_pipe.Token. |
mov eax, [ecx+ehci_pipe.Token-ehci_pipe.SoftwarePart] |
mov eax, [ecx+ehci_pipe.Token-sizeof.ehci_pipe] |
; copy following fields from the config pipe: |
; DeviceAddress, EndpointSpeed, ControlEndpoint if new type is control |
mov ecx, eax |
915,7 → 902,7 |
@@: |
or eax, 40000000h |
.nonak: |
mov [edi+ehci_pipe.Token-ehci_pipe.SoftwarePart], eax |
mov [edi+ehci_pipe.Token-sizeof.ehci_pipe], eax |
; 5. Select the corresponding list and insert to the list. |
; 5a. Use Control list for control pipes, Bulk list for bulk pipes. |
lea edx, [esi+ehci_controller.ControlED.SoftwarePart-sizeof.ehci_controller] |
931,7 → 918,7 |
; another for split transactions. |
; This could fail if the requested bandwidth is not available; |
; if so, return an error. |
test word [edi+ehci_pipe.Flags-ehci_pipe.SoftwarePart+2], 3FFFh |
test word [edi+ehci_pipe.Flags-sizeof.ehci_pipe+2], 3FFFh |
jnz .interrupt_fs |
call ehci_select_hs_interrupt_list |
jmp .interrupt_common |
940,9 → 927,9 |
.interrupt_common: |
test edx, edx |
jz .return0 |
mov word [edi+ehci_pipe.Flags-ehci_pipe.SoftwarePart], ax |
mov word [edi+ehci_pipe.Flags-sizeof.ehci_pipe], ax |
.insert: |
mov [edi+ehci_pipe.BaseList-ehci_pipe.SoftwarePart], edx |
mov [edi+ehci_pipe.BaseList-sizeof.ehci_pipe], edx |
; Insert to the head of the corresponding list. |
; Note: inserting to the head guarantees that the list traverse in |
; ehci_process_updated_schedule, once started, will not interact with new pipes. |
957,8 → 944,8 |
; 5d. Insert in the hardware list: copy previous NextQH to the new pipe, |
; store the physical address of the new pipe to previous NextQH. |
mov ecx, [edx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart] |
mov [edi+ehci_pipe.NextQH-ehci_pipe.SoftwarePart], ecx |
lea eax, [edi-ehci_pipe.SoftwarePart] |
mov [edi+ehci_pipe.NextQH-sizeof.ehci_pipe], ecx |
lea eax, [edi-sizeof.ehci_pipe] |
call get_phys_addr |
inc eax |
inc eax |
1058,15 → 1045,21 |
; this corresponds to 4001h bytes. If the requested size is |
; greater, we should split the transfer into several descriptors. |
; Boundaries to split must be multiples of endpoint transfer size |
; to avoid short packets except in the end of the transfer, |
; 4000h is always a good value. |
; to avoid short packets except in the end of the transfer. |
cmp [size], 4001h |
jbe .lastpacket |
; 2. While the remaining data cannot fit in one descriptor, |
; allocate full descriptors (of maximal possible size). |
mov edi, 4000h |
; 2a. Calculate size of one descriptor: must be a multiple of transfer size |
; and must be not greater than 4001h. |
movzx ecx, word [ebx+ohci_pipe.Flags+2-sizeof.ohci_pipe] |
mov eax, 4001h |
xor edx, edx |
mov edi, eax |
div ecx |
sub edi, edx |
mov [packetSize], edi |
.fullpackets: |
cmp [size], edi |
jbe .lastpacket |
call ehci_alloc_packet |
test eax, eax |
jz .fail |
1073,7 → 1066,8 |
mov [td], eax |
add [buffer], edi |
sub [size], edi |
jmp .fullpackets |
cmp [size], 4001h |
ja .fullpackets |
; 3. The remaining data can fit in one packet; |
; allocate the last descriptor with size = size of remaining data. |
.lastpacket: |
1084,7 → 1078,7 |
jz .fail |
; 9. Update flags in the last packet. |
mov edx, [flags] |
mov [ecx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], edx |
mov [ecx+ehci_gtd.Flags-sizeof.ehci_gtd], edx |
; 10. Fill AlternateNextTD field in all allocated TDs. |
; If the caller says that short transfer is ok, the queue must advance to |
; the next descriptor, which is in eax. |
1093,7 → 1087,7 |
push eax |
test dl, 1 |
jz .disable_short |
sub eax, ehci_gtd.SoftwarePart |
sub eax, sizeof.ehci_gtd |
jmp @f |
.disable_short: |
mov eax, [ebx+usb_pipe.Controller] |
1104,7 → 1098,7 |
@@: |
cmp edx, [esp] |
jz @f |
mov [edx+ehci_gtd.AlternateNextTD-ehci_gtd.SoftwarePart], eax |
mov [edx+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], eax |
mov edx, [edx+usb_gtd.NextVirt] |
jmp @b |
@@: |
1144,28 → 1138,28 |
call usb_init_transfer |
pop eax |
; 3. Copy PID to the new descriptor. |
mov edx, [ecx+ehci_gtd.Token-ehci_gtd.SoftwarePart] |
mov [eax+ehci_gtd.Token-ehci_gtd.SoftwarePart], edx |
mov [eax+ehci_gtd.NextTD-ehci_gtd.SoftwarePart], 1 |
mov [eax+ehci_gtd.AlternateNextTD-ehci_gtd.SoftwarePart], 1 |
mov edx, [ecx+ehci_gtd.Token-sizeof.ehci_gtd] |
mov [eax+ehci_gtd.Token-sizeof.ehci_gtd], edx |
mov [eax+ehci_gtd.NextTD-sizeof.ehci_gtd], 1 |
mov [eax+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], 1 |
; 4. Save the returned value (next descriptor). |
push eax |
; 5. Store the physical address of the next descriptor. |
sub eax, ehci_gtd.SoftwarePart |
sub eax, sizeof.ehci_gtd |
call get_phys_addr |
mov [ecx+ehci_gtd.NextTD-ehci_gtd.SoftwarePart], eax |
mov [ecx+ehci_gtd.NextTD-sizeof.ehci_gtd], eax |
; 6. For zero-length transfers, store zero in all fields for buffer addresses. |
; Otherwise, fill them with real values. |
xor eax, eax |
mov [ecx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], eax |
mov [ecx+ehci_gtd.Flags-sizeof.ehci_gtd], eax |
repeat 10 |
mov [ecx+ehci_gtd.BufferPointers-ehci_gtd.SoftwarePart+(%-1)*4], eax |
mov [ecx+ehci_gtd.BufferPointers-sizeof.ehci_gtd+(%-1)*4], eax |
end repeat |
cmp [.packetSize], eax |
jz @f |
mov eax, [.buffer] |
call get_phys_addr |
mov [ecx+ehci_gtd.BufferPointers-ehci_gtd.SoftwarePart], eax |
mov [ecx+ehci_gtd.BufferPointers-sizeof.ehci_gtd], eax |
and eax, 0xFFF |
mov edx, [.packetSize] |
add edx, eax |
1174,25 → 1168,25 |
mov eax, [.buffer] |
add eax, 0x1000 |
call get_pg_addr |
mov [ecx+ehci_gtd.BufferPointers+4-ehci_gtd.SoftwarePart], eax |
mov [ecx+ehci_gtd.BufferPointers+4-sizeof.ehci_gtd], eax |
sub edx, 0x1000 |
jbe @f |
mov eax, [.buffer] |
add eax, 0x2000 |
call get_pg_addr |
mov [ecx+ehci_gtd.BufferPointers+8-ehci_gtd.SoftwarePart], eax |
mov [ecx+ehci_gtd.BufferPointers+8-sizeof.ehci_gtd], eax |
sub edx, 0x1000 |
jbe @f |
mov eax, [.buffer] |
add eax, 0x3000 |
call get_pg_addr |
mov [ecx+ehci_gtd.BufferPointers+12-ehci_gtd.SoftwarePart], eax |
mov [ecx+ehci_gtd.BufferPointers+12-sizeof.ehci_gtd], eax |
sub edx, 0x1000 |
jbe @f |
mov eax, [.buffer] |
add eax, 0x4000 |
call get_pg_addr |
mov [ecx+ehci_gtd.BufferPointers+16-ehci_gtd.SoftwarePart], eax |
mov [ecx+ehci_gtd.BufferPointers+16-sizeof.ehci_gtd], eax |
@@: |
; 7. Fill Token field: |
; set Status = 0 (inactive, ehci_insert_transfer would mark everything active); |
1202,7 → 1196,7 |
; set current page to 0; |
; do not interrupt on complete (ehci_insert_transfer sets this bit where needed); |
; set DataToggle to bit 2 of [.direction]. |
mov eax, [ecx+ehci_gtd.Token-ehci_gtd.SoftwarePart] |
mov eax, [ecx+ehci_gtd.Token-sizeof.ehci_gtd] |
and eax, 300h ; keep PID code |
mov edx, [.direction] |
test edx, edx |
1222,7 → 1216,7 |
mov edx, [.packetSize] |
shl edx, 16 |
or eax, edx |
mov [ecx+ehci_gtd.Token-ehci_gtd.SoftwarePart], eax |
mov [ecx+ehci_gtd.Token-sizeof.ehci_gtd], eax |
; 4. Restore the returned value saved in step 2. |
pop eax |
.nothing: |
1234,10 → 1228,10 |
; ehci_alloc_transfer. |
; ecx -> last descriptor for the transfer, ebx -> usb_pipe |
proc ehci_insert_transfer |
or byte [ecx+ehci_gtd.Token+1-ehci_gtd.SoftwarePart], 80h ; set IOC bit |
or byte [ecx+ehci_gtd.Token+1-sizeof.ehci_gtd], 80h ; set IOC bit |
mov eax, [esp+4] |
.activate: |
or byte [eax+ehci_gtd.Token-ehci_gtd.SoftwarePart], 80h ; set Active bit |
or byte [eax+ehci_gtd.Token-sizeof.ehci_gtd], 80h ; set Active bit |
cmp eax, ecx |
mov eax, [eax+usb_gtd.NextVirt] |
jnz .activate |
1328,7 → 1322,7 |
.found_hs_hub: |
mov edx, [edx+usb_hub.ConfigPipe] |
inc ecx |
mov edx, [edx+ehci_pipe.Token-ehci_pipe.SoftwarePart] |
mov edx, [edx+ehci_pipe.Token-sizeof.ehci_pipe] |
shl ecx, 23 |
and edx, 7Fh |
shl edx, 16 |
1338,15 → 1332,15 |
.common: |
; 5. Create pseudo-pipe in the stack. |
; See ehci_init_pipe: only .Controller, .Token, .Flags fields are used. |
push esi ; ehci_pipe.SoftwarePart.Controller |
push esi ; usb_pipe.Controller |
mov ecx, esp |
sub esp, ehci_pipe.SoftwarePart - ehci_pipe.Flags - 4 |
sub esp, sizeof.ehci_pipe - ehci_pipe.Flags - 4 |
push edx ; ehci_pipe.Flags |
push eax ; ehci_pipe.Token |
; 6. Notify the protocol layer. |
call usb_new_device |
; 7. Cleanup the stack after step 5 and return. |
add esp, ehci_pipe.SoftwarePart - ehci_pipe.Flags + 8 |
add esp, sizeof.ehci_pipe - ehci_pipe.Flags + 8 |
pop ecx ebx ; restore used registers |
ret |
endp |
1658,7 → 1652,7 |
; if either of conditions holds, exit from the internal loop. |
cmp ebx, [esp] |
jz .tddone |
cmp byte [ebx+ehci_gtd.Token-ehci_gtd.SoftwarePart], 0 |
cmp byte [ebx+ehci_gtd.Token-sizeof.ehci_gtd], 0 |
js .tddone |
; Release the queue lock while processing one descriptor: |
; callback function could (and often would) schedule another transfer. |
1690,7 → 1684,7 |
; cmp [eax+usb_pipe.Type], INTERRUPT_PIPE |
; jnz @f |
; DEBUGF 1,'K : finalized TD for pipe %x:\n',eax |
; lea eax, [ebx-ehci_gtd.SoftwarePart] |
; lea eax, [ebx-sizeof.ehci_gtd] |
; DEBUGF 1,'K : %x %x %x %x\n',[eax],[eax+4],[eax+8],[eax+12] |
; DEBUGF 1,'K : %x %x %x %x\n',[eax+16],[eax+20],[eax+24],[eax+28] |
;@@: |
1697,7 → 1691,7 |
; 1. Remove this descriptor from the list of descriptors for this pipe. |
call usb_unlink_td |
; 2. Calculate actual number of bytes transferred. |
mov eax, [ebx+ehci_gtd.Token-ehci_gtd.SoftwarePart] |
mov eax, [ebx+ehci_gtd.Token-sizeof.ehci_gtd] |
lea edx, [eax+eax] |
shr edx, 17 |
sub edx, [ebx+usb_gtd.Length] |
1715,7 → 1709,7 |
xor ecx, ecx |
test al, 40h |
jnz .error |
test byte [ebx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], 1 |
test byte [ebx+ehci_gtd.Flags-sizeof.ehci_gtd], 1 |
jnz .notify |
cmp edx, [ebx+usb_gtd.Length] |
jnz .special |
1745,7 → 1739,7 |
ret |
.error: |
push ebx |
sub ebx, ehci_gtd.SoftwarePart |
sub ebx, sizeof.ehci_gtd |
DEBUGF 1,'K : TD failed:\n' |
DEBUGF 1,'K : %x %x %x %x\n',[ebx],[ebx+4],[ebx+8],[ebx+12] |
DEBUGF 1,'K : %x %x %x %x\n',[ebx+16],[ebx+20],[ebx+24],[ebx+28] |
1752,7 → 1746,7 |
pop ebx |
DEBUGF 1,'K : pipe now:\n' |
mov ecx, [ebx+usb_gtd.Pipe] |
sub ecx, ehci_pipe.SoftwarePart |
sub ecx, sizeof.ehci_pipe |
DEBUGF 1,'K : %x %x %x %x\n',[ecx],[ecx+4],[ecx+8],[ecx+12] |
DEBUGF 1,'K : %x %x %x %x\n',[ecx+16],[ecx+20],[ecx+24],[ecx+28] |
DEBUGF 1,'K : %x %x %x %x\n',[ecx+32],[ecx+36],[ecx+40],[ecx+44] |
1802,7 → 1796,7 |
; it is not an error; in this case, go to 4 with ecx = 0. |
cmp ecx, USB_STATUS_UNDERRUN |
jnz @f |
test byte [ebx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], 1 |
test byte [ebx+ehci_gtd.Flags-sizeof.ehci_gtd], 1 |
jz @f |
xor ecx, ecx |
pop edx ; length |
1832,20 → 1826,20 |
; to the next transfer. (According to the standard, "A control pipe may also |
; support functional stall as well, but this is not recommended."). |
mov edx, [ebx+usb_gtd.Pipe] |
mov eax, [ebx+ehci_gtd.NextTD-ehci_gtd.SoftwarePart] |
mov eax, [ebx+ehci_gtd.NextTD-sizeof.ehci_gtd] |
or al, 1 |
mov [edx+ehci_pipe.Overlay.NextTD-ehci_pipe.SoftwarePart], eax |
mov [edx+ehci_pipe.Overlay.AlternateNextTD-ehci_pipe.SoftwarePart], eax |
mov [edx+ehci_pipe.Overlay.NextTD-sizeof.ehci_pipe], eax |
mov [edx+ehci_pipe.Overlay.AlternateNextTD-sizeof.ehci_pipe], eax |
cmp [edx+usb_pipe.Type], CONTROL_PIPE |
jz .control |
; Bulk/interrupt transfer; halt the queue. |
mov [edx+ehci_pipe.Overlay.Token-ehci_pipe.SoftwarePart], 40h |
mov [edx+ehci_pipe.Overlay.Token-sizeof.ehci_pipe], 40h |
pop edx |
jmp .notify |
; Control transfer. |
.control: |
and [edx+ehci_pipe.Overlay.Token-ehci_pipe.SoftwarePart], 0 |
dec [edx+ehci_pipe.Overlay.NextTD-ehci_pipe.SoftwarePart] |
and [edx+ehci_pipe.Overlay.Token-sizeof.ehci_pipe], 0 |
dec [edx+ehci_pipe.Overlay.NextTD-sizeof.ehci_pipe] |
pop edx |
jmp .notify |
endp |
1855,7 → 1849,7 |
proc ehci_unlink_pipe |
cmp [ebx+usb_pipe.Type], INTERRUPT_PIPE |
jnz @f |
test word [ebx+ehci_pipe.Flags-ehci_pipe.SoftwarePart+2], 3FFFh |
test word [ebx+ehci_pipe.Flags-sizeof.ehci_pipe+2], 3FFFh |
jnz .interrupt_fs |
call ehci_hs_interrupt_list_unlink |
jmp .interrupt_common |
1870,9 → 1864,9 |
mov edx, esi |
sub edx, eax |
cmp edx, sizeof.ehci_controller |
mov edx, [ebx+ehci_pipe.NextQH-ehci_pipe.SoftwarePart] |
mov edx, [ebx+ehci_pipe.NextQH-sizeof.ehci_pipe] |
jb .prev_is_static |
mov [eax+ehci_pipe.NextQH-ehci_pipe.SoftwarePart], edx |
mov [eax+ehci_pipe.NextQH-sizeof.ehci_pipe], edx |
ret |
.prev_is_static: |
mov [eax+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart], edx |
1882,10 → 1876,10 |
proc ehci_alloc_td |
push ebx |
mov ebx, ehci_gtd_mutex |
stdcall usb_allocate_common, sizeof.ehci_gtd |
stdcall usb_allocate_common, (sizeof.ehci_gtd + sizeof.usb_gtd + 1Fh) and not 1Fh |
test eax, eax |
jz @f |
add eax, ehci_gtd.SoftwarePart |
add eax, sizeof.ehci_gtd |
@@: |
pop ebx |
ret |
1895,6 → 1889,6 |
; frees all additional data associated with the transfer descriptor. |
; EHCI has no additional data, so just free ehci_gtd structure. |
proc ehci_free_td |
sub dword [esp+4], ehci_gtd.SoftwarePart |
sub dword [esp+4], sizeof.ehci_gtd |
jmp usb_free_common |
endp |
/kernel/branches/Kolibri-acpi/bus/usb/memory.inc |
---|
26,7 → 26,7 |
endg |
; sanity check: structures in UHCI and OHCI should be the same for allocation |
if (sizeof.ohci_pipe=sizeof.uhci_pipe)&(ohci_pipe.SoftwarePart=uhci_pipe.SoftwarePart) |
if (sizeof.ohci_pipe = sizeof.uhci_pipe) |
; Allocates one endpoint structure for UHCI/OHCI. |
; Returns pointer to software part (usb_pipe) in eax. |
33,10 → 33,10 |
proc usb1_allocate_endpoint |
push ebx |
mov ebx, usb1_ep_mutex |
stdcall usb_allocate_common, sizeof.ohci_pipe |
stdcall usb_allocate_common, (sizeof.ohci_pipe + sizeof.usb_pipe + 0Fh) and not 0Fh |
test eax, eax |
jz @f |
add eax, ohci_pipe.SoftwarePart |
add eax, sizeof.ohci_pipe |
@@: |
pop ebx |
ret |
45,7 → 45,7 |
; Free one endpoint structure for UHCI/OHCI. |
; Stdcall with one argument, pointer to software part (usb_pipe). |
proc usb1_free_endpoint |
sub dword [esp+4], ohci_pipe.SoftwarePart |
sub dword [esp+4], sizeof.ohci_pipe |
jmp usb_free_common |
endp |
55,7 → 55,7 |
end if |
; sanity check: structures in UHCI and OHCI should be the same for allocation |
if (sizeof.ohci_gtd=sizeof.uhci_gtd)&(ohci_gtd.SoftwarePart=uhci_gtd.SoftwarePart) |
if (sizeof.ohci_gtd = sizeof.uhci_gtd) |
; Allocates one general transfer descriptor structure for UHCI/OHCI. |
; Returns pointer to software part (usb_gtd) in eax. |
62,10 → 62,10 |
proc usb1_allocate_general_td |
push ebx |
mov ebx, usb_gtd_mutex |
stdcall usb_allocate_common, sizeof.ohci_gtd |
stdcall usb_allocate_common, (sizeof.ohci_gtd + sizeof.usb_gtd + 0Fh) and not 0Fh |
test eax, eax |
jz @f |
add eax, ohci_gtd.SoftwarePart |
add eax, sizeof.ohci_gtd |
@@: |
pop ebx |
ret |
74,7 → 74,7 |
; Free one general transfer descriptor structure for UHCI/OHCI. |
; Stdcall with one argument, pointer to software part (usb_gtd). |
proc usb1_free_general_td |
sub dword [esp+4], ohci_gtd.SoftwarePart |
sub dword [esp+4], sizeof.ohci_gtd |
jmp usb_free_common |
endp |
/kernel/branches/Kolibri-acpi/bus/usb/ohci.inc |
---|
44,8 → 44,8 |
; specification. |
; * The hardware requires 16-bytes alignment of the hardware part. |
; Since the allocator (usb_allocate_common) allocates memory sequentially |
; from page start (aligned on 0x1000 bytes), size of the structure must be |
; divisible by 16. |
; from page start (aligned on 0x1000 bytes), block size for the allocator |
; must be divisible by 16; usb1_allocate_endpoint ensures this. |
struct ohci_pipe |
; All addresses are physical. |
Flags dd ? |
95,14 → 95,8 |
; * There is no "next" list for Bulk and Control lists, they are processed |
; separately from others. |
; * There is no "next" list for Periodic list for 1ms interval. |
SoftwarePart rd sizeof.usb_pipe/4 |
; Software part, common for all controllers. |
ends |
if sizeof.ohci_pipe mod 16 |
.err ohci_pipe must be 16-bytes aligned |
end if |
; This structure describes the static head of every list of pipes. |
; The hardware requires 16-bytes alignment of this structure. |
; All instances of this structure are located sequentially in uhci_controller, |
204,7 → 198,8 |
; * The hardware requires 16-bytes alignment of the hardware part, so |
; the entire descriptor must be 16-bytes aligned. Since the allocator |
; (usb_allocate_common) allocates memory sequentially from page start |
; (aligned on 0x1000 bytes), size of the structure must be divisible by 16. |
; (aligned on 0x1000 bytes), block size for the allocator must be |
; divisible by 16; usb1_allocate_generic_td ensures this. |
struct ohci_gtd |
; ------------------------------ hardware fields ------------------------------ |
; All addresses in this part are physical. |
248,15 → 243,9 |
; Virtual pointer to the next processed TD. |
BufEnd dd ? |
; Physical address of the last byte in the buffer for this TD. |
dd ? ; padding for 16-bytes alignment |
SoftwarePart rd sizeof.usb_gtd/4 |
; Common part for all controllers. |
dd ? ; padding to align with uhci_gtd |
ends |
if sizeof.ohci_gtd mod 16 |
.err ohci_gtd must be 16-bytes aligned |
end if |
; OHCI isochronous transfer descriptor. |
; * The structure describes transfers to be performed on Isochronous endpoints. |
; * The structure includes two parts, the hardware part and the software part. |
726,7 → 715,7 |
.tdloop: |
mov ecx, [eax+ohci_gtd.NextTD] |
mov [eax+ohci_gtd.NextTD], ebx |
lea ebx, [eax+ohci_gtd.SoftwarePart] |
lea ebx, [eax+sizeof.ohci_gtd] |
test ecx, ecx |
jz .tddone |
call usb_td_to_virt |
893,7 → 882,7 |
; and stores USB device address in the ohci_pipe structure. |
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address |
proc ohci_set_device_address |
mov byte [ebx+ohci_pipe.Flags-ohci_pipe.SoftwarePart], cl |
mov byte [ebx+ohci_pipe.Flags-sizeof.ohci_pipe], cl |
; Wait until the hardware will forget the old value. |
call usb_subscribe_control |
ret |
903,7 → 892,7 |
; in: esi -> usb_controller, ebx -> usb_pipe |
; out: eax = endpoint address |
proc ohci_get_device_address |
mov eax, [ebx+ohci_pipe.Flags-ohci_pipe.SoftwarePart] |
mov eax, [ebx+ohci_pipe.Flags-sizeof.ohci_pipe] |
and eax, 7Fh |
ret |
endp |
923,7 → 912,7 |
; stores the packet size in ohci_pipe structure. |
; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size |
proc ohci_set_endpoint_packet_size |
mov byte [ebx+ohci_pipe.Flags+2-ohci_pipe.SoftwarePart], cl |
mov byte [ebx+ohci_pipe.Flags+2-sizeof.ohci_pipe], cl |
; Wait until the hardware will forget the old value. |
call usb_subscribe_control |
ret |
943,20 → 932,20 |
.interval dd ? |
end virtual |
; 1. Initialize the queue of transfer descriptors: empty. |
sub eax, ohci_gtd.SoftwarePart |
sub eax, sizeof.ohci_gtd |
call get_phys_addr |
mov [edi+ohci_pipe.TailP-ohci_pipe.SoftwarePart], eax |
mov [edi+ohci_pipe.HeadP-ohci_pipe.SoftwarePart], eax |
mov [edi+ohci_pipe.TailP-sizeof.ohci_pipe], eax |
mov [edi+ohci_pipe.HeadP-sizeof.ohci_pipe], eax |
; 2. Generate ohci_pipe.Flags, see the description in ohci_pipe. |
mov eax, [ecx+ohci_pipe.Flags-ohci_pipe.SoftwarePart] |
mov eax, [ecx+ohci_pipe.Flags-sizeof.ohci_pipe] |
and eax, 0x207F ; keep Speed bit and FunctionAddress |
mov edx, [.endpoint] |
and edx, 15 |
shl edx, 7 |
or eax, edx |
mov [edi+ohci_pipe.Flags-ohci_pipe.SoftwarePart], eax |
mov [edi+ohci_pipe.Flags-sizeof.ohci_pipe], eax |
mov eax, [.maxpacket] |
mov word [edi+ohci_pipe.Flags+2-ohci_pipe.SoftwarePart], ax |
mov word [edi+ohci_pipe.Flags+2-sizeof.ohci_pipe], ax |
cmp [.type], CONTROL_PIPE |
jz @f |
test byte [.endpoint], 80h |
963,7 → 952,7 |
setnz al |
inc eax |
shl al, 3 |
or byte [edi+ohci_pipe.Flags+1-ohci_pipe.SoftwarePart], al |
or byte [edi+ohci_pipe.Flags+1-sizeof.ohci_pipe], al |
@@: |
; 3. Insert the new pipe to the corresponding list of endpoints. |
; 3a. Use Control list for control pipes, Bulk list for bulk pipes. |
992,11 → 981,11 |
mov [edi+usb_pipe.PrevVirt], edx |
mov [ecx+usb_pipe.PrevVirt], edi |
mov [edx+usb_pipe.NextVirt], edi |
mov ecx, [edx+ohci_pipe.NextED-ohci_pipe.SoftwarePart] |
mov [edi+ohci_pipe.NextED-ohci_pipe.SoftwarePart], ecx |
lea eax, [edi-ohci_pipe.SoftwarePart] |
mov ecx, [edx+ohci_pipe.NextED-sizeof.ohci_pipe] |
mov [edi+ohci_pipe.NextED-sizeof.ohci_pipe], ecx |
lea eax, [edi-sizeof.ohci_pipe] |
call get_phys_addr |
mov [edx+ohci_pipe.NextED-ohci_pipe.SoftwarePart], eax |
mov [edx+ohci_pipe.NextED-sizeof.ohci_pipe], eax |
; 4. Return something non-zero. |
ret |
.return0: |
1069,15 → 1058,22 |
; this corresponds to 1001h bytes. If the requested size is |
; greater, we should split the transfer into several descriptors. |
; Boundaries to split must be multiples of endpoint transfer size |
; to avoid short packets except in the end of the transfer, |
; 1000h is always a good value. |
; to avoid short packets except in the end of the transfer. |
cmp [size], 1001h |
jbe .lastpacket |
; 2. While the remaining data cannot fit in one packet, |
; allocate page-sized descriptors. |
mov edi, 1000h |
; allocate full-sized descriptors. |
; 2a. Calculate size of one descriptor: must be a multiple of transfer size |
; and must be not greater than 1001h. |
movzx ecx, word [ebx+ohci_pipe.Flags+2-sizeof.ohci_pipe] |
mov eax, 1001h |
xor edx, edx |
mov edi, eax |
div ecx |
sub edi, edx |
; 2b. Allocate in loop. |
mov [packetSize], edi |
.fullpackets: |
cmp [size], edi |
jbe .lastpacket |
call ohci_alloc_packet |
test eax, eax |
jz .fail |
1084,7 → 1080,8 |
mov [td], eax |
add [buffer], edi |
sub [size], edi |
jmp .fullpackets |
cmp [size], 1001h |
ja .fullpackets |
; 3. The remaining data can fit in one descriptor; |
; allocate the last descriptor with size = size of remaining data. |
.lastpacket: |
1094,7 → 1091,7 |
test eax, eax |
jz .fail |
; 4. Enable an immediate interrupt on completion of the last packet. |
and byte [ecx+ohci_gtd.Flags+2-ohci_gtd.SoftwarePart], not (7 shl (21-16)) |
and byte [ecx+ohci_gtd.Flags+2-sizeof.ohci_gtd], not (7 shl (21-16)) |
; 5. If a short transfer is ok for a caller, set the corresponding bit in |
; the last descriptor, but not in others. |
; Note: even if the caller says that short transfers are ok, |
1104,7 → 1101,7 |
; transparently to the caller. |
test [flags], 1 |
jz @f |
or byte [ecx+ohci_gtd.Flags+2-ohci_gtd.SoftwarePart], 1 shl (18-16) |
or byte [ecx+ohci_gtd.Flags+2-sizeof.ohci_gtd], 1 shl (18-16) |
@@: |
ret |
.fail: |
1143,24 → 1140,24 |
; 3. Save the returned value (next descriptor). |
push eax |
; 4. Store the physical address of the next descriptor. |
sub eax, ohci_gtd.SoftwarePart |
sub eax, sizeof.ohci_gtd |
call get_phys_addr |
mov [ecx+ohci_gtd.NextTD-ohci_gtd.SoftwarePart], eax |
mov [ecx+ohci_gtd.NextTD-sizeof.ohci_gtd], eax |
; 5. For zero-length transfers, store zero in both fields for buffer addresses. |
; Otherwise, fill them with real values. |
xor eax, eax |
mov [ecx+ohci_gtd.CurBufPtr-ohci_gtd.SoftwarePart], eax |
mov [ecx+ohci_gtd.BufEnd-ohci_gtd.SoftwarePart], eax |
mov [ecx+ohci_gtd.CurBufPtr-sizeof.ohci_gtd], eax |
mov [ecx+ohci_gtd.BufEnd-sizeof.ohci_gtd], eax |
cmp [.packetSize], eax |
jz @f |
mov eax, [.buffer] |
call get_phys_addr |
mov [ecx+ohci_gtd.CurBufPtr-ohci_gtd.SoftwarePart], eax |
mov [ecx+ohci_gtd.CurBufPtr-sizeof.ohci_gtd], eax |
mov eax, [.buffer] |
add eax, [.packetSize] |
dec eax |
call get_phys_addr |
mov [ecx+ohci_gtd.BufEnd-ohci_gtd.SoftwarePart], eax |
mov [ecx+ohci_gtd.BufEnd-sizeof.ohci_gtd], eax |
@@: |
; 6. Generate Flags field: |
; - set bufferRounding (bit 18) to zero = disallow short transfers; |
1179,7 → 1176,7 |
and edx, (3 shl 2) |
shl edx, 24 - 2 |
lea eax, [eax + edx + (7 shl 21) + (15 shl 28)] |
mov [ecx+ohci_gtd.Flags-ohci_gtd.SoftwarePart], eax |
mov [ecx+ohci_gtd.Flags-sizeof.ohci_gtd], eax |
; 7. Restore the returned value saved in step 3. |
pop eax |
.nothing: |
1192,8 → 1189,8 |
; ecx -> last descriptor for the transfer, ebx -> usb_pipe |
proc ohci_insert_transfer |
; 1. Advance the queue of transfer descriptors. |
mov eax, [ecx+ohci_gtd.NextTD-ohci_gtd.SoftwarePart] |
mov [ebx+ohci_pipe.TailP-ohci_pipe.SoftwarePart], eax |
mov eax, [ecx+ohci_gtd.NextTD-sizeof.ohci_gtd] |
mov [ebx+ohci_pipe.TailP-sizeof.ohci_pipe], eax |
; 2. For control and bulk pipes, notify the controller that |
; there is new work in control/bulk queue respectively. |
ohci_notify_new_work: |
1393,7 → 1390,7 |
mov edx, [ebx+usb_gtd.Pipe] |
test [edx+usb_pipe.Flags], USB_FLAG_CLOSED |
jz @f |
lea eax, [ebx+ohci_gtd.NextTD-ohci_gtd.SoftwarePart] |
lea eax, [ebx+ohci_gtd.NextTD-sizeof.ohci_gtd] |
xor ebx, ebx |
jmp .next_td2 |
@@: |
1402,13 → 1399,13 |
; 3. Get number of bytes that remain to be transferred. |
; If CurBufPtr is zero, everything was transferred. |
xor edx, edx |
cmp [ebx+ohci_gtd.CurBufPtr-ohci_gtd.SoftwarePart], edx |
cmp [ebx+ohci_gtd.CurBufPtr-sizeof.ohci_gtd], edx |
jz .gotlen |
; Otherwise, the remaining length is |
; (BufEnd and 0xFFF) - (CurBufPtr and 0xFFF) + 1, |
; plus 0x1000 if BufEnd and CurBufPtr are in different pages. |
mov edx, [ebx+ohci_gtd.BufEnd-ohci_gtd.SoftwarePart] |
mov eax, [ebx+ohci_gtd.CurBufPtr-ohci_gtd.SoftwarePart] |
mov edx, [ebx+ohci_gtd.BufEnd-sizeof.ohci_gtd] |
mov eax, [ebx+ohci_gtd.CurBufPtr-sizeof.ohci_gtd] |
mov ecx, edx |
and edx, 0xFFF |
inc edx |
1425,7 → 1422,7 |
neg edx |
; 4. Check for error. If so, go to 7. |
push ebx |
mov eax, [ebx+ohci_gtd.Flags-ohci_gtd.SoftwarePart] |
mov eax, [ebx+ohci_gtd.Flags-sizeof.ohci_gtd] |
shr eax, 28 |
jnz .error |
.notify: |
1451,7 → 1448,7 |
stdcall usb1_free_general_td, ebx |
@@: |
pop ebx |
lea eax, [ebx+ohci_gtd.NextTD-ohci_gtd.SoftwarePart] |
lea eax, [ebx+ohci_gtd.NextTD-sizeof.ohci_gtd] |
.next_td2: |
push ebx |
mov ebx, eax |
1484,10 → 1481,10 |
push eax |
push edx |
; DEBUGF 1,'K : TD failed:\n' |
; DEBUGF 1,'K : %x %x %x %x\n',[ebx-ohci_gtd.SoftwarePart],[ebx-ohci_gtd.SoftwarePart+4],[ebx-ohci_gtd.SoftwarePart+8],[ebx-ohci_gtd.SoftwarePart+12] |
; DEBUGF 1,'K : %x %x %x %x\n',[ebx-ohci_gtd.SoftwarePart+16],[ebx-ohci_gtd.SoftwarePart+20],[ebx-ohci_gtd.SoftwarePart+24],[ebx-ohci_gtd.SoftwarePart+28] |
; DEBUGF 1,'K : %x %x %x %x\n',[ebx-sizeof.ohci_gtd],[ebx-sizeof.ohci_gtd+4],[ebx-sizeof.ohci_gtd+8],[ebx-sizeof.ohci_gtd+12] |
; DEBUGF 1,'K : %x %x %x %x\n',[ebx-sizeof.ohci_gtd+16],[ebx-sizeof.ohci_gtd+20],[ebx-sizeof.ohci_gtd+24],[ebx-sizeof.ohci_gtd+28] |
; mov eax, [ebx+usb_gtd.Pipe] |
; DEBUGF 1,'K : pipe: %x %x %x %x\n',[eax-ohci_pipe.SoftwarePart],[eax-ohci_pipe.SoftwarePart+4],[eax-ohci_pipe.SoftwarePart+8],[eax-ohci_pipe.SoftwarePart+12] |
; DEBUGF 1,'K : pipe: %x %x %x %x\n',[eax-sizeof.ohci_pipe],[eax-sizeof.ohci_pipe+4],[eax-sizeof.ohci_pipe+8],[eax-sizeof.ohci_pipe+12] |
; 7b. Traverse the list of descriptors looking for the final packet |
; for this transfer. |
; Free and unlink non-final descriptors, except the current one. |
1517,18 → 1514,18 |
; After that, go to step 5 with eax = 0 (no error). |
cmp dword [.error_code], USB_STATUS_UNDERRUN |
jnz .no_underrun |
test byte [ebx+ohci_gtd.Flags+2-ohci_gtd.SoftwarePart], 1 shl (18-16) |
test byte [ebx+ohci_gtd.Flags+2-sizeof.ohci_gtd], 1 shl (18-16) |
jz .no_underrun |
and dword [.error_code], 0 |
mov ecx, [ebx+usb_gtd.Pipe] |
mov edx, [ecx+ohci_pipe.HeadP-ohci_pipe.SoftwarePart] |
mov edx, [ecx+ohci_pipe.HeadP-sizeof.ohci_pipe] |
and edx, 2 |
.advance_queue: |
mov eax, [ebx+usb_gtd.NextVirt] |
sub eax, ohci_gtd.SoftwarePart |
sub eax, sizeof.ohci_gtd |
call get_phys_addr |
or eax, edx |
mov [ecx+ohci_pipe.HeadP-ohci_pipe.SoftwarePart], eax |
mov [ecx+ohci_pipe.HeadP-sizeof.ohci_pipe], eax |
push ebx |
mov ebx, ecx |
call ohci_notify_new_work |
1562,10 → 1559,10 |
; support functional stall as well, but this is not recommended."). |
; Advance the transfer queue to the next descriptor. |
mov ecx, [ebx+usb_gtd.Pipe] |
mov edx, [ecx+ohci_pipe.HeadP-ohci_pipe.SoftwarePart] |
mov edx, [ecx+ohci_pipe.HeadP-sizeof.ohci_pipe] |
and edx, 2 ; keep toggleCarry bit |
cmp [ecx+usb_pipe.Type], CONTROL_PIPE |
jnz @f |
jz @f |
inc edx ; set Halted bit |
@@: |
jmp .advance_queue |
1577,7 → 1574,7 |
proc ohci_unlink_pipe |
cmp [ebx+usb_pipe.Type], INTERRUPT_PIPE |
jnz @f |
mov eax, [ebx+ohci_pipe.Flags-ohci_pipe.SoftwarePart] |
mov eax, [ebx+ohci_pipe.Flags-sizeof.ohci_pipe] |
bt eax, 13 |
setc cl |
bt eax, 11 |
1589,7 → 1586,7 |
mov eax, [ebx+usb_pipe.PrevVirt] |
mov [edx+usb_pipe.PrevVirt], eax |
mov [eax+usb_pipe.NextVirt], edx |
mov edx, [ebx+ohci_pipe.NextED-ohci_pipe.SoftwarePart] |
mov [eax+ohci_pipe.NextED-ohci_pipe.SoftwarePart], edx |
mov edx, [ebx+ohci_pipe.NextED-sizeof.ohci_pipe] |
mov [eax+ohci_pipe.NextED-sizeof.ohci_pipe], edx |
ret |
endp |
/kernel/branches/Kolibri-acpi/bus/usb/protocol.inc |
---|
459,10 → 459,7 |
; save length for step 2 |
push eax |
add eax, sizeof.usb_device_data + 8 |
; Note that malloc destroys ebx. |
push ebx |
call malloc |
pop ebx |
; 1b. If failed, say something to the debug board and stop the initialization. |
test eax, eax |
jz .nomemory |
/kernel/branches/Kolibri-acpi/bus/usb/scheduler.inc |
---|
432,14 → 432,14 |
; in the list header. |
proc ehci_hs_interrupt_list_unlink |
; get target list |
mov edx, [ebx+ehci_pipe.BaseList-ehci_pipe.SoftwarePart] |
mov edx, [ebx+ehci_pipe.BaseList-sizeof.ehci_pipe] |
; TODO: calculate real bandwidth |
movzx eax, word [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart+2] |
mov ecx, [ebx+ehci_pipe.Flags-ehci_pipe.SoftwarePart] |
movzx eax, word [ebx+ehci_pipe.Token-sizeof.ehci_pipe+2] |
mov ecx, [ebx+ehci_pipe.Flags-sizeof.ehci_pipe] |
and eax, (1 shl 11) - 1 |
shr ecx, 30 |
imul eax, ecx |
movzx ecx, byte [ebx+ehci_pipe.Flags-ehci_pipe.SoftwarePart] |
movzx ecx, byte [ebx+ehci_pipe.Flags-sizeof.ehci_pipe] |
add edx, ehci_static_ep.Bandwidths - ehci_static_ep.SoftwarePart |
; update bandwidth |
.dec_bandwidth: |
/kernel/branches/Kolibri-acpi/bus/usb/uhci.inc |
---|
20,9 → 20,8 |
USB_PID_OUT = 0E1h |
; UHCI does not support an interrupt on root hub status change. We must poll |
; the controller periodically. This is the period in timer ticks (10ms). |
; We use the value 100 ms: it is valid value for USB hub poll rate (1-255 ms), |
; small enough to be responsible to connect events and large enough to not |
; load CPU too often. |
; We use the value 100 ticks: it is small enough to be responsive to connect |
; events and large enough to not load CPU too often. |
UHCI_POLL_INTERVAL = 100 |
; the following constant is an invalid encoding for length fields in |
; uhci_gtd; it is used to check whether an inactive TD has been |
42,8 → 41,8 |
; software book-keeping. |
; * The hardware requires 16-bytes alignment of the hardware part. |
; Since the allocator (usb_allocate_common) allocates memory sequentially |
; from page start (aligned on 0x1000 bytes), size of the structure must be |
; divisible by 16. |
; from page start (aligned on 0x1000 bytes), block size for the allocator |
; must be divisible by 16; usb1_allocate_endpoint ensures this. |
struct uhci_pipe |
NextQH dd ? |
; 1. First bit (bit 0) is Terminate bit. 1 = there is no next QH. |
81,14 → 80,8 |
ErrorTD dd ? |
; Usually NULL. If nonzero, it is a pointer to descriptor which was error'd |
; and should be freed sometime in the future (the hardware could still use it). |
SoftwarePart rd sizeof.usb_pipe/4 |
; Common part for all controllers, described by usb_pipe structure. |
ends |
if sizeof.uhci_pipe mod 16 |
.err uhci_pipe must be 16-bytes aligned |
end if |
; This structure describes the static head of every list of pipes. |
; The hardware requires 16-bytes alignment of this structure. |
; All instances of this structure are located sequentially in uhci_controller, |
167,7 → 160,8 |
; * The hardware requires 16-bytes alignment of the hardware part, so |
; the entire descriptor must be 16-bytes aligned. Since the allocator |
; (uhci_allocate_common) allocates memory sequentially from page start |
; (aligned on 0x1000 bytes), size of the structure must be divisible by 16. |
; (aligned on 0x1000 bytes), block size for the allocator must be |
; divisible by 16; usb1_allocate_general_td ensures this. |
struct uhci_gtd |
NextTD dd ? |
; 1. First bit (bit 0) is Terminate bit. 1 = there is no next TD. |
231,14 → 225,8 |
; bit 0: 1 = short packet is NOT allowed |
; (before the TD is processed, it is the copy of bit 29 of ControlStatus; |
; some controllers modify that bit, so we need a copy in a safe place) |
SoftwarePart rd sizeof.usb_gtd/4 |
; Software part, common for all controllers. |
ends |
if sizeof.uhci_gtd mod 16 |
.err uhci_gtd must be 16-bytes aligned |
end if |
; UHCI requires that the entire transfer buffer should be on one page. |
; If the actual buffer crosses page boundary, uhci_alloc_packet |
; allocates additional memory for buffer for hardware. |
853,7 → 841,7 |
; if either of conditions holds, exit from the internal loop. |
cmp ebx, [esp] |
jz .tddone |
mov eax, [ebx+uhci_gtd.ControlStatus-uhci_gtd.SoftwarePart] |
mov eax, [ebx+uhci_gtd.ControlStatus-sizeof.uhci_gtd] |
test eax, 1 shl 23 ; active? |
jnz .tddone |
; Release the queue lock while processing one descriptor: |
889,10 → 877,10 |
; DEBUGF 1,'K : %x %x %x %x\n',[ebx-4],[ebx],[ebx+4],[ebx+8] |
; 2. If this is IN transfer into special buffer, copy the data |
; to target location. |
mov edx, [ebx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart] |
mov edx, [ebx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd] |
and edx, not 1 ; clear lsb (used for another goal) |
jz .nocopy |
cmp byte [ebx+uhci_gtd.Token-uhci_gtd.SoftwarePart], USB_PID_IN |
cmp byte [ebx+uhci_gtd.Token-sizeof.uhci_gtd], USB_PID_IN |
jnz .nocopy |
; Note: we assume that pointer to buffer is valid in the memory space of |
; the USB thread. This means that buffer must reside in kernel memory |
900,7 → 888,7 |
push esi edi |
mov esi, [edx+uhci_original_buffer.UsedBuffer] |
mov edi, [edx+uhci_original_buffer.OrigBuffer] |
mov ecx, [ebx+uhci_gtd.ControlStatus-uhci_gtd.SoftwarePart] |
mov ecx, [ebx+uhci_gtd.ControlStatus-sizeof.uhci_gtd] |
inc ecx |
and ecx, 7FFh |
mov edx, ecx |
913,8 → 901,8 |
.nocopy: |
; 3. Calculate actual number of bytes transferred. |
; 3a. Read the state. |
mov eax, [ebx+uhci_gtd.ControlStatus-uhci_gtd.SoftwarePart] |
mov ecx, [ebx+uhci_gtd.Token-uhci_gtd.SoftwarePart] |
mov eax, [ebx+uhci_gtd.ControlStatus-sizeof.uhci_gtd] |
mov ecx, [ebx+uhci_gtd.Token-sizeof.uhci_gtd] |
; 3b. Get number of bytes processed. |
lea edx, [eax+1] |
and edx, 7FFh |
938,7 → 926,7 |
xor ecx, ecx |
test eax, 1 shl 22 |
jnz .error |
test byte [ebx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart], 1 |
test byte [ebx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 1 |
jz .notify |
cmp edx, [ebx+usb_gtd.Length] |
jz .notify |
946,7 → 934,7 |
; 5. There was an error while processing this packet. |
; The hardware has stopped processing the queue. |
DEBUGF 1,'K : TD failed:\n' |
if uhci_gtd.SoftwarePart <> 20 |
if sizeof.uhci_gtd <> 20 |
.err modify offsets for debug output |
end if |
DEBUGF 1,'K : %x %x %x %x\n',[ebx-20],[ebx-16],[ebx-12],[ebx-8] |
955,17 → 943,17 |
push edx |
push eax |
mov eax, [ebx+usb_gtd.Pipe] |
DEBUGF 1,'K : pipe: %x %x\n',[eax+0-uhci_pipe.SoftwarePart],[eax+4-uhci_pipe.SoftwarePart] |
DEBUGF 1,'K : pipe: %x %x\n',[eax+0-sizeof.uhci_pipe],[eax+4-sizeof.uhci_pipe] |
; 5b. Store the current TD as an error packet. |
; If an error packet is already stored for this pipe, |
; it is definitely not used already, so free the old packet. |
mov eax, [eax+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart] |
mov eax, [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe] |
test eax, eax |
jz @f |
stdcall uhci_free_td, eax |
@@: |
mov eax, [ebx+usb_gtd.Pipe] |
mov [eax+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart], ebx |
mov [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe], ebx |
; 5c. Traverse the list of descriptors looking for the final packet |
; for this transfer. |
; Free and unlink non-final descriptors, except the current one. |
1019,7 → 1007,7 |
; After that, go to step 6 with ecx = 0 (no error). |
cmp ecx, USB_STATUS_UNDERRUN |
jnz @f |
test byte [ebx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart], 1 |
test byte [ebx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 1 |
jnz @f |
; The controller has stopped this queue on the error packet. |
; Update uhci_pipe.HeadTD to point to the next packet in the queue. |
1026,10 → 1014,10 |
call uhci_fix_toggle |
xor ecx, ecx |
.control: |
mov eax, [ebx+uhci_gtd.NextTD-uhci_gtd.SoftwarePart] |
mov eax, [ebx+uhci_gtd.NextTD-sizeof.uhci_gtd] |
and al, not 0xF |
mov edx, [ebx+usb_gtd.Pipe] |
mov [edx+uhci_pipe.HeadTD-uhci_pipe.SoftwarePart], eax |
mov [edx+uhci_pipe.HeadTD-sizeof.uhci_pipe], eax |
pop edx ; length |
jmp .notify |
@@: |
1047,7 → 1035,7 |
push ecx |
mov eax, [ebx+usb_gtd.Pipe] |
push [ebx+usb_gtd.NextVirt] |
cmp ebx, [eax+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart] |
cmp ebx, [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe] |
jz @f |
stdcall uhci_free_td, ebx |
@@: |
1065,10 → 1053,10 |
cmp [edx+usb_pipe.Type], CONTROL_PIPE |
jz .control |
; Bulk/interrupt transfer; halt the queue. |
mov eax, [ebx+uhci_gtd.NextTD-uhci_gtd.SoftwarePart] |
mov eax, [ebx+uhci_gtd.NextTD-sizeof.uhci_gtd] |
and al, not 0xF |
inc eax ; set Halted bit |
mov [edx+uhci_pipe.HeadTD-uhci_pipe.SoftwarePart], eax |
mov [edx+uhci_pipe.HeadTD-sizeof.uhci_pipe], eax |
pop edx ; restore length saved in step 5a |
.notify: |
; 6. Either the descriptor in ebx was processed without errors, |
1094,7 → 1082,7 |
push [ebx+usb_gtd.NextVirt] |
; 7b. Free the descriptor, unless it is saved as ErrorTD. |
mov eax, [ebx+usb_gtd.Pipe] |
cmp [eax+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart], ebx |
cmp [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe], ebx |
jz @f |
stdcall uhci_free_td, ebx |
@@: |
1118,9 → 1106,9 |
; 2. The hardware expects next packet with toggle = (ErrorTD.toggle xor 1), |
; the current value in next packet is (ebx.toggle xor 1). |
; Nothing to do if ErrorTD.toggle == ebx.toggle. |
mov eax, [ecx+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart] |
mov eax, [eax+uhci_gtd.Token-uhci_gtd.SoftwarePart] |
xor eax, [ebx+uhci_gtd.Token-uhci_gtd.SoftwarePart] |
mov eax, [ecx+uhci_pipe.ErrorTD-sizeof.uhci_pipe] |
mov eax, [eax+uhci_gtd.Token-sizeof.uhci_gtd] |
xor eax, [ebx+uhci_gtd.Token-sizeof.uhci_gtd] |
test eax, 1 shl 19 |
jz .nothing |
; 3. Lock the transfer queue. |
1130,13 → 1118,13 |
; (inclusive). |
mov eax, [ebx+usb_gtd.NextVirt] |
.loop: |
xor byte [eax+uhci_gtd.Token-uhci_gtd.SoftwarePart+2], 1 shl (19-16) |
xor byte [eax+uhci_gtd.Token-sizeof.uhci_gtd+2], 1 shl (19-16) |
cmp eax, [ecx+usb_pipe.LastTD-usb_pipe.Lock] |
mov eax, [eax+usb_gtd.NextVirt] |
jnz .loop |
; 5. Flip the toggle bit in uhci_pipe structure. |
xor byte [ecx+uhci_pipe.Token-uhci_pipe.SoftwarePart-usb_pipe.Lock+2], 1 shl (19-16) |
or dword [ecx+uhci_pipe.Token-uhci_pipe.SoftwarePart-usb_pipe.Lock], eax |
xor byte [ecx+uhci_pipe.Token-sizeof.uhci_pipe-usb_pipe.Lock+2], 1 shl (19-16) |
or dword [ecx+uhci_pipe.Token-sizeof.uhci_pipe-usb_pipe.Lock], eax |
; 6. Unlock the transfer queue. |
call mutex_unlock |
.nothing: |
1338,7 → 1326,7 |
; and stores USB device address in the uhci_pipe structure. |
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address |
proc uhci_set_device_address |
mov byte [ebx+uhci_pipe.Token+1-uhci_pipe.SoftwarePart], cl |
mov byte [ebx+uhci_pipe.Token+1-sizeof.uhci_pipe], cl |
call usb_subscription_done |
ret |
endp |
1347,7 → 1335,7 |
; in: esi -> usb_controller, ebx -> usb_pipe |
; out: eax = endpoint address |
proc uhci_get_device_address |
mov al, byte [ebx+uhci_pipe.Token+1-uhci_pipe.SoftwarePart] |
mov al, byte [ebx+uhci_pipe.Token+1-sizeof.uhci_pipe] |
and eax, 7Fh |
ret |
endp |
1372,8 → 1360,8 |
proc uhci_set_endpoint_packet_size |
dec ecx |
shl ecx, 21 |
and [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart], (1 shl 21) - 1 |
or [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart], ecx |
and [ebx+uhci_pipe.Token-sizeof.uhci_pipe], (1 shl 21) - 1 |
or [ebx+uhci_pipe.Token-sizeof.uhci_pipe], ecx |
; uhci_pipe.Token field is purely for software bookkeeping and does not affect |
; the hardware; thus, we can continue initialization immediately. |
call usb_subscription_done |
1395,18 → 1383,18 |
.interval dd ? |
end virtual |
; 1. Initialize ErrorTD to zero. |
and [edi+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart], 0 |
and [edi+uhci_pipe.ErrorTD-sizeof.uhci_pipe], 0 |
; 2. Initialize HeadTD to the physical address of the first TD. |
push eax ; store pointer to the first TD for step ? |
sub eax, uhci_gtd.SoftwarePart |
push eax ; store pointer to the first TD for step 4 |
sub eax, sizeof.uhci_gtd |
call get_phys_addr |
mov [edi+uhci_pipe.HeadTD-uhci_pipe.SoftwarePart], eax |
mov [edi+uhci_pipe.HeadTD-sizeof.uhci_pipe], eax |
; 3. Initialize Token field: |
; take DeviceAddress and LowSpeedDevice from the parent pipe, |
; take Endpoint and MaximumLength fields from API arguments, |
; set PID depending on pipe type and provided pipe direction, |
; set DataToggle to zero. |
mov eax, [ecx+uhci_pipe.Token-uhci_pipe.SoftwarePart] |
mov eax, [ecx+uhci_pipe.Token-sizeof.uhci_pipe] |
and eax, 0x107F00 ; keep DeviceAddress and LowSpeedDevice |
mov edx, [.endpoint] |
and edx, 15 |
1424,20 → 1412,22 |
jz @f |
mov al, USB_PID_IN |
@@: |
mov [edi+uhci_pipe.Token-uhci_pipe.SoftwarePart], eax |
mov [edi+uhci_pipe.Token-sizeof.uhci_pipe], eax |
; 4. Initialize the first TD: |
; copy Token from uhci_pipe.Token zeroing reserved bit 20, |
; set ControlStatus for future transfers, bit make it inactive, |
; set bit 0 in NextTD = "no next TD". |
; set bit 0 in NextTD = "no next TD", |
; zero OrigBufferInfo. |
pop edx ; restore pointer saved in step 2 |
mov [edx+uhci_gtd.Token-uhci_gtd.SoftwarePart], eax |
and byte [edx+uhci_gtd.Token+2-uhci_gtd.SoftwarePart], not (1 shl (20-16)) |
mov [edx+uhci_gtd.Token-sizeof.uhci_gtd], eax |
and byte [edx+uhci_gtd.Token+2-sizeof.uhci_gtd], not (1 shl (20-16)) |
and eax, 1 shl 20 |
shl eax, 6 |
or eax, UHCI_INVALID_LENGTH + (3 shl 27) |
; not processed, inactive, allow 3 errors |
mov [edx+uhci_gtd.ControlStatus-uhci_gtd.SoftwarePart], eax |
mov [edx+uhci_gtd.NextTD-uhci_gtd.SoftwarePart], 1 |
and [edx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 0 |
mov [edx+uhci_gtd.ControlStatus-sizeof.uhci_gtd], eax |
mov [edx+uhci_gtd.NextTD-sizeof.uhci_gtd], 1 |
; 5. Select the corresponding list and insert to the list. |
; 5a. Use Control list for control pipes, Bulk list for bulk pipes. |
lea edx, [esi+uhci_controller.ControlED.SoftwarePart-sizeof.uhci_controller] |
1471,8 → 1461,8 |
; 5d. Insert in the hardware list: copy previous NextQH to the new pipe, |
; store the physical address of the new pipe to previous NextQH. |
mov ecx, [edx+uhci_static_ep.NextQH-uhci_static_ep.SoftwarePart] |
mov [edi+uhci_pipe.NextQH-uhci_pipe.SoftwarePart], ecx |
lea eax, [edi-uhci_pipe.SoftwarePart] |
mov [edi+uhci_pipe.NextQH-sizeof.uhci_pipe], ecx |
lea eax, [edi-sizeof.uhci_pipe] |
call get_phys_addr |
inc eax |
inc eax |
1486,13 → 1476,13 |
; This procedure is called when a pipe is closing (either due to API call |
; or due to disconnect); it unlinks a pipe from the corresponding list. |
if uhci_static_ep.SoftwarePart <> uhci_pipe.SoftwarePart |
.err uhci_unlink_pipe assumes that uhci_static_ep.SoftwarePart == uhci_pipe.SoftwarePart |
if uhci_static_ep.SoftwarePart <> sizeof.uhci_pipe |
.err uhci_unlink_pipe assumes that uhci_static_ep.SoftwarePart == sizeof.uhci_pipe |
end if |
proc uhci_unlink_pipe |
cmp [ebx+usb_pipe.Type], INTERRUPT_PIPE |
jnz @f |
mov eax, [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart] |
mov eax, [ebx+uhci_pipe.Token-sizeof.uhci_pipe] |
cmp al, USB_PID_IN |
setz ch |
bt eax, 20 |
1510,8 → 1500,8 |
mov [eax+usb_pipe.NextVirt], edx |
; Note: eax could be either usb_pipe or usb_static_ep; |
; fortunately, NextQH and SoftwarePart have same offsets in both. |
mov edx, [ebx+uhci_pipe.NextQH-uhci_pipe.SoftwarePart] |
mov [eax+uhci_pipe.NextQH-uhci_pipe.SoftwarePart], edx |
mov edx, [ebx+uhci_pipe.NextQH-sizeof.uhci_pipe] |
mov [eax+uhci_pipe.NextQH-sizeof.uhci_pipe], edx |
ret |
endp |
1519,7 → 1509,7 |
; For UHCI, this includes usb_pipe structure and ErrorTD, if present. |
proc uhci_free_pipe |
mov eax, [esp+4] |
mov eax, [eax+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart] |
mov eax, [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe] |
test eax, eax |
jz @f |
stdcall uhci_free_td, eax |
1544,7 → 1534,7 |
; with size <= endpoint max packet size. |
; 2. Get the maximum packet size for endpoint from uhci_pipe.Token |
; and generate Token field for TDs. |
mov edi, [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart] |
mov edi, [ebx+uhci_pipe.Token-sizeof.uhci_pipe] |
mov eax, edi |
shr edi, 21 |
inc edi |
1602,14 → 1592,14 |
; transparently to the caller. |
test [flags], 1 |
jz @f |
and byte [ecx+uhci_gtd.ControlStatus+3-uhci_gtd.SoftwarePart], not (1 shl (29-24)) |
and byte [ecx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart], not 1 |
and byte [ecx+uhci_gtd.ControlStatus+3-sizeof.uhci_gtd], not (1 shl (29-24)) |
and byte [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], not 1 |
@@: |
; 6. Update toggle bit in uhci_pipe structure from current value of [token]. |
mov edx, [token] |
xor edx, [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart] |
xor edx, [ebx+uhci_pipe.Token-sizeof.uhci_pipe] |
and edx, 1 shl 19 |
xor [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart], edx |
xor [ebx+uhci_pipe.Token-sizeof.uhci_pipe], edx |
.nothing: |
ret |
.fail: |
1652,12 → 1642,10 |
; 1c. We need a temporary buffer. Allocate [packetSize]*2 bytes, so that |
; there must be [packetSize] bytes on one page, |
; plus space for a header uhci_original_buffer. |
push ebx |
mov eax, [.packetSize] |
add eax, eax |
add eax, sizeof.uhci_original_buffer |
call malloc |
pop ebx |
; 1d. If failed, return zero. |
test eax, eax |
jz .nothing |
1712,31 → 1700,36 |
; mark it as last one (this will be changed when further packets will be |
; allocated), copy Token field from uhci_pipe.Token zeroing bit 20, |
; generate ControlStatus field, mark as Active |
; (for last descriptor, this will be changed by uhci_insert_transfer). |
mov [eax+uhci_gtd.NextTD-uhci_gtd.SoftwarePart], 1 ; no next TD |
mov edx, [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart] |
mov [eax+uhci_gtd.Token-uhci_gtd.SoftwarePart], edx |
and byte [eax+uhci_gtd.Token+2-uhci_gtd.SoftwarePart], not (1 shl (20-16)) |
; (for last descriptor, this will be changed by uhci_insert_transfer), |
; zero OrigBufferInfo (otherwise uhci_free_td would try to free it). |
and [eax+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 0 |
mov [eax+uhci_gtd.NextTD-sizeof.uhci_gtd], 1 ; no next TD |
mov edx, [ebx+uhci_pipe.Token-sizeof.uhci_pipe] |
mov [eax+uhci_gtd.Token-sizeof.uhci_gtd], edx |
and byte [eax+uhci_gtd.Token+2-sizeof.uhci_gtd], not (1 shl (20-16)) |
and edx, 1 shl 20 |
shl edx, 6 |
or edx, UHCI_INVALID_LENGTH + (1 shl 23) + (3 shl 27) |
; not processed, active, allow 3 errors |
mov [eax+uhci_gtd.ControlStatus-uhci_gtd.SoftwarePart], edx |
mov [eax+uhci_gtd.ControlStatus-sizeof.uhci_gtd], edx |
; 5. Initialize remaining fields of the current TD. |
; 5a. Store pointer to the buffer allocated in step 1 (or zero). |
pop [ecx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart] |
pop [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd] |
; 5b. Store physical address of the next TD. |
push eax |
sub eax, uhci_gtd.SoftwarePart |
sub eax, sizeof.uhci_gtd |
call get_phys_addr |
; use Depth traversal unless this is the first TD in the transfer stage; |
; for Control/Bulk pipes, use Depth traversal unless this is the first TD |
; in the transfer stage; |
; uhci_insert_transfer will set Depth traversal for the first TD and clear |
; it in the last TD |
test [ebx+usb_pipe.Type], 1 |
jnz @f |
cmp ecx, [ebx+usb_pipe.LastTD] |
jz @f |
or eax, 4 |
@@: |
mov [ecx+uhci_gtd.NextTD-uhci_gtd.SoftwarePart], eax |
mov [ecx+uhci_gtd.NextTD-sizeof.uhci_gtd], eax |
; 5c. Store physical address of the buffer: zero if no data present, |
; the temporary buffer if it was allocated, the given buffer otherwise. |
xor eax, eax |
1743,7 → 1736,7 |
cmp [.packetSize], eax |
jz .hasphysbuf |
mov eax, [.buffer] |
mov edx, [ecx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart] |
mov edx, [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd] |
test edx, edx |
jz @f |
mov eax, [edx+uhci_original_buffer.UsedBuffer] |
1750,7 → 1743,7 |
@@: |
call get_phys_addr |
.hasphysbuf: |
mov [ecx+uhci_gtd.Buffer-uhci_gtd.SoftwarePart], eax |
mov [ecx+uhci_gtd.Buffer-sizeof.uhci_gtd], eax |
; 5d. For IN transfers, disallow short packets. |
; This will be overridden, if needed, by uhci_alloc_transfer. |
mov eax, [.token] |
1758,13 → 1751,13 |
dec edx |
cmp al, USB_PID_IN |
jnz @f |
or byte [ecx+uhci_gtd.ControlStatus+3-uhci_gtd.SoftwarePart], 1 shl (29-24) ; disallow short packets |
or byte [ecx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart], 1 |
or byte [ecx+uhci_gtd.ControlStatus+3-sizeof.uhci_gtd], 1 shl (29-24) ; disallow short packets |
or byte [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 1 |
@@: |
; 5e. Get Token field: combine [.token] with [.packetSize]. |
shl edx, 21 |
or edx, eax |
mov [ecx+uhci_gtd.Token-uhci_gtd.SoftwarePart], edx |
mov [ecx+uhci_gtd.Token-sizeof.uhci_gtd], edx |
; 6. Flip toggle bit in [.token]. |
xor eax, 1 shl 19 |
mov [.token], eax |
1785,11 → 1778,14 |
; ecx -> last descriptor for the transfer, ebx -> usb_pipe |
proc uhci_insert_transfer |
; DEBUGF 1,'K : uhci_insert_transfer: eax=%x, ecx=%x, [esp+4]=%x\n',eax,ecx,[esp+4] |
and byte [eax+uhci_gtd.ControlStatus+2-uhci_gtd.SoftwarePart], not (1 shl (23-16)) ; clear Active bit |
or byte [ecx+uhci_gtd.ControlStatus+3-uhci_gtd.SoftwarePart], 1 shl (24-24) ; set InterruptOnComplete bit |
and byte [eax+uhci_gtd.ControlStatus+2-sizeof.uhci_gtd], not (1 shl (23-16)) ; clear Active bit |
or byte [ecx+uhci_gtd.ControlStatus+3-sizeof.uhci_gtd], 1 shl (24-24) ; set InterruptOnComplete bit |
mov eax, [esp+4] |
or byte [eax+uhci_gtd.ControlStatus+2-uhci_gtd.SoftwarePart], 1 shl (23-16) ; set Active bit |
or byte [eax+uhci_gtd.NextTD-uhci_gtd.SoftwarePart], 4 ; set Depth bit |
or byte [eax+uhci_gtd.ControlStatus+2-sizeof.uhci_gtd], 1 shl (23-16) ; set Active bit |
test [ebx+usb_pipe.Type], 1 |
jnz @f |
or byte [eax+uhci_gtd.NextTD-sizeof.uhci_gtd], 4 ; set Depth bit |
@@: |
ret |
endp |
1798,7 → 1794,7 |
; and the temporary buffer, if present. |
proc uhci_free_td |
mov eax, [esp+4] |
mov eax, [eax+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart] |
mov eax, [eax+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd] |
and eax, not 1 |
jz .nobuf |
push ebx |
1805,6 → 1801,6 |
call free |
pop ebx |
.nobuf: |
sub dword [esp+4], uhci_gtd.SoftwarePart |
sub dword [esp+4], sizeof.uhci_gtd |
jmp usb_free_common |
endp |
/kernel/branches/Kolibri-acpi/const.inc |
---|
272,6 → 272,11 |
BOOT_APM_CODE_32 equ 0x9050 |
BOOT_APM_CODE_16 equ 0x9052 |
BOOT_APM_DATA_16 equ 0x9054 |
BOOT_IDE_BAR0_16 equ 0x9056 |
BOOT_IDE_BAR1_16 equ 0x9058 |
BOOT_IDE_BAR2_16 equ 0x905A |
BOOT_IDE_BAR3_16 equ 0x905C |
BOOT_IDE_PI_16 equ 0x905E |
TMP_FILE_NAME equ 0 |
TMP_CMD_LINE equ 1024 |
/kernel/branches/Kolibri-acpi/core/malloc.inc |
---|
22,7 → 22,7 |
; |
align 4 |
malloc: |
push esi |
push ebx esi |
; nb = ((size+7)&~7)+8; |
96,7 → 96,7 |
mov ecx, mst.mutex |
call mutex_unlock |
mov eax, esi |
pop esi |
pop esi ebx |
ret |
.split: |
205,7 → 205,7 |
test eax, eax |
jz .exit |
push edi |
push ebx edi |
mov edi, eax |
add edi, -8 |
298,7 → 298,7 |
mov eax, esi |
pop esi |
.fail: |
pop edi |
pop edi ebx |
.exit: |
ret |
/kernel/branches/Kolibri-acpi/core/v86.inc |
---|
896,6 → 896,7 |
iretd |
.found: |
mov cr3, eax |
mov esi, [ebx+APPDATA.saved_esp0] |
sub word [esi-sizeof.v86_regs+v86_regs.esp], 6 |
mov ecx, [esi-sizeof.v86_regs+v86_regs.eip] |
mov word [edx], cx |
916,7 → 917,7 |
call update_counters |
lea edi, [ebx + 0x100000000 - SLOT_BASE] |
shr edi, 3 |
add edi, TASK_DATA |
add edi, CURRENT_TASK |
call find_next_task.found |
call do_change_task |
popad |
/kernel/branches/Kolibri-acpi/detect/dev_hdcd.inc |
---|
44,6 → 44,8 |
jmp EndFindHDD |
FindHDD_1: |
DEBUGF 1, "K : Channel %d ",[ChannelNumber]:2 |
DEBUGF 1, "Disk %d\n",[DiskNumber]:1 |
call ReadHDD_ID |
cmp [DevErrorCode], 0 |
jne FindHDD_2 |
52,7 → 54,7 |
cmp [Sector512+12], word 255 |
ja FindHDD_2 |
inc byte [DRIVE_DATA+1] |
jmp FindHDD_2_2 |
jmp Print_Device_Name |
FindHDD_2: |
call DeviceReset |
cmp [DevErrorCode], 0 |
62,6 → 64,21 |
jne FindHDD_2_2 |
inc byte [DRIVE_DATA+1] |
inc byte [DRIVE_DATA+1] |
Print_Device_Name: |
pushad |
pushfd |
mov esi, Sector512+27*2 |
mov edi, dev_name |
mov ecx, 20 |
cld |
@@: |
lodsw |
xchg ah, al |
stosw |
loop @b |
popfd |
popad |
DEBUGF 1, "K : Dev: %s \n", dev_name |
FindHDD_2_2: |
ret |
70,10 → 87,11 |
shl byte [DRIVE_DATA+1], 2 |
ret |
; Адрес считываемого сектора в режиме LBA |
uglobal |
SectorAddress DD ? |
dev_name: |
rb 41 |
endg |
;************************************************* |
;* ЧТЕНИЕ ИДЕНТИФИКАТОРА ЖЕСТКОГО ДИСКА * |
/kernel/branches/Kolibri-acpi/detect/getcache.inc |
---|
206,7 → 206,4 |
ret |
end_get_cache: |
; mov [cache_ide0_pointer],HD_CACHE |
; mov [cache_ide0_system_data],HD_CACHE+65536 |
; mov [cache_ide0_system_sad_size],1919 |
popa |
/kernel/branches/Kolibri-acpi/detect/sear_par.inc |
---|
17,7 → 17,8 |
search_partitions_ide0: |
test [DRIVE_DATA+1], byte 0x40 |
jz search_partitions_ide1 |
mov [hdbase], 0x1f0 |
mov eax, [hd_address_table] |
mov [hdbase], eax ;0x1f0 |
mov [hdid], 0x0 |
mov [hdpos], 1 |
mov [known_part], 1 |
39,7 → 40,8 |
search_partitions_ide1: |
test [DRIVE_DATA+1], byte 0x10 |
jz search_partitions_ide2 |
mov [hdbase], 0x1f0 |
mov eax, [hd_address_table] |
mov [hdbase], eax ;0x1f0 |
mov [hdid], 0x10 |
mov [hdpos], 2 |
mov [known_part], 1 |
61,7 → 63,8 |
search_partitions_ide2: |
test [DRIVE_DATA+1], byte 0x4 |
jz search_partitions_ide3 |
mov [hdbase], 0x170 |
mov eax, [hd_address_table+16] |
mov [hdbase], eax ;0x170 |
mov [hdid], 0x0 |
mov [hdpos], 3 |
mov [known_part], 1 |
83,7 → 86,8 |
search_partitions_ide3: |
test [DRIVE_DATA+1], byte 0x1 |
jz end_search_partitions_ide |
mov [hdbase], 0x170 |
mov eax, [hd_address_table+16] |
mov [hdbase], eax ;0x170 |
mov [hdid], 0x10 |
mov [hdpos], 4 |
mov [known_part], 1 |
/kernel/branches/Kolibri-acpi/docs/sysfuncr.txt |
---|
1794,6 → 1794,23 |
* При создании процесса/потока текущая папка наследуется от |
родителя. |
---- Подфункция 3 - установить доп. системную директорию для ядра ---- |
Параметры: |
* eax = 30 - номер функции |
* ebx = 3 - номер подфункции |
* ecx = указатель на блок данных: |
sysdir_name rb 64 |
sysdir_path rb 64 |
Пример: |
dir_name1 db 'addappl',0 |
rb 64-8 |
dir_path1 db 'HD0/1',0 |
rb 64-6 |
Возвращаемое значение: |
* функция не возвращает значения |
Замечания: |
* Функция может быть вызвана только 1 раз за 1 сессию работы ОС. |
====================================================================== |
========= Функция 34 - узнать кому принадлежит точка экрана. ========= |
====================================================================== |
/kernel/branches/Kolibri-acpi/docs/sysfuncs.txt |
---|
1776,6 → 1776,23 |
* At process/thread creation the current folder will be inherited |
from the parent. |
--- Subfunction 3 - install the add.system directory for the kernel -- |
Parameters: |
* eax = 30 - function number |
* ebx = 3 - subfunction number |
* ecx = pointer to a block of data: |
sysdir_name rb 64 |
sysdir_path rb 64 |
For example: |
dir_name1 db 'addappl',0 |
rb 64-8 |
dir_path1 db 'HD0/1',0 |
rb 64-6 |
Returned value: |
* function does not return value |
Remarks: |
* The function can be called only 1 time for 1 session of the OS. |
====================================================================== |
========= Function 34 - who owner the pixel on the screen. =========== |
====================================================================== |
/kernel/branches/Kolibri-acpi/drivers/vidintel.asm |
---|
310,7 → 310,9 |
end if |
and byte [esi+7000Bh], not 80h ; PIPEACONF: disable pipe |
and byte [esi+7100Bh], not 80h ; PIPEBCONF: disable pipe |
if 1 |
cmp [deviceType], gen4_start |
jb .wait_watching_scanline |
; g45 and later: use special flag from PIPE*CONF |
mov edx, 10000h |
@@: |
mov ecx, 1000h |
319,20 → 321,17 |
jz @f |
dec edx |
jnz @b |
.not_disabled: |
sti |
jmp .return |
jmp .not_disabled |
@@: |
test byte [esi+7100Bh], 40h ; PIPEBCONF: wait until pipe disabled |
jz @f |
jz .disabled |
mov ecx, 1000h |
loop $ |
dec edx |
jnz @b |
jmp .not_disabled |
@@: |
else |
; alternative way of waiting for pipe stop, works too |
; pineview and before: wait while scanline still changes |
.wait_watching_scanline: |
mov edx, 1000h |
.dis1: |
push dword [esi+71000h] |
354,7 → 353,6 |
sti |
jmp .return |
.disabled: |
end if |
lea eax, [esi+61183h] |
cmp [deviceType], ironlake_start |
jb @f |
378,6 → 376,7 |
and ecx, not 15 |
shl ecx, 2 |
mov dword [edx+10188h], ecx ; DSPASTRIDE: set scanline length |
mov dword [edx+10184h], 0 ; DSPALINOFF: force write to DSPA* registers |
and byte [esi+61233h], not 80h ; PFIT_CONTROL: disable panel fitting |
or byte [edx+1000Bh], 80h ; PIPEACONF: enable pipe |
; and byte [edx+1000Ah], not 0Ch ; PIPEACONF: enable Display+Cursor Planes |
437,6 → 436,9 |
dw 0x29b2 ; q35g |
dw 0x29c2 ; g33g |
dw 0x29d2 ; q33g |
dw 0xa001 ; pineview |
dw 0xa011 ; pineview |
gen4_start = ($ - pciids) / 2 |
dw 0x2a02 ; i965gm |
dw 0x2a12 ; i965gm |
dw 0x2a42 ; gm45 |
446,8 → 448,6 |
dw 0x2e32 ; g45 |
dw 0x2e42 ; g45 |
dw 0x2e92 ; g45 |
dw 0xa001 ; pineview |
dw 0xa011 ; pineview |
ironlake_start = ($ - pciids) / 2 |
dw 0x0042 ; ironlake_d |
dw 0x0046 ; ironlake_m |
/kernel/branches/Kolibri-acpi/fs/ext2.inc |
---|
4,8 → 4,8 |
;; Distributed under terms of the GNU General Public License ;; |
;; 02.02.2010 turbanoff - support 70.5 ;; |
;; 23.01.2010 turbanoff - support 70.0 70.1 ;; |
;; 21.06.2013 yogev_ezra - Translate Russian comments ;; |
;; ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
17,31 → 17,34 |
EXT2_BOOT_LOADER_INO = 5 |
EXT2_UNDEL_DIR_INO = 6 |
;флаги, указываемый в inode файла |
;RUS: флаги, указываемые в inode файла ;ENG: flags specified in file inode |
EXT2_S_IFREG = 0x8000 |
EXT2_S_IFDIR = 0x4000 |
EXT2_S_IFMT = 0xF000 ;маска для типа файла |
EXT2_S_IFMT = 0xF000 ;RUS: маска для типа файла ;ENG: mask for file type |
;флаги, указываемые в linked list родительской папки |
EXT2_FT_REG_FILE = 1 ;это файл, запись в родительском каталоге |
EXT2_FT_DIR = 2 ;это папка |
;RUS: флаги, указываемые в linked list родительской папки |
;ENG: flags specified in linked list of parent folder |
EXT2_FT_REG_FILE = 1 ;RUS: это файл, запись в родительском каталоге |
;ENG: this is a file, record in parent catalog |
EXT2_FT_DIR = 2 ;RUS: это папка ;ENG: this is a folder |
;флаги используемые KolibriOS |
;RUS: флаги используемые KolibriOS ;ENG: flags used by KolibriOS |
FS_FT_HIDDEN = 2 |
FS_FT_DIR = 0x10 ;это папка |
FS_FT_ASCII = 0 ;имя в ascii |
FS_FT_UNICODE = 1 ;имя в unicode |
FS_FT_DIR = 0x10 ;RUS: это папка ;ENG: this is a folder |
FS_FT_ASCII = 0 ;RUS: имя в ascii ;ENG: name in ASCII |
FS_FT_UNICODE = 1 ;RUS: имя в unicode ;ENG: name in UNICODE |
EXT2_FEATURE_INCOMPAT_FILETYPE = 0x0002 ;тип файла должен указываться в директории |
EXT4_FEATURE_INCOMPAT_EXTENTS = 0x0040 ;экстенты |
EXT4_FEATURE_INCOMPAT_FLEX_BG = 0x0200 ;гибкие группы блоков |
;реализованные ext[234] features |
EXT2_FEATURE_INCOMPAT_FILETYPE = 0x0002 ;RUS: тип файла должен указываться в директории |
;ENG: file type must be specified in the folder |
EXT4_FEATURE_INCOMPAT_EXTENTS = 0x0040 ;RUS: экстенты ;ENG: extents |
EXT4_FEATURE_INCOMPAT_FLEX_BG = 0x0200 ;RUS: гибкие группы блоков ;ENG: flexible block groups |
;RUS: реализованные ext[234] features ;ENG: implemented ext[234] features |
EXT4_FEATURE_INCOMPAT_SUPP = EXT2_FEATURE_INCOMPAT_FILETYPE \ |
or EXT4_FEATURE_INCOMPAT_EXTENTS \ |
or EXT4_FEATURE_INCOMPAT_FLEX_BG |
;флаги, указываемые для inode в i_flags |
;RUS: флаги, указываемые для inode в i_flags ;ENG: flags specified for inode in i_flags |
EXT2_EXTENTS_FL = 0x00080000 |
struct EXT2_INODE_STRUC |
147,26 → 150,31 |
log_groups_per_flex db ? ;+372 |
ends |
struct EXT4_EXTENT_HEADER ;заголовок блока экстентов/индексов |
eh_magic dw ? ;в текущей реализации ext4 должно быть 0xF30A |
eh_entries dw ? ;количество экстентов/индексов в блоке |
eh_max dw ? ;max количество (используется при записи) |
eh_depth dw ? ;глубина дерева (0, если это блок экстентов) |
struct EXT4_EXTENT_HEADER ;RUS: заголовок блока экстентов/индексов |
eh_magic dw ? ;RUS: в текущей реализации ext4 должно быть 0xF30A |
eh_entries dw ? ;RUS: количество экстентов/индексов в блоке |
eh_max dw ? ;RUS: max количество (используется при записи) |
eh_depth dw ? ;RUS: глубина дерева (0, если это блок экстентов) |
eh_generation dd ? ;??? |
ends |
struct EXT4_EXTENT ;экстент |
ee_block dd ? ;номер ext4 блока |
ee_len dw ? ;длина экстента |
ee_start_hi dw ? ;старшие 16 бит 48-битного адреса (пока не используются в KOS) |
ee_start_lo dd ? ;младшие 32 бита 48-битного адреса |
struct EXT4_EXTENT ;RUS: экстент ;ENG: extent |
ee_block dd ? ;RUS: номер ext4 блока ;ENG: number of ext4 block |
ee_len dw ? ;RUS: длина экстента ;ENG: extent length |
ee_start_hi dw ? ;RUS: старшие 16 бит 48-битного адреса (пока не используются в KOS) |
;ENG: upper 16 bits of the 48-bit address (not used in KolibriOS yet) |
ee_start_lo dd ? ;RUS: младшие 32 бита 48-битного адреса |
;ENG: lower 32 bits of the 48-bit address |
ends |
struct EXT4_EXTENT_IDX ;индес - указатель на блок с экстентами/индексами |
ei_block dd ? ;номер ext4 блока |
ei_leaf_lo dd ? ;младшие 32 бит 48-битного адреса |
ei_leaf_hi dw ? ;старшие 16 бит 48-битного адреса (пока не используются в KOS) |
ei_unused dw ? ;зарезервировано |
struct EXT4_EXTENT_IDX ;RUS: индекс - указатель на блок с экстентами/индексами |
;ENG: index - pointer to block of extents/indexes |
ei_block dd ? ;RUS: номер ext4 блока ;ENG: number of ext4 block |
ei_leaf_lo dd ? ;RUS: младшие 32 бит 48-битного адреса |
;ENG: lower 32 bits of the 48-bit address |
ei_leaf_hi dw ? ;RUS: старшие 16 бит 48-битного адреса (пока не используются в KOS) |
;ENG: upper 16 bits of the 48-bit address (not used in KolibriOS yet) |
ei_unused dw ? ;RUS: зарезервировано ;ENG: reserved |
ends |
ext2_test_superblock: |
230,7 → 238,7 |
shl eax, 7 |
mov [ext2_data.count_pointer_in_block], eax |
mov edx, eax ; потом еще квадрат найдем |
mov edx, eax ;RUS: потом еще квадрат найдем ;ENG: we'll find a square later |
shl eax, 2 |
mov [ext2_data.block_size], eax |
294,11 → 302,11 |
;=================================================================== |
;получает номер блока из extent inode |
;in: ecx = номер блока по порядку |
; ebp = адрес extent header`а |
;out: ecx - адрес очередного блока в случае успеха |
; eax - номер ошибки (если равно 0, то ошибки нет) |
;RUS: получает номер блока из extent inode ;ENG: receives block number from extent inode |
;RUS: in: ecx = номер блока по порядку ;ENG: in: ecx = consecutive block number |
;RUS: ebp = адрес extent header`а ;ENG: ebp = address of extent header |
;RUS: out: ecx - адрес очередного блока в случае успеха ;ENG: out: ecx - address of next block, if successful |
;RUS: eax - номер ошибки (если равно 0, то ошибки нет) ;ENG: eax - error number (0 - no error) |
ext4_block_recursive_search: |
cmp word [ebp + EXT4_EXTENT_HEADER.eh_magic], 0xF30A ;EXT4_EXT_MAGIC |
jne .fail |
369,10 → 377,10 |
;=================================================================== |
;получает адрес ext2 блока из inode с определнным номером |
;in: ecx = номер блока в inode (0..) |
; ebp = адрес inode |
;out: ecx = адрес очередного блока |
; eax - error code |
;RUS: in: ecx = номер блока в inode (0..) ;ENG: in: ecx = number of block in inode (0..) |
;RUS: ebp = адрес inode ;ENG: ebp = inode address |
;RUS: out: ecx = адрес очередного блока ;ENG: out: ecx = next block address |
;RUS: eax - error code ;ENG: eax - error code |
ext2_get_inode_block: |
test [ebp + EXT2_INODE_STRUC.i_flags], EXT2_EXTENTS_FL |
jz @F |
411,7 → 419,8 |
mov eax, ecx |
div [ext2_data.count_pointer_in_block_square] |
;eax - номер в полученном блоке edx - номер дальше |
;RUS: eax - номер в полученном блоке edx - номер дальше |
;ENG: eax - current block number, edx - next block number |
mov eax, [ebx + eax*4] |
call ext2_get_block |
test eax, eax |
450,9 → 459,9 |
mov ebx, [ext2_data.ext2_temp_block] |
call ext2_get_block |
test eax, eax |
jnz @F ;если не было ошибки |
jnz @F ;RUS: если не было ошибки ;ENG: if there was no error |
mov ecx, [ebx + ecx*4] ;заносим результат |
mov ecx, [ebx + ecx*4] ;RUS: заносим результат ;ENG: ??? |
@@: |
pop ebx |
ret |
481,8 → 490,10 |
mov edx, 32 |
mul edx ; address block_group in global_desc_table |
; в eax - смещение группы с inode-ом относительно начала глобальной дескрипторной таблицы |
; найдем блок в котором он находится |
;RUS: в eax - смещение группы с inode-ом относительно начала глобальной дескрипторной таблицы |
;RUS: найдем блок в котором он находится |
;ENG: in eax - inode group offset relative to global descriptor table start |
;ENG: let's find the block this inode is in |
div [ext2_data.block_size] |
add eax, [ecx + EXT2_SB_STRUC.first_data_block] |
inc eax |
491,32 → 502,32 |
test eax, eax |
jnz .fail |
add ebx, edx ; локальный номер в блоке |
mov eax, [ebx + EXT2_BLOCK_GROUP_DESC.inode_table]; номер блока - в терминах ext2 |
add ebx, edx ;RUS: локальный номер в блоке ;ENG: local number inside block |
mov eax, [ebx + EXT2_BLOCK_GROUP_DESC.inode_table] ;RUS: номер блока - в терминах ext2 |
;ENG: block number - in ext2 terms |
mov ecx, [ext2_data.log_block_size] |
shl eax, cl |
add eax, [PARTITION_START] ; а старт раздела - в терминах hdd (512) |
add eax, [PARTITION_START] ;RUS: а старт раздела - в терминах hdd (512) |
;ENG: partition start - in HDD terms (512) |
;RUS: eax - указывает на таблицу inode-ов на hdd ;ENG: eax - points to inode table on HDD |
mov esi, eax ;RUS: сохраним его пока в esi ;ENG: let's save it in esi for now |
;eax - указывает на таблицу inode-ов на hdd |
mov esi, eax ;сохраним его пока в esi |
; прибавим локальный адрес inode-а |
;RUS: прибавим локальный адрес inode-а ;ENG: add local address of inode |
pop eax ; index |
mov ecx, [ext2_data.inode_size] |
mul ecx ; (index * inode_size) |
mov ebp, 512 |
div ebp ;поделим на размер блока |
div ebp ;RUS: поделим на размер блока ;ENG: divide by block size |
add eax, esi ;нашли адрес блока для чтения |
add eax, esi ;RUS: нашли адрес блока для чтения ;ENG: found block address to read |
mov ebx, [ext2_data.ext2_temp_block] |
call hd_read |
cmp [hd_error], 0 |
jnz .fail |
mov esi, edx ;добавим "остаток" |
add esi, ebx ;к адресу |
rep movsb ;копируем inode |
mov esi, edx ;RUS: добавим "остаток" ;ENG: add the "remainder" |
add esi, ebx ;RUS: к адресу ;ENG: to the address |
rep movsb ;RUS: копируем inode ;ENG: copy inode |
xor eax, eax |
.fail: |
mov PUSHAD_EAX, eax |
745,7 → 756,8 |
lea esp, [edi + 32] |
xor eax, eax ;зарезервировано: нули в текущей реализации |
xor eax, eax ;RUS: зарезервировано: нули в текущей реализации |
;ENG: reserved: zeros in current implementation |
lea edi, [edx + 12] |
mov ecx, 20 / 4 |
rep stosd |
760,12 → 772,12 |
or ebx, -1 |
ret |
.error_empty_dir: ;inode папки без блоков |
.error_root: ;root - не папка |
.error_empty_dir: ;RUS: inode папки без блоков ;ENG: inode of folder without blocks |
.error_root: ;RUS: root - не папка ;ENG: root is not a folder |
mov eax, ERROR_FS_FAIL |
jmp .error_ret |
.error_not_found: ;файл не найден |
.error_not_found: ;RUS: файл не найден ;ENG: file not found |
mov eax, ERROR_FILE_NOT_FOUND |
jmp .error_ret |
867,9 → 879,9 |
jz @F |
mov esi, ebx ; esi = pointer to first_wanted |
mov ebx, [esi+4] |
mov eax, [esi] ; ebx : eax - стартовый номер байта |
mov eax, [esi] ;RUS: ebx : eax - стартовый номер байта ;ENG: ebx : eax - start byte number |
;///// сравним хватит ли нам файла или нет |
;RUS: ///// сравним хватит ли нам файла или нет ;ENG: ///// check if file is big enough for us |
cmp [ebp + EXT2_INODE_STRUC.i_dir_acl], ebx |
ja .size_great |
jb .size_less |
886,7 → 898,8 |
xor ebx, ebx |
xor eax, eax |
.size_great: |
add eax, ecx ;add to first_wanted кол-во байт для чтения |
add eax, ecx ;RUS: add to first_wanted кол-во байт для чтения |
;ENG: add to first_wanted number of bytes to read |
adc ebx, 0 |
cmp [ebp + EXT2_INODE_STRUC.i_dir_acl], ebx |
893,16 → 906,16 |
ja .size_great_great |
jb .size_great_less |
cmp [ebp + EXT2_INODE_STRUC.i_size], eax |
jae .size_great_great |
jae .size_great_great ; and if it's equal, no matter where we jump |
.size_great_less: |
push 1 ;читаем по границе размера |
push 1 ;RUS: читаем по границе размера ;ENG: reading till the end of file |
mov ecx, [ebp + EXT2_INODE_STRUC.i_size] |
sub ecx, [esi] ;(размер - старт) = сколько читать |
sub ecx, [esi] ;RUS: (размер - старт) = сколько читать ;ENG: to read = (size - start) |
jmp @F |
.size_great_great: |
push 0 ;читаем столько сколько запросили |
push 0 ;RUS: читаем столько, сколько запросили ;ENG: reading as much as requested |
@@: |
;здесь мы точно знаем сколько байт читать - ecx |
934,7 → 947,8 |
add ebx, edx |
neg edx |
add edx, [ext2_data.block_size] ;block_size - стартовый байт = сколько байт 1-го блока |
add edx, [ext2_data.block_size] ;RUS: block_size - стартовый байт = сколько байт 1-го блока |
;ENG: block_size - start byte = number of bytes in 1st block |
cmp ecx, edx |
jbe .only_one_block |
943,7 → 957,7 |
mov ecx, edx |
mov esi, ebx |
rep movsb ;кусок 1-го блока |
rep movsb ;RUS: кусок 1-го блока ;ENG: part of 1st block |
jmp .calc_blocks_count |
.zero_start: |
1031,7 → 1045,7 |
ext2_test_block_by_name: |
sub esp, 256 ;EXT2_filename |
mov edx, ebx |
add edx, [ext2_data.block_size] ;запомним конец блока |
add edx, [ext2_data.block_size] ;RUS: запомним конец блока ;ENG: save block end |
.start_rec: |
cmp [ebx + EXT2_DIR_STRUC.inode], 0 |
1045,7 → 1059,7 |
mov ecx, edi |
lea edi, [esp + 4] |
sub ecx, edi ;кол-во байт в получившейся строке |
sub ecx, edi ;RUS: кол-во байт в получившейся строке ;ENG: number of bytes in resulting string |
mov esi, [esp] |
@@: |
1061,12 → 1075,12 |
call char_toupper |
cmp al, ah |
je @B |
@@: ;не подошло |
@@: ;RUS: не подошло ;ENG: didn't fit |
pop esi |
.next_rec: |
movzx eax, [ebx + EXT2_DIR_STRUC.rec_len] |
add ebx, eax ;к след. записи |
cmp ebx, edx ;проверим конец ли |
add ebx, eax ;RUS: к след. записи ;ENG: go to next record |
cmp ebx, edx ;RUS: проверим конец ли ;ENG: check if this is the end |
jb .start_rec |
add esp, 256 |
ret |
1073,7 → 1087,7 |
.test_find: |
cmp byte [esi], 0 |
je .ret ;нашли конец |
je .ret ;RUS: нашли конец ;ENG: the end reached |
cmp byte [esi], '/' |
jne @B |
inc esi |
1111,27 → 1125,28 |
call ext2_test_block_by_name |
pop edi ecx |
cmp edi, esi ;нашли имя? |
je .next_folder_block ;не нашли -> к след. блоку |
cmp edi, esi ;RUS: нашли имя? ;ENG: did we find a name? |
je .next_folder_block ;RUS: не нашли -> к след. блоку ;ENG: we didn't -> moving to next block |
cmp byte [esi], 0 ;дошли до "конца" пути -> возваращаемся |
cmp byte [esi], 0 ;RUS: дошли до "конца" пути -> возваращаемся |
;ENG: reached the "end" of path -> returning |
jz .get_inode_ret |
cmp [ebx + EXT2_DIR_STRUC.file_type], EXT2_FT_DIR ;нашли, но это не папка |
jne .not_found |
cmp [ebx + EXT2_DIR_STRUC.file_type], EXT2_FT_DIR ;RUS: нашли, но это не папка |
jne .not_found ;ENG: found, but it's not a folder |
mov eax, [ebx + EXT2_DIR_STRUC.inode] |
mov ebx, [ext2_data.ext2_save_inode] ;все же папка. |
mov ebx, [ext2_data.ext2_save_inode] ;RUS: все же папка. ;ENG: it's a folder afterall |
call ext2_get_inode |
test eax, eax |
jnz .error_get_inode |
pop ecx ;в стеке лежит кол-во блоков |
pop ecx ;RUS: в стеке лежит кол-во блоков ;ENG: stack top contains number of blocks |
mov ebp, ebx |
jmp .next_path_part |
.next_folder_block: |
;к следующему блоку в текущей папке |
pop eax ;счетчик блоков |
pop eax ;RUS: счетчик блоков ;ENG: blocks counter |
sub eax, [ext2_data.count_block_in_block] |
jle .not_found |
1144,8 → 1159,8 |
ret |
.get_inode_ret: |
pop ecx ;в стеке лежит кол-во блоков |
mov dl, [ebx + EXT2_DIR_STRUC.name] ;в dl - первый символ () |
pop ecx ;RUS: в стеке лежит кол-во блоков ;ENG: stack top contains number of blocks |
mov dl, [ebx + EXT2_DIR_STRUC.name] ;RUS: в dl - первый символ () ;ENG: ??? |
mov eax, [ebx + EXT2_DIR_STRUC.inode] |
mov ebx, [ext2_data.ext2_save_inode] |
call ext2_get_inode |
1182,7 → 1197,7 |
ret |
.is_root: |
xor ebx, ebx ;root не может быть скрытым |
xor ebx, ebx ;RUS: root не может быть скрытым ;ENG: root cannot be hidden |
mov ebp, [ext2_data.root_inode] |
@@: |
xor eax, eax |
/kernel/branches/Kolibri-acpi/fs/fat32.inc |
---|
166,10 → 166,8 |
; FAT size requires knowledge of some calculated values, which are also used |
; in the normal operation, let's hope for the best and allocate data now; if |
; it will prove wrong, just deallocate it. |
push ebx |
movi eax, sizeof.FAT |
call malloc |
pop ebx |
test eax, eax |
jz .return0 |
mov ecx, [ebp+8] |
2441,7 → 2439,6 |
pop eax |
lea ebx, [ebp+FAT.buffer] |
call fs_write32_sys |
pop edi |
test eax, eax |
jz @f |
push ERROR_DEVICE |
/kernel/branches/Kolibri-acpi/fs/fs_lfn.inc |
---|
525,25 → 525,29 |
fs_OnHd0: |
call reserve_hd1 |
mov [hdbase], 0x1F0 |
mov eax, [hd_address_table] |
mov [hdbase], eax ;0x1F0 |
mov [hdid], 0 |
push 1 |
jmp fs_OnHd |
fs_OnHd1: |
call reserve_hd1 |
mov [hdbase], 0x1F0 |
mov eax, [hd_address_table] |
mov [hdbase], eax ;0x1F0 |
mov [hdid], 0x10 |
push 2 |
jmp fs_OnHd |
fs_OnHd2: |
call reserve_hd1 |
mov [hdbase], 0x170 |
mov eax, [hd_address_table+16] |
mov [hdbase], eax ;0x170 |
mov [hdid], 0 |
push 3 |
jmp fs_OnHd |
fs_OnHd3: |
call reserve_hd1 |
mov [hdbase], 0x170 |
mov eax, [hd_address_table+16] |
mov [hdbase], eax ;0x170 |
mov [hdid], 0x10 |
push 4 |
fs_OnHd: |
932,24 → 936,30 |
pop eax |
inc eax |
ret |
;----------------------------------------------------------------------------- |
process_replace_file_name: |
; in |
; esi - path with filename(f.70) |
; |
; out |
; ebp - full filename |
pushfd |
cli |
mov ebp, [full_file_name_table] |
mov edi, [full_file_name_table.size] |
dec edi |
shl edi, 7 |
add edi, ebp |
xor edi, edi |
.loop: |
cmp edi, ebp |
jb .notfound |
cmp edi, [full_file_name_table.size] |
jae .notfound |
push esi edi |
shl edi, 7 ; edi*128 |
add edi, ebp |
@@: |
cmp byte [edi], 0 |
cmp byte [edi], 0 ; end of dir_name |
jz .dest_done |
lodsb |
test al, al |
jz .cont |
or al, 20h |
or al, 20h ; 32 - space char |
scasb |
jz @b |
jmp .cont |
962,10 → 972,12 |
jmp .found |
.cont: |
pop edi esi |
sub edi, 128 |
inc edi |
jmp .loop |
.found: |
pop edi eax |
shl edi, 7 ; edi*128 |
add edi, ebp |
mov ebp, esi |
cmp byte [esi], 0 |
lea esi, [edi+64] |
973,7 → 985,12 |
.notfound: |
xor ebp, ebp |
.ret: |
popfd |
ret |
;----------------------------------------------------------------------------- |
uglobal |
lock_flag_for_f30_3 rb 1 |
endg |
sys_current_directory: |
; mov esi, [current_slot] |
988,7 → 1005,45 |
jz .set |
dec ebx |
jz .get |
dec ebx |
jz .mount_additional_directory |
ret |
.mount_additional_directory: |
; sysfunction 30.2: [for app] eax=30,ebx=3,ecx->dir name+dir path (128) |
; for our code: nothing |
; check lock of the function |
cmp [lock_flag_for_f30_3], 1 |
je @f |
mov esi, ecx |
mov edi, sysdir_name1 |
; copying fake directory name |
mov ecx, 63 |
pushfd |
cli |
cld |
rep movsb |
; terminator of name, in case if we get the inlet trash |
inc esi |
xor eax, eax |
stosb |
; copying real directory path for mounting |
mov ecx, 63 |
rep movsb |
; terminator of name, in case if we get the inlet trash |
xor eax, eax |
stosb |
; increase the pointer of inputs for procedure "process_replace_file_name" |
mov [full_file_name_table.size], 2 |
; block the ability to call f.30.3 because for one session is necessary |
; for us only once |
mov [lock_flag_for_f30_3], 1 |
popfd |
@@: |
ret |
.get: |
; sysfunction 30.2: [for app] eax=30,ebx=2,ecx->buffer,edx=len |
; for our code: ebx->buffer,ecx=len |
/kernel/branches/Kolibri-acpi/fs/parse_fn.inc |
---|
32,6 → 32,17 |
; Parser_params will initialize: sysdir_name = "sys", sysdir_path = <sysdir> |
sysdir_name rb 64 |
sysdir_path rb 64 |
sysdir_name1 rb 64 |
sysdir_path1 rb 64 |
; for example: |
;dir_name1 db 'addappl',0 |
; rb 64-8 |
;dir_path1 db 'HD0/1',0 |
; rb 64-6 |
endg |
uglobal |
tmp_file_name_table dd ? |
endg |
/kernel/branches/Kolibri-acpi/fs/part_set.inc |
---|
77,10 → 77,10 |
.inode_size dd ? |
.count_pointer_in_block dd ? ; block_size / 4 |
.count_pointer_in_block_square dd ? ; (block_size / 4)**2 |
.ext2_save_block dd ? ; блок на глобальную 1 процедуру |
.ext2_temp_block dd ? ; блок для мелких процедур |
.ext2_save_inode dd ? ; inode на глобальную процедуру |
.ext2_temp_inode dd ? ; inode для мелких процедур |
.ext2_save_block dd ? ;RUS: блок на глобальную 1 процедуру ;ENG: block for 1 global procedure |
.ext2_temp_block dd ? ;RUS: блок для мелких процедур ;ENG: block for small procedures |
.ext2_save_inode dd ? ;RUS: inode на глобальную процедуру ;ENG: inode for global procedure |
.ext2_temp_inode dd ? ;RUS: inode для мелких процедур ;ENG: inode for small procedures |
.sb dd ? ; superblock |
.groups_count dd ? |
if $ > fs_dependent_data_end |
/kernel/branches/Kolibri-acpi/gui/font.inc |
---|
7,8 → 7,6 |
$Revision$ |
include "lang.inc" |
;------------------------------------------------------------------------------ |
align 4 |
dtext_asciiz_esi: ; for skins title out |
/kernel/branches/Kolibri-acpi/init.inc |
---|
453,6 → 453,9 |
acpi_dev_size rd 1 |
acpi_rsdt_base rd 1 |
acpi_fadt_base rd 1 |
acpi_dsdt_base rd 1 |
acpi_dsdt_size rd 1 |
acpi_madt_base rd 1 |
acpi_ioapic_base rd 1 |
464,6 → 467,7 |
ACPI_HI_RSDP_WINDOW_END equ 0x00100000 |
ACPI_RSDP_CHECKSUM_LENGTH equ 20 |
ACPI_MADT_SIGN equ 0x43495041 |
ACPI_FADT_SIGN equ 0x50434146 |
acpi_locate: |
535,10 → 539,23 |
jz .done |
mov ecx, [eax+16] |
mov edx, ACPI_MADT_SIGN |
mov edx, 0x50434146 |
mov [acpi_rsdt_base-OS_BASE], ecx |
call rsdt_find |
mov [acpi_fadt_base-OS_BASE], eax |
test eax, eax |
jz @f |
mov eax, [eax+40] |
mov [acpi_dsdt_base-OS_BASE], eax |
mov eax, [eax+4] |
mov [acpi_dsdt_size-OS_BASE], eax |
@@: |
mov edx, ACPI_MADT_SIGN |
mov ecx, [acpi_rsdt_base-OS_BASE] |
call rsdt_find |
test eax, eax |
jz .done |
mov [acpi_madt_base-OS_BASE], eax |
/kernel/branches/Kolibri-acpi/kernel.asm |
---|
358,8 → 358,44 |
call mutex_init |
; SAVE REAL MODE VARIABLES |
xor eax, eax |
mov ax, [BOOT_VAR + BOOT_IDE_PI_16] |
mov [IDEContrProgrammingInterface], ax |
mov ax, [BOOT_VAR + BOOT_IDE_BASE_ADDR] |
mov [IDEContrRegsBaseAddr], ax |
mov ax, [BOOT_VAR + BOOT_IDE_BAR0_16] |
mov [IDE_BAR0_val], ax |
cmp ax, 0 |
je @f |
cmp ax, 1 |
je @f |
and ax, 0xfff0 |
mov [StandardATABases], ax |
mov [hd_address_table], eax |
mov [hd_address_table+8], eax |
@@: |
mov ax, [BOOT_VAR + BOOT_IDE_BAR1_16] |
mov [IDE_BAR1_val], ax |
mov ax, [BOOT_VAR + BOOT_IDE_BAR2_16] |
mov [IDE_BAR2_val], ax |
cmp ax, 0 |
je @f |
cmp ax, 1 |
je @f |
and ax, 0xfff0 |
mov [StandardATABases+2], ax |
mov [hd_address_table+16], eax |
mov [hd_address_table+24], eax |
@@: |
mov ax, [BOOT_VAR + BOOT_IDE_BAR3_16] |
mov [IDE_BAR3_val], ax |
; --------------- APM --------------------- |
; init selectors |
1014,6 → 1050,12 |
@@: |
DEBUGF 1, "K : %d CPU detected\n", eax |
DEBUGF 1, "K : BAR0 %x \n", [IDE_BAR0_val]:4 |
DEBUGF 1, "K : BAR1 %x \n", [IDE_BAR1_val]:4 |
DEBUGF 1, "K : BAR2 %x \n", [IDE_BAR2_val]:4 |
DEBUGF 1, "K : BAR3 %x \n", [IDE_BAR3_val]:4 |
DEBUGF 1, "K : BAR4 %x \n", [IDEContrRegsBaseAddr]:4 |
DEBUGF 1, "K : IDEContrProgrammingInterface %x \n", [IDEContrProgrammingInterface]:4 |
; START MULTITASKING |
; A 'All set - press ESC to start' messages if need |
1028,6 → 1070,17 |
cmp [IDEContrRegsBaseAddr], 0 |
setnz [dma_hdd] |
cmp [dma_hdd], 0 |
je .print_pio |
.print_dma: |
DEBUGF 1, "K : IDE DMA mode\n" |
jmp .continue |
.print_pio: |
DEBUGF 1, "K : IDE PIO mode\n" |
.continue: |
mov [timer_ticks_enable], 1 ; for cd driver |
sti |
1585,23 → 1638,27 |
dec ecx |
jnz noprma |
mov [cdbase], 0x1f0 |
mov eax, [hd_address_table] |
mov [cdbase], eax ;0x1f0 |
mov [cdid], 0xa0 |
noprma: |
dec ecx |
jnz noprsl |
mov [cdbase], 0x1f0 |
mov eax, [hd_address_table] |
mov [cdbase], eax ;0x1f0 |
mov [cdid], 0xb0 |
noprsl: |
dec ecx |
jnz nosema |
mov [cdbase], 0x170 |
mov eax, [hd_address_table+16] |
mov [cdbase], eax ;0x170 |
mov [cdid], 0xa0 |
nosema: |
dec ecx |
jnz nosesl |
mov [cdbase], 0x170 |
mov eax, [hd_address_table+16] |
mov [cdbase], eax ;0x170 |
mov [cdid], 0xb0 |
nosesl: |
ret |
1630,7 → 1687,8 |
cmp ecx, 1 |
jnz noprmahd |
mov [hdbase], 0x1f0 |
mov eax, [hd_address_table] |
mov [hdbase], eax ;0x1f0 |
and dword [hdid], 0x0 |
mov dword [hdpos], ecx |
; call set_FAT32_variables |
1638,7 → 1696,8 |
cmp ecx, 2 |
jnz noprslhd |
mov [hdbase], 0x1f0 |
mov eax, [hd_address_table] |
mov [hdbase], eax ;0x1f0 |
mov [hdid], 0x10 |
mov dword [hdpos], ecx |
; call set_FAT32_variables |
1646,7 → 1705,8 |
cmp ecx, 3 |
jnz nosemahd |
mov [hdbase], 0x170 |
mov eax, [hd_address_table+16] |
mov [hdbase], eax ;0x170 |
and dword [hdid], 0x0 |
mov dword [hdpos], ecx |
; call set_FAT32_variables |
1654,7 → 1714,8 |
cmp ecx, 4 |
jnz noseslhd |
mov [hdbase], 0x170 |
mov eax,[hd_address_table+16] |
mov [hdbase], eax ;0x170 |
mov [hdid], 0x10 |
mov dword [hdpos], ecx |
; call set_FAT32_variables |
5409,7 → 5470,6 |
; calculate data area for fast getting offset to _WinMapAddress |
xor eax, eax |
mov ecx, [_display.height] |
inc ecx |
mov edi, d_width_calc_area |
cld |
@@: |
5424,7 → 5484,6 |
; calculate data area for fast getting offset to LFB |
xor eax, eax |
mov ecx, [_display.height] |
inc ecx |
mov edi, BPSLine_calc_area |
cld |
@@: |
5816,7 → 5875,6 |
__REV__ = __REV |
uglobals_size = $ - endofcode |
if ~ lang eq sp |
diff16 "end of kernel code",0,$ |
end if |
/kernel/branches/Kolibri-acpi/network/ARP.inc |
---|
55,10 → 55,9 |
ends |
uglobal |
align 4 |
uglobal |
ARP_table rb NET_DEVICES_MAX*(ARP_TABLE_SIZE * sizeof.ARP_entry) |
ARP_entries_num rd NET_DEVICES_MAX |
176,13 → 175,13 |
cmp ecx, sizeof.ARP_header |
jb .exit |
call NET_ptr_to_num |
call NET_ptr_to_num4 |
cmp edi, -1 |
jz .exit |
inc [ARP_PACKETS_RX + 4*edi] ; update stats |
inc [ARP_PACKETS_RX + edi] ; update stats |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: got packet from %u.%u.%u.%u through device %u\n",\ |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: got packet from %u.%u.%u.%u (device*4=%u)\n",\ |
[edx + ARP_header.SenderIP]:1, [edx + ARP_header.SenderIP + 1]:1,\ |
[edx + ARP_header.SenderIP + 2]:1, [edx + ARP_header.SenderIP + 3]:1, edi |
190,7 → 189,7 |
; First, check for IP collision |
mov eax, [edx + ARP_header.SenderIP] |
cmp eax, [IP_LIST + 4*edi] |
cmp eax, [IP_LIST + edi] |
je .collision |
;--------------------- |
201,12 → 200,12 |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: It's a reply\n" |
mov ecx, [ARP_entries_num + 4*edi] |
mov ecx, [ARP_entries_num + edi] |
test ecx, ecx |
jz .exit |
mov esi, (ARP_TABLE_SIZE * sizeof.ARP_entry) |
imul esi, edi |
mov esi, edi |
imul esi, (ARP_TABLE_SIZE * sizeof.ARP_entry)/4 |
add esi, ARP_table |
.loop: |
cmp [esi + ARP_entry.IP], eax |
245,7 → 244,7 |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: its a request\n" |
mov eax, [IP_LIST + 4*edi] |
mov eax, [IP_LIST + edi] |
cmp eax, [edx + ARP_header.TargetIP] ; Is it looking for my IP address? |
jne .exit |
262,7 → 261,7 |
movsd ; Move sender IP to Dest IP |
pop esi |
mov esi, [NET_DRV_LIST + 4*esi] |
mov esi, [NET_DRV_LIST + esi] |
lea esi, [esi + ETH_DEVICE.mac] |
lea edi, [edx + ARP_header.SenderMAC] |
movsd ; Copy MAC address from in MAC_LIST |
290,7 → 289,7 |
ret |
.collision: |
inc [ARP_CONFLICTS + 4*edi] |
inc [ARP_CONFLICTS + edi] |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: IP address conflict detected!\n" |
.exit: |
337,11 → 336,11 |
movsw ; |
movsd ; |
; mov esi, [ebx + NET_DEVICE.number] |
xor esi, esi ;;;; FIXME |
inc esi ;;;;;;;;; |
inc [ARP_PACKETS_TX + 4*esi] ; assume we will succeed |
lea esi, [IP_LIST + 4*esi] ; SenderIP |
push edi |
call NET_ptr_to_num4 |
inc [ARP_PACKETS_TX + edi] ; assume we will succeed |
lea esi, [IP_LIST + edi] ; SenderIP |
pop edi |
movsd |
mov esi, ETH_BROADCAST ; DestMac |
364,7 → 363,7 |
; ARP_add_entry (or update) |
; |
; IN: esi = ptr to entry (can easily be made on the stack) |
; edi = device num |
; edi = device num*4 |
; OUT: eax = entry #, -1 on error |
; esi = ptr to newly created entry |
; |
374,17 → 373,17 |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_add_entry: device=%u\n", edi |
mov ecx, [ARP_entries_num + 4*edi] |
mov ecx, [ARP_entries_num + edi] |
cmp ecx, ARP_TABLE_SIZE ; list full ? |
jae .full |
; From this point on, we can only fail if IP has a static entry, or if table is corrupt. |
inc [ARP_entries_num + 4*edi] ; assume we will succeed |
inc [ARP_entries_num + edi] ; assume we will succeed |
push edi |
xor ecx, ecx |
imul edi, ARP_TABLE_SIZE*sizeof.ARP_entry |
imul edi, ARP_TABLE_SIZE*sizeof.ARP_entry/4 |
add edi, ARP_table |
mov eax, [esi + ARP_entry.IP] |
.loop: |
419,7 → 418,7 |
.error: |
pop edi |
dec [ARP_entries_num + 4*edi] |
dec [ARP_entries_num + edi] |
DEBUGF DEBUG_NETWORK_ERROR, "ARP_add_entry_failed\n" |
.full: |
mov eax, -1 |
475,7 → 474,7 |
; This function translates an IP address to a MAC address |
; |
; IN: eax = IPv4 address |
; edi = device number |
; edi = device number * 4 |
; OUT: eax = -1 on error, -2 means request send |
; else, ax = first two bytes of mac (high 16 bits of eax will be 0) |
; ebx = last four bytes of mac |
487,7 → 486,7 |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: %u.%u", al, ah |
rol eax, 16 |
DEBUGF DEBUG_NETWORK_VERBOSE, ".%u.%u device: %u\n", al, ah, edi |
DEBUGF DEBUG_NETWORK_VERBOSE, ".%u.%u device*4: %u\n", al, ah, edi |
rol eax, 16 |
cmp eax, 0xffffffff |
496,11 → 495,11 |
;-------------------------------- |
; Try to find the IP in ARP_table |
mov ecx, [ARP_entries_num + 4*edi] |
mov ecx, [ARP_entries_num + edi] |
test ecx, ecx |
jz .not_in_list |
mov esi, edi |
imul esi, sizeof.ARP_entry * ARP_TABLE_SIZE |
imul esi, (sizeof.ARP_entry * ARP_TABLE_SIZE)/4 |
add esi, ARP_table + ARP_entry.IP |
.scan_loop: |
cmp [esi], eax |
538,7 → 537,7 |
pop edi eax ; IP in eax, device number in ebx, for ARP_output_request |
push esi edi |
mov ebx, [NET_DRV_LIST + 4*edi] |
mov ebx, [NET_DRV_LIST + edi] |
call ARP_output_request |
pop edi esi |
.found_it: |
655,7 → 654,6 |
.write: |
; esi = pointer to buffer |
mov edi, eax |
shr edi, 2 |
call ARP_add_entry ; out: eax = entry number, -1 on error |
ret |
/kernel/branches/Kolibri-acpi/network/IPv4.inc |
---|
55,8 → 55,8 |
ends |
uglobal |
align 4 |
uglobal |
IP_LIST rd NET_DEVICES_MAX |
SUBNET_LIST rd NET_DEVICES_MAX |
69,6 → 69,7 |
IP_packets_dumped rd NET_DEVICES_MAX |
FRAGMENT_LIST rb MAX_FRAGMENTS * sizeof.FRAGMENT_slot |
endg |
223,8 → 224,7 |
;----------------------------------- |
; Check if destination IP is correct |
call NET_ptr_to_num |
shl edi, 2 |
call NET_ptr_to_num4 |
; check if it matches local ip (Using RFC1122 strong end system model) |
586,9 → 586,9 |
push ebx ; push the mac onto the stack |
push ax |
inc [IP_packets_tx + 4*edi] ; update stats |
inc [IP_packets_tx + edi] ; update stats |
mov ebx, [NET_DRV_LIST + 4*edi] |
mov ebx, [NET_DRV_LIST + edi] |
lea eax, [ebx + ETH_DEVICE.mac] |
mov edx, esp |
mov ecx, [esp + 10 + 6] |
857,7 → 857,7 |
; IPv4_route |
; |
; IN: eax = Destination IP |
; OUT: edi = device number |
; OUT: edi = device number*4 |
; eax = ip of gateway if nescessary, unchanged otherwise |
; |
;--------------------------------------------------------------------------- |
890,8 → 890,7 |
.invalid: |
mov eax, [GATEWAY_LIST+4] ;;; FIXME |
.broadcast: |
xor edi, edi ; if none found, use device 1 as default ;;;; FIXME |
inc di |
mov edi, 4 ; if none found, use device 1 as default ;;;; FIXME |
ret |
/kernel/branches/Kolibri-acpi/network/IPv6.inc |
---|
30,8 → 30,8 |
ends |
uglobal |
align 4 |
uglobal |
IPv6: |
.addresses rd 4*NET_DEVICES_MAX |
/kernel/branches/Kolibri-acpi/network/PPPoE.inc |
---|
23,8 → 23,11 |
ends |
uglobal |
align 4 |
PPPoE_SID dw ? |
PPPoE_MAC dp ? |
endg |
;----------------------------------------------------------------- |
63,6 → 66,11 |
; First, find open PPPoE socket |
pusha |
mov ecx, socket_mutex |
call mutex_lock |
popa |
mov eax, net_sockets |
.next_socket: |
76,6 → 84,11 |
cmp [eax + SOCKET.Protocol], PPP_PROTO_ETHERNET |
jne .next_socket |
pusha |
mov ecx, socket_mutex |
call mutex_unlock |
popa |
; Now, send it to the this socket |
mov ecx, [esp + 4] |
84,6 → 97,11 |
jmp SOCKET_input |
.dump: |
pusha |
mov ecx, socket_mutex |
call mutex_unlock |
popa |
DEBUGF DEBUG_NETWORK_VERBOSE, 'PPPoE_discovery_input: dumping\n' |
call kernel_free |
add esp, 4 |
/kernel/branches/Kolibri-acpi/network/ethernet.inc |
---|
32,8 → 32,8 |
ends |
iglobal |
align 4 |
iglobal |
ETH_BROADCAST dp 0xffffffffffff |
endg |
57,9 → 57,8 |
mov ecx, [esp+4] |
DEBUGF DEBUG_NETWORK_VERBOSE,"ETH_input: size=%u\n", ecx |
cmp ecx, ETH_FRAME_MINIMUM |
sub ecx, sizeof.ETH_header |
jb .dump |
sub ecx, sizeof.ETH_header |
lea edx, [eax + sizeof.ETH_header] |
mov ax, [eax + ETH_header.Type] |
/kernel/branches/Kolibri-acpi/network/icmp.inc |
---|
97,10 → 97,12 |
ends |
uglobal |
align 4 |
uglobal |
ICMP_PACKETS_TX rd NET_DEVICES_MAX |
ICMP_PACKETS_RX rd NET_DEVICES_MAX |
endg |
156,9 → 158,17 |
pop ecx edx |
jne .checksum_mismatch |
; Check packet type |
cmp [edx + ICMP_header.Type], ICMP_ECHO ; Is this an echo request? |
jne .check_sockets |
; Update stats (and validate device ptr) |
call NET_ptr_to_num4 |
cmp edi, -1 |
je .dump |
inc [ICMP_PACKETS_RX + edi] |
; We well re-use the packet so we can create the response as fast as possible |
; Notice: this only works on pure ethernet |
166,14 → 176,6 |
mov [edx + ICMP_header.Type], ICMP_ECHOREPLY ; Change Packet type to reply |
mov esi, [esp] ; Start of buffer |
; Update stats (and validate device ptr) |
call NET_ptr_to_num |
cmp edi, -1 |
je .dump |
inc [ICMP_PACKETS_RX + 4*edi] |
inc [ICMP_PACKETS_TX + 4*edi] |
cmp ebx, LOOPBACK_DEVICE |
je .loopback |
225,6 → 227,11 |
; Transmit the packet (notice that packet ptr and packet size have been on stack since start of the procedure!) |
call [ebx + NET_DEVICE.transmit] |
test eax, eax |
jnz @f |
call NET_ptr_to_num4 |
inc [UDP_PACKETS_TX + edi] |
@@: |
ret |
233,6 → 240,11 |
.check_sockets: |
; Look for an open ICMP socket |
pusha |
mov ecx, socket_mutex |
call mutex_lock |
popa |
mov esi, [edi] ; ipv4 source address |
mov eax, net_sockets |
.try_more: |
240,7 → 252,7 |
.next_socket: |
mov eax, [eax + SOCKET.NextPtr] |
or eax, eax |
jz .dump |
jz .dump_ |
cmp [eax + SOCKET.Domain], AF_INET4 |
jne .next_socket |
254,11 → 266,17 |
; cmp [eax + ICMP_SOCKET.Identifier], |
; jne .next_socket |
; call IPv4_dest_to_dev |
; cmp edi,-1 |
; je .dump |
; inc [ICMP_PACKETS_RX+edi] |
; Update stats (and validate device ptr) |
call NET_ptr_to_num4 |
cmp edi, -1 |
je .dump_ |
inc [ICMP_PACKETS_RX + edi] |
pusha |
mov ecx, socket_mutex |
call mutex_unlock |
popa |
DEBUGF DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax |
pusha |
269,7 → 287,17 |
mov esi, edx |
jmp SOCKET_input |
.dump_: |
pusha |
mov ecx, socket_mutex |
call mutex_unlock |
popa |
DEBUGF DEBUG_NETWORK_VERBOSE, "ICMP_input: no socket found\n" |
jmp .dump |
.checksum_mismatch: |
DEBUGF DEBUG_NETWORK_VERBOSE, "checksum mismatch\n" |
336,6 → 364,11 |
push edx edi |
DEBUGF DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n" |
call [ebx + NET_DEVICE.transmit] |
test eax, eax |
jnz @f |
call NET_ptr_to_num4 |
inc [ICMP_PACKETS_TX + edi] |
@@: |
ret |
.exit: |
DEBUGF DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n" |
386,6 → 419,11 |
DEBUGF DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n" |
call [ebx + NET_DEVICE.transmit] |
test eax, eax |
jnz @f |
call NET_ptr_to_num4 |
inc [ICMP_PACKETS_TX + edi] |
@@: |
ret |
.exit: |
DEBUGF DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n" |
/kernel/branches/Kolibri-acpi/network/loopback.inc |
---|
17,6 → 17,7 |
$Revision: 2891 $ |
iglobal |
align 4 |
LOOPBACK_DEVICE: |
/kernel/branches/Kolibri-acpi/network/queue.inc |
---|
28,6 → 28,7 |
size dd ? ; number of queued packets in this queue |
w_ptr dd ? ; current writing pointer in queue |
r_ptr dd ? ; current reading pointer |
mutex MUTEX |
ends |
44,9 → 45,23 |
macro add_to_queue ptr, size, entry_size, failaddr { |
local .ok, .no_wrap |
pusha |
lea ecx, [ptr + queue.mutex] |
call mutex_lock |
popa |
cmp [ptr + queue.size], size ; Check if queue isnt full |
jae failaddr |
jb .ok |
pusha |
lea ecx, [ptr + queue.mutex] |
call mutex_unlock |
popa |
jmp failaddr |
.ok: |
inc [ptr + queue.size] ; if not full, queue one more |
mov edi, [ptr + queue.w_ptr] ; Current write pointer (FIFO!) |
58,10 → 73,14 |
jb .no_wrap |
sub edi, size*entry_size |
.no_wrap: |
mov [ptr + queue.w_ptr], edi |
pusha |
lea ecx, [ptr + queue.mutex] |
call mutex_unlock |
popa |
} |
68,9 → 87,23 |
macro get_from_queue ptr, size, entry_size, failaddr { |
local .ok, .no_wrap |
pusha |
lea ecx, [ptr + queue.mutex] |
call mutex_lock |
popa |
cmp [ptr + queue.size], 0 ; any packets queued? |
je failaddr |
ja .ok |
pusha |
lea ecx, [ptr + queue.mutex] |
call mutex_unlock |
popa |
jmp failaddr |
.ok: |
dec [ptr + queue.size] ; if so, dequeue one |
mov esi, [ptr + queue.r_ptr] |
89,6 → 122,11 |
pop esi |
pusha |
lea ecx, [ptr + queue.mutex] |
call mutex_unlock |
popa |
} |
macro init_queue ptr { |
97,4 → 135,7 |
lea edi, [ptr + sizeof.queue] |
mov [ptr + queue.w_ptr], edi |
mov [ptr + queue.r_ptr], edi |
lea ecx, [ptr + queue.mutex] |
call mutex_init |
} |
/kernel/branches/Kolibri-acpi/network/socket.inc |
---|
17,7 → 17,6 |
$Revision$ |
struct SOCKET |
NextPtr dd ? ; pointer to next socket in list |
195,10 → 194,14 |
SOCKET_QUEUE_LOCATION = (SOCKETBUFFSIZE - SOCKET_QUEUE_SIZE*sizeof.socket_queue_entry - sizeof.queue) |
uglobal |
align 4 |
net_sockets rd 4 |
last_socket_num dd ? |
last_UDP_port dw ? ; These values give the number of the last used ephemeral port |
last_TCP_port dw ? ; |
socket_mutex MUTEX |
endg |
232,6 → 235,9 |
xchg al, ah |
mov [last_TCP_port], ax |
mov ecx, socket_mutex |
call mutex_init |
} |
;----------------------------------------------------------------- |
242,11 → 248,13 |
align 4 |
sys_socket: |
mov dword[esp+20], 0 ; Set error code to 0 |
cmp ebx, 255 |
jz SOCKET_debug |
cmp ebx, .number |
ja s_error |
ja .error |
jmp dword [.table + 4*ebx] |
.table: |
263,9 → 271,9 |
dd SOCKET_pair ; 10 |
.number = ($ - .table) / 4 - 1 |
s_error: |
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET: error\n" |
.error: |
mov dword [esp+32], -1 |
mov dword[esp+20], EINVAL |
ret |
287,16 → 295,16 |
push ecx edx esi |
call SOCKET_alloc |
pop esi edx ecx |
jz s_error |
jz .nobuffs |
mov [esp+32], edi ; return socketnumber |
DEBUGF DEBUG_NETWORK_VERBOSE, "socknum=%u\n", edi |
; push edx |
; and edx, SO_NONBLOCK |
or [eax + SOCKET.options], SO_NONBLOCK ;edx |
; pop edx |
; and edx, not SO_NONBLOCK |
test edx, SO_NONBLOCK |
jz @f |
or [eax + SOCKET.options], SO_NONBLOCK |
and edx, not SO_NONBLOCK |
@@: |
mov [eax + SOCKET.Domain], ecx |
mov [eax + SOCKET.Type], edx |
322,25 → 330,28 |
je .pppoe |
.no_ppp: |
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_open: Unknown socket family/protocol\n" |
.unsupported: |
push eax |
call SOCKET_free |
pop eax |
mov dword[esp+20], EOPNOTSUPP |
mov dword[esp+32], -1 |
ret |
align 4 |
.nobuffs: |
mov dword[esp+20], ENOBUFS |
mov dword[esp+32], -1 |
ret |
.raw: |
test esi, esi ; IP_PROTO_IP |
jz .ip |
jz .raw_ip |
cmp esi, IP_PROTO_ICMP |
je .icmp |
je .raw_icmp |
cmp esi, IP_PROTO_UDP |
je .udp |
jmp .unsupported |
cmp esi, IP_PROTO_TCP |
je .tcp |
ret |
align 4 |
.udp: |
mov [eax + SOCKET.Protocol], IP_PROTO_UDP |
359,7 → 370,7 |
align 4 |
.ip: |
.raw_ip: |
mov [eax + SOCKET.snd_proc], SOCKET_send_ip |
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram |
ret |
366,7 → 377,7 |
align 4 |
.icmp: |
.raw_icmp: |
mov [eax + SOCKET.snd_proc], SOCKET_send_icmp |
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram |
ret |
398,10 → 409,10 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi |
call SOCKET_num_to_ptr |
jz s_error |
jz .invalid |
cmp esi, 2 |
jb s_error |
jb .invalid |
cmp word [edx], AF_INET4 |
je .af_inet4 |
409,18 → 420,24 |
cmp word [edx], AF_LOCAL |
je .af_local |
jmp s_error |
.notsupp: |
mov dword[esp+20], EOPNOTSUPP |
mov dword[esp+32], -1 |
ret |
.invalid: |
mov dword[esp+20], EINVAL |
mov dword[esp+32], -1 |
ret |
.af_local: |
; TODO: write code here |
mov dword [esp+32], 0 |
ret |
.af_inet4: |
cmp esi, 6 |
jb s_error |
jb .invalid |
cmp [eax + SOCKET.Protocol], IP_PROTO_UDP |
je .udp |
428,12 → 445,11 |
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP |
je .tcp |
jmp s_error |
jmp .notsupp |
.tcp: |
.udp: |
cmp ebx, [edx + 4] ; First, fill in the IP |
mov ebx, [edx + 4] ; First, fill in the IP |
test ebx, ebx ; If IP is 0, use default |
jnz @f |
mov ebx, [IP_LIST + 4] ;;;;; FIXME !i!i!i |
442,7 → 458,7 |
mov bx, [edx + 2] ; Now fill in the local port if it's still available |
call SOCKET_check_port |
jz s_error ; ZF is set by socket_check_port, on error |
jz .addrinuse ; ZF is set by socket_check_port, on error |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_bind: local ip=%u.%u.%u.%u\n",\ |
[eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\ |
451,9 → 467,14 |
mov dword [esp+32], 0 |
ret |
.addrinuse: |
mov dword[esp+32], -1 |
mov dword[esp+20], EADDRINUSE |
ret |
;----------------------------------------------------------------- |
; |
; SOCKET_connect |
470,16 → 491,24 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi |
call SOCKET_num_to_ptr |
jz s_error |
jz .invalid |
cmp esi, 8 |
jb s_error |
jb .invalid |
cmp word [edx], AF_INET4 |
je .af_inet4 |
jmp s_error |
.notsupp: |
mov dword[esp+20], EOPNOTSUPP |
mov dword[esp+32], -1 |
ret |
.invalid: |
mov dword[esp+20], EINVAL |
mov dword[esp+32], -1 |
ret |
.af_inet4: |
cmp [eax + IP_SOCKET.LocalIP], 0 |
jne @f |
499,7 → 528,7 |
cmp [eax + SOCKET.Protocol], IP_PROTO_ICMP |
je .ip |
jmp s_error |
jmp .notsupp |
align 4 |
.udp: |
557,18 → 586,15 |
pop [eax + TCP_SOCKET.ISS] |
mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init |
TCP_sendseqinit eax |
; mov [ebx + TCP_SOCKET.timer_retransmission], ;; todo: create macro to set retransmission timer |
mov ebx, eax |
lea eax, [ebx + STREAM_SOCKET.snd] |
call SOCKET_ring_create |
call SOCKET_ring_create ; TODO: check if memory was available or not |
lea eax, [ebx + STREAM_SOCKET.rcv] |
call SOCKET_ring_create |
call SOCKET_ring_create ; TODO: same here |
pusha |
lea ecx, [ebx + SOCKET.mutex] |
575,14 → 601,40 |
call mutex_unlock |
popa |
push ebx |
mov eax, ebx |
call TCP_output |
pop eax |
;;; TODO: wait for successfull connection if blocking socket |
.block: |
test [eax + SOCKET.options], SO_NONBLOCK |
jz .loop |
mov dword[esp+20], EWOULDBLOCK |
mov dword[esp+32], -1 |
ret |
.loop: |
cmp [eax + TCP_SOCKET.t_state], TCPS_CLOSED |
je .fail |
cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED |
je .established |
ja .fail |
call SOCKET_block |
jmp .loop |
.fail: |
mov eax, [eax + SOCKET.errorcode] |
mov [esp+20], eax |
mov dword[esp+32], -1 |
ret |
.established: |
mov dword [esp+32], 0 |
ret |
align 4 |
.ip: |
pusha |
619,16 → 671,16 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx |
call SOCKET_num_to_ptr |
jz s_error |
jz .invalid |
cmp [eax + SOCKET.Domain], AF_INET4 |
jne s_error |
jne .notsupp |
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP |
jne s_error |
jne .invalid |
cmp [eax + TCP_SOCKET.LocalPort], 0 |
je s_error |
je .already |
cmp [eax + IP_SOCKET.LocalIP], 0 |
jne @f |
651,10 → 703,24 |
pop eax |
mov dword [esp+32], 0 |
ret |
.notsupp: |
mov dword[esp+20], EOPNOTSUPP |
mov dword[esp+32], -1 |
ret |
.invalid: |
mov dword[esp+20], EINVAL |
mov dword[esp+32], -1 |
ret |
.already: |
mov dword[esp+20], EALREADY |
mov dword[esp+32], -1 |
ret |
;----------------------------------------------------------------- |
; |
; SOCKET_accept |
671,16 → 737,16 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi |
call SOCKET_num_to_ptr |
jz s_error |
jz .invalid |
test [eax + SOCKET.options], SO_ACCEPTCON |
jz s_error |
jz .invalid |
cmp [eax + SOCKET.Domain], AF_INET4 |
jne s_error |
jne .notsupp |
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP |
jne s_error |
jne .invalid |
.loop: |
get_from_queue (eax + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .block |
688,14 → 754,15 |
; Ok, we got a socket ptr |
mov eax, [esi] |
; Convert it to a socket number |
call SOCKET_ptr_to_num |
jz .invalid ; FIXME ? |
; Change thread ID to that of the current thread |
mov ebx, [TASK_BASE] |
mov ebx, [ebx + TASKDATA.pid] |
mov [eax + SOCKET.TID], ebx |
; Convert it to a socket number |
call SOCKET_ptr_to_num |
jz s_error |
; and return it to caller |
mov [esp+32], eax |
ret |
702,11 → 769,26 |
.block: |
test [eax + SOCKET.options], SO_NONBLOCK |
jnz s_error |
jnz .wouldblock |
call SOCKET_block |
jmp .loop |
.wouldblock: |
mov dword[esp+20], EWOULDBLOCK |
mov dword[esp+32], -1 |
ret |
.invalid: |
mov dword[esp+20], EINVAL |
mov dword[esp+32], -1 |
ret |
.notsupp: |
mov dword[esp+20], EOPNOTSUPP |
mov dword[esp+32], -1 |
ret |
;----------------------------------------------------------------- |
; |
; SOCKET_close |
721,11 → 803,10 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_close: socknum=%u\n", ecx |
call SOCKET_num_to_ptr |
jz s_error |
jz .invalid |
mov dword [esp+32], 0 ; The socket exists, so we will succeed in closing it. |
.socket: |
or [eax + SOCKET.options], SO_NONBLOCK ; Mark the socket as non blocking, we dont want it to block any longer! |
test [eax + SOCKET.state], SS_BLOCKED ; Is the socket still in blocked state? |
749,10 → 830,17 |
call TCP_usrclosed |
call TCP_output ;;;; Fixme: is this nescessary?? |
call SOCKET_free |
ret |
.invalid: |
mov dword[esp+20], EINVAL |
mov dword[esp+32], -1 |
ret |
;----------------------------------------------------------------- |
; |
; SOCKET_receive |
770,29 → 858,52 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi |
call SOCKET_num_to_ptr |
jz s_error |
jz .invalid |
.loop: |
push edi |
call [eax + SOCKET.rcv_proc] |
pop edi |
cmp ebx, EWOULDBLOCK |
jne .return |
test edi, MSG_DONTWAIT |
jnz .return_err |
; test [eax + SOCKET.options], SO_NONBLOCK |
; jnz .return_err |
call SOCKET_block |
jmp .loop |
.invalid: |
push EINVAL |
pop ebx |
.return_err: |
mov eax, -1 |
.return: |
mov [esp+20], ebx |
mov [esp+32], eax |
ret |
align 4 |
SOCKET_receive_dgram: |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: DGRAM\n" |
mov ebx, esi |
mov edi, edx ; addr to buffer |
mov ebx, esi ; bufferlength |
.loop: |
get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .block ; destroys esi and ecx |
get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .wouldblock ; sets esi only on success. |
mov ecx, [esi + socket_queue_entry.data_size] |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: %u bytes data\n", ecx |
cmp ecx, ebx |
cmp ecx, ebx ; If data segment does not fit in applications buffer, abort |
ja .too_small |
push ecx |
800,7 → 911,8 |
mov esi, [esi + socket_queue_entry.data_ptr] |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi |
; copy the data |
; copy the data from kernel buffer to application buffer |
mov edi, edx ; bufferaddr |
shr ecx, 1 |
jnc .nb |
movsb |
814,24 → 926,22 |
rep movsd |
.nd: |
call kernel_free ; remove the packet |
pop eax |
call kernel_free ; free kernel buffer |
pop eax ; return number of bytes copied to application |
xor ebx, ebx |
ret |
.too_small: |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Buffer too small\n" |
.fail: |
mov eax, -1 |
push EMSGSIZE |
pop ebx |
ret |
.block: |
test [eax + SOCKET.options], SO_NONBLOCK |
jnz .fail |
.wouldblock: |
push EWOULDBLOCK |
pop ebx |
ret |
call SOCKET_block |
jmp .loop |
align 4 |
850,56 → 960,42 |
mov [eax + SOCKET.rcv_proc], SOCKET_receive_stream |
; ... continue to SOCKET_receive_stream |
align 4 |
SOCKET_receive_stream: |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: STREAM\n" |
mov ebx, edi |
cmp [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0 |
je .wouldblock |
test edi, MSG_PEEK |
jnz .peek |
mov ecx, esi |
mov edi, edx |
xor edx, edx |
test ebx, MSG_DONTWAIT |
jnz .dontwait |
.loop: |
cmp [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0 |
je .block |
.dontwait: |
test ebx, MSG_PEEK |
jnz .peek |
add eax, STREAM_SOCKET.rcv |
call SOCKET_ring_read |
call SOCKET_ring_free |
call SOCKET_ring_read ; copy data from kernel buffer to application buffer |
call SOCKET_ring_free ; free read memory |
mov eax, ecx ; return number of bytes copied |
xor ebx, ebx ; errorcode = 0 (no error) |
ret |
.wouldblock: |
push EWOULDBLOCK |
pop ebx |
ret |
.peek: |
mov eax, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size] |
xor ebx, ebx |
ret |
.block: |
test [eax + SOCKET.options], SO_NONBLOCK |
jnz .return0 |
call SOCKET_block |
jmp .loop |
.return0: |
test [eax + SOCKET.options], SS_CANTRCVMORE |
jz .ok |
xor eax, eax |
dec eax |
ret |
.ok: |
xor eax, eax |
ret |
;----------------------------------------------------------------- |
; |
; SOCKET_send |
918,7 → 1014,7 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi |
call SOCKET_num_to_ptr |
jz s_error |
jz .invalid |
mov ecx, esi |
mov esi, edx |
925,7 → 1021,12 |
jmp [eax + SOCKET.snd_proc] |
.invalid: |
mov dword[esp+20], EINVAL |
mov dword[esp+32], -1 |
ret |
align 4 |
SOCKET_send_udp: |
934,10 → 1035,15 |
mov [esp+32], ecx |
call UDP_output |
cmp eax, -1 |
je s_error |
je .error |
ret |
.error: |
mov dword[esp+32], -1 |
mov dword[esp+20], EMSGSIZE ; FIXME: UDP_output should return error codes! |
ret |
align 4 |
SOCKET_send_tcp: |
949,8 → 1055,12 |
pop eax |
mov [esp+32], ecx |
call TCP_output |
mov [eax + SOCKET.errorcode], 0 |
push eax |
call TCP_output ; FIXME: this doesnt look pretty, does it? |
pop eax |
mov eax, [eax + SOCKET.errorcode] |
mov [esp+20], eax |
ret |
960,12 → 1070,17 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n" |
mov [esp+32], ecx |
call IPv4_output_raw |
call IPv4_output_raw ; FIXME: IPv4_output_raw should return error codes! |
cmp eax, -1 |
je s_error |
je .error |
ret |
.error: |
mov dword[esp+32], -1 |
mov dword[esp+20], EMSGSIZE |
ret |
align 4 |
SOCKET_send_icmp: |
972,12 → 1087,17 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n" |
mov [esp+32], ecx |
call ICMP_output_raw |
call ICMP_output_raw ; FIXME: errorcodes |
cmp eax, -1 |
je s_error |
je .error |
ret |
.error: |
mov dword[esp+32], -1 |
mov dword[esp+20], EMSGSIZE |
ret |
align 4 |
SOCKET_send_pppoe: |
986,13 → 1106,18 |
mov [esp+32], ecx |
mov ebx, [eax + SOCKET.device] |
call PPPoE_discovery_output |
call PPPoE_discovery_output ; FIXME: errorcodes |
cmp eax, -1 |
je s_error |
je .error |
ret |
.error: |
mov dword[esp+32], -1 |
mov dword[esp+20], EMSGSIZE |
ret |
align 4 |
SOCKET_send_local: |
1016,7 → 1141,7 |
; get the other side's socket and check if it still exists |
mov eax, [eax + SOCKET.device] |
call SOCKET_check |
jz s_error |
jz .invalid |
; allright, shove in the data! |
push eax |
1032,7 → 1157,12 |
ret |
.invalid: |
mov dword[esp+32], -1 |
mov dword[esp+20], EINVAL |
ret |
;----------------------------------------------------------------- |
; |
; SOCKET_get_options |
1053,14 → 1183,14 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_get_opt\n" |
call SOCKET_num_to_ptr |
jz s_error |
jz .invalid |
cmp dword [edx], IP_PROTO_TCP |
jne s_error |
jne .invalid |
cmp dword [edx+4], -2 |
je @f |
cmp dword [edx+4], -3 |
jne s_error |
jne .invalid |
@@: |
; mov eax, [edx+12] |
; test eax, eax |
1085,8 → 1215,13 |
mov dword [esp+32], 0 |
ret |
.invalid: |
mov dword[esp+32], -1 |
mov dword[esp+20], EINVAL |
ret |
;----------------------------------------------------------------- |
; |
; SOCKET_set_options |
1103,19 → 1238,19 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt\n" |
call SOCKET_num_to_ptr |
jz s_error |
jz .invalid |
cmp dword [edx], SOL_SOCKET |
jne s_error |
jne .invalid |
cmp dword [edx+4], SO_BINDTODEVICE |
je .bind |
cmp dword [edx+4], SO_BLOCK |
je .block |
.invalid: |
mov dword[esp+32], -1 |
mov dword[esp+20], EINVAL |
ret |
jmp s_error |
.bind: |
cmp dword [edx+8], 0 |
je .unbind |
1122,11 → 1257,11 |
movzx edx, byte [edx + 9] |
cmp edx, NET_DEVICES_MAX |
ja s_error |
ja .invalid |
mov edx, [NET_DRV_LIST + 4*edx] |
test edx, edx |
jz s_error |
jz .already |
mov [eax + SOCKET.device], edx |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx |
1140,23 → 1275,14 |
mov dword [esp+32], 0 ; success! |
ret |
.block: |
cmp dword [edx+8], 0 |
je .unblock |
and [eax + SOCKET.options], not SO_NONBLOCK |
mov dword [esp+32], 0 ; success! |
.already: |
mov dword[esp+20], EALREADY |
mov dword[esp+32], -1 |
ret |
.unblock: |
or [eax + SOCKET.options], SO_NONBLOCK |
mov dword [esp+32], 0 ; success! |
ret |
;----------------------------------------------------------------- |
; |
; SOCKET_pair |
1174,7 → 1300,7 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_pair\n" |
call SOCKET_alloc |
jz s_error |
jz .nomem1 |
mov [esp+32], edi ; application's eax |
mov [eax + SOCKET.Domain], AF_LOCAL |
1186,8 → 1312,8 |
mov ebx, eax |
call SOCKET_alloc |
jz .error |
mov [esp+24], edi ; application's ebx |
jz .nomem2 |
mov [esp+20], edi ; application's ebx |
mov [eax + SOCKET.Domain], AF_LOCAL |
mov [eax + SOCKET.Type], SOCK_STREAM |
1209,10 → 1335,13 |
ret |
.error: |
.nomem2: |
mov eax, ebx |
call SOCKET_free |
jmp s_error |
.nomem1: |
mov dword[esp+32], -1 |
mov dword[esp+28], ENOMEM |
ret |
1238,7 → 1367,7 |
jz .returnall |
call SOCKET_num_to_ptr |
jz s_error |
jz .invalid |
mov esi, eax |
mov ecx, SOCKETBUFFSIZE/4 |
1259,8 → 1388,12 |
.done: |
xor eax, eax |
stosd |
mov dword[esp+32], eax |
ret |
mov dword [esp+32], 0 |
.invalid: |
mov dword[esp+32], -1 |
mov dword[esp+28], EINVAL |
ret |
1342,6 → 1475,11 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_check_port: " |
pusha |
mov ecx, socket_mutex |
call mutex_lock |
popa |
mov ecx, [eax + SOCKET.Protocol] |
mov edx, [eax + IP_SOCKET.LocalIP] |
mov esi, net_sockets |
1360,10 → 1498,20 |
cmp [esi + UDP_SOCKET.LocalPort], bx |
jne .next_socket |
pusha |
mov ecx, socket_mutex |
call mutex_unlock |
popa |
DEBUGF DEBUG_NETWORK_VERBOSE, "local port %x already in use\n", bx ; FIXME: find a way to print big endian values with debugf |
ret |
.port_ok: |
pusha |
mov ecx, socket_mutex |
call mutex_unlock |
popa |
DEBUGF DEBUG_NETWORK_VERBOSE, "local port %x is free\n", bx ; FIXME: find a way to print big endian values with debugf |
mov [eax + UDP_SOCKET.LocalPort], bx |
or bx, bx ; clear the zero-flag |
1659,7 → 1807,7 |
; Suspends the thread attached to a socket |
; |
; IN: eax = socket ptr |
; OUT: / |
; OUT: eax = unchanged |
; |
;----------------------------------------------------------------- |
align 4 |
1668,6 → 1816,7 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_block: %x\n", eax |
pushf |
push eax |
cli |
; Set the 'socket is blocked' flag |
1685,6 → 1834,7 |
pop edx |
call change_task |
pop eax |
popf |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_block: continueing\n" |
1699,7 → 1849,7 |
; notify's the owner of a socket that something happened |
; |
; IN: eax = socket ptr |
; OUT: / |
; OUT: eax = unchanged |
; |
;----------------------------------------------------------------- |
align 4 |
1713,8 → 1863,8 |
test [eax + SOCKET.state], SS_BLOCKED |
jnz .unblock |
test [eax + SOCKET.options], SO_NONBLOCK |
jz .error |
; test [eax + SOCKET.options], SO_NONBLOCK |
; jz .error |
push eax ecx esi |
1811,9 → 1961,14 |
pop eax |
; set send-and receive procedures to return -1 |
mov [eax + SOCKET.snd_proc], s_error |
mov [eax + SOCKET.rcv_proc], s_error |
mov [eax + SOCKET.snd_proc], .not_yet |
mov [eax + SOCKET.rcv_proc], .not_yet |
pusha |
mov ecx, socket_mutex |
call mutex_lock |
popa |
; find first free socket number and use it |
mov edi, [last_socket_num] |
.next_socket_number: |
1872,12 → 2027,23 |
mov [net_sockets + SOCKET.NextPtr], eax |
or eax, eax ; used to clear zero flag |
pusha |
mov ecx, socket_mutex |
call mutex_unlock |
popa |
.exit: |
pop ebx |
ret |
.not_yet: |
mov dword[esp+20], ENOTCONN |
mov dword[esp+32], -1 |
ret |
;---------------------------------------------------- |
; |
; SOCKET_free |
1893,6 → 2059,11 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_free: %x\n", eax |
pusha |
mov ecx, socket_mutex |
call mutex_lock |
popa |
call SOCKET_check |
jz .error |
1915,6 → 2086,7 |
mov eax, ebx |
.no_tcp: |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_free: freeing socket %x\n", eax |
push eax ; this will be passed to kernel_free |
mov ebx, [eax + SOCKET.NextPtr] |
mov eax, [eax + SOCKET.PrevPtr] |
1937,6 → 2109,12 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_free: success!\n" |
.error: |
pusha |
mov ecx, socket_mutex |
call mutex_unlock |
popa |
ret |
;------------------------------------ |
2005,6 → 2183,11 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_num_to_ptr: num=%u ", ecx |
pusha |
mov ecx, socket_mutex |
call mutex_lock |
popa |
mov eax, net_sockets |
.next_socket: |
2016,11 → 2199,21 |
test eax, eax |
pusha |
mov ecx, socket_mutex |
call mutex_unlock |
popa |
DEBUGF DEBUG_NETWORK_VERBOSE, "ptr=%x\n", eax |
ret |
.error: |
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_nuto_ptr: not found\n", eax |
pusha |
mov ecx, socket_mutex |
call mutex_unlock |
popa |
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_num_to_ptr: not found\n", eax |
ret |
2129,8 → 2322,16 |
align 4 |
SOCKET_process_end: |
pushf |
cli ; FIXME |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: %x\n", edx |
pusha |
mov ecx, socket_mutex |
call mutex_lock |
popa |
push ebx |
mov ebx, net_sockets |
2148,14 → 2349,45 |
mov [ebx + SOCKET.PID], 0 |
mov eax, ebx |
mov ebx, [ebx + SOCKET.NextPtr] |
pusha |
call SOCKET_close.socket |
mov ecx, socket_mutex |
call mutex_unlock |
popa |
pusha |
cmp [eax + SOCKET.Domain], AF_INET4 |
jne .free |
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP |
jne .free |
call TCP_close |
jmp .closed |
.free: |
call SOCKET_free |
.closed: |
popa |
pusha |
mov ecx, socket_mutex |
call mutex_lock |
popa |
jmp .next_socket_test |
.done: |
pop ebx |
pusha |
mov ecx, socket_mutex |
call mutex_unlock |
popa |
popf |
ret |
2196,8 → 2428,8 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_is_connected: %x\n", eax |
and [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING) |
or [eax + SOCKET.options], SS_ISCONNECTED |
and [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING) |
or [eax + SOCKET.state], SS_ISCONNECTED |
jmp SOCKET_notify |
2218,8 → 2450,8 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnecting: %x\n", eax |
and [eax + SOCKET.options], not (SS_ISCONNECTING) |
or [eax + SOCKET.options], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE |
and [eax + SOCKET.state], not (SS_ISCONNECTING) |
or [eax + SOCKET.state], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE |
jmp SOCKET_notify |
2239,8 → 2471,8 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnected: %x\n", eax |
and [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING) |
or [eax + SOCKET.options], SS_CANTRCVMORE + SS_CANTSENDMORE |
and [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING) |
or [eax + SOCKET.state], SS_CANTRCVMORE + SS_CANTSENDMORE |
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP |
je .tcp |
2272,7 → 2504,7 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_cant_recv_more: %x\n", eax |
or [eax + SOCKET.options], SS_CANTRCVMORE |
or [eax + SOCKET.state], SS_CANTRCVMORE |
call SOCKET_notify |
2294,9 → 2526,14 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_cant_send_more: %x\n", eax |
or [eax + SOCKET.options], SS_CANTSENDMORE |
mov [eax + SOCKET.snd_proc], s_error |
or [eax + SOCKET.state], SS_CANTSENDMORE |
mov [eax + SOCKET.snd_proc], .notconn |
call SOCKET_notify |
ret |
.notconn: |
mov dword[esp+20], ENOTCONN |
mov dword[esp+32], -1 |
ret |
/kernel/branches/Kolibri-acpi/network/stack.inc |
---|
81,7 → 81,6 |
SO_USELOOPBACK = 1 shl 8 |
SO_BINDTODEVICE = 1 shl 9 |
SO_BLOCK = 1 shl 10 ; TO BE REMOVED |
SO_NONBLOCK = 1 shl 31 |
; Socket flags for user calls |
104,9 → 103,9 |
SS_RESTARTSYS = 0x0100 ; restart blocked system calls |
SS_ISDISCONNECTED = 0x0800 ; socket disconnected from peer |
SS_ASYNC = 0x0100 ; async i/o notify |
SS_ISCONFIRMING = 0x0200 ; deciding to accept connection req |
SS_MORETOCOME = 0x0400 |
SS_ASYNC = 0x1000 ; async i/o notify |
SS_ISCONFIRMING = 0x2000 ; deciding to accept connection req |
SS_MORETOCOME = 0x4000 |
SS_BLOCKED = 0x8000 |
115,7 → 114,15 |
MAX_backlog = 20 ; maximum backlog for stream sockets |
; Error Codes |
ENOBUFS = 55 |
ENOBUFS = 1 |
EOPNOTSUPP = 4 |
EWOULDBLOCK = 6 |
ENOTCONN = 9 |
EALREADY = 10 |
EINVAL = 11 |
EMSGSIZE = 12 |
ENOMEM = 18 |
EADDRINUSE = 20 |
ECONNREFUSED = 61 |
ECONNRESET = 52 |
ETIMEDOUT = 60 |
213,8 → 220,8 |
uglobal |
align 4 |
uglobal |
NET_RUNNING dd ? |
NET_DRV_LIST rd NET_DEVICES_MAX |
450,29 → 457,33 |
;----------------------------------------------------------------- |
align 4 |
NET_ptr_to_num: |
call NET_ptr_to_num4 |
ror edi, 2 ; If -1, stay -1 |
; valid device numbers have last two bits 0, so do just shr |
ret |
align 4 |
NET_ptr_to_num4: ; Todo, place number in device structure so we only need to verify? |
push ecx |
mov ecx, NET_DEVICES_MAX |
mov edi, NET_DRV_LIST |
.loop: |
cmp ebx, [edi] |
jz .found |
je .found |
add edi, 4 |
dec ecx |
jnz .loop |
; repnz scasd could work too if eax is used instead of ebx! |
or edi, -1 |
pop ecx |
ret |
.found: |
sub edi, NET_DRV_LIST |
shr edi, 2 |
pop ecx |
ret |
/kernel/branches/Kolibri-acpi/network/tcp.inc |
---|
127,8 → 127,9 |
ends |
uglobal |
align 4 |
uglobal |
TCP_segments_tx rd NET_DEVICES_MAX |
TCP_segments_rx rd NET_DEVICES_MAX |
TCP_segments_missed rd NET_DEVICES_MAX |
136,7 → 137,7 |
; TCP_bytes_rx rq NET_DEVICES_MAX |
; TCP_bytes_tx rq NET_DEVICES_MAX |
TCP_sequence_num dd ? |
TCP_queue rd TCP_QUEUE_SIZE*sizeof.TCP_queue_entry/4 |
TCP_queue rd (TCP_QUEUE_SIZE*sizeof.TCP_queue_entry + sizeof.queue)/4 |
TCP_input_event dd ? |
endg |
163,6 → 164,10 |
movi ebx, 1 |
mov ecx, TCP_process_input |
call new_sys_threads |
test eax, eax |
jns @f |
DEBUGF DEBUG_NETWORK_ERROR,'K : cannot create kernel thread for TCP, error %d\n', eax |
@@: |
} |
/kernel/branches/Kolibri-acpi/network/tcp_input.inc |
---|
50,6 → 50,9 |
add esp, sizeof.TCP_queue_entry |
call NET_ptr_to_num4 |
inc [TCP_segments_rx + edi] |
xor edx, edx |
mov eax, [TCP_input_event] |
mov ebx, [eax + EVENT.id] |
62,7 → 65,8 |
popf |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP incoming queue is full, discarding packet!\n" |
inc [TCP_segments_missed] ; FIXME: use correct interface |
call NET_ptr_to_num4 |
inc [TCP_segments_missed + edi] |
add esp, sizeof.TCP_queue_entry - 8 |
call kernel_free |
146,6 → 150,11 |
; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0) |
.findpcb: |
pusha |
mov ecx, socket_mutex |
call mutex_lock |
popa |
mov ebx, net_sockets |
mov si, [edx + TCP_header.DestinationPort] |
152,7 → 161,7 |
.socket_loop: |
mov ebx, [ebx + SOCKET.NextPtr] |
or ebx, ebx |
jz .respond_seg_reset |
jz .no_socket ;respond_seg_reset |
cmp [ebx + SOCKET.Domain], AF_INET4 |
jne .socket_loop |
176,13 → 185,13 |
test ax, ax |
jnz .socket_loop |
.found_socket: ; ebx now contains the socketpointer |
pusha |
mov ecx, socket_mutex |
call mutex_unlock |
popa |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: socket ptr=%x state=%u flags=%x\n", ebx, [ebx + TCP_SOCKET.t_state], [edx + TCP_header.Flags]:2 |
;------------- |
; update stats |
inc [TCP_segments_rx] ; FIXME: correct interface? |
;---------------------------- |
; Check if socket isnt closed |
1161,10 → 1170,18 |
.ack_la: |
jnc .ack_processed |
push ebx |
lea ecx, [ebx + SOCKET.mutex] |
call mutex_unlock |
pop ebx |
push ebx |
mov eax, ebx |
call TCP_disconnect |
jmp .drop |
pop ebx |
jmp .destroy_new_socket |
.ack_tw: |
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL |
or [ebx + TCP_SOCKET.timer_flags], timer_flag_wait |
1223,7 → 1240,10 |
and [ebx + TCP_SOCKET.temp_bits], not TCP_BIT_DROPSOCKET |
;;; call SOCKET_notify_owner |
pusha |
mov eax, ebx |
call SOCKET_notify |
popa |
jmp .trim_then_step6 |
1298,7 → 1318,10 |
;;; TODO: update stats |
; set socket state to connected |
mov [ebx + SOCKET.state], SS_ISCONNECTED |
push eax |
mov eax, ebx |
call SOCKET_is_connected |
pop eax |
mov [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED |
; Do window scaling on this connection ? |
1620,6 → 1643,13 |
pop ebx |
jmp .destroy_new_socket |
.no_socket: |
pusha |
mov ecx, socket_mutex |
call mutex_unlock |
popa |
.respond_seg_reset: |
test [edx + TCP_header.Flags], TH_RST |
jnz .drop_no_socket |
/kernel/branches/Kolibri-acpi/network/tcp_output.inc |
---|
35,6 → 35,8 |
call mutex_lock |
pop eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: socket locked\n" |
; We'll detect the length of the data to be transmitted, and flags to be used |
; If there is some data, or any critical controls to send (SYN / RST), then transmit |
; Otherwise, investigate further |
216,6 → 218,7 |
mov ebx, TCP_max_win |
shl ebx, cl |
pop ecx |
cmp ebx, ecx |
jb @f |
mov ebx, ecx |
549,7 → 552,8 |
pop ecx |
pop eax |
inc [TCP_segments_tx] ; FIXME: correct interface? |
call NET_ptr_to_num4 |
inc [TCP_segments_tx + edi] |
; update advertised receive window |
test ecx, ecx |
570,6 → 574,8 |
;-------------- |
; unlock socket |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: unlocking socket 0x%x\n", eax |
push eax |
lea ecx, [eax + SOCKET.mutex] |
call mutex_unlock |
606,7 → 612,8 |
.send_error: |
add esp, 8 |
add esp, 4 |
pop eax |
lea ecx, [eax + SOCKET.mutex] |
call mutex_unlock |
/kernel/branches/Kolibri-acpi/network/tcp_subr.inc |
---|
164,7 → 164,7 |
;;; TODO: check if error code is "Connection timed out' and handle accordingly |
mov [eax + SOCKET.errorcode], ebx |
; mov [eax + SOCKET.errorcode], ebx |
302,6 → 302,11 |
; And send the segment |
call [ebx + NET_DEVICE.transmit] |
test eax, eax |
jnz @f |
call NET_ptr_to_num4 |
inc [TCP_segments_tx + edi] |
@@: |
ret |
.error: |
378,6 → 383,11 |
; And send the segment |
call [ebx + NET_DEVICE.transmit] |
test eax, eax |
jnz @f |
call NET_ptr_to_num4 |
inc [TCP_segments_tx + edi] |
@@: |
ret |
.error: |
/kernel/branches/Kolibri-acpi/network/tcp_usreq.inc |
---|
97,6 → 97,9 |
call SOCKET_is_disconnecting |
call TCP_usrclosed |
push eax |
call TCP_output |
pop eax |
ret |
/kernel/branches/Kolibri-acpi/network/udp.inc |
---|
27,10 → 27,12 |
ends |
uglobal |
align 4 |
uglobal |
UDP_PACKETS_TX rd NET_DEVICES_MAX |
UDP_PACKETS_RX rd NET_DEVICES_MAX |
endg |
114,6 → 116,7 |
; |
;----------------------------------------------------------------- |
align 4 |
diff16 "UDP packetgfgfgfgfs", 0, $ |
UDP_input: |
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: size=%u\n", ecx |
139,6 → 142,11 |
; IP Packet UDP Destination Port = local Port |
; IP Packet SA = Remote IP |
pusha |
mov ecx, socket_mutex |
call mutex_lock |
popa |
mov cx, [esi + UDP_header.SourcePort] |
mov dx, [esi + UDP_header.DestinationPort] |
mov edi, [edi + 4] ; ipv4 source address |
147,7 → 155,7 |
.next_socket: |
mov eax, [eax + SOCKET.NextPtr] |
or eax, eax |
jz .dump |
jz .dump_ |
cmp [eax + SOCKET.Domain], AF_INET4 |
jne .next_socket |
160,6 → 168,11 |
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: socket=%x\n", eax |
pusha |
mov ecx, socket_mutex |
call mutex_unlock |
popa |
;;; TODO: when packet is processed, check more sockets! |
; cmp [eax + IP_SOCKET.RemoteIP], 0xffffffff |
182,7 → 195,8 |
popa |
.updatesock: |
inc [UDP_PACKETS_RX] ; Fixme: correct interface? |
call NET_ptr_to_num4 |
inc [UDP_PACKETS_RX + edi] |
movzx ecx, [esi + UDP_header.Length] |
sub ecx, sizeof.UDP_header |
202,7 → 216,17 |
jmp .updatesock |
.dump_: |
pusha |
mov ecx, socket_mutex |
call mutex_unlock |
popa |
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: no socket found\n" |
jmp .dump |
.checksum_mismatch: |
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: checksum mismatch\n" |
274,7 → 298,8 |
call [ebx + NET_DEVICE.transmit] |
test eax, eax |
jnz @f |
inc [UDP_PACKETS_TX] ; FIXME: correct device? |
call NET_ptr_to_num4 |
inc [UDP_PACKETS_TX + edi] |
@@: |
ret |