kolibri-acpi:update

git-svn-id: svn://kolibrios.org@4265 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2013-11-21 02:42:12 +00:00
parent 7450ef6270
commit 080b8dcdc4
54 changed files with 10208 additions and 1989 deletions

View File

@ -1006,6 +1006,9 @@ end virtual
call ext2_create_partition
test eax, eax
jnz .success
call xfs_create_partition
test eax, eax
jnz .success
; 3. No file system has recognized the volume, so just allocate the PARTITION
; structure without extra fields.
movi eax, sizeof.PARTITION

View File

@ -512,7 +512,7 @@ disk_init_cache:
push edi
mov edi, [esi+DISK.SysCache.pointer]
lea ecx, [ecx*3]
lea ecx, [(ecx+1)*3]
xor eax, eax
rep stosd
pop edi
@ -527,7 +527,7 @@ disk_init_cache:
push edi
mov edi, [esi+DISK.AppCache.pointer]
lea ecx, [ecx*3]
lea ecx, [(ecx+1)*3]
xor eax, eax
rep stosd
pop edi

View File

@ -162,7 +162,7 @@ FDCDataInput:
mov [FDC_Status], FDC_Normal
; Проверить готовность контроллера к передаче данных
mov DX, 3F4h ;(порт состояния FDC)
xor CX, CX ;установить счетчик тайм-аута
mov ecx, 0x10000 ;установить счетчик тайм-аута
@@TestRS_1:
in AL, DX ;прочитать регистр RS
and AL, 0C0h ;выдлить разряды 6 и 7
@ -197,8 +197,6 @@ WaitFDCInterrupt:
pusha
; Сбросить байт состояния операции
mov [FDC_Status], FDC_Normal
; Сбросить флаг прерывани
mov [FDD_IntFlag], 0
; Обнулить счетчик тиков
mov eax, [timer_ticks]
mov [TickCounter], eax
@ -372,6 +370,8 @@ RecalibrateFDD:
SeekTrack:
pusha
call save_timer_fdd_motor
; Сбросить флаг прерывания
mov [FDD_IntFlag], 0
; Подать команду "Поиск"
mov AL, 0Fh
call FDCDataOutput
@ -431,6 +431,8 @@ SeekTrack:
ReadSector:
pushad
call save_timer_fdd_motor
; Сбросить флаг прерывания
mov [FDD_IntFlag], 0
; Установить скорость передачи 500 Кбайт/с
mov AX, 0
mov DX, 03F7h
@ -531,6 +533,8 @@ ReadSectWithRetr:
WriteSector:
pushad
call save_timer_fdd_motor
; Сбросить флаг прерывания
mov [FDD_IntFlag], 0
; Установить скорость передачи 500 Кбайт/с
mov AX, 0
mov DX, 03F7h

View File

@ -51,18 +51,20 @@ getkey: ; Use BIOS INT 16h to read a key from the keyboa
; get number in range [bl,bh] (bl,bh in ['0'..'9'])
; in: bx=range
; out: ax=digit (1..9, 10 for 0)
mov ah, 0 ; If 'int 16h' is called with 'ah' equal to zero, the BIOS will not return control
int 16h ; to the caller until a key is available in the system type ahead buffer. On return,
cmp al, bl ; 'al' contains the ASCII code for the key read from the buffer and 'ah' contains
jb getkey ; the keyboard scan code. Here we compare 'al' with the range of accepted characters.
cmp al, bh ; If the key pressed is not in the range, continue waiting for another key.
ja getkey
mov ah, 0 ; If 'int 16h' is called with 'ah' equal to zero, the BIOS will not return control to the caller
int 16h ; until a key is available in the system type ahead buffer. On return, 'al' contains the ASCII
cmp al, 27 ; code for the key read from the buffer and 'ah' contains the keyboard scan code. (27=>ESC)
jz @f ; If ESC is pressed, return (user doesn't want to change any value).
cmp al, bl ; Compare 'al' (ASCII code of key pressed) with 'bl' (lowest accepted char from the range).
jb getkey ; ASCII code is below lowest accepted value => continue waiting for another key.
cmp al, bh ; Compare 'al' (ASCII code of key pressed) with 'bh' (highest accepted char from the range).
ja getkey ; ASCII code is above highest accepted value => continue waiting for another key.
push ax ; If the pressed key is in the accepted range, save it on the stack and echo to screen.
call putchar
pop ax
and ax, 0Fh ; ASCII code for '0' is 48 (110000b). 0F4=1111b. (110000b AND 1111b) = 0
jnz @f ; So if key '0' was entered, return 10 in 'ax'
mov al, 10
and ax, 0Fh ; Convert ASCII code to number: '1'->1, '2'->2, etc. 0Fh=1111b.
jnz @f ; ASCII code for '0' is 48 (110000b). (110000b AND 1111b) = 0
mov al, 10 ; So if key '0' was entered, return 10 in 'ax'
@@:
ret
@ -79,6 +81,18 @@ macro _setcursor row,column
call setcursor
}
macro _ask_question question,range,variable_to_set
{
_setcursor 16,0
mov si, question ; Print the question
call print
mov bx, range ; range accepted for answer
call getkey
cmp al, 27 ; If ESC was pressed, do not change the value
jz .esc_pressed
mov [variable_to_set], al
}
boot_read_floppy:
push si
xor si, si
@ -433,7 +447,7 @@ sayerr:
mov [es:BOOT_IDE_PI_16], cx
xor si, si ; device index = 0
int 0x1A
jnc .found_1 ; Parallel IDE Controller
jnc .found ; Parallel IDE Controller
; Controller not found!
xor ax, ax
mov [es:BOOT_IDE_PI_16], ax
@ -775,25 +789,26 @@ end if
cmp al, 'e' ; select boot origin
jnz .show_remarks
; e) preboot_device = from where to boot?
_setcursor 16,0
mov si, bdev
call print
if defined extended_primary_loader
mov bx, '12' ; range accepted for answer: 1-2
_ask_question bdev,'12',preboot_device ; range accepted for answer: 1-2
else
mov bx, '14' ; range accepted for answer: 1-4
_ask_question bdev,'14',preboot_device ; range accepted for answer: 1-4
end if
call getkey
mov [preboot_device], al
_setcursor 14,0
.d:
if ~ defined extended_primary_loader
mov [.bSettingsChanged], 1
end if
.esc_pressed:
call clear_vmodes_table ;clear vmodes_table
jmp .printcfg
.change_a:
call clear_vmodes_table ;clear vmodes_table
mov si, word [cursor_pos]
mov word [cursor_pos_old], si
.loops:
call draw_vmodes_table
_setcursor 25,0 ; out of screen
@ -803,6 +818,13 @@ end if
mov si, word [cursor_pos]
cmp al, 27 ; If ESC was pressed, do not change the value
jnz @f ; Just exit the resolution selection box
mov si, word [cursor_pos_old]
mov word [cursor_pos], si
jmp .esc_pressed
@@:
cmp ah, 0x48;x,0x48E0 ; up
jne .down
cmp si, modes_table
@ -873,17 +895,13 @@ end if
jmp .d
.change_b: ; b) preboot_biosdisk = use BIOS disks through V86 emulation?
_setcursor 16,0
; _setcursor 16,0
; mov si, ask_dma // (earlier was: preboot_dma = use DMA access?)
; call print
; mov bx, '13' ; range accepted for answer: 1-3
; call getkey
; mov [preboot_dma], al
mov si, ask_bd
call print
mov bx, '12' ; range accepted for answer: 1-2
call getkey
mov [preboot_biosdisk], al
_ask_question ask_bd,'12',preboot_biosdisk ; range accepted for answer: 1-2
_setcursor 11,0
jmp .d
;.change_c: ; // VRR is an obsolete functionality, used only with CRT monitors
@ -896,21 +914,11 @@ end if
; _setcursor 12,0
; jmp .d
.change_c: ; c) preboot_debug = duplicates kernel debug output to the screen
_setcursor 16,0
mov si, ask_debug
call print
mov bx, '12' ; range accepted for answer: 1-2
call getkey
mov [preboot_debug], al
_ask_question ask_debug,'12',preboot_debug ; range accepted for answer: 1-2
_setcursor 12,0
jmp .d
.change_d: ; d) preboot_launcher = start the first app (right now it's LAUNCHER) after kernel is loaded?
_setcursor 16,0
mov si, ask_launcher
call print
mov bx, '12' ; range accepted for answer: 1-2
call getkey
mov [preboot_launcher], al
_ask_question ask_launcher,'12',preboot_launcher ; range accepted for answer: 1-2
_setcursor 13,0
jmp .d
;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -15,10 +15,10 @@ $Revision: 2455 $
d80x25_bottom:
db 186,' KolibriOS comes with ABSOLUTELY NO WARRANTY. See file COP'
db 'YING for details ',186
db 186,' KolibriOS comes with ABSOLUTELY NO WARRANTY. See file COPYING for details ',186
db 186,' If you find any bugs, please report them at: http://board.kolibrios.org ',186
line_full_bottom
d80x25_bottom_num = 2
d80x25_bottom_num = 3
msg_apm db " APM x.x ", 0
novesa db "Display: EGA/CGA",13,10,0
@ -79,7 +79,7 @@ preboot_device_msgs dw 0,pdm1,pdm2,0
pdm1 db "real floppy",13,10,0
pdm2 db "C:\kolibri.img (FAT32)",13,10,0
else
preboot_device_msgs dw 0,pdm1,pdm2,pdm3
preboot_device_msgs dw 0,pdm1,pdm2,pdm3,pdm4,0
pdm1 db "real floppy",13,10,0
pdm2 db "C:\kolibri.img (FAT32)",13,10,0
pdm3 db "use already loaded image",13,10,0
@ -93,13 +93,14 @@ save_quest db "Remember current settings? [y/n]: ",0
loader_block_error db "Bootloader data invalid, I cannot continue. Stopped.",0
end if
_st:latin1 '║ ┌───────────────────────────────┬─┐',13,10,0
_r1:latin1 '║ │ 320x200 EGA/CGA 256 colors │ │',13,10,0
_r2:latin1 '║ │ 640x480 VGA 16 colors │ │',13,10,0
_rs:latin1 '║ │ ????x????@?? SVGA VESA │ │',13,10,0
_bt:latin1 '║ └───────────────────────────────┴─┘',13,10,0
_st latin1 '║ ┌───────────────────────────────┬─┐',13,10,0
_r1 latin1 '║ │ 320x200 EGA/CGA 256 colors │ │',13,10,0
_r2 latin1 '║ │ 640x480 VGA 16 colors │ │',13,10,0
_rs latin1 '║ │ ????x????@?? SVGA VESA │ │',13,10,0
_bt latin1 '║ └───────────────────────────────┴─┘',13,10,0
remark1 db "Default values were selected to match most of configurations, but not all.",0
remark2 db "If the system does not boot, try to disable the item [b].",0
remarks dw remark1, remark2
num_remarks = 2
remark2 db "If the system does not boot, try to disable option [b]. If the system gets",0
remark3 db "stuck after booting, enable option [c], disable option [d] and make photo.",0
remarks dw remark1, remark2, remark3
num_remarks = 3

View File

@ -15,91 +15,92 @@ $Revision$
d80x25_bottom:
latin1 '║ KolibriOS kaasas IGASUGUSE GARANTIITA. Naha faili COPY'
latin1 'ING detailid ║'
latin1 '║ KolibriOS on IGASUGUSE GARANTIITA. Vaata faili COPYING info saamiseks. Kui ║'
latin1 '║ leiate vigu, anna neist palun teada aadressil: http://board.kolibrios.org ║'
line_full_bottom
d80x25_bottom_num = 2
d80x25_bottom_num = 3
msg_apm: latin1 " APM x.x ", 0
novesa: latin1 "Ekraan: EGA/CGA",13,10,0
s_vesa: latin1 "Vesa versioon: "
msg_apm latin1 " APM x.x ", 0
novesa latin1 "Ekraan: EGA/CGA",13,10,0
s_vesa latin1 "Vesa versioon: "
.ver db "?.?",13,10,0
gr_mode: latin1 "Vali videomode: ",13,10,0
gr_mode latin1 "Vali video resolutsioon: ",13,10,0
ask_bd: latin1 "Lisa kettad nahtavaks BIOS reziim V86? [1-jah, 2-no]: ",0
ask_bd latin1 "Lisa V86 reziimis BIOSle nähtavad kettad? [1-jah, 2-ei]: ",0
if defined extended_primary_loader
bdev: latin1 "Paigalda mäluketas [1-diskett; 2-kolibri.img]: ",0
bdev latin1 "Paigalda mäluketas [1-diskett; 2-kolibri.img]: ",0
else
bdev: latin1 "Paigalda mäluketas [1-diskett; 2-C:\kolibri.img (FAT32);"
bdev latin1 "Paigalda mäluketas [1-diskett; 2-C:\kolibri.img (FAT32);"
latin1 13,10,""
latin1 "3-kasuta eellaaditud mäluketast kerneli restardist;"
latin1 13,10,""
latin1 "4-loo tühi pilt]: ",0
end if
prnotfnd: latin1 "Fataalne - Videoreziimi ei leitud.",0
prnotfnd latin1 "Fataalne - Video resolutsiooni ei leitud.",0
not386: latin1 "Fataalne - CPU 386+ on vajalik.",0
fatalsel: latin1 "Fataalne - Graafilist reziimi riistvara ei toeta.",0
pres_key: latin1 "Vajutage suvalist klahvi, et valida uus videomode.",0
badsect: latin1 13,10,"║ Fataalne - Vigane sektor. Asenda diskett.",0
memmovefailed:latin1 13,10,"║ Fataalne - Int 0x15 liigutamine ebaõnnestus.",0
okt: latin1 " ... OK"
linef: latin1 13,10,0
diskload: latin1 "Loen disketti: 00 %",8,8,8,8,0
pros: latin1 "00"
backspace2:latin1 8,8,0
not386 latin1 "Fataalne - CPU 386+ on vajalik.",0
fatalsel latin1 "Fataalne - Riistvara ei toeta graafilist resolutsiooni.",0
pres_key latin1 "Vajutage suvalist klahvi, et valida uus videomode.",0
badsect latin1 13,10,"║ Fataalne - Vigane sektor. Asenda diskett.",0
memmovefailed latin1 13,10,"║ Fataalne - Int 0x15 liigutamine ebaõnnestus.",0
okt latin1 " ... OK"
linef latin1 13,10,0
diskload latin1 "Loen disketti: 00 %",8,8,8,8,0
pros latin1 "00"
backspace2 latin1 8,8,0
boot_dev db 0 ; 0=floppy, 1=hd
start_msg:latin1 "Vajuta [abcde] seadete muutmiseks, vajuta [Enter] laadimise jätkamiseks",13,10,0
time_msg: latin1 " või oota "
time_str: latin1 " 5 sekundit"
start_msg latin1 "Vajuta [abcde] seadete muutmiseks, vajuta [Enter] laadimise jätkamiseks",13,10,0
time_msg latin1 " või oota "
time_str latin1 " 5 sekundit"
latin1 " automaatseks jätkamiseks",13,10,0
current_cfg_msg:latin1 "Praegused seaded:",13,10,0
curvideo_msg:latin1 " [a] Videoreziim: ",0
current_cfg_msg latin1 "Praegused seaded:",13,10,0
curvideo_msg latin1 " [a] Video resolutsioon: ",0
mode0: latin1 "320x200, EGA/CGA 256 värvi",0
mode9: latin1 "640x480, VGA 16 värvi",0
mode0 latin1 "320x200, EGA/CGA 256 värvi",0
mode9 latin1 "640x480, VGA 16 värvi",0
usebd_msg:latin1 " [b] Lisa kettad nahtavaks BIOS:",0
on_msg: latin1 " sees",13,10,0
off_msg: latin1 " väljas",13,10,0
usebd_msg latin1 " [b] Lisa BIOSle nähtavad kettad:",0
on_msg latin1 " sees",13,10,0
off_msg latin1 " väljas",13,10,0
debug_mode_msg: latin1 " [c] Duplicate siluda väljund ekraani:",0
ask_debug: latin1 "Duplicate siluda väljund ekraani? [1-jah, 2-no]: ",0
debug_mode_msg latin1 " [c] Dubleeri silumisinfo ekraanile:",0
ask_debug latin1 "Dubleeri silumisinfo ekraanile? [1-jah, 2-ei]: ",0
launcher_msg: latin1 " [d] Alusta LAUNCHER pärast kernel on koormatud:",0
ask_launcher: latin1 "Alusta esimese taotluse (LAUNCHER) pärast kernel laetakse? [1-jah, 2-no]: ",0
launcher_msg latin1 " [d] Käivita LAUNCHER pärast kerneli laadimist:",0
ask_launcher latin1 "Käivita esimese programm (LAUNCHER) peale kerneli laadimist? [1-jah, 2-ei]: ",0
preboot_device_msg:latin1 " [e] Disketi kujutis: ",0
preboot_device_msg latin1 " [e] Disketi kujutis: ",0
if defined extended_primary_loader
preboot_device_msgs dw 0,pdm1,pdm2,0
pdm1: latin1 "reaalne diskett",13,10,0
pdm2: latin1 "kolibri.img",13,10,0
pdm1 latin1 "reaalne diskett",13,10,0
pdm2 latin1 "kolibri.img",13,10,0
else
preboot_device_msgs dw 0,pdm1,pdm2,pdm3
pdm1: latin1 "reaalne diskett",13,10,0
pdm2: latin1 "C:\kolibri.img (FAT32)",13,10,0
pdm3: latin1 "kasuta juba laaditud kujutist",13,10,0
pdm4: latin1 "loo tühi pilt",13,10,0
preboot_device_msgs dw 0,pdm1,pdm2,pdm3,pdm4,0
pdm1 latin1 "reaalne diskett",13,10,0
pdm2 latin1 "C:\kolibri.img (FAT32)",13,10,0
pdm3 latin1 "kasuta juba laaditud kujutist",13,10,0
pdm4 latin1 "loo tühi pilt",13,10,0
end if
loading_msg:latin1 "Laadin KolibriOS...",0
loading_msg latin1 "Laadin KolibriOS...",0
if ~ defined extended_primary_loader
save_quest:latin1 "Jäta meelde praegused seaded? [y/n]: ",0
loader_block_error:latin1 "Alglaaduri andmed vigased, ei saa jätkata. Peatatud.",0
save_quest latin1 "Jäta meelde praegused seaded? [y/n]: ",0
loader_block_error latin1 "Alglaaduri andmed vigased, ei saa jätkata. Peatatud.",0
end if
_st:latin1 '║ ┌───────────────────────────────┬─┐',13,10,0
_r1:latin1 '║ │ 320x200 EGA/CGA 256 colors │ │',13,10,0
_r2:latin1 '║ │ 640x480 VGA 16 colors │ │',13,10,0
_rs:latin1 '║ │ ????x????@?? SVGA VESA │ │',13,10,0
_bt:latin1 '║ └───────────────────────────────┴─┘',13,10,0
_st latin1 '║ ┌───────────────────────────────┬─┐',13,10,0
_r1 latin1 '║ │ 320x200 EGA/CGA 256 colors │ │',13,10,0
_r2 latin1 '║ │ 640x480 VGA 16 colors │ │',13,10,0
_rs latin1 '║ │ ????x????@?? SVGA VESA │ │',13,10,0
_bt latin1 '║ └───────────────────────────────┴─┘',13,10,0
remark1:latin1 "Vaikimisi maaratud vaartused on valitud mugavuse enamikes, kuid mitte koik.",0
remark2:latin1 "Kui susteem ei kaivitu, proovige lulitada kirje [b].",0
remarks dw remark1, remark2
num_remarks = 2
remark1 latin1 "Vaikimisi väärtused on kasutatavad enamikes arvutites, kuid mitte kõigis.",0
remark2 latin1 "Kui süsteem ei käivitu, proovige lülitada kirje [b] välja. Kui see läheb",0
remark3 latin1 "kinni pärast käivitamist, võimaldama valik [c], keelake [d] ja teha foto.",0
remarks dw remark1, remark2, remark3
num_remarks = 3

View File

@ -15,10 +15,8 @@ $Revision$
d80x25_bottom:
db 186,' KolibriOS wird ohne jegliche Garantie vertrieben. '
db ' ',186
db 186,' Details stehen in der Datei COPYING '
db ' ',186
db 186,' KolibriOS wird ohne jegliche Garantie vertrieben. Details stehen in der ',186
db 186,' Datei COPYING. Bitte melden Sie Fehler bei: http://board.kolibrios.org ',186
line_full_bottom
d80x25_bottom_num = 3
@ -81,7 +79,7 @@ preboot_device_msgs dw 0,pdm1,pdm2,0
pdm1 db "Echte Diskette",13,10,0
pdm2 db "kolibri.img",13,10,0
else
preboot_device_msgs dw 0,pdm1,pdm2,pdm3
preboot_device_msgs dw 0,pdm1,pdm2,pdm3,pdm4,0
pdm1 db "Echte Diskette",13,10,0
pdm2 db "C:\kolibri.img (FAT32)",13,10,0
pdm3 db "Nutze bereits geladenes Image",13,10,0
@ -95,13 +93,15 @@ save_quest db "Aktuelle Einstellungen speichern? [y/n]: ",0
loader_block_error db "Bootloader Daten ungueltig, Kann nicht fortfahren. Angehalten.",0
end if
_st:latin1 '║ ┌───────────────────────────────┬─┐',13,10,0
_r1:latin1 '║ │ 320x200 EGA/CGA 256 colors │ │',13,10,0
_r2:latin1 '║ │ 640x480 VGA 16 colors │ │',13,10,0
_rs:latin1 '║ │ ????x????@?? SVGA VESA │ │',13,10,0
_bt:latin1 '║ └───────────────────────────────┴─┘',13,10,0
_st latin1 '║ ┌───────────────────────────────┬─┐',13,10,0
_r1 latin1 '║ │ 320x200 EGA/CGA 256 colors │ │',13,10,0
_r2 latin1 '║ │ 640x480 VGA 16 colors │ │',13,10,0
_rs latin1 '║ │ ????x????@?? SVGA VESA │ │',13,10,0
_bt latin1 '║ └───────────────────────────────┴─┘',13,10,0
remark1 db "Die Standardwerte sind fur die meisten gewahlt, aber nicht fur jedermann.",0
remark2 db "Wenn das System nicht bootet, versuchen, das Element [b] deaktivieren.",0
remarks dw remark1, remark2
num_remarks = 2
remark2 db "Wenn das System nicht bootet, das Option [b] deaktivieren versuchen. Wenn es",0
remark3 db "nach dem Booten hangen bleibt, aktivieren Sie Option [c], deaktivieren [d]",0
remark4 db "und machen Fotos.",0
remarks dw remark1, remark2, remark3, remark4
num_remarks = 4

View File

@ -15,89 +15,90 @@ $Revision$
d80x25_bottom:
cp866 '║ KolibriOS НЕ ПРЕДОСТАВЛЯЕТ НИКАКИХ ГАРAНТИЙ. ║'
cp866 '║ Подробнее смотрите в файле COPYING.TXT ║'
cp866 '║ KolibriOS НЕ ПРЕДОСТАВЛЯЕТ НИКАКИХ ГАРAНТИЙ. Подробнее смотрите в файле ║'
cp866 '║ COPYING.TXT. О найденных ошибках сообщайте на http://board.kolibrios.org ║'
line_full_bottom
d80x25_bottom_num = 3
msg_apm: cp866 " APM x.x ", 0
novesa: cp866 "Видеокарта: EGA/CGA",13,10,0
s_vesa: cp866 "Версия VESA: "
msg_apm cp866 " APM x.x ", 0
novesa cp866 "Видеокарта: EGA/CGA",13,10,0
s_vesa cp866 "Версия VESA: "
.ver db "?.?",13,10,0
gr_mode: cp866 "Выберите видеорежим: ",13,10,0
gr_mode cp866 "Выберите видеорежим: ",13,10,0
ask_bd: cp866 "Добавить диски, видимые через BIOS в режиме V86? [1-да, 2-нет]: ",0
ask_bd cp866 "Добавить диски, видимые через BIOS в режиме V86? [1-да, 2-нет]: ",0
if defined extended_primary_loader
bdev: cp866 "Загрузить образ из [1-дискета; 2-kolibri.img из папки загрузки]: ",0
bdev cp866 "Загрузить образ из [1-дискета; 2-kolibri.img из папки загрузки]: ",0
else
bdev: cp866 "Загрузить образ из [1-дискета; 2-C:\kolibri.img (FAT32);",13,10
bdev cp866 "Загрузить образ из [1-дискета; 2-C:\kolibri.img (FAT32);",13,10
cp866 "║ 3-использовать уже загруженный образ;",13,10
cp866 "║ 4-создать чистый образ]: ",0
end if
prnotfnd: cp866 "Ошибка - Видеорежим не найден.",0
prnotfnd cp866 "Ошибка - Видеорежим не найден.",0
not386: cp866 "Ошибка - Требуется процессор 386+.",0
fatalsel: cp866 "Ошибка - Выбранный видеорежим не поддерживается.",0
pres_key: cp866 "Нажимите любую клавишу, для перехода в выбор режимов.",0
badsect: cp866 13,10,"║ Ошибка - Дискета повреждена. Попробуйте другую.",0
memmovefailed:cp866 13,10,"║ Ошибка - Int 0x15 move failed.",0
okt: cp866 " ... OK"
linef: cp866 13,10,0
diskload: cp866 "Загрузка дискеты: 00 %",8,8,8,8,0
pros: cp866 "00"
backspace2:cp866 8,8,0
not386 cp866 "Ошибка - Требуется процессор 386+.",0
fatalsel cp866 "Ошибка - Выбранный видеорежим не поддерживается.",0
pres_key cp866 "Нажимите любую клавишу, для перехода в выбор режимов.",0
badsect cp866 13,10,"║ Ошибка - Дискета повреждена. Попробуйте другую.",0
memmovefailed cp866 13,10,"║ Ошибка - Int 0x15 move failed.",0
okt cp866 " ... OK"
linef cp866 13,10,0
diskload cp866 "Загрузка дискеты: 00 %",8,8,8,8,0
pros cp866 "00"
backspace2 cp866 8,8,0
boot_dev db 0
start_msg:cp866 "Нажмите [abcde] для изменения настроек, [Enter] для продолжения загрузки",13,10,0
time_msg: cp866 " или подождите "
time_str: cp866 " 5 секунд "
start_msg cp866 "Нажмите [abcde] для изменения настроек, [Enter] для продолжения загрузки",13,10,0
time_msg cp866 " или подождите "
time_str cp866 " 5 секунд "
cp866 " до автоматического продолжения",13,10,0
current_cfg_msg:cp866 "Текущие настройки:",13,10,0
curvideo_msg:cp866 " [a] Видеорежим: ",0
current_cfg_msg cp866 "Текущие настройки:",13,10,0
curvideo_msg cp866 " [a] Видеорежим: ",0
mode0: cp866 "320x200, EGA/CGA 256 цветов",13,10,0
mode9: cp866 "640x480, VGA 16 цветов",13,10,0
mode0 cp866 "320x200, EGA/CGA 256 цветов",13,10,0
mode9 cp866 "640x480, VGA 16 цветов",13,10,0
usebd_msg:cp866 " [b] Добавить диски, видимые через BIOS:",0
on_msg: cp866 " вкл",13,10,0
off_msg: cp866 " выкл",13,10,0
usebd_msg cp866 " [b] Добавить диски, видимые через BIOS:",0
on_msg cp866 " вкл",13,10,0
off_msg cp866 " выкл",13,10,0
debug_mode_msg: cp866 " [c] Дублировать дебаг-вывод на экран монитора:",0
ask_debug: cp866 "Дублировать дебаг-вывод на экран монитора? [1-да, 2-нет]: ",0
debug_mode_msg cp866 " [c] Дублировать дебаг-вывод на экран монитора:",0
ask_debug cp866 "Дублировать дебаг-вывод на экран монитора? [1-да, 2-нет]: ",0
launcher_msg: cp866 " [d] Запустить программу LAUNCHER после загрузки ядра:",0
ask_launcher: cp866 "Запустить первую программу (LAUNCHER) после загрузки ядра? [1-да, 2-нет]: ",0
launcher_msg cp866 " [d] Запустить программу LAUNCHER после загрузки ядра:",0
ask_launcher cp866 "Запустить первую программу (LAUNCHER) после загрузки ядра? [1-да, 2-нет]: ",0
preboot_device_msg:cp866 " [e] Образ дискеты: ",0
preboot_device_msg cp866 " [e] Образ дискеты: ",0
if defined extended_primary_loader
preboot_device_msgs dw 0,pdm1,pdm2,0
pdm1: cp866 "настоящая дискета",13,10,0
pdm2: cp866 "kolibri.img из папки загрузки",13,10,0
pdm1 cp866 "настоящая дискета",13,10,0
pdm2 cp866 "kolibri.img из папки загрузки",13,10,0
else
preboot_device_msgs dw 0,pdm1,pdm2,pdm3,pdm4
pdm1: cp866 "настоящая дискета",13,10,0
pdm2: cp866 "C:\kolibri.img (FAT32)",13,10,0
pdm3: cp866 "использовать уже загруженный образ",13,10,0
pdm4: cp866 "создать чистый образ",13,10,0
preboot_device_msgs dw 0,pdm1,pdm2,pdm3,pdm4,0
pdm1 cp866 "настоящая дискета",13,10,0
pdm2 cp866 "C:\kolibri.img (FAT32)",13,10,0
pdm3 cp866 "использовать уже загруженный образ",13,10,0
pdm4 cp866 "создать чистый образ",13,10,0
end if
loading_msg:cp866 "Идёт загрузка KolibriOS...",0
loading_msg cp866 "Идёт загрузка KolibriOS...",0
if ~ defined extended_primary_loader ; saving not supported in this case
save_quest:cp866 "Запомнить текущие настройки? [y/n]: ",0
loader_block_error:cp866 "Ошибка в данных начального загрузчика, продолжение невозможно.",0
save_quest cp866 "Запомнить текущие настройки? [y/n]: ",0
loader_block_error cp866 "Ошибка в данных начального загрузчика, продолжение невозможно.",0
end if
_st:cp866 '║ ┌───────────────────────────────┬─┐ ',13,10,0
_r1:cp866 '║ │ 320x200 EGA/CGA 256 цветов │ │ ',13,10,0
_r2:cp866 '║ │ 640x480 VGA 16 цветов │ │ ',13,10,0
_rs:cp866 '║ │ ????x????@?? SVGA VESA │ │ ',13,10,0
_bt:cp866 '║ └───────────────────────────────┴─┘ ',13,10,0
_st cp866 '║ ┌───────────────────────────────┬─┐ ',13,10,0
_r1 cp866 '║ │ 320x200 EGA/CGA 256 цветов │ │ ',13,10,0
_r2 cp866 '║ │ 640x480 VGA 16 цветов │ │ ',13,10,0
_rs cp866 '║ │ ????x????@?? SVGA VESA │ │ ',13,10,0
_bt cp866 '║ └───────────────────────────────┴─┘ ',13,10,0
remark1:cp866 "Значения по умолчанию выбраны для удобства большинства, но не всех.",0
remark2:cp866 "Если у Вас не грузится система, попробуйте отключить пункт [b].",0
remarks dw remark1, remark2
num_remarks = 2
remark1 cp866 "Значения по умолчанию выбраны для удобства большинства, но не всех. Если у",0
remark2 cp866 "Вас не грузится система, попробуйте отключить пункт [b]. Если она зависла",0
remark3 cp866 "после запуска, включите пункт [c], отключите пункт [d] и сделайте фото лога.",0
remarks dw remark1, remark2, remark3
num_remarks = 3

View File

@ -17,93 +17,92 @@ $Revision: 2455 $
d80x25_bottom:
cp850 '║ KolibriOS y viene ABSOLUTAMENTE SIN GARANTíA. '
cp850 ' ║'
cp850 '║ Lee el archivo COPYING por más detalles '
cp850 ' ║'
cp850 '║ KolibriOS viene ABSOLUTAMENTE SIN GARANTíA. Lee el archivo COPYING por más ║'
cp850 '║ detalles. Por favor, informar de los errores en: http://board.kolibrios.org ║'
line_full_bottom
d80x25_bottom_num = 3
msg_apm: cp850 " APM x.x ", 0
novesa: cp850 "Monitor: EGA/CGA",13,10,0
s_vesa: cp850 "Versión de VESA: "
msg_apm cp850 " APM x.x ", 0
novesa cp850 "Monitor: EGA/CGA",13,10,0
s_vesa cp850 "Versión de VESA: "
.ver db "?.?",13,10,0
gr_mode: cp850 "Selecciona un modo de video: ",13,10,0
gr_mode cp850 "Selecciona un modo de video: ",13,10,0
ask_bd: cp850 "¿Agregar discos visibles por el BIOS emulados en modo V86? [1-si, 2-no]: ",0
ask_bd cp850 "¿Agregar discos visibles por el BIOS emulados en modo V86? [1-si, 2-no]: ",0
if defined extended_primary_loader
bdev: cp850 "Cargar unidad ram desde [1-disquete; 2-kolibri.img]: ",0
bdev cp850 "Cargar unidad ram desde [1-disquete; 2-kolibri.img]: ",0
else
bdev: cp850 "Cargar unidad ram desde [1-disquete; 2-C:\kolibri.img (FAT32);"
bdev cp850 "Cargar unidad ram desde [1-disquete; 2-C:\kolibri.img (FAT32);"
cp850 13,10,""
cp850 "3-usar imagen precargada en el reinicio del núcleo;"
cp850 13,10,""
cp850 "4-crear imagen vacía]: ",0
end if
prnotfnd: cp850 "Fatal - Modo de video no encontrado.",0
prnotfnd cp850 "Fatal - Modo de video no encontrado.",0
not386: cp850 "Fatal - CPU 386+ requerido.",0
fatalsel: cp850 "Fatal - Modo de gráficos no soportado por hardware.",0
pres_key: cp850 "Presiona una tecla para seleccionar otro modo de video.",0
badsect: cp850 13,10,"║ Fatal - Sector mal. Reemplaze el disquete.",0
memmovefailed:cp850 13,10,"║ Fatal - Int 0x15 move failed.",0
okt: cp850 " ... BIEN"
linef: cp850 13,10,0
diskload: cp850 "Cargando disquete: 00 %",8,8,8,8,0
pros: cp850 "00"
backspace2:cp850 8,8,0
not386 cp850 "Fatal - CPU 386+ requerido.",0
fatalsel cp850 "Fatal - Modo de gráficos no soportado por hardware.",0
pres_key cp850 "Presiona una tecla para seleccionar otro modo de video.",0
badsect cp850 13,10,"║ Fatal - Sector mal. Reemplaze el disquete.",0
memmovefailed cp850 13,10,"║ Fatal - Int 0x15 move failed.",0
okt cp850 " ... BIEN"
linef cp850 13,10,0
diskload cp850 "Cargando disquete: 00 %",8,8,8,8,0
pros cp850 "00"
backspace2 cp850 8,8,0
boot_dev db 0 ; 0=floppy, 1=hd
start_msg:cp850 "Presiona [abcde] para cambiar la configuración, [Enter] para continuar",13,10,0
time_msg: cp850 " o espera "
time_str: cp850 " 5 segundos"
start_msg cp850 "Presiona [abcde] para cambiar la configuración, [Enter] para continuar",13,10,0
time_msg cp850 " o espera "
time_str cp850 " 5 segundos"
cp850 " para que inicie automáticamente",13,10,0
current_cfg_msg:cp850 "Configuración actual:",13,10,0
curvideo_msg:cp850 " [a] Modo de video: ",0
current_cfg_msg cp850 "Configuración actual:",13,10,0
curvideo_msg cp850 " [a] Modo de video: ",0
mode0: cp850 "320x200, EGA/CGA 256 colores",13,10,0
mode9: cp850 "640x480, VGA 16 colores",13,10,0
mode0 cp850 "320x200, EGA/CGA 256 colores",13,10,0
mode9 cp850 "640x480, VGA 16 colores",13,10,0
usebd_msg:cp850 " [b] Agregar discos visibles por el BIOS:",0
on_msg: cp850 " activado",13,10,0
off_msg: cp850 " desactivado",13,10,0
usebd_msg cp850 " [b] Agregar discos visibles por el BIOS:",0
on_msg cp850 " activado",13,10,0
off_msg cp850 " desactivado",13,10,0
debug_mode_msg: cp850 " [c] Duplicar depurar salida a la pantalla:",0
ask_debug: cp850 "¿Duplicar depurar la salida a la pantalla? [1-si, 2-no]: ",0
debug_mode_msg cp850 " [c] Duplicar depurar salida a la pantalla:",0
ask_debug cp850 "¿Duplicar depurar la salida a la pantalla? [1-si, 2-no]: ",0
launcher_msg: cp850 " [d] Iniciar LAUNCHER después de cargar kernel:",0
ask_launcher: cp850 "¿Inicie la primera aplicación después de cargar el kernel? [1-si, 2-no]: ",0
launcher_msg cp850 " [d] Iniciar LAUNCHER después de cargar kernel:",0
ask_launcher cp850 "¿Inicie la primera aplicación después de cargar el kernel? [1-si, 2-no]: ",0
preboot_device_msg:cp850 " [e] Imagen de disquete: ",0
preboot_device_msg cp850 " [e] Imagen de disquete: ",0
if defined extended_primary_loader
preboot_device_msgs dw 0,pdm1,pdm2,0
pdm1: cp850 "disquete real",13,10,0
pdm2: cp850 "C:\kolibri.img (FAT32)",13,10,0
pdm1 cp850 "disquete real",13,10,0
pdm2 cp850 "C:\kolibri.img (FAT32)",13,10,0
else
preboot_device_msgs dw 0,pdm1,pdm2,pdm3
pdm1: cp850 "disquete real",13,10,0
pdm2: cp850 "C:\kolibri.img (FAT32)",13,10,0
pdm3: cp850 "usar imagen ya cargada",13,10,0
pdm4: cp850 "crear imagen vacía",13,10,0
preboot_device_msgs dw 0,pdm1,pdm2,pdm3,pdm4,0
pdm1 cp850 "disquete real",13,10,0
pdm2 cp850 "C:\kolibri.img (FAT32)",13,10,0
pdm3 cp850 "usar imagen ya cargada",13,10,0
pdm4 cp850 "crear imagen vacía",13,10,0
end if
loading_msg:cp850 "Cargando KolibriOS...",0
loading_msg cp850 "Cargando KolibriOS...",0
if ~ defined extended_primary_loader
save_quest:cp850 "¿Recordar configuración actual? [s/n]: ",0
loader_block_error:cp850 "Bootloader inválido, no puedo continuar. Detenido.",0
save_quest cp850 "¿Recordar configuración actual? [s/n]: ",0
loader_block_error cp850 "Bootloader inválido, no puedo continuar. Detenido.",0
end if
_st:cp850 '║ ┌───────────────────────────────┬─┐',13,10,0
_r1:cp850 '║ │ 320x200 EGA/CGA 256 colores │ │',13,10,0
_r2:cp850 '║ │ 640x480 VGA 16 colores │ │',13,10,0
_rs:cp850 '║ │ ????x????@?? SVGA VESA │ │',13,10,0
_bt:cp850 '║ └───────────────────────────────┴─┘',13,10,0
_st cp850 '║ ┌───────────────────────────────┬─┐',13,10,0
_r1 cp850 '║ │ 320x200 EGA/CGA 256 colores │ │',13,10,0
_r2 cp850 '║ │ 640x480 VGA 16 colores │ │',13,10,0
_rs cp850 '║ │ ????x????@?? SVGA VESA │ │',13,10,0
_bt cp850 '║ └───────────────────────────────┴─┘',13,10,0
remark1:cp850 "Los valores por defecto puede que no funcionen en algunas configuraciones.",0
remark2:cp850 "Si el sistema no inicia, prueba deshabilitar la opción [b].",0
remarks dw remark1, remark2
num_remarks = 2
remark1 cp850 "Los valores por defecto puede que no funcionen en algunas configuraciones.",0
remark2 cp850 "Si el sistema no inicia, prueba deshabilitar la opción [b]. Si se bloquea",0
remark3 cp850 "después de arrancar, habilite la opción [c], desactivar [d] y hacer fotos.",0
remarks dw remark1, remark2, remark3
num_remarks = 3

View File

@ -79,6 +79,7 @@ virtual at $A000
modes_table:
end virtual
cursor_pos dw 0 ;временное хранение курсора.
cursor_pos_old dw 0
home_cursor dw 0 ;current shows rows a table
end_cursor dw 0 ;end of position current shows rows a table
scroll_start dw 0 ;start position of scroll bar

View File

@ -9,7 +9,7 @@ $Revision$
; Full ASCII code font
; only õ and ä added
; only õ,ä,ü added
; Kaitz
ET_FNT:
fontfile file "ETFONT.FNT"

View File

@ -105,6 +105,9 @@ ConfigPipe dd ?
StatusPipe dd ?
NumPorts dd ?
; Number of downstream ports; from 1 to 255.
MaxPacketSize dd ?
; Maximum packet size for interrupt endpoint.
; Usually equals ceil((1+NumPorts)/8), but some hubs give additional bytes.
Actions dd ?
; Bitfield with HUB_* constants.
PoweredOnTime dd ?
@ -250,10 +253,11 @@ end virtual
; the pointer is in edx.
; 2. Allocate memory for the hub descriptor.
; Maximum length (assuming 255 downstream ports) is 40 bytes.
; Allocate 4 extra bytes to keep wMaxPacketSize.
; 2a. Save registers.
push edx
; 2b. Call the allocator.
movi eax, 40
movi eax, 44
call malloc
; 2c. Restore registers.
pop ecx
@ -267,7 +271,11 @@ end virtual
movzx eax, [ecx+usb_endpoint_descr.bEndpointAddress]
movzx edx, [ecx+usb_endpoint_descr.bInterval]
movzx ecx, [ecx+usb_endpoint_descr.wMaxPacketSize]
test ecx, (1 shl 11) - 1
jz .free
push ecx
stdcall usb_open_pipe, ebx, eax, ecx, INTERRUPT_PIPE, edx
pop ecx
; If failed, free the memory allocated in step 2,
; say something to the debug board and return error.
test eax, eax
@ -275,6 +283,8 @@ end virtual
; 4. Send control query for the hub descriptor,
; pass status pipe as a callback parameter,
; allow short packets.
and ecx, (1 shl 11) - 1
mov [esi+40], ecx
mov dword [esi], 0xA0 + \ ; class-specific request
(USB_GET_DESCRIPTOR shl 8) + \
(0 shl 16) + \ ; descriptor index 0
@ -352,8 +362,9 @@ end if
cmp [length], edx
jb .invalid
; 5. Allocate the memory for usb_hub structure.
; Total size of variable-length data is ALIGN_UP(2*(floor(NumPorts/8)+1),4)+8*NumPorts.
lea edx, [sizeof.usb_hub+(edx-sizeof.usb_hub_descr)*2+3]
; Total size of variable-length data is ALIGN_UP(floor(NumPorts/8)+1+MaxPacketSize,4)+8*NumPorts.
add edx, [eax+40]
add edx, sizeof.usb_hub - sizeof.usb_hub_descr + 3
and edx, not 3
lea eax, [edx+ecx*8]
push ecx edx
@ -374,6 +385,8 @@ end if
mov [ebx+usb_hub.StatusPipe], eax
push esi edi
mov esi, [buffer]
mov eax, [esi+40]
mov [ebx+usb_hub.MaxPacketSize], eax
; The following commands load bNbrPorts, wHubCharacteristics, bPwrOn2PwrGood.
mov edx, dword [esi+usb_hub_descr.bNbrPorts]
mov dl, 0
@ -487,11 +500,8 @@ endp
; Called when initial configuration is done and when a previous notification
; has been processed.
proc usb_hub_wait_change
mov ecx, [eax+usb_hub.NumPorts]
shr ecx, 3
inc ecx
stdcall usb_normal_transfer_async, [eax+usb_hub.StatusPipe], \
[eax+usb_hub.StatusChangePtr], ecx, usb_hub_changed, eax, 1
[eax+usb_hub.StatusChangePtr], [eax+usb_hub.MaxPacketSize], usb_hub_changed, eax, 1
ret
endp
@ -513,6 +523,7 @@ proc usb_hub_changed stdcall, pipe:dword, status:dword, buffer:dword, length:dwo
shr ecx, 3
inc ecx
sub ecx, [length]
jbe .restart
push eax edi
mov edi, [buffer]
add edi, [length]

View File

@ -202,8 +202,7 @@ proc usb_new_device
; For now, we need sizeof.usb_device_data and extra 8 bytes for GET_DESCRIPTOR
; input and output, see usb_after_set_address. Later we will reallocate it
; to actual size needed for descriptors.
push sizeof.usb_device_data + 8
pop eax
movi eax, sizeof.usb_device_data + 8
push ecx
call malloc
pop ecx
@ -498,10 +497,7 @@ proc usb_after_set_endpoint_size
pop edi esi
call usb_reinit_pipe_list
; 1d. Free the old memory.
; Note that free destroys ebx.
push ebx
call free
pop ebx
pop eax
; 2. Issue control transfer GET_DESCRIPTOR(DEVICE) for full descriptor.
; restore length saved in step 1a

View File

@ -0,0 +1,148 @@
;------------------------------------------------------------------------------
align 4
sys_clipboard:
xor eax, eax
dec eax
; check availability of main list
cmp [clipboard_main_list], eax
je .exit_1 ; main list area not found
test ebx, ebx ; 0 - Get the number of slots in the clipboard
jnz .1
; get the number of slots
mov eax, [clipboard_slots]
jmp .exit_1
;------------------------------------------------------------------------------
align 4
.1:
dec ebx ; 1 - Read the data from the clipboard
jnz .2
; verify the existence of slot
cmp ecx, [clipboard_slots]
jae .exit_2
; get a pointer to the data of slot
shl ecx, 2
add ecx, [clipboard_main_list]
mov esi, [ecx]
mov ecx, [esi]
; allocate memory for application for copy the data of slots
push ecx
stdcall user_alloc, ecx
pop ecx
; copying data of slots
mov edi, eax
cld
rep movsb
jmp .exit_1
;------------------------------------------------------------------------------
align 4
.2:
dec ebx ; 2 - Write the data to the clipboard
jnz .3
; check the lock
mov ebx, clipboard_write_lock
xor eax, eax
cmp [ebx], eax
jne .exit_2
; lock last slot
inc eax
mov [ebx], eax
; check the overflow pointer of slots
cmp [clipboard_slots], 1024
jae .exit_3
; get memory for new slot
push ebx ecx edx
stdcall kernel_alloc, ecx
pop edx ecx ebx
test eax, eax
jz .exit_3
; create a new slot
mov edi, eax
mov eax, [clipboard_slots]
shl eax, 2
add eax, [clipboard_main_list]
mov [eax], edi
; copy the data into the slot
mov esi, edx
mov eax, ecx
cld
stosd ; store size of slot
sub ecx, 4
add esi, 4
rep movsb ; store slot data
; increase the counter of slots
inc [clipboard_slots]
; unlock last slot
xor eax, eax
mov [ebx], eax
jmp .exit_1
;------------------------------------------------------------------------------
align 4
.3:
dec ebx ; 3 - Delete the last slot in the clipboard
jnz .4
; check the availability of slots
mov eax, [clipboard_slots]
test eax, eax
jz .exit_2
; check the lock
mov ebx, clipboard_write_lock
xor eax, eax
cmp [ebx], eax
jne .exit_2
; lock last slot
inc eax
mov [ebx], eax
; decrease the counter of slots
mov eax, clipboard_slots
dec dword [eax]
; free of kernel memory allocated for the slot
mov eax, [eax]
shl eax, 2
add eax, [clipboard_main_list]
mov eax, [eax]
push ebx
stdcall kernel_free, eax
pop ebx
; unlock last slot
xor eax, eax
mov [ebx], eax
jmp .exit_1
;------------------------------------------------------------------------------
align 4
.4:
dec ebx ; 4 - Emergency discharge of clipboard
jnz .exit
; check the lock
mov ebx, clipboard_write_lock
xor eax, eax
cmp [ebx], eax
je .exit_2
; there should be a procedure for checking the integrity of the slots
; and I will do so in the future
; unlock last slot
mov [ebx], eax
jmp .exit
;------------------------------------------------------------------------------
align 4
.exit_3:
; unlock last slot
xor eax, eax
mov [ebx], eax
.exit_2:
xor eax, eax
inc eax ; error
.exit_1:
mov [esp + 32], eax
.exit:
ret
;------------------------------------------------------------------------------
uglobal
align 4
clipboard_slots dd ?
clipboard_main_list dd ?
clipboard_write_lock dd ?
endg
;------------------------------------------------------------------------------

View File

@ -1,11 +1,11 @@
; Éste archivo debe ser editado con codificación CP866
ugui_mouse_speed:cp850 'velocidad del ratón',0
ugui_mouse_delay:cp850 'demora del ratón',0
ugui_mouse_speed cp850 'velocidad del ratón',0
ugui_mouse_delay cp850 'demora del ratón',0
udev:cp850 'disp',0
unet:cp850 'red',0
unet_active:cp850 'activa',0
unet_addr:cp850 'direc',0
unet_mask:cp850 'másc',0
unet_gate:cp850 'puer',0
udev cp850 'disp',0
unet cp850 'red',0
unet_active cp850 'activa',0
unet_addr cp850 'direc',0
unet_mask cp850 'másc',0
unet_gate cp850 'puer',0

View File

@ -458,7 +458,6 @@ proc load_file_umode stdcall, file_name:dword
push edi
push ebx
lea eax, [attr]
stdcall get_fileinfo, [file_name], eax ;find file and get info
test eax, eax
@ -484,11 +483,26 @@ proc load_file_umode stdcall, file_name:dword
mov ebx, [eax+4] ;get real size of file
mov [file_size], ebx
stdcall user_alloc, ebx ;and allocate memory from user heap
stdcall user_alloc, ebx ;and allocate space from user heap
mov [um_file], eax
test eax, eax
jz .err_2
mov edx, [file_size] ;preallocate page memory
shr eax, 10
lea edi, [page_tabs+eax]
add edx, 4095
shr edx, 12
@@:
call alloc_page
test eax, eax
jz .err_3
or eax, PG_UW
stosd
dec edx
jnz @B
pushad
mov ecx, unpack_mutex
call mutex_lock
@ -501,15 +515,28 @@ proc load_file_umode stdcall, file_name:dword
stdcall kernel_free, [km_file] ;we don't need packed file anymore
.exit:
mov edi, [um_file]
mov esi, [um_file]
mov eax, [file_size]
mov edx, eax
add edi, eax ;cleanup remain space
mov ecx, 4096 ;from file end
and eax, 4095
jz @f
sub ecx, eax
xor eax, eax
cld
rep stosb
@@:
mov eax, [um_file]
mov edx, [file_size]
pop ebx
pop edi
pop esi
ret
.raw_file: ; sometimes we load unpacked file
stdcall user_alloc, ebx ; allocate space from user heap
mov [um_file], eax
@ -533,13 +560,14 @@ proc load_file_umode stdcall, file_name:dword
@@:
lodsd
and eax, 0xFFFFF000
or eax, PG_USER
or eax, PG_UW
stosd
loop @B
stdcall free_kernel_space, [km_file] ; release allocated kernel space
jmp .exit ; physical pages still in use
.err_3:
stdcall user_free, [um_file]
.err_2:
stdcall kernel_free, [km_file]
.err_1:

View File

@ -81,6 +81,8 @@ __exports:
register_keyboard, 'RegKeyboard', \
delete_keyboard, 'DelKeyboard', \
get_cpu_freq, 'GetCpuFreq', \
\
new_sys_threads, 'CreateThread', \ ; ebx, ecx, edx
\
srv_handler, 'ServiceHandler', \
fpu_save, 'FpuSave', \

View File

@ -1,4 +1,4 @@
; Éste archivo debe ser editado con codificación CP866
msg_sel_ker: cp850 "núcleo", 0
msg_sel_app: cp850 "aplicación", 0
msg_sel_ker cp850 "núcleo", 0
msg_sel_app cp850 "aplicación", 0

View File

@ -247,6 +247,83 @@ show_error_parameters:
DEBUGF 1, "K : EDX : %x ESI : %x EDI : %x\n", [reg_edx+4], [reg_esi+4], [reg_edi+4]
DEBUGF 1, "K : EBP : %x EIP : %x ESP : %x\n", [reg_ebp+4], [reg_eip+4], ebx
DEBUGF 1, "K : Flags : %x CS : %x (%s)\n", [reg_eflags+4], eax, edi
DEBUGF 1, "K : Stack dump:\n"
push eax ebx ecx edx
call .check_ESP
test eax, eax
jnz .error_ESP
DEBUGF 1, "K : [ESP+00]: %x",[ebx]
add ebx, 4
call .check_ESP
test eax, eax
jnz .error_ESP
DEBUGF 1, " [ESP+04]: %x",[ebx]
add ebx, 4
call .check_ESP
test eax, eax
jnz .error_ESP
DEBUGF 1, " [ESP+08]: %x\n",[ebx]
add ebx, 4
call .check_ESP
test eax, eax
jnz .error_ESP
DEBUGF 1, "K : [ESP+12]: %x",[ebx]
add ebx, 4
call .check_ESP
test eax, eax
jnz .error_ESP
DEBUGF 1, " [ESP+16]: %x",[ebx]
add ebx, 4
call .check_ESP
test eax, eax
jnz .error_ESP
DEBUGF 1, " [ESP+20]: %x\n",[ebx]
add ebx, 4
call .check_ESP
test eax, eax
jnz .error_ESP
DEBUGF 1, "K : [ESP+24]: %x",[ebx]
add ebx, 4
call .check_ESP
test eax, eax
jnz .error_ESP
DEBUGF 1, " [ESP+28]: %x",[ebx]
add ebx, 4
call .check_ESP
test eax, eax
jnz .error_ESP
DEBUGF 1, " [ESP+32]: %x\n",[ebx]
pop edx ecx ebx eax
ret
.error_ESP:
pop edx ecx ebx eax
DEBUGF 1, "\n"
DEBUGF 1, "K : Unexpected end of the stack\n"
ret
;--------------------------------------
.check_ESP:
push ebx
shr ebx, 12
mov ecx, ebx
shr ecx, 10
mov edx, [master_tab+ecx*4]
test edx, PG_MAP
jz .fail ;page table is not created
;incorrect address in the program
mov eax, [page_tabs+ebx*4]
test eax, 2
jz .fail ;address not reserved for use. error
pop ebx
xor eax, eax
ret
.fail:
pop ebx
xor eax, eax
dec eax
ret
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

View File

@ -184,7 +184,7 @@ iglobal
dd syscall_threads ; 51-Threads
dd undefined_syscall ; 52- deprecated Stack driver status
dd undefined_syscall ; 53- deprecated Socket interface
dd undefined_syscall ; 54-reserved
dd sys_clipboard ; 54-Custom clipboard
dd sound_interface ; 55-Sound interface
dd undefined_syscall ; 56-reserved
dd sys_pcibios ; 57-PCI BIOS32

View File

@ -924,10 +924,17 @@ proc write_process_memory
ret
endp
;ebx = 1 - kernel thread
;ecx=thread entry point
;edx=thread stack pointer
;creation flags 0x01 - debugged
; 0x02 - kernel
align 4
proc new_sys_threads
locals
slot dd ?
flags dd ?
app_cmdline dd ? ;0x00
app_path dd ? ;0x04
app_eip dd ? ;0x08
@ -935,16 +942,15 @@ proc new_sys_threads
app_mem dd ? ;0x10
endl
cmp ebx, 1
jne .failed ;other subfunctions
shl ebx, 1
mov [flags], ebx
xor eax, eax
mov [app_eip], ecx
mov [app_cmdline], eax
mov [app_esp], edx
mov [app_path], eax
;mov esi,new_process_loading
;call sys_msg_board_str
call lock_application_table
call get_new_process_place
@ -998,10 +1004,8 @@ proc new_sys_threads
lea eax, [app_cmdline]
stdcall set_app_params , [slot], eax, dword 0, \
dword 0,dword 0
dword 0, [flags]
;mov esi,new_process_running
;call sys_msg_board_str ;output information about succefull startup
mov eax, [process_number] ;set result
call unlock_application_table
ret
@ -1207,14 +1211,13 @@ proc set_app_params stdcall,slot:dword, params:dword,\
mov [ebx+REG_EIP], eax;app_entry
mov [ebx+REG_CS], dword app_code
mov ecx, USER_PRIORITY
mov eax, [CURRENT_TASK]
shl eax, 8 ; created by kernel?
cmp [SLOT_BASE+eax+APPDATA.dir_table], sys_pgdir - OS_BASE
jnz @f
cmp [app_path], 0 ; it is a thread?
jnz @f
test byte [flags], 2
jz @F
mov [ebx+REG_CS], dword os_code ; kernel thread
mov ecx, MAX_PRIORITY
@@:
mov [ebx+REG_EFLAGS], dword EFL_IOPL1+EFL_IF
@ -1238,8 +1241,6 @@ proc set_app_params stdcall,slot:dword, params:dword,\
mov [CURRENT_TASK+ebx+TASKDATA.state], dl
lea edx, [SLOT_BASE+ebx*8]
call scheduler_add_thread
;mov esi,new_process_running
;call sys_msg_board_str ;output information about succefull startup
ret
endp

View File

@ -49,48 +49,50 @@ keymap_alt:
if lang eq ru
boot_initirq: cp866 'Инициализация IRQ',0
boot_picinit: cp866 'Инициализация PIC',0
boot_v86machine: cp866 'Инициализация системы V86 машины',0
boot_inittimer: cp866 'Инициализация системного таймера (IRQ0)',0
boot_initapic: cp866 'Попытка инициализации APIC',0
boot_enableirq: cp866 'Включить прерывания 2, 13',0
boot_disabling_ide:cp866 'Запрещение прерываний в контроллере IDE',0
boot_enabling_ide:cp866 'Разрешение прерываний в контроллере IDE',0
boot_set_int_IDE: cp866 'Установка обработчиков прерываний IDE',0
boot_detectfloppy:cp866 'Поиск floppy дисководов',0
boot_detecthdcd: cp866 'Поиск жестких дисков и ATAPI приводов',0
boot_getcache: cp866 'Получение памяти для кэша',0
boot_detectpart: cp866 'Поиск разделов на дисковых устройствах',0
boot_init_sys: cp866 'Инициализация системного каталога /sys',0
boot_loadlibs: cp866 'Загрузка библиотек (.obj)',0
boot_memdetect: cp866 'Количество оперативной памяти',' ',' Мб',0
boot_tss: cp866 'Установка TSSs',0
boot_cpuid: cp866 'Чтение CPUIDs',0
; boot_devices: cp866 'Поиск устройств',0
boot_timer: cp866 'Установка таймера',0
boot_irqs: cp866 'Переопределение IRQ',0
boot_setmouse: cp866 'Установка мыши',0
boot_windefs: cp866 'Установка настроек окон по умолчанию',0
boot_bgr: cp866 'Установка фона',0
boot_resirqports: cp866 'Резервирование IRQ и портов',0
boot_setrports: cp866 'Установка адресов IRQ',0
boot_setostask: cp866 'Создание процесса ядра',0
boot_allirqs: cp866 'Открытие всех IRQ',0
boot_tsc: cp866 'Чтение TSC',0
boot_cpufreq: cp866 'Частота процессора ',' ',' МГц',0
boot_pal_ega: cp866 'Установка EGA/CGA 320x200 палитры',0
boot_pal_vga: cp866 'Установка VGA 640x480 палитры',0
boot_failed: cp866 'Загрузка первого приложения не удалась',0
boot_mtrr: cp866 'Установка MTRR',0
boot_initirq cp866 'Инициализация IRQ',0
boot_picinit cp866 'Инициализация PIC',0
boot_v86machine cp866 'Инициализация системы V86 машины',0
boot_inittimer cp866 'Инициализация системного таймера (IRQ0)',0
boot_initapic cp866 'Попытка инициализации APIC',0
boot_enableirq cp866 'Включить прерывания 2, 13',0
boot_disabling_ide cp866 'Запрещение прерываний в контроллере IDE',0
boot_enabling_ide cp866 'Разрешение прерываний в контроллере IDE',0
boot_set_int_IDE cp866 'Установка обработчиков прерываний IDE',0
boot_detectfloppy cp866 'Поиск floppy дисководов',0
boot_detecthdcd cp866 'Поиск жестких дисков и ATAPI приводов',0
boot_getcache cp866 'Получение памяти для кэша',0
boot_detectpart cp866 'Поиск разделов на дисковых устройствах',0
boot_init_sys cp866 'Инициализация системного каталога /sys',0
boot_loadlibs cp866 'Загрузка библиотек (.obj)',0
boot_memdetect cp866 'Количество оперативной памяти',' ',' Мб',0
boot_tss cp866 'Установка TSSs',0
boot_cpuid cp866 'Чтение CPUIDs',0
; boot_devices cp866 'Поиск устройств',0
boot_timer cp866 'Установка таймера',0
boot_irqs cp866 'Переопределение IRQ',0
boot_setmouse cp866 'Установка мыши',0
boot_windefs cp866 'Установка настроек окон по умолчанию',0
boot_bgr cp866 'Установка фона',0
boot_resirqports cp866 'Резервирование IRQ и портов',0
boot_setrports cp866 'Установка адресов IRQ',0
boot_setostask cp866 'Создание процесса ядра',0
boot_allirqs cp866 'Открытие всех IRQ',0
boot_tsc cp866 'Чтение TSC',0
boot_cpufreq cp866 'Частота процессора ',' ',' МГц',0
boot_pal_ega cp866 'Установка EGA/CGA 320x200 палитры',0
boot_pal_vga cp866 'Установка VGA 640x480 палитры',0
boot_failed cp866 'Загрузка первого приложения не удалась',0
boot_mtrr cp866 'Установка MTRR',0
boot_APIC_found: cp866 'APIC включен', 0
boot_APIC_nfound: cp866 'APIC не найден', 0
boot_APIC_found cp866 'APIC включен', 0
boot_APIC_nfound cp866 'APIC не найден', 0
if preboot_blogesc
boot_tasking: cp866 'Все готово для запуска, нажмитре ESC для старта',0
boot_tasking cp866 'Все готово для запуска, нажмитре ESC для старта',0
end if
else if lang eq sp
include 'data32sp.inc'
else if lang eq et
include 'data32et.inc'
else
boot_initirq db 'Initialize IRQ',0
boot_picinit db 'Initialize PIC',0
@ -163,7 +165,7 @@ read_firstapp db '/sys/'
firstapp db 'LAUNCHER',0
notifyapp db '@notify',0
if lang eq ru
ud_user_message: cp866 'Ошибка: неподдерживаемая инструкция процессора',0
ud_user_message cp866 'Ошибка: неподдерживаемая инструкция процессора',0
else if ~ lang eq sp
ud_user_message db 'Error: unsupported processor instruction',0
end if
@ -385,7 +387,7 @@ end if
REDRAW_BACKGROUND rb 4
align 4
draw_data: rb 16*256
draw_data: rb 32*256
BPSLine_calc_area rd 1440
d_width_calc_area rd 1140

View File

@ -0,0 +1,37 @@
boot_initirq latin1 'Algväärtustan IRQ',0
boot_picinit latin1 'Algväärtustan PIC',0
boot_v86machine latin1 'Algväärtustan süsteemi V86 masinat',0
boot_inittimer latin1 'Algväärtustan süsteemi taimerit (IRQ0)',0
boot_initapic latin1 'Proovin Algväärtustada APIC',0
boot_enableirq latin1 'Luban katkestused 2, 13',0
boot_disabling_ide latin1 'Keelan IDE kontrolleri katkestused',0
boot_enabling_ide latin1 'Luban IDE kontrolleri katkestused',0
boot_set_int_IDE latin1 'Määran IDE kontrolleri halduri',0
boot_detectfloppy latin1 'Otsin floppi kettaid',0
boot_detecthdcd latin1 'Otsin kõvakettaid ja ATAPI seadmeid',0
boot_getcache latin1 'Küsin puhvri mälu',0
boot_detectpart latin1 'Otsin kettaseadmete partitsioone',0
boot_init_sys latin1 'Algväärtustan süsteemi kataloogi /sys',0
boot_loadlibs latin1 'Laadin mooduleid (.obj)',0
boot_memdetect latin1 'Avastan mälu mahtu',0
boot_tss latin1 'Määran TSSe',0
boot_cpuid latin1 'Loen CPUIDd',0
; boot_devices db 'Detecting devices',0
boot_setmouse latin1 'Seadistan hiirt',0
boot_windefs latin1 'Seadistan akende vaikeväärtusi',0
boot_bgr latin1 'Kalkuleerin tausta',0
boot_resirqports latin1 'Reserveerin IRQsi ja porte',0
boot_setostask latin1 'Seadistan OS protsessi',0
boot_allirqs latin1 'Unmasking IRQs',0
boot_tsc latin1 'Loen TSC',0
boot_cpufreq latin1 'CPU sagedus on ',' ',' MHz',0
boot_pal_ega latin1 'Seadistan EGA/CGA 320x200 paletti',0
boot_pal_vga latin1 'Seadistan VGA 640x480 paletti',0
boot_failed latin1 'Esimese programmi käivitamine ebaõnnestus',0
boot_mtrr latin1 'Määran MTRR',0
boot_APIC_found latin1 'APIC aktiveeritud', 0
boot_APIC_nfound latin1 'APIC ei leitud', 0
if preboot_blogesc
boot_tasking latin1 'Kõik valmis - vajuta ESC alustamiseks',0
end if

View File

@ -0,0 +1,92 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; 20/11/2013 yogev_ezra: Initial version ;;
;; Thanks for help to: dunkaist, eAndrew, hidnplayr, Mario ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision: 4261 $
VORTEX86DEBUG = 0 ; For testing in emulators and in non-Vortex86 CPU computers, set this to 1
VORTEX86DEBUGVALUE = 0x35504d44 ; FAKE port output = used for testing
; Detect Vortex86 CPU and generate CPU name in string format (PCI address at 93H~90H in Vortex86 North Bridge contains SoC type)
; Available Vortex86 CPU codes taken from Coreboot project. New codes should be added to "Vortex86SoClist" below
; #define DMP_CPUID_SX 0x31504d44 ("DMP1")
; #define DMP_CPUID_DX 0x32504d44 ("DMP2")
; #define DMP_CPUID_MX 0x33504d44 ("DMP3")
; #define DMP_CPUID_DX2 0x34504d44 ("DMP4")
; #define DMP_CPUID_MX_PLUS 0x35504d44 ("DMP5")
; #define DMP_CPUID_EX 0x37504d44 ("DMP7")
iglobal
Vortex86CPUcode dd ? ; Vortex86 CPU code in HEX format (4 bytes), can be shown as string if converted to ASCII characters
Vortex86CPUid db 0 ; Vortex86 CPU id in integer format (1=Vortex86SX, 2=Vortex86DX, ...)
Vortex86SoCname db 'Vortex86 ',0 ; This variable will hold the full name of Vortex86 SoC
Vortex86SoClist: ; List of Vortex86 CPUs known today. Add new record to this list when new CPU becomes available
db 0x31, 'SX ' ; id=1
db 0x32, 'DX ' ; id=2
db 0x33, 'MX ' ; id=3
db 0x34, 'DX2' ; id=4
db 0x35, 'MX+' ; id=5
db 0x37, 'EX ' ; id=6
Vortex86SoCnum = ($ - Vortex86SoClist) / 4 ; Calculate the total number of known Vortex86 CPUs (if id=Vortex86SoCnum+1 --> unknown SoC)
endg
mov dx, 0xcf8 ; CF8h = Vortex86 PCI Configuration Address port
mov eax, 0x80000090 ; 0x80000090 = Starting PCI address to read from (32-bit register - accessed as DWORD)
out dx, eax ; Send request to PCI address port to retrieve data from this address
mov dx, 0xcfc ; CFCh = Vortex86 PCI Configuration Data port
in eax, dx ; Read data (SoC type) from PCI data port
if VORTEX86DEBUG
; // Used for debug purposes: testing in emulator and in non-Vortex86 CPU computers
mov eax, VORTEX86DEBUGVALUE
end if
DEBUGF 1, "K : Vortex86 SoC register returned 0x"
test eax, eax ; We need to break out in case the result is '\0' since otherwise we will fail at NULL string
jz .nullPCIoutput
mov [Vortex86CPUcode], eax
DEBUGF 1, "%x (%s): ", eax, Vortex86CPUcode
cmp ax, 4d44h ; Check whether it's Vortex86 family (all Vortex86 SoC have ID in form of "0xNN504d44")
jnz .notVortex86
shr eax, 16 ; Discard lower word in EAX which is always 4d44h in Vortex86 family
cmp al, 50h ; The 3rd byte is always 50h in Vortex86 SoC
jnz .notVortex86
shr ax, 8 ; Discard 3rd byte in EAX, the highest byte determines the SoC type
mov bl, al ; Copy SoC type to BL since EAX (that contains AL) is used implicitly in "LODSD" command below
mov esi, Vortex86SoClist ; ESI points to the start of Vortex86SoClist (used implicitly in "LODSD" command below)
xor ecx, ecx ; Zero ECX (it is used as counter)
cld ; Clears the DF flag in the EFLAGS register (DF=0 --> String operations increment ESI)
@@:
cmp ecx, Vortex86SoCnum ; Check if we iterated Vortex86SoCnum times already (i.e. went over the entire Vortex86SoClist)
ja .unknownVortex86 ; If the entire list was tested and our CPU is not in that list, it is unknown Vortex86 SoC
inc ecx ; Increment our counter
lodsd ; Load DWORD at address DS:ESI into EAX (puts 1 line from Vortex86SoClist into EAX, then increments ESI)
cmp bl, al ; Check if our CPU matches the current record in the list
jne @b ; No match --> repeat with next record
shr eax, 8 ; Match found --> drop the SoC type code from Vortex86SoClist name and replace it with \0
mov dword [Vortex86SoCname+8], eax ; Concatenate it with prefix to receive complete SoC name (\0 is string termination)
mov [Vortex86CPUid], cl ; Save the CPUid (1=Vortex86SX, 2=Vortex86DX, ..., Vortex86SoCnum+1=Unknown Vortex86)
DEBUGF 1, "%s (id=%d)\n", Vortex86SoCname, [Vortex86CPUid]:1
jmp .Vortex86end ; Say what we have found (CPU name and id) and exit
.nullPCIoutput: ; Emulators and non-Vortex86 CPU computers will usually return \0 in this register
DEBUGF 1, "0 (NULL)\n"
jmp .Vortex86end
.unknownVortex86:
mov [Vortex86CPUid], cl ; Save the CPUid (Vortex86SoCnum+1=Unknown Vortex86)
DEBUGF 1, "unknown Vortex86 CPU (has id=%d, last known is %d)\n", [Vortex86CPUid]:1, Vortex86SoCnum
jmp .Vortex86end
.notVortex86: ; In case this register is used by other CPUs for other purpose, it's interesting what it contains
DEBUGF 1, "not a Vortex86 CPU\n"
.Vortex86end:

View File

@ -0,0 +1,232 @@
Дата последней правки 26/07/2013.
Подсистема событий ядра может понадобиться при написании драйверов и сервисов, работающих в режиме ядра.
Она не имеет отношения к подсистеме событий пользовательского интерфейса.
С точки зрения ядра событие - объект ядра и принадлежит создавшему его потоку.
struc EVENT
{
.magic dd ? ; 'EVNT'
.destroy dd ? ; internal destructor
.fd dd ? ; next object in list
.bk dd ? ; prev object in list
.pid dd ? ; owner id. идентификатор владельца (потока)
.id dd ? ; event uid. уникальный идентификатор события (просто номерок)
.state dd ? ; internal flags; см. далее.
.code dd ? ; старший байт класс события, ; следующий байт приоритет
; (будет использоваться только внутри ядра, при чтении всегда 0),
; Чем больше численное значение двойного слова тем важнее событие.
; два младших байта код события.
rd 5 ; .data - точная структура этого поля не определена и зависит
; от поля .code. (Здесь можно передавать какие-то свои данные,
; при необходимости :)
.size = $ - .magic
.codesize = $ - .code
}
События реального времени получили класс 0хFF. Пока определёны только:
EVENT.code= ;(Используется в звуковой подсистеме).
RT_INP_EMPTY equ 0xFF000001
RT_OUT_EMPTY equ 0xFF000002
RT_INP_FULL equ 0xFF000003
RT_OUT_FULL equ 0xFF000004
Флаги поля EVENT.state определены в gui/event.inc.
EVENT_SIGNALED equ 0x20000000 ;Бит 29 событие активно/неактивно;
EVENT_WATCHED equ 0x10000000 ;бит 28, поток-владелец ожидает активации события;
MANUAL_RESET equ 0x40000000 ;бит 30, не деактивировать событие автоматически по получении;
MANUAL_DESTROY equ 0x80000000 ;бит 31, не возвращать событие в список свободных по получении.
На момент ревизии 3732 (и далее по тексту то же) определение находится в \kernel\trunk\const.inc
и выглядит так:
struct APPOBJ ; common object header
magic dd ? ;
destroy dd ? ; internal destructor
fd dd ? ; next object in list
bk dd ? ; prev object in list
pid dd ? ; owner id
ends
struct EVENT APPOBJ
id dd ? ;event uid
state dd ? ;internal flags
code dd ?
rd 5 ; .data
ends
Код находится в gui/event.inc.
Сами события как обьекты существуют в памяти ядра в виде двусвязного списка (см. поля .bk и .fd).
При инициализации ядро резервирует память и создает 512 таких обьектов, помещая их в список FreeEvents
(свободных событий). При нехватке событий (все заняты, а нужно ещё) ядро создает ещё 512 свободных
и т.д. Каждый поток имеет свои (двусвязные) списки (в которые может быть помещено событие):
ObjList - список объектов ядра, ассоциированных с этим потоком;
EventList - список событий ядра для потока.
Сами события, физически, при перемещении между списками и смене очередности в списке не перемещаются
и не копируются. Это происходит только благодаря модификации полей .fd и .bk. Принцип работы списков,
как очередей - FIFO. Использутся неблокирующая отправка и блокирующее получение. Адресация - прямая
(у события всегда есть поток-владелец), по идентификатору потока.
Жизненый цикл событий определяется флагами при создании. По умолчанию ядро использует значения
MANUAL_RESET = 0 и MANUAL_DESTROY = 0. Такое событие является "одноразовым", и автоматически освобождается
ядром, возвращаясь в список свободных событий после получения.
Событие с флагом MANUAL_DESTROY = 1 после получения переходит в неактивное состояние, но остаётся в списке
объектов потока и может использоваться снова. Событие с флагами MANUAL_DESTROY =1 и MANUAL_RESET = 1
остаётся активным после получения и может быть сброшено вызовом ClearEvent.
Пример (вариант) жизненного цикла события из звуковой подсистемы:
Для зукового буфера (их может быть несколько) драйвер создает событие в списке ObjList с помощью
CreateEvent и флагом MANUAL_DESTROY. Далее драйвер вызывает WaitEvent для этого события (ожидает флага
EVENT_SIGNALED в событии) и блокируется, в ожидании запроса на пополнение буфера. Запрос отправляется
с помощью RaiseEvent из другого потока. Отправка (RaiseEvent) и получение (WaitEvent) циклически
повторяются при опустошении буфера. При остановке воспроизведения драйвер деактивирует событие с помощью
ClearEvent.
Вообще говоря, структура события приведена здесь только лишь для понимания принципов работы подсистемы.
Самостоятельная работа с полями не приветствуется, ввиду возможных в будущем проблем с совместимостью.
Работа должна производится только через API (функции подсистемы), с доступом только к тем полям, доступ к
которым предоставляет функция. При этом пару "указатель на событие" и "уникальный идентификатор события"
следует рассматривать как один 64-х битный уникальный идентификатор. (Если вы вызвали CreateEvent, напимер,
его нужно запомнить где-нибудь [если это нужно] для дальнейшей работы с событием).
Функции для работы с событиями экспортитуемые ядром:
(для драйверов и т.п.; вызываются в режиме ядра)
CreateEvent
RaiseEvent
ClearEvent
SendEvent
DestroyEvent
WaitEvent
WaitEventTimeout
GetEvent
Для пользовательских приложений Ф68.14 (GetEvent с обёрткой)
---------------------------------------------------------------------------------------------
CreateEvent:
Создаёт новое событие в очереди ObjList текущего потока.
Устанавливает:
EVENT.destroy <= внутренний деструктор по умолчанию;
EVENT.pid <= текущий Process id;
EVENT.id <= уникальный идентификатор;
EVENT.state <= ecx - флаги;
EVENT.code <= [esi], (если esi=0, то не копирует), размер 6*dword;
Возвращает:
eax - указатель на событие или 0 при ошибке.
edx - Event.id.
Портит: eax,ebx,edx,ecx,esi,edi
---------------------------------------------------------------------------------------------
RaiseEvent:
Активирует уже существующее событие (может принадлежать другому потоку) установкой
флага EVENT_SIGNALED. Если необходимо, - устанавливает данные EVENT.code.
Если флаг EVENT_SIGNALED в самом событии уже активен - больше ничего не делает.
Если EVENT_SIGNALED не установлен в самом событии, то он будет установлен, кроме случая
{EVENT_WATCHED в edx=1 и EVENT_WATCHED в событии=0}.
Т.е. при установке EVENT_WATCHED в edx, проверяется, ожидает ли поток-владелец активации
события.
Кроме EVENT_SIGNALED в событии никакие другие флаги не модифицируются.
Принимает:
eax - указатель на событие;
ebx - id, уникальный идентификатор события;
edx - флаги для операции (формат EVENT.state);
EVENT.code <= [esi], (если esi=0, то не копирует), размер 6*dword;
Возвращает: ?
Портит: eax,ebx,edx,ecx,esi,edi .
---------------------------------------------------------------------------------------------
ClearEvent:
Перемещает событие в список ObjList потока-владельца. (Возможно оно там и находилось.)
Сбрасывает флаги EVENT_SIGNALED, EVENT_WATCHED. С остальными полями (.code, .id),
ничего не делает.
Принимает:
eax - указатель на событие;
ebx - id, уникальный идентификатор события.
Возвращает: ?
Портит: eax,ebx,ecx,edi .
---------------------------------------------------------------------------------------------
SendEvent:
Создаёт новое событие в списке событий целевого потока. Устанавливает в событии
флаг EVENT_SIGNALED.
Принимает:
EVENT.pid <= eax - pid, идентификатор целевого потока;
EVENT.code <= [esi], (если esi=0, то не копирует), размер 6*dword;
Возвращает:
eax - указатель на событие или 0 при ошибке.
edx - Event.id. уникальный идентификатор.
Портит: eax,ebx,ecx,esi,edi .
---------------------------------------------------------------------------------------------
DestroyEvent:
Переносит EVENT в список FreeEvents, чистит поля .magic,.destroy,.pid,.id.
Событие может принадлежать другому потоку.
Принимает:
eax - указатель на событие;
ebx - id, уникальный идентификатор события.
Возвращает:
eax - 0 при ошибке, не 0 при успехе.
Портит: eax,ebx,ecx .
---------------------------------------------------------------------------------------------
WaitEvent:
Бесконечно ожидает установки флага EVENT_SIGNALED в конкретном событии, принадлежащем
вызывающему WaitEvent потоку. Сигнализирующий поток устанавливат этот флаг через
RaiseEvent. Ожидающий поток замораживается путем перевода TASKDATA.state<=TSTATE_WAITING=5.
Перед заморозкой устанавливается флаг EVENT_WATCHED в событии.
Если в полученном событии НЕ установлен MANUAL_RESET, то:
{EVENT_SIGNALED и EVENT_WATCHED по получении события сбрасываются.
При неактивном MANUAL_DESTROY - событие уничтожается штатно (DestroyEvent),
а при активном - перемещается в список ObjList текущего слота.}
Принимает:
eax - указатель на событие;
ebx - id, уникальный идентификатор события.
Возвращает: ?
Портит: eax,ebx,edx,ecx,esi,edi .
---------------------------------------------------------------------------------------------
WaitEventTimeout:
Ожидает с таймаутом установки флага EVENT_SIGNALED в конкретном событии, принадлежащем
вызывающему WaitEventTimeout потоку. Сигнализирующий поток устанавливат этот флаг через
RaiseEvent. Ожидающий поток замораживается путем перевода TASKDATA.state<=TSTATE_WAITING=5.
Перед заморозкой устанавливается флаг EVENT_WATCHED в событии.
Если в полученном событии НЕ установлен MANUAL_RESET, то:
{EVENT_SIGNALED и EVENT_WATCHED по получении события сбрасываются.
При неактивном MANUAL_DESTROY - событие уничтожается штатно (DestroyEvent),
а при активном - перемещается в список ObjList текущего слота.}
Принимает:
eax - указатель на событие;
ebx - id, уникальный идентификатор события.
ecx - время ожидания в тиках системного таймера.
Возвращает:
eax - 0 - таймаут, если событие не активировалось, или
не 0, если было активировано.
Портит: eax,ebx,edx,ecx,esi,edi .
---------------------------------------------------------------------------------------------
GetEvent:
Бесконечно ожидает любое событие в очереди событий текущего потока. Поток замораживается
путем перевода TASKDATA.state<=TSTATE_WAITING=5. Данные события (EVENT.code+5*dword)
по получении копируются в указанный буфер. Сбрасывает байт приоритета (см. выше) в буфере.
Если в полученном событии НЕ установлен MANUAL_RESET, то:
{EVENT_SIGNALED и EVENT_WATCHED по получении события сбрасываются.
При неактивном MANUAL_DESTROY - событие уничтожается штатно (DestroyEvent),
а при активном - перемещается в список ObjList текущего слота.}
Принимает:
edi - указатель на буфер, куда копировать данные.
Возвращает:
буфер, содержащий следующую информацию:
+0: (EVENT.code) dword: идентификатор последующих данных сигнала
+4: (EVENT.data, поле формально не определено) данные принятого
сигнала (5*dword), формат которых определяется первым dword-ом.
Портит: eax,ebx,edx,ecx,esi,edi .
--------------------------------------------------------------------------------------------
Ф 68.14 для приложений: ;это тот же GetEvent, но с обёрткой.
Бесконечно ожидает любое событие в очереди событий текущего потока. Ожидающий поток
замораживается путем перевода TASKDATA.state<=TSTATE_WAITING=5. Данные события (EVENT.code+5*dword)
копируются в указанный буфер. Сбрасывает байт приоритета (см. выше) в буфере.
Принимает:
eax - 68 - номер функции
ebx - 14 - номер подфункции
ecx - указатель на буфер для информации (размер 6*dword)
Возвращает:
буфер, на который указывает ecx, содержит следующую информацию:
+0: (EVENT.code) dword: идентификатор последующих данных сигнала
+4: (EVENT.data, поле формально не определено) данные принятого
сигнала (5*dword), формат которых определяется первым dword-ом.
Портит:
eax .
---------------------------------------------------------------------------------------------

View File

@ -34,7 +34,7 @@
вызов функции с такими Y игнорируется
* RR, GG, BB = соответственно красная, зеленая, синяя
составляющие цвета рабочей области окна
(игнорируется для стиля Y=2)
(игнорируется для стиля Y=1)
* X = DCBA (биты)
* A = 1 - у окна есть заголовок; для стилей Y=3,4 адрес строки
заголовка задаётся в edi, для прочих стилей
@ -47,7 +47,7 @@
игнорируются для стилей Y=1,3:
* esi = 0xXYRRGGBB - цвет заголовка
* RR, GG, BB определяют сам цвет
* Y=0 - обычное окно, Y=1 - неперемещаемое окно
* Y=0 - обычное окно, Y=1 - неперемещаемое окно (работает для всех стилей окон)
* X определяет градиент заголовка: X=0 - нет градиента,
X=8 - обычный градиент,
для окон типа II X=4 - негативный градиент
@ -372,6 +372,7 @@
* бит 1 (маска 2): окно минимизировано в панель задач
* бит 2 (маска 4): окно свёрнуто в заголовок
* +71 = +0x47: dword: маска событий
* +75 = +0x4B: byte: режим ввода с клавиатуры(ASCII = 0; SCAN = 1)
Замечания:
* Слоты нумеруются с 1.
* Возвращаемое значение не есть общее число потоков, поскольку
@ -416,7 +417,7 @@
положение и размеры этого окна полагаются нулями.
* Координаты клиентской области окна берутся относительно окна.
* В данный момент используется только часть буфера размером
71 = 0x47 байта. Тем не менее рекомендуется использовать буфер
76 = 0x4C байта. Тем не менее рекомендуется использовать буфер
размером 1 Кб для будущей совместимости, в будущем могут быть
добавлены некоторые поля.
@ -1803,7 +1804,7 @@ dd 1675
sysdir_path rb 64
Пример:
dir_name1 db 'KolibriOS',0
rb 64-8
rb 64-10
dir_path1 db 'HD0/1',0
rb 64-6
Возвращаемое значение:
@ -2027,6 +2028,14 @@ dir_path1 db 'HD0/1',0
* eax = 40 - номер функции
* ebx = маска: бит i соответствует событию i+1 (см. список событий)
(установленный бит разрешает извещение о событии)
bit 31: фильтр активности событий мыши
bit 31 = 0 - неактивное окно всегда получает события от мыши
bit 31 = 1 - неактивное окно не получает события от мыши
bit 30: фильтр позиции курсора
bit 30 = 0 - окно принимает события мыши, если курсор
за пределами окна
bit 30 = 1 - окно не принимает события мыши, если курсор
за пределами окна
Возвращаемое значение:
* eax = предыдущее значение маски
Замечания:
@ -2419,6 +2428,70 @@ dword-значение цвета 0x00RRGGBB
* eax = -1 - ошибка (в системе слишком много потоков)
* иначе eax = TID - идентификатор потока
======================================================================
====================== Функция 54, подфункция 0 ======================
============== Узнать количество слотов в буфере обмена. =============
======================================================================
Параметры:
* eax = 54 - номер функции
* ebx = 0 - номер подфункции
Возвращаемое значение:
* eax = количество слотов в буфере
* eax = -1 - отсутствует область главного списка
======================================================================
====================== Функция 54, подфункция 1 ======================
================== Считать данные из буфера обмена. ==================
======================================================================
Параметры:
* eax = 54 - номер функции
* ebx = 1 - номер подфункции
* eсx = номер слота
Возвращаемое значение:
* eax = если успешно - указатель на область памяти с данными
* eax = 1 - ошибка
* eax = -1 - отсутствует область главного списка
======================================================================
====================== Функция 54, подфункция 2 ======================
================== Записать данные в буфер обмена. ===================
======================================================================
Параметры:
* eax = 54 - номер функции
* ebx = 2 - номер подфункции
* eсx = количество копируемых байт
* edx = указатель на буфер под копируемые данные
Возвращаемое значение:
* eax = 0 - успешно
* eax = 1 - ошибка
* eax = -1 - отсутствует область главного списка
======================================================================
====================== Функция 54, подфункция 3 ======================
========= Удалить последний слот с данными в буфере обмена ===========
======================================================================
Параметры:
* eax = 54 - номер функции
* ebx = 3 - номер подфункции
Возвращаемое значение:
* eax = 0 - успешно
* eax = 1 - ошибка
* eax = -1 - отсутствует область главного списка
======================================================================
====================== Функция 54, подфункция 4 ======================
=================== Аварийный сброс блокировки буфера ================
======================================================================
Параметры:
* eax = 54 - номер функции
* ebx = 4 - номер подфункции
Возвращаемое значение:
* eax = 0 - успешно
* eax = -1 - отсутствует область главного списка или нет блокировки
Замечания:
* Используется в исключительных случаях, когда зависшее или убитое
приложение заблокировало работу с буфером обмена.
======================================================================
====================== Функция 55, подфункция 55 =====================
========== Начать проигрывать данные на встроенном спикере. ==========
@ -3494,6 +3567,32 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
обработчика исключений, установленного подфункцией 24. При этом
номер сигнала соответствует номеру исключения.
======================================================================
= Функция 68, подфункция 26 - освободить страницы памяти ============
======================================================================
Параметры:
* eax = 68 - номер функции
* ebx = 26 - номер подфункции
* ecx = указатель на блок памяти выделенный подфункцией 12
* edx = смещение от начала блока
* esi = размер высвобождаемого блока памяти, в байтах
Примечания:
* функция освобождает страницы с ecx+edx по ecx+edx+esi
и устанавливает виртуальную память в зарезервированное состояние.
======================================================================
= Функция 68, подфункция 27 - загрузить файл ===================
======================================================================
Параметры:
* eax = 68 - номер функции
* ebx = 27 - номер подфункции
* ecx = указатель на ASCIIZ-строку с именем файла
Возвращаемое значение:
* eax = указатель на загруженный файл или 0
* edx = размер загруженного файла или 0
Примечания:
* функция загружает и, при необходимости, распаковывает файл (kunpack)
======================================================================
======================== Функция 69 - отладка. =======================
======================================================================

View File

@ -33,7 +33,7 @@ Parameters:
* other possible values (from 5 up to 15) are reserved,
function call with such Y is ignored
* RR, GG, BB = accordingly red, green, blue components of a color
of the working area of the window (are ignored for style Y=2)
of the working area of the window (are ignored for style Y=1)
* X = DCBA (bits)
* A = 1 - window has caption; for styles Y=3,4 caption string
must be passed in edi, for other styles use
@ -46,7 +46,7 @@ Parameters:
of a type I and II, and ignored for styles Y=1,3:
* esi = 0xXYRRGGBB - color of the header
* RR, GG, BB define color
* Y=0 - usual window, Y=1 - unmovable window
* Y=0 - usual window, Y=1 - unmovable window (works for all window styles)
* X defines a gradient of header: X=0 - no gradient,
X=8 - usual gradient,
for windows of a type II X=4 - negative gradient
@ -367,6 +367,7 @@ Returned value:
* bit 1 (mask 2): window is minimized to panel
* bit 2 (mask 4): window is rolled up
* +71 = +0x47: dword: event mask
* +75 = +0x4B: byte: keyboard mode(ASCII = 0; SCAN = 1)
Remarks:
* Slots are numbered starting from 1.
* Returned value is not a total number of threads, because there
@ -411,7 +412,7 @@ Remarks:
of its window are considered to be zero.
* Coordinates of the client area are relative to the window.
* At the moment only the part of the buffer by a size
71 = 0x37 bytes is used. Nevertheless it is recommended to use
76 = 0x4C bytes is used. Nevertheless it is recommended to use
1-Kb buffer for the future compatibility, in the future
some fields can be added.
@ -1785,7 +1786,7 @@ Parameters:
sysdir_path rb 64
For example:
dir_name1 db 'KolibriOS',0
rb 64-8
rb 64-10
dir_path1 db 'HD0/1',0
rb 64-6
Returned value:
@ -2010,7 +2011,7 @@ Parameters:
* eax = 40 - function number
* ebx = mask: bit i corresponds to event i+1 (see list of events)
(set bit permits notice on event)
bit 31: active/inactive filter
bit 31: mouse active/inactive filter
bit 31 = 0 - inactive window receive mouse events
bit 31 = 1 - inactive window does not receive mouse events
bit 30: cursor position filter
@ -2410,6 +2411,70 @@ Returned value:
* otherwise eax = TID - thread identifier
</UL>
======================================================================
==================== Function 54, subfunction 0 ======================
============== Get the number of slots in the clipboard. =============
======================================================================
Parameters:
* eax = 54 - function number
* ebx = 0 - subfunction number
Returned value:
* eax = slots in the clipboard
* eax = -1 - main list area not found
======================================================================
==================== Function 54, subfunction 1 ======================
================= Read the data from the clipboard. ==================
======================================================================
Parameters:
* eax = 54 - function number
* ebx = 1 - subfunction number
* eсx = slot number
Returned value:
* eax = if successful - pointer to a memory with data
* eax = 1 - error
* eax = -1 - main list area not found
======================================================================
==================== Function 54, subfunction 2 ======================
================= Write the data to the clipboard. ===================
======================================================================
Parameters:
* eax = 54 - function number
* ebx = 2 - subfunction number
* eсx = the number of bytes to be copied
* edx = a pointer to a buffer for data to be copied
Returned value:
* eax = 0 - success
* eax = 1 - error
* eax = -1 - main list area not found
======================================================================
===================== Function 54, subfunction 3 =====================
================ Delete the last slot in the clipboard ===============
======================================================================
Parameters:
* eax = 54 - function number
* ebx = 3 - subfunction number
Returned value:
* eax = 0 - success
* eax = 1 - error
* eax = -1 - main list area not found
======================================================================
===================== Function 54, subfunction 4 =====================
===================== Alarm reset the lock buffer ====================
======================================================================
Parameters:
* eax = 54 - function number
* ebx = 4 - subfunction number
Returned value:
* eax = 0 - success
* eax = -1 - main list area not found or no blocking
Remarks:
* Used in exceptional cases, where no responsible or killed
application blocked the clipboard operations.
======================================================================
Function 55, subfunction 55 - begin to play data on built-in speaker.
======================================================================
@ -3953,7 +4018,7 @@ Format of the information structure:
* +0: dword: 2 = subfunction number
* +4: dword: 0 (reserved)
* +8: dword: 0 (reserved)
* +12 = +0xC: dword: number of bytes to read
* +12 = +0xC: dword: number of bytes to write
* +16 = +0x10: dword: pointer to data
* +20 = +0x14: ASCIIZ-name of file, the rules of names forming are
given in the general description

View File

@ -0,0 +1,249 @@
Когда ядро ​​обнаруживает подключенное устройство USB, оно настраивает его
согласно USB-протокола - SET_ADDRESS + SET_CONFIGURATION. Всегда
устанавливается первая конфигурация. Ядро также читает дескриптор
устройства, чтобы показать некоторую информацию, читает и анализирует
дескриптор конфигурации. Для каждого интерфейса ядро будет искать класс этого
интерфейса и попытается загрузить соответствующий драйвер COFF. В настоящее
время соответствие кодов классов и имен драйверов жестко прописано в коде ядра
и выглядит следующим образом:
3 = usbhid.obj,
7 = usbprint.obj,
8 = usbstor.obj,
9 = поддерживаются самим ядром,
другие = usbother.obj.
Драйвер должен быть стандартным драйвером в формате COFF, экспортирующим
процедуру под названием "START" и переменную "version". Загрузчик вызывает
процедуру "START" как STDCALL с одним параметром DRV_ENTRY = 1. При завершении
работы системы, если инициализация драйвера была успешна, "START" процедуру
также вызывает код остановки системы с одним параметром DRV_EXIT = -1.
Драйвер должен зарегистрировать себя в качестве драйвера USB в процедуре
"START". Это делается путем вызова экспортируемой ядром функции RegUSBDriver и
возврата её результата в качестве результата "START" процедуры.
void* __stdcall RegUSBDriver(
const char* name,
void* handler,
const USBFUNC* usbfunc
);
Параметр 'name' должен совпадать с именем драйвера, например "usbhid" для
usbhid.obj.
Параметр 'handler' является необязательным. Если он не NULL, то он должен
указывать на стандартный обработчик IOCTL интерфейса, как в обычном (не-USB)
драйвере.
Параметр "Usbfunc" представляет собой указатель на следующую структуру:
struc USBFUNC
{
.strucsize dd ? ; размер структуры, включая это поле
.add_device dd ? ; указатель на AddDevice процедуру в драйвере
; (необходимо)
.device_disconnect dd ? ; указатель на DeviceDisconnected процедуру в драйвере
; опционально, может быть NULL
; В будущем могут быть добавлены другие функции
}
Драйвер ДОЛЖЕН реализовать функцию:
void* __stdcall AddDevice(
void* pipe0,
void* configdescr,
void* interfacedescr
);
Параметр "Pipe0" - хэндл контрольного канала для нулевой конечной точки
устройства. Он может быть использован в качестве аргумента для
USBControlTransferAsync (см. далее).
Параметр 'configdescr' указывает на дескриптор конфигурации и все связанные с
ним данные, представленные так, как их возвращает запрос GET_DESCRIPTOR.
Полный размер данных содержится в поле Length самого дескриптора.
(см. USB2.0 spec.)
Параметр 'interfacedescr' указывает на дескриптор интерфейса инициализируемого
в данный момент. Это указатель на данные находящиеся внутри структуры
"configdescr". (Помним, что структура INTERFACE_DESCRIPTOR, находится внутри
структуры CONFIGURATION_DESCRIPTOR. См. USB2.0 Spec.) Обратите внимание, что
одно устройство может реализовывать много интерфейсов и AddDevice может быть
вызвана несколько раз с одним "configdescr" но разными "interfacedescr".
Возвращенное значение NULL показывает, что инициализация не была успешной.
Любое другое значение означает инициализацию устройства. Ядро не делает попыток
как-то интерпретировать это значение. Это может быть, например, указатель на
внутренние данные драйвера в памяти, выделенной с помощью Kmalloc или индексом
в какой-то своей таблице. (Помните, что Kmalloc() НЕ stdcall-функция! Она
портит регистр ebx!)
Драйвер МОЖЕТ реализовать функцию:
void __stdcall DeviceDisconnected(
void* devicedata
);
Если данная функция реализована, то ядро вызывает её, когда устройство
отключено, посылая ей в качестве параметра "devicedata" то, что было возвращено
ему функцией "AddDevice" при старте драйвера.
Драйвер может использовать следующие функции экспортируемые ядром:
void* __stdcall USBOpenPipe(
void* pipe0,
int endpoint,
int maxpacketsize,
int type,
int interval
);
Параметр "Pipe0" - хэндл контрольного канала для нулевой конечной точки
устройства. Используется для идентификации устройства.
Параметр "endpoint" номер конечной точки USB. Младшие 4 бита, собственно, номер
точки, а бит 7 имеет следующее значение: 0 - для OUT точки, 1 - для IN точки.
Остальные биты должны быть равны нулю.
Параметр "maxpacketsize" устанавливает максимальный размер пакета для канала.
Параметр "type" устанавливает тип передачи для конечной точки, как это прописано
в USB спецификации:
0 = control,
1 = isochronous (сейчас не поддерживается),
2 = bulk,
3 = interrupt.
Параметр "interval" игнорируется для control и bulk передач. Для конечных точек
по прерываниям устанавливает периодичность опроса в миллисекундах.
Функция возвращает хэндл канала при успешном его открытии либо NULL при ошибке.
Хэндл канала обращается в NULL когда:
а) канал будет явно закрыт функцией USBClosePipe (см. ниже);
б) была выполнена предоставленная драйвером функция "DeviceDisconnected".
void __stdcall USBClosePipe(
void* pipe
);
Освобождает все ресурсы, связанные с выбранным каналом. Единственный параметр -
указатель на хэндл, который был возвращен функцией USBOpenPipe при открытии
канала. Когда устройство отключается, все связанные с ним каналы закрываются
ядром; нет необходимости в самостоятельном вызове этой функции.
void* __stdcall USBNormalTransferAsync(
void* pipe,
void* buffer,
int size,
void* callback,
void* calldata,
int flags
);
void* __stdcall USBControlTransferAsync(
void* pipe,
void* setup,
void* buffer,
int size,
void* callback,
void* calldata,
int flags
);
Первая функция ставит в очередь bulk или interrupt передачу для выбранного
канала. Тип и направление передачи фиксированы для bulk и interrupt типов
конечных точек, как это было выбрано функцией USBOpenPipe.
Вторая функция ставит в очередь control передачу для выбранного канала.
Направление этой передачи определяется битом 7 байта 0 пакета "setup"
(0 - для OUT, 1 - для IN передачи). Эта функция возвращает управление немедленно.
По окончании передачи вызывается функция "callback" заданная как аргумент
USB______TransferAsync.
Параметр "pipe" - хэндл, возвращенный функцией USBOpenPipe.
Параметр 'setup' функции USBControlTransferAsync указывает на 8-байтный
конфигурационный пакет (см. USB2.0 Spec).
Параметр "buffer" - это указатель на буфер. Для IN передач он будет заполнен
принятыми данными. Для OUT передач он должен быть заполнен данными, которые мы
хотим передать. Указатель может быть NULL для пустых передач, либо для передач
control, если дополнительных данных не требуется.
Параметр "size" - это размер данных для передачи. Он может быть равен 0 для
пустых передач, либо для передач control, если дополнительных данных не требуется.
Параметр "callback" - это указатель на функцию, которая будет вызвана по
окончании передачи.
Параметр "calldata" будет передан функции "callback" вызываемой по окончании
передачи. Например, он может быть NULL или указывать на данные устройства или
указывать на данные используемые как дополнительные параметры, передаваемые от
вызывающей USB_____TransferAsync функции в callback функцию.
Другие данные, связанные с передачей, могут быть помещены до буфера (по смещению)
или после него. Они могут быть использованы из callback-функции, при необходимости.
Параметр "flags" - это битовое поле. Бит 0 игнорируется для OUT передач. Для IN
передач он означает, может ли устройство передать меньше данных (бит=1), чем
определено в "size" или нет (бит=0). Остальные биты не используются и должны
быть равны 0.
Возвращаемое функциями значение равно NULL в случае ошибки и не NULL если
передача успешно поставлена в очередь. Если происходит ошибка при передаче, то
callback функция будет об этом оповещена.
void __stdcall CallbackFunction(
void* pipe,
int status,
void* buffer,
int length,
void* calldata
);
Параметры 'pipe', 'buffer', 'calldata' значат то же, что и для
USB_____TransferAsync.
Параметр "length" это счетчик переданных байт. Для control передач он отражает
дополнительные 8 байт этапа SETUP. Т.е. 0 означает ошибку на этапе SETUP, а
"size"+8 успешную передачу.
Параметр "status" не равен 0 в случае ошибки:
USB_STATUS_OK = 0 ; без ошибок
USB_STATUS_CRC = 1 ; ошибка контрольной суммы
USB_STATUS_BITSTUFF = 2 ; ошибка инверсии битов (bitstuffing)
USB_STATUS_TOGGLE = 3 ; data toggle mismatch
; (Нарушение последовательности DAT0/DAT1)
USB_STATUS_STALL = 4 ; устройство возвратило STALL статус (остановлено)
USB_STATUS_NORESPONSE = 5 ; устройство не отвечает
USB_STATUS_PIDCHECK = 6 ; ошибка в поле PacketID (PID)
USB_STATUS_WRONGPID = 7 ; неожидаемое PacketID (PID) значение
USB_STATUS_OVERRUN = 8 ; слишком много данных от конечной точки
USB_STATUS_UNDERRUN = 9 ; слишком мало данных от конечной точки
USB_STATUS_BUFOVERRUN = 12 ; переполнение внутреннего буфера контроллера
; возможна только для изохронных передач
USB_STATUS_BUFUNDERRUN = 13 ; опустошение внутреннего буфера контроллера
; возможна только для изохронных передач
USB_STATUS_CLOSED = 16 ; канал закрыт либо через ClosePipe, либо в
; результате отключения устройства
Если несколько передач были поставлены в очередь для одного канала, то callback
функции для них будут вызываться в порядке постановки передач в очередь.
Если канал был закрыт ввиду USBClosePipe или отключения устройства, то callback
функции (если очередь передач не пуста) получат USB_STATUS_CLOSED.
Вызов DeviceDisconnected() последует после отработки всех оставшихся в очереди
callback функций.
void* __stdcall USBGetParam(void* pipe0, int param);
Возвращает указатель на некоторые параметры устройства запомненные ядром при
инициализации первой конфигурации. Не передает ничего устройству по шине.
pipe0 - хэндл контрольного канала для нулевой конечной точки устройства.
param - выбор возвращаемого параметра:
0 - возвратить указатель на дескриптор устройства;
1 - возвратить указатель на дескриптор конфигурации;
2 - возвратить режим шины устройства:
USB_SPEED_FS = 0 ; full-speed
USB_SPEED_LS = 1 ; low-speed
USB_SPEED_HS = 2 ; high-speed

View File

@ -60,6 +60,7 @@ kernel_export \
CreateRingBuffer,\
\
GetPid,\
CreateThread,\
CreateObject,\
DestroyObject,\
CreateEvent,\

View File

@ -1002,13 +1002,12 @@ proc inquiry_callback
; to allow the USB thread to continue working and handling those requests.
; 4. Thus, create a temporary kernel thread which would do it.
mov edx, [esp+8]
push ebx ecx
movi eax, 51
push ebx ecx esi edi
movi ebx, 1
mov ecx, new_disk_thread
; edx = parameter
int 0x40
pop ecx ebx
call CreateThread
pop edi esi ecx ebx
cmp eax, -1
jnz .nothing
; on error, reverse step 3

View File

@ -97,6 +97,12 @@ macro cp866 [arg]
end while
}
struc cp866 [arg]
{
common
cp866 arg
}
; Latin-1 encoding
; 0x00-0xFF - trivial map
macro latin1 [arg]
@ -117,6 +123,12 @@ macro latin1 [arg]
end while
}
struc latin1 [arg]
{
common
latin1 arg
}
; CP850 encoding
macro cp850 [arg]
{ local offs, char, graph
@ -147,3 +159,9 @@ macro cp850 [arg]
end if
end while
}
struc cp850 [arg]
{
common
cp850 arg
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,409 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Contains ext2 block handling code. ;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under the terms of the new BSD license. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;---------------------------------------------------------------------
; Write ext2 block from memory to disk.
; Input: eax = i_block (block number in ext2 terms);
; ebx = buffer address
; ebp = pointer to EXTFS
; Output: eax = error code (0 implies no error)
;---------------------------------------------------------------------
ext2_block_write:
push edx ebx ecx
mov edx, fs_write32_sys
jmp ext2_block_modify
;---------------------------------------------------------------------
; Read ext2 block from disk to memory.
; Input: eax = i_block (block number in ext2 terms);
; ebx = address of where to read block
; ebp = pointer to EXTFS
; Output: eax = error code (0 implies no error)
;---------------------------------------------------------------------
ext2_block_read:
push edx ebx ecx
mov edx, fs_read32_sys
jmp ext2_block_modify
;---------------------------------------------------------------------
; Modify ext2 block.
; Input: eax = i_block (block number in ext2 terms);
; ebx = I/O buffer address;
; edx = fs_read/write32_sys
; ebp = pointer to EXTFS
; edx, ebx, ecx on stack.
; Output: eax = error code (0 implies no error)
;---------------------------------------------------------------------
ext2_block_modify:
; Get block number in hard-disk terms in eax.
mov ecx, [ebp + EXTFS.log_block_size]
shl eax, cl
mov ecx, eax
push [ebp + EXTFS.count_block_in_block]
@@:
mov eax, ecx
call edx
test eax, eax
jnz .fail
inc ecx
add ebx, 512
dec dword[esp]
jnz @B
xor eax, eax
@@:
pop ecx
pop ecx ebx edx
ret
.fail:
mov eax, ERROR_DEVICE
jmp @B
;---------------------------------------------------------------------
; Zeroes a block.
; Input: ebx = block ID.
; ebp = pointer to EXTFS.
; Output: eax = error code.
;---------------------------------------------------------------------
ext2_block_zero:
push ebx
mov eax, ebx
mov ebx, [ebp + EXTFS.ext2_temp_block]
call ext2_block_read
test eax, eax
jnz .return
push edi ecx
xor eax, eax
mov ecx, [ebp + EXTFS.block_size]
mov edi, [ebp + EXTFS.ext2_temp_block]
rep stosb
pop ecx edi
mov eax, [esp]
call ext2_block_write
.return:
pop ebx
ret
;---------------------------------------------------------------------
; Allocates a block.
; Input: eax = inode ID for "preference".
; ebp = pointer to EXTFS.
; Output: Block marked as set in block group.
; eax = error code.
; ebx = block ID.
;---------------------------------------------------------------------
ext2_block_alloc:
push [ebp + EXTFS.superblock + EXT2_SB_STRUC.blocks_count]
push EXT2_BLOCK_GROUP_DESC.free_blocks_count
push [ebp + EXTFS.superblock + EXT2_SB_STRUC.blocks_per_group]
lea ebx, [ebp + EXTFS.superblock + EXT2_SB_STRUC.free_block_count]
push ebx
push ext2_bg_read_blk_bitmap
call ext2_resource_alloc
ret
;---------------------------------------------------------------------
; Zero-allocates a block.
; Input: eax = inode ID for "preference".
; ebp = pointer to EXTFS.
; Output: Block marked as set in block group.
; eax = error code.
; ebx = block ID.
;---------------------------------------------------------------------
ext2_block_calloc:
call ext2_block_alloc
test eax, eax
jnz @F
call ext2_block_zero
@@:
ret
;---------------------------------------------------------------------
; Frees a block.
; Input: eax = block ID.
; ebp = pointer to EXTFS.
; Output: Block marked as free in block group.
; eax = error code.
;---------------------------------------------------------------------
ext2_block_free:
push edi ecx
mov edi, ext2_bg_read_blk_bitmap
xor ecx, ecx
call ext2_resource_free
pop ecx edi
ret
;---------------------------------------------------------------------
; Find parent from file path in block.
; Input: esi = file path.
; ebx = pointer to directory block.
; ebp = pointer to EXTFS structure.
; Output: esi = name without parent, or not changed.
; ebx = directory record matched.
;---------------------------------------------------------------------
ext2_block_find_parent:
sub esp, 256 ; Space for EXT2 filename.
mov edx, ebx
add edx, [ebp + EXTFS.block_size] ; Save block end.
.start_rec:
cmp [ebx + EXT2_DIR_STRUC.inode], 0
jz .next_rec
mov edi, esp
push esi
movzx ecx, [ebx + EXT2_DIR_STRUC.name_len]
lea esi, [ebx + EXT2_DIR_STRUC.name]
call utf8_to_cp866
mov ecx, edi
lea edi, [esp + 4]
sub ecx, edi ; Number of bytes in resulting string.
mov esi, [esp]
; esi: original file path.
; edi: converted string stored on stack.
; ecx: size of converted string.
@@:
; If no bytes left in resulting string, test it.
jecxz .test_find
dec ecx
lodsb
call char_toupper
mov ah, [edi]
inc edi
xchg al, ah
call char_toupper
; If both are same, check next byte.
cmp al, ah
je @B
@@: ; Doesn't match.
pop esi
.next_rec:
movzx eax, [ebx + EXT2_DIR_STRUC.rec_len]
add ebx, eax ; Go to next record.
cmp ebx, edx ; Check if this is the end.
jb .start_rec
add esp, 256
ret
.test_find:
cmp byte [esi], 0
je .ret ; The end reached.
cmp byte [esi], '/' ; If not end of directory name, not matched.
jne @B
inc esi
.ret:
add esp, 256 + 4
ret
;---------------------------------------------------------------------
; Finds free space in a directory block, modifying last entry appropriately.
; Input: ebp = pointer to EXTFS.
; ecx = size of free space required.
; [EXTFS.ext2_temp_block] contains the block relevant.
; Output: edi = free entry.
; rec_len of free entry is set.
; eax = error code; if the block doesn't link to the next one, this is 0x00000001 on failure.
; ; else, 0xFFFFFFFF.
;---------------------------------------------------------------------
ext2_block_find_fspace:
push ebx edx
mov edi, [ebp + EXTFS.ext2_temp_block]
mov edx, edi
add edx, [ebp + EXTFS.block_size]
@@:
movzx eax, [edi + EXT2_DIR_STRUC.rec_len]
test eax, eax
jz .zero_len
cmp [edi + EXT2_DIR_STRUC.inode], 0
je .unused_entry
; It's a used entry, so see if we can fit it between current one and next.
; Subtract the size used by the name and the structure from rec_len.
movzx ebx, [edi + EXT2_DIR_STRUC.name_len]
add ebx, 8 + 3
and ebx, 0xfffffffc ; Align it on the next 4-byte boundary.
sub eax, ebx
add edi, ebx
cmp eax, ecx
jb .next_iter
sub edi, ebx
mov [edi + EXT2_DIR_STRUC.rec_len], bx ; Make previous entry point to us.
add edi, ebx
mov [edi + EXT2_DIR_STRUC.rec_len], ax ; Make current entry point to next one.
jmp .found
.unused_entry:
; It's an unused inode.
cmp eax, ecx
jge .found
.next_iter:
add edi, eax
cmp edi, edx
jb @B
.not_found:
xor eax, eax
not eax
jmp .ret
; Zero length entry means we have the rest of the block for us.
.zero_len:
mov eax, edx
sub eax, edi
; Point to next block.
mov [edi + EXT2_DIR_STRUC.rec_len], ax
cmp eax, ecx
jge .fits
mov [edi + EXT2_DIR_STRUC.inode], 0
; It doesn't fit, but the block doesn't link to the next block.
xor eax, eax
inc eax
jmp .ret
.fits:
mov [edi + EXT2_DIR_STRUC.rec_len], cx
.found:
xor eax, eax
.ret:
pop edx ebx
ret
;---------------------------------------------------------------------
; Gets the block group's descriptor.
; Input: eax = block group.
; Output: eax = if zero, error; else, points to block group descriptor.
; [EXTFS.ext2_temp_block] contains relevant block.
; ebp = pointer to EXTFS.
;---------------------------------------------------------------------
ext2_bg_read_desc:
push edx ebx
mov edx, 32
mul edx ; Get index of descriptor in global_desc_table.
; eax: block group descriptor offset relative to global descriptor table start
; Find the block this block descriptor is in.
div [ebp + EXTFS.block_size]
add eax, [ebp + EXTFS.superblock + EXT2_SB_STRUC.first_data_block]
inc eax
mov ebx, [ebp + EXTFS.ext2_temp_block]
call ext2_block_read
test eax, eax
jnz .fail
add ebx, edx ; edx: local index of descriptor inside block
mov eax, ebx
.return:
pop ebx edx
ret
.fail:
xor eax, eax
jmp .return
;---------------------------------------------------------------------
; Writes a block group's descriptor.
; Input: eax = block group.
; [EXTFS.ext2_temp_data] contains the block relevant.
; ebp = pointer to EXTFS.
; Output: eax = error code.
;---------------------------------------------------------------------
ext2_bg_write_desc:
push edx ebx
mov edx, 32
mul edx ; Get index of descriptor in global_desc_table.
; eax: block group descriptor offset relative to global descriptor table start
; Find the block this block descriptor is in.
div [ebp + EXTFS.block_size]
add eax, [ebp + EXTFS.superblock + EXT2_SB_STRUC.first_data_block]
inc eax
mov ebx, [ebp + EXTFS.ext2_temp_block]
call ext2_block_write
.return:
pop ebx edx
ret
;---------------------------------------------------------------------
; Gets the block group's block bitmap.
; Input: eax = block group.
; Output: eax = if zero, error; else, points to block group descriptor.
; ebx = block bitmap's block (hard disk).
;---------------------------------------------------------------------
ext2_bg_read_blk_bitmap:
push ecx
call ext2_bg_read_desc
test eax, eax
jz .fail
mov ebx, [eax + EXT2_BLOCK_GROUP_DESC.block_bitmap] ; Block number of block group bitmap - in ext2 terms.
.return:
pop ecx
ret
.fail:
xor eax, eax
jmp .return
;---------------------------------------------------------------------
; Updates superblock, plus backups.
; Input: ebp = pointer to EXTFS.
; Output: eax = error code.
;---------------------------------------------------------------------
ext2_sb_update:
push ebx
mov eax, 2
lea ebx, [ebp + EXTFS.superblock]
call fs_write32_sys
pop ebx
ret

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,670 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Contains ext2 structures, and macros. ;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under the terms of the new BSD license. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Future jobs for driver, in order of preference:
; * clean up existing extents support.
; * add b-tree directories support.
; * add long file support.
; * add journal support.
; * add minor features that come with ext3/4.
; Recommended move to some kernel-wide bitmap handling code (with a bit of abstraction, of course).
;---------------------------------------------------------------------
; Clears a bit.
; Input: eax = index into bitmap.
; [EXTFS.ext2_save_block] = address of bitmap.
; ebp = address of EXTFS.
; Output: Bit cleared.
; eax = non-zero, if already cleared.
;---------------------------------------------------------------------
bitmap_clear_bit:
push ebx ecx edx
xor edx, edx
mov ecx, 8
div ecx
add eax, [ebp + EXTFS.ext2_save_block]
; Get the mask.
mov ebx, 1
mov ecx, edx
shl ebx, cl
test [eax], ebx
jz .cleared
not ebx
and [eax], ebx
xor eax, eax
.return:
pop edx ecx ebx
ret
; Already cleared.
.cleared:
xor eax, eax
not eax
jmp .return
;---------------------------------------------------------------------
; Finds free bit in the bitmap.
; Input: ecx = number of bits in the bitmap.
; [EXTFS.ext2_save_block] = address of bitmap.
; ebp = address of EXTFS.
; Output: eax = index of free bit in the bitmap; marked set.
; 0xFFFFFFFF if no free bit found.
;---------------------------------------------------------------------
ext2_find_free_bit:
bitmap_find_free_bit:
push esi ebx ecx edx
mov esi, [ebp + EXTFS.ext2_save_block]
; Get total DWORDS in eax; total bits in last dword, if any, in edx.
xor edx, edx
mov eax, ecx
mov ecx, 32
div ecx
mov ecx, eax
xor eax, eax
push edx
test ecx, ecx
jz .last_bits
; Check in the DWORDS.
.dwords:
mov ebx, [esi]
not ebx
bsf edx, ebx
; If 0, then the original value would be 0xFFFFFFFF, hence no free bits.
jz @F
; We found the value. Let's return with it.
add esp, 4
add eax, edx
jmp .return
@@:
add esi, 4
add eax, 32
loop .dwords
.last_bits:
; Check in the last few bits.
pop ecx
test ecx, ecx
jz @F
mov ebx, [esi]
not ebx
bsf ebx, edx
; If 0, no free bits.
jz @F
; If free bit is greater than the last known bit, then error.
cmp edx, ecx
jg @F
add eax, edx
jmp .return
@@:
; Didn't find any free bits.
xor eax, eax
not eax
jmp @F
.return:
mov ecx, edx
mov edx, 1
shl edx, cl
or [esi], edx
@@:
pop edx ecx ebx esi
ret
; Recommended move to some kernel-wide string handling code.
;---------------------------------------------------------------------
; Find the length of a string.
; Input: esi = source.
; Output: length in ecx
;---------------------------------------------------------------------
strlen:
push eax esi
xor ecx, ecx
@@:
lodsb
test al, al
jz .ret
inc ecx
jmp @B
.ret:
pop esi eax
ret
;---------------------------------------------------------------------
; Convert UTF-8 string to ASCII-string (codepage 866)
; Input: esi = source.
; edi = buffer.
; ecx = length of source.
; Output: destroys eax, esi, edi
;---------------------------------------------------------------------
utf8_to_cp866:
; Check for zero-length string.
jecxz .return
.start:
lodsw
cmp al, 0x80
jb .ascii
xchg al, ah ; Big-endian.
cmp ax, 0xd080
jz .yo1
cmp ax, 0xd191
jz .yo2
cmp ax, 0xd090
jb .unk
cmp ax, 0xd180
jb .rus1
cmp ax, 0xd190
jb .rus2
.unk:
mov al, '_'
jmp .doit
.yo1:
mov al, 0xf0 ; Ё capital.
jmp .doit
.yo2:
mov al, 0xf1 ; ё small.
jmp .doit
.rus1:
sub ax, 0xd090 - 0x80
jmp .doit
.rus2:
sub ax, 0xd18f - 0xEF
.doit:
stosb
sub ecx, 2
ja .start
ret
.ascii:
stosb
dec esi
dec ecx
jnz .start
.return:
ret
; Recommended move to some kernel-wide time handling code.
; Total cumulative seconds till each month.
cumulative_seconds_in_month:
.january: dd 0 * (60 * 60 * 24)
.february: dd 31 * (60 * 60 * 24)
.march: dd 59 * (60 * 60 * 24)
.april: dd 90 * (60 * 60 * 24)
.may: dd 120 * (60 * 60 * 24)
.june: dd 151 * (60 * 60 * 24)
.july: dd 181 * (60 * 60 * 24)
.august: dd 212 * (60 * 60 * 24)
.september: dd 243 * (60 * 60 * 24)
.october: dd 273 * (60 * 60 * 24)
.november: dd 304 * (60 * 60 * 24)
.december: dd 334 * (60 * 60 * 24)
current_bdfe_time:
dd 0
current_bdfe_date:
dd 0
;---------------------------------------------------------------------
; Stores current unix time.
; Input: edi = buffer to output Unix time.
;---------------------------------------------------------------------
current_unix_time:
push eax esi
mov esi, current_bdfe_time
; Just a small observation:
; The CMOS is a pretty bad source to get time from. One shouldn't rely on it,
; since it messes up the time by tiny bits. Of course, this is all technical,
; but one can look it up on the osdev wiki. What is better is to get the time
; from CMOS during boot, then update system time using a more accurate timer.
; I'll probably add that after the Summer of Code, so TODO! TODO! TODO!.
; Get time from CMOS.
; Seconds.
mov al, 0x00
out 0x70, al
in al, 0x71
call bcd2bin
mov [esi + 0], al
; Minute.
mov al, 0x02
out 0x70, al
in al, 0x71
call bcd2bin
mov [esi + 1], al
; Hour.
mov al, 0x04
out 0x70, al
in al, 0x71
call bcd2bin
mov [esi + 2], al
; Get date.
; Day.
mov al, 0x7
out 0x70, al
in al, 0x71
call bcd2bin
mov [esi + 4], al
; Month.
mov al, 0x8
out 0x70, al
in al, 0x71
call bcd2bin
mov [esi + 5], al
; Year.
mov al, 0x9
out 0x70, al
in al, 0x71
call bcd2bin
add ax, 2000 ; CMOS only returns last two digits.
; Note that everywhere in KolibriOS this is used.
; This is hacky, since the RTC can be incorrectly set
; to something before 2000.
mov [esi + 6], ax
call bdfe_to_unix_time
pop esi eax
ret
;---------------------------------------------------------------------
; Convert time+date from BDFE to Unix time.
; Input: esi = pointer to BDFE time+date.
; edi = buffer to output Unix time.
;---------------------------------------------------------------------
bdfe_to_unix_time:
push eax ebx ecx edx
mov dword[edi], 0x00000000
; The minimum representable time is 1901-12-13.
cmp word[esi + 6], 1901
jb .ret
jg .max
cmp byte[esi + 5], 12
jb .ret
cmp byte[esi + 4], 13
jbe .ret
jg .convert
; Check if it is more than the maximum representable time.
.max:
; The maximum representable time is 2038-01-19.
cmp word[esi + 6], 2038
jg .ret
jb .convert
cmp byte[esi + 5], 1
jg .ret
cmp byte[esi + 4], 19
jge .ret
; Convert the time.
.convert:
; Get if current year is leap year in ECX.
xor ecx, ecx
mov ebx, 4
xor edx, edx
cmp word[esi + 6], 1970
jb .negative
movzx eax, word[esi + 6] ; Year.
cmp byte[esi + 5], 3 ; If the month is less than March, than that year doesn't matter.
jge @F
test eax, 3
; Not a leap year.
jnz @F
inc ecx
@@:
; Number of leap years between two years = ((end date - 1)/4) - (1970/4)
dec eax
div ebx
sub eax, 1970/4
; EAX is the number of leap years.
add eax, ecx
mov ecx, (60 * 60 * 24) ; Seconds in a day.
mul ecx
; Account for leap years, i.e., one day extra for each.
add [edi], eax
; Get total days in EAX.
movzx eax, byte[esi + 4]
dec eax
mul ecx
; Account for days.
add [edi], eax
; Account for month.
movzx eax, byte[esi + 5]
dec eax
mov eax, [cumulative_seconds_in_month + (eax * 4)]
add [edi], eax
; Account for year.
movzx eax, word[esi + 6]
sub eax, 1970
mov ecx, (60 * 60 * 24) * 365 ; Seconds in a year.
mul ecx
add [edi], eax
; Seconds.
movzx eax, byte[esi + 0]
add [edi], eax
; Minutes.
movzx eax, byte[esi + 1]
mov ecx, 60
mul ecx
add [edi], eax
; Hours.
movzx eax, byte[esi + 2]
mov ecx, (60 * 60)
mul ecx
add [edi], eax
; The time wanted is before the epoch; handle it here.
.negative:
; TODO.
.ret:
pop edx ecx ebx eax
ret
; Recommended move to some kernel-wide alloc handling code.
macro KERNEL_ALLOC store, label
{
call kernel_alloc
mov store, eax
test eax, eax
jz label
}
macro KERNEL_FREE data, label
{
cmp data, 0
jz label
push data
call kernel_free
}
struct EXTFS PARTITION
lock MUTEX
partition_flags dd ?
log_block_size dd ?
block_size dd ?
count_block_in_block dd ?
blocks_per_group dd ?
global_desc_table dd ?
root_inode dd ? ; Pointer to root inode in memory.
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 ? ; Block for 1 global procedure.
ext2_temp_block dd ? ; Block for small procedures.
ext2_save_inode dd ? ; inode for global procedures.
ext2_temp_inode dd ? ; inode for small procedures.
groups_count dd ?
superblock rd 1024/4
ends
; EXT2 revisions.
EXT2_GOOD_OLD_REV = 0
; For fs_type.
FS_TYPE_UNDEFINED = 0
FS_TYPE_EXT = 2
; Some set inodes.
EXT2_BAD_INO = 1
EXT2_ROOT_INO = 2
EXT2_ACL_IDX_INO = 3
EXT2_ACL_DATA_INO = 4
EXT2_BOOT_LOADER_INO = 5
EXT2_UNDEL_DIR_INO = 6
; EXT2_SUPER_MAGIC.
EXT2_SUPER_MAGIC = 0xEF53
EXT2_VALID_FS = 1
; Flags defining i_mode values.
EXT2_S_IFMT = 0xF000 ; Mask for file type.
EXT2_S_IFREG = 0x8000 ; Regular file.
EXT2_S_IFDIR = 0x4000 ; Directory.
EXT2_S_IRUSR = 0x0100 ; User read
EXT2_S_IWUSR = 0x0080 ; User write
EXT2_S_IXUSR = 0x0040 ; User execute
EXT2_S_IRGRP = 0x0020 ; Group read
EXT2_S_IWGRP = 0x0010 ; Group write
EXT2_S_IXGRP = 0x0008 ; Group execute
EXT2_S_IROTH = 0x0004 ; Others read
EXT2_S_IWOTH = 0x0002 ; Others write
EXT2_S_IXOTH = 0x0001 ; Others execute
PERMISSIONS = EXT2_S_IRUSR or EXT2_S_IWUSR \
or EXT2_S_IRGRP or EXT2_S_IWGRP \
or EXT2_S_IROTH or EXT2_S_IWOTH
; File type defining values in directory entry.
EXT2_FT_REG_FILE = 1 ; Regular file.
EXT2_FT_DIR = 2 ; Directory.
; Flags used by KolibriOS.
FS_FT_HIDDEN = 2
FS_FT_DIR = 0x10 ; Directory.
; ext2 partition flags.
EXT2_RO = 0x01
FS_FT_ASCII = 0 ; Name in ASCII.
FS_FT_UNICODE = 1 ; Name in Unicode.
EXT2_FEATURE_INCOMPAT_FILETYPE = 0x0002 ; Have file type in directory entry.
EXT4_FEATURE_INCOMPAT_EXTENTS = 0x0040 ; Extents.
EXT4_FEATURE_INCOMPAT_FLEX_BG = 0x0200 ; Flexible block groups.
EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER = 0x0001 ; Sparse Superblock
EXT2_FEATURE_RO_COMPAT_LARGE_FILE = 0x0002 ; Large file support (64-bit file size)
; Implemented ext[2,3,4] features.
EXT4_FEATURE_INCOMPAT_SUPP = EXT2_FEATURE_INCOMPAT_FILETYPE \
or EXT4_FEATURE_INCOMPAT_EXTENTS \
or EXT4_FEATURE_INCOMPAT_FLEX_BG
; Implemented features which otherwise require "read-only" mount.
EXT2_FEATURE_RO_COMPAT_SUPP = EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER \
or EXT2_FEATURE_RO_COMPAT_LARGE_FILE
; ext4 features not support for write.
EXT4_FEATURE_INCOMPAT_W_NOT_SUPP = EXT4_FEATURE_INCOMPAT_EXTENTS \
or EXT4_FEATURE_INCOMPAT_FLEX_BG
; Flags specified in i_flags.
EXT2_EXTENTS_FL = 0x00080000 ; Extents.
struct EXT2_INODE_STRUC
i_mode dw ?
i_uid dw ?
i_size dd ?
i_atime dd ?
i_ctime dd ?
i_mtime dd ?
i_dtime dd ?
i_gid dw ?
i_links_count dw ?
i_blocks dd ?
i_flags dd ?
i_osd1 dd ?
i_block rd 15
i_generation dd ?
i_file_acl dd ?
i_dir_acl dd ?
i_faddr dd ?
i_osd2 dd ? ; 12 bytes.
ends
struct EXT2_DIR_STRUC
inode dd ?
rec_len dw ?
name_len db ?
file_type db ?
name db ? ; 255 (max) bytes.
ends
struct EXT2_BLOCK_GROUP_DESC
block_bitmap dd ? ; +0
inode_bitmap dd ? ; +4
inode_table dd ? ; +8
free_blocks_count dw ? ; +12
free_inodes_count dw ? ; +14
used_dirs_count dw ? ; +16
pad dw ? ; +18
reserved rb 12 ; +20
ends
struct EXT2_SB_STRUC
inodes_count dd ? ; +0
blocks_count dd ? ; +4
r_block_count dd ? ; +8
free_block_count dd ? ; +12
free_inodes_count dd ? ; +16
first_data_block dd ? ; +20
log_block_size dd ? ; +24
log_frag_size dd ? ; +28
blocks_per_group dd ? ; +32
frags_per_group dd ? ; +36
inodes_per_group dd ? ; +40
mtime dd ? ; +44
wtime dd ? ; +48
mnt_count dw ? ; +52
max_mnt_count dw ? ; +54
magic dw ? ; +56
state dw ? ; +58
errors dw ? ; +60
minor_rev_level dw ? ; +62
lastcheck dd ? ; +64
check_intervals dd ? ; +68
creator_os dd ? ; +72
rev_level dd ? ; +76
def_resuid dw ? ; +80
def_resgid dw ? ; +82
first_ino dd ? ; +84
inode_size dw ? ; +88
block_group_nr dw ? ; +90
feature_compat dd ? ; +92
feature_incompat dd ? ; +96
feature_ro_compat dd ? ; +100
uuid rb 16 ; +104
volume_name rb 16 ; +120
last_mounted rb 64 ; +136
algo_bitmap dd ? ; +200
prealloc_blocks db ? ; +204
preallock_dir_blocks db ? ; +205
reserved_gdt_blocks dw ? ; +206
journal_uuid rb 16 ; +208
journal_inum dd ? ; +224
journal_dev dd ? ; +228
last_orphan dd ? ; +232
hash_seed rd 4 ; +236
def_hash_version db ? ; +252
reserved rb 3 ; +253 (reserved)
default_mount_options dd ? ; +256
first_meta_bg dd ? ; +260
mkfs_time dd ? ; +264
jnl_blocks rd 17 ; +268
blocks_count_hi dd ? ; +336
r_blocks_count_hi dd ? ; +340
free_blocks_count_hi dd ? ; +344
min_extra_isize dw ? ; +348
want_extra_isize dw ? ; +350
flags dd ? ; +352
raid_stride dw ? ; +356
mmp_interval dw ? ; +358
mmp_block dq ? ; +360
raid_stripe_width dd ? ; +368
log_groups_per_flex db ? ; +372
ends
; Header block extents.
struct EXT4_EXTENT_HEADER
eh_magic dw ? ; Magic value of 0xF30A, for ext4.
eh_entries dw ? ; Number of blocks covered by the extent.
eh_max dw ? ; Capacity of entries.
eh_depth dw ? ; Tree depth (if 0, extents in the array are not extent indexes)
eh_generation dd ? ; ???
ends
; Extent.
struct EXT4_EXTENT
ee_block dd ? ; First logical block extent covers.
ee_len dw ? ; Number of blocks covered by extent.
ee_start_hi dw ? ; Upper 16 bits of 48-bit address (unused in KOS)
ee_start_lo dd ? ; Lower 32 bits of 48-bit address.
ends
; Index on-disk structure; pointer to block of extents/indexes.
struct EXT4_EXTENT_IDX
ei_block dd ? ; Covers logical blocks from here.
ei_leaf_lo dd ? ; Lower 32-bits of pointer to the physical block of the next level.
ei_leaf_hi dw ? ; Higher 16-bits (unused in KOS).
ei_unused dw ? ; Reserved.
ends

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,223 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Contains common resource allocation + freeing code. ;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under the terms of the new BSD license. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;---------------------------------------------------------------------
; Frees a resource (block/inode).
; Input: eax = resource ID.
; edi = function pointer of ext2_bg_*_bitmap form, to
; get bitmap of resource.
; ecx = 0, block; 1, inode.
; ebp = pointer to EXTFS.
; Output: Block marked as free in block group.
; eax = error code.
;---------------------------------------------------------------------
ext2_resource_free:
push ebx edx esi
; Get block group.
sub eax, [ebp + EXTFS.superblock + EXT2_SB_STRUC.first_data_block]
xor edx, edx
div [ebp + EXTFS.superblock + EXT2_SB_STRUC.blocks_per_group]
push eax edx
call edi
test eax, eax
jz .fail
mov esi, eax
; Read the bitmap.
mov eax, ebx
mov edx, eax
mov ebx, [ebp + EXTFS.ext2_save_block]
call ext2_block_read
test eax, eax
jnz .fail
pop eax
; Mark bit free.
call bitmap_clear_bit
test eax, eax
jz @F
; No need to save anything.
xor eax, eax
add esp, 4
jmp .return
@@:
mov eax, edx
mov ebx, [ebp + EXTFS.ext2_save_block]
call ext2_block_write
test eax, eax
jnz .fail
; Read the descriptor.
mov eax, [esp]
call ext2_bg_read_desc
test eax, eax
jz .fail_bg_desc_read
lea eax, [eax + EXT2_BLOCK_GROUP_DESC.free_blocks_count]
shl ecx, 1
add eax, ecx
inc word[eax]
lea eax, [ebp + EXTFS.superblock + EXT2_SB_STRUC.free_block_count]
shl ecx, 1
add eax, ecx
inc dword[eax]
pop eax
call ext2_bg_write_desc
.return:
pop esi edx ebx
ret
.fail:
add esp, 4
.fail_bg_desc_read:
add esp, 4
xor eax, eax
not eax
jmp .return
;---------------------------------------------------------------------
; Allocates a resource.
; Input: eax = inode ID for "preference".
; ebp = pointer to EXTFS.
; [esp + 4], func pointer to ext2_bg_*_bitmap
; [esp + 8], pointer to free_*_count in SB.
; [esp + 12], *_per_group
; [esp + 16], offset to free_*_count in bg descriptor.
; [esp + 20], *_count
; Output: Resource marked as set in block group.
; eax = error code.
; ebx = resource ID.
;---------------------------------------------------------------------
ext2_resource_alloc:
; Block allocation is a pretty serious area, since bad allocation
; can lead to fragmentation. Thus, the best way to allocate that
; comes to mind is to allocate around an inode as much as possible.
; On the other hand, this isn't about a single inode/file/directory,
; and focusing just around the preferred inode would lead to
; congestion. Thus, after much thought, the chosen allocation algorithm
; is to search forward, then backward.
push ecx edx esi edi
cmp dword[esp + 16 + 8], 0
jnz @F
; No free blocks.
xor eax, eax
not eax
pop edi esi edx ecx
ret 20
@@:
; Calculate which block group the preferred inode belongs to.
dec eax
xor edx, edx
; EAX = block group.
div [ebp + EXTFS.superblock + EXT2_SB_STRUC.inodes_per_group]
push eax
push eax
mov edi, .forward
.test_block_group:
call dword[esp + 16 + 8 + 4]
test eax, eax
jz .fail
mov esi, eax
mov eax, ebx
mov edx, eax
mov ebx, [ebp + EXTFS.ext2_save_block]
call ext2_block_read
test eax, eax
jnz .fail
mov ecx, [esp + 16 + 8 + 12]
call ext2_find_free_bit
cmp eax, 0xFFFFFFFF
jne @F
mov eax, edi
jmp eax
@@:
mov ecx, eax
mov eax, edx
mov ebx, [ebp + EXTFS.ext2_save_block]
call ext2_block_write
test eax, eax
jnz .fail
; ecx: the index of the matched entry.
; [esp]: block group where we found.
; [esp + 4]: starting block group.
; esi: block group descriptor.
mov eax, [esp] ; Index of block group in which we found.
mul dword[esp + 16 + 8 + 12]
add eax, ecx
mov ebx, eax
mov eax, [esp + 16 + 8 + 8]
dec dword[eax]
mov eax, esi
add eax, [esp + 16 + 8 + 16]
dec word[eax]
pop eax
call ext2_bg_write_desc
add esp, 4
jmp .return
; Continue forward.
.forward:
inc dword[esp]
mov eax, [esp]
mul dword[esp + 16 + 8 + 12]
cmp eax, [esp + 16 + 8 + 20]
jbe @F
; We need to go backward.
mov eax, [esp + 4]
mov [esp], eax
mov edi, .backward
jmp .backward
@@:
mov eax, [esp]
jmp .test_block_group
; Continue backward.
.backward:
cmp dword[esp], 0
je .fail
dec dword[esp]
mov eax, [esp]
jmp .test_block_group
.return:
pop edi esi edx ecx
ret 20
.fail:
add esp, 8
xor eax, eax
not eax
jmp .return

View File

@ -0,0 +1,12 @@
dir0:
db 'KÕVAKETAS '
db 'MÄLUKETAS '
db 'FLOPPIKETAS'
db 0
dir1:
db 'ESIMENE '
db 'TEINE '
db 'KOLAMS '
db 'NELJAS '
db 0

View File

@ -24,6 +24,8 @@ iglobal
if lang eq sp
include 'fs/fs-sp.inc'
else if lang eq et
include 'fs/fs-et.inc'
else
dir0:
db 'HARDDISK '

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,518 @@
; from stat.h
; distinguish file types
S_IFMT = 0170000o ; These bits determine file type.
S_IFDIR = 0040000o ; Directory.
S_IFCHR = 0020000o ; Character device.
S_IFBLK = 0060000o ; Block device.
S_IFREG = 0100000o ; Regular file.
S_IFIFO = 0010000o ; FIFO.
S_IFLNK = 0120000o ; Symbolic link.
S_IFSOCK = 0140000o ; Socket.
; end stat.h
; XFS null constant: empty fields must be all ones, not zeros!
XFS_NULL = -1
; static sector numbers
XFS_SECT_SB = 0
XFS_SECT_AGF = 1
XFS_SECT_AGI = 2
XFS_SECT_AGFL = 3
; signatures of file system structures
; 'string' numbers are treated by fasm as big endian
XFS_SB_MAGIC = 'XFSB'
XFS_AGF_MAGIC = 'XAGF'
XFS_AGI_MAGIC = 'XAGI'
XFS_ABTB_MAGIC = 'ABTB'
XFS_ABTC_MAGIC = 'ABTC'
XFS_IBT_MAGIC = 'IABT'
XFS_DINODE_MAGIC = 'IN'
XFS_BMAP_MAGIC = 'BMAP'
XFS_DA_NODE_MAGIC = 0xbefe ; those are little endian here
XFS_ATTR_LEAF_MAGIC = 0xeefb ; but big endian in docs
XFS_DIR2_LEAF1_MAGIC = 0xf1d2 ; pay attention!
XFS_DIR2_LEAFN_MAGIC = 0xffd2 ;
XFS_DIR2_BLOCK_MAGIC = 'XD2B'
XFS_DIR2_DATA_MAGIC = 'XD2D'
XFS_DIR2_FREE_MAGIC = 'XD2F'
XFS_DQUOT_MAGIC = 'DQ'
; bitfield lengths for packed extent
; MSB to LSB / left to right
BMBT_EXNTFLAG_BITLEN = 1
BMBT_STARTOFF_BITLEN = 54
BMBT_STARTBLOCK_BITLEN = 52
BMBT_BLOCKCOUNT_BITLEN = 21
; those constants are taken from linux source (xfs_dir2_leaf.h)
; they are magic infile offsets for directories
XFS_DIR2_DATA_ALIGN_LOG = 3 ; i.e., 8 bytes
XFS_DIR2_LEAF_SPACE = 1
XFS_DIR2_SPACE_SIZE = (1 SHL (32 + XFS_DIR2_DATA_ALIGN_LOG))
XFS_DIR2_LEAF_OFFSET = (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE)
XFS_DIR2_FREE_SPACE = 2
XFS_DIR2_SPACE_SIZE = (1 SHL (32 + XFS_DIR2_DATA_ALIGN_LOG))
XFS_DIR2_FREE_OFFSET = (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE)
; data section magic constants for directories (xfs_dir2_data.h)
XFS_DIR2_DATA_FD_COUNT = 3
XFS_DIR2_DATA_FREE_TAG = 0xffff
; valid inode formats
; enum xfs_dinode_fmt (xfs_dinode.h)
XFS_DINODE_FMT_DEV = 0 ; xfs_dev_t
XFS_DINODE_FMT_LOCAL = 1 ; one inode is enough (shortdir)
XFS_DINODE_FMT_EXTENTS = 2 ; one or more extents (leafdir, nodedir, regular files)
XFS_DINODE_FMT_BTREE = 3 ; highly fragmented files or really huge directories
XFS_DINODE_FMT_UUID = 4 ; uuid_t
; size of the unlinked inode hash table in the agi
XFS_AGI_UNLINKED_BUCKETS = 64
; possible extent states
; enum xfs_exntst_t (xfs_bmap_btree.h)
XFS_EXT_NORM = 0
XFS_EXT_UNWRITTEN = 1
XFS_EXT_DMAPI_OFFLINE = 2
XFS_EXT_INVALID = 3
; values for inode core flags / di_flags (xfs_dinode.h)
XFS_DIFLAG_REALTIME_BIT = 0 ; file's blocks come from rt area
XFS_DIFLAG_PREALLOC_BIT = 1 ; file space has been preallocated
XFS_DIFLAG_NEWRTBM_BIT = 2 ; for rtbitmap inode, new format
XFS_DIFLAG_IMMUTABLE_BIT = 3 ; inode is immutable
XFS_DIFLAG_APPEND_BIT = 4 ; inode is append-only
XFS_DIFLAG_SYNC_BIT = 5 ; inode is written synchronously
XFS_DIFLAG_NOATIME_BIT = 6 ; do not update atime
XFS_DIFLAG_NODUMP_BIT = 7 ; do not dump
XFS_DIFLAG_RTINHERIT_BIT = 8 ; create with realtime bit set
XFS_DIFLAG_PROJINHERIT_BIT = 9 ; create with parents projid
XFS_DIFLAG_NOSYMLINKS_BIT = 10 ; disallow symlink creation
XFS_DIFLAG_EXTSIZE_BIT = 11 ; inode extent size allocator hint
XFS_DIFLAG_EXTSZINHERIT_BIT = 12 ; inherit inode extent size
XFS_DIFLAG_NODEFRAG_BIT = 13 ; do not reorganize/defragment
XFS_DIFLAG_FILESTREAM_BIT = 14 ; use filestream allocator
XFS_DIFLAG_REALTIME = (1 SHL XFS_DIFLAG_REALTIME_BIT)
XFS_DIFLAG_PREALLOC = (1 SHL XFS_DIFLAG_PREALLOC_BIT)
XFS_DIFLAG_NEWRTBM = (1 SHL XFS_DIFLAG_NEWRTBM_BIT)
XFS_DIFLAG_IMMUTABLE = (1 SHL XFS_DIFLAG_IMMUTABLE_BIT)
XFS_DIFLAG_APPEND = (1 SHL XFS_DIFLAG_APPEND_BIT)
XFS_DIFLAG_SYNC = (1 SHL XFS_DIFLAG_SYNC_BIT)
XFS_DIFLAG_NOATIME = (1 SHL XFS_DIFLAG_NOATIME_BIT)
XFS_DIFLAG_NODUMP = (1 SHL XFS_DIFLAG_NODUMP_BIT)
XFS_DIFLAG_RTINHERIT = (1 SHL XFS_DIFLAG_RTINHERIT_BIT)
XFS_DIFLAG_PROJINHERIT = (1 SHL XFS_DIFLAG_PROJINHERIT_BIT)
XFS_DIFLAG_NOSYMLINKS = (1 SHL XFS_DIFLAG_NOSYMLINKS_BIT)
XFS_DIFLAG_EXTSIZE = (1 SHL XFS_DIFLAG_EXTSIZE_BIT)
XFS_DIFLAG_EXTSZINHERIT = (1 SHL XFS_DIFLAG_EXTSZINHERIT_BIT)
XFS_DIFLAG_NODEFRAG = (1 SHL XFS_DIFLAG_NODEFRAG_BIT)
XFS_DIFLAG_FILESTREAM = (1 SHL XFS_DIFLAG_FILESTREAM_BIT)
; superblock _ondisk_ structure (xfs_sb.h)
; this is _not_ the partition structure
; for XFS partition structure see XFS below
struct xfs_sb
sb_magicnum dd ? ; signature, must be XFS_SB_MAGIC
sb_blocksize dd ? ; block is the minimal file system unit, in bytes
sb_dblocks dq ? ; number of data blocks
sb_rblocks dq ? ; number of realtime blocks (not supported yet!)
sb_rextents dq ? ; number of realtime extents (not supported yet!)
sb_uuid rb 16 ; file system unique identifier
sb_logstart dq ? ; starting block of log (for internal journal; journals on separate devices are not supported!)
sb_rootino dq ? ; root inode number
sb_rbmino dq ? ; bitmap inode for realtime extents (ignored)
sb_rsumino dq ? ; summary inode for rt bitmap (ignored)
sb_rextsize dd ? ; realtime extent size, blocks
sb_agblocks dd ? ; size of an allocation group (the last one may be smaller!)
sb_agcount dd ? ; number of allocation groups
sb_rbmblocks dd ? ; number of rt bitmap blocks
sb_logblocks dd ? ; number of log blocks
sb_versionnum dw ? ; header version == XFS_SB_VERSION
sb_sectsize dw ? ; volume sector size in bytes (only 512B sectors are supported)
sb_inodesize dw ? ; inode size, bytes
sb_inopblock dw ? ; inodes per block
sb_fname rb 12 ; inodes per block (aka label)
sb_blocklog db ? ; log2 of sb_blocksize
sb_sectlog db ? ; log2 of sb_blocksize
sb_inodelog db ? ; log2 of sb_inodesize
sb_inopblog db ? ; log2 of sb_inopblock
sb_agblklog db ? ; log2 of sb_agblocks (rounded up!)
sb_rextslog db ? ; log2 of sb_rextents
sb_inprogress db ? ; mkfs is in progress, don't mount
sb_imax_pct db ? ; max % of fs for inode space
; statistics
sb_icount dq ? ; allocated inodes
sb_ifree dq ? ; free inodes
sb_fdblocks dq ? ; free data blocks
sb_frextents dq ? ; free realtime extents
sb_uquotino dq ? ; user quota inode
sb_gquotino dq ? ; group quota inode
sb_qflags dw ? ; quota flags
sb_flags db ? ; misc. flags
sb_shared_vn db ? ; shared version number
sb_inoalignmt dd ? ; inode chunk alignment, fsblocks
sb_unit dd ? ; stripe or raid unit
sb_width dd ? ; stripe or raid width
sb_dirblklog db ? ; log2 of dir block size (fsbs)
sb_logsectlog db ? ; log2 of the log sector size
sb_logsectsize dw ? ; sector size for the log, bytes
sb_logsunit dd ? ; stripe unit size for the log
sb_features2 dd ? ; additional feature bits
ends
; allocation group inode (xfs_ag.h)
struct xfs_agi
agi_magicnum dd ? ; magic number == XFS_AGI_MAGIC
agi_versionnum dd ? ; header version == XFS_AGI_VERSION
agi_seqno dd ? ; sequence number starting from 0
agi_length dd ? ; size in blocks of a.g.
agi_count dd ? ; count of allocated inodes
agi_root dd ? ; root of inode btree
agi_level dd ? ; levels in inode btree
agi_freecount dd ? ; number of free inodes
agi_newino dd ? ; new inode just allocated
agi_dirino dd ? ; last directory inode chunk
agi_unlinked rd XFS_AGI_UNLINKED_BUCKETS ; Hash table of inodes which have been unlinked but are still being referenced
ends
; superblock structure of b+tree node/leaf (same structure, bb_level matters)
struct xfs_btree_sblock
bb_magic dd ?
bb_level dw ? ; distinguishes nodeds and leaves
bb_numrecs dw ?
bb_leftsib dd ?
bb_rightsib dd ?
ends
; record of b+tree inode
struct xfs_inobt_rec
ir_startino dd ?
ir_freecount dd ?
ir_free dq ?
ends
; structure to store create, access and modification time in inode core
struct xfs_timestamp
t_sec dd ?
t_nsec dd ? ; nanoseconds
ends
; inode core structure: basic information about file
struct xfs_dinode_core
di_magic dw ? ; inode magic = XFS_DINODE_MAGIC
di_mode dw ? ; mode and type of file
di_version db ? ; inode version
di_format db ? ; format of di_c data
di_onlink dw ? ; old number of links to file
di_uid dd ? ; owner's user id
di_gid dd ? ; owner's group id
di_nlink dd ? ; number of links to file
di_projid dw ? ; owner's project id
di_pad rb 8 ; unused, zeroed space
di_flushiter dw ? ; incremented on flush
di_atime xfs_timestamp ; time last accessed
di_mtime xfs_timestamp ; time last modified
di_ctime xfs_timestamp ; time created/inode modified
di_size dq ? ; number of bytes in file
di_nblocks dq ? ; number of direct & btree blocks used
di_extsize dd ? ; basic/minimum extent size for file
di_nextents dd ? ; number of extents in data fork
di_anextents dw ? ; number of extents in attribute fork
di_forkoff db ? ; attr fork offs, <<3 for 64b align
di_aformat db ? ; format of attr fork's data
di_dmevmask dd ? ; DMIG event mask
di_dmstate dw ? ; DMIG state info
di_flags dw ? ; random flags, XFS_DIFLAG_...
di_gen dd ? ; generation number
ends
; shortform dir header
struct xfs_dir2_sf_hdr
count db ? ; the number of directory entries, used only if each inode number fits 4 bytes; zero otherwise
i8count db ? ; the number of directory entries, used only when count is zero
parent dq ? ; parent inode number: xfs_dir2_inou_t (4 or 8 bytes)
ends
; shortform dir entry
struct xfs_dir2_sf_entry
namelen db ? ; actual name length (ASCII)
offset rb 2 ; saved offset
name db ? ; name, variable size
; inumber dq ? ; xfs_dir2_inou_t
ends
; active entry in a data block
; aligned to 8 bytes
; tag appears as the last 2 bytes
struct xfs_dir2_data_entry
inumber dq ? ; inode number
namelen db ? ; name length
name db ? ; name bytes, no null
; tag dw ? ; starting offset of us
ends
; unused entry in a data block
; aligned to 8 bytes
; tag appears as the last 2 bytes
struct xfs_dir2_data_unused
freetag dw ? ; XFS_DIR2_DATA_FREE_TAG
length dw ? ; total free length
; tag dw ? ; starting offset of us
ends
; generic data entry
struct xfs_dir2_data_union
union
xentry xfs_dir2_data_entry
unused xfs_dir2_data_unused
ends
ends
; describe a free area in the data block
; the freespace will be formatted as a xfs_dir2_data_unused_t
struct xfs_dir2_data_free
offset dw ? ; start of freespace
length dw ? ; length of freespace
ends
; header for the data blocks
; always at the beginning of a directory-sized block
; the code knows that XFS_DIR2_DATA_FD_COUNT is 3
struct xfs_dir2_data_hdr
magic dd ? ; XFS_DIR2_DATA_MAGIC or XFS_DIR2_BLOCK_MAGIC
bestfree xfs_dir2_data_free
bestfree2 xfs_dir2_data_free
bestfree3 xfs_dir2_data_free
ends
; leaf block entry
struct xfs_dir2_leaf_entry
hashval dd ? ; hash value of name
address dd ? ; address of data entry
ends
; the tail of directory block
struct xfs_dir2_block_tail
count dd ? ; count of leaf entries
stale dd ? ; count of stale leaf entries
ends
; generic single-block structure, for xfs_db
struct xfs_dir2_block
hdr xfs_dir2_data_hdr
u xfs_dir2_data_union
; leaf xfs_dir2_leaf_entry
; tail xfs_dir2_block_tail
ends
;
struct xfs_dir2_data
hdr xfs_dir2_data_hdr ; magic XFS_DIR2_DATA_MAGIC
u xfs_dir2_data_union
ends
;
struct xfs_da_blkinfo
forw dd ? ; previous block in list
back dd ? ; following block in list
magic dw ? ; validity check on block
pad dw ? ; unused
ends
; leaf block header
struct xfs_dir2_leaf_hdr
info xfs_da_blkinfo ; header for da routines
count dw ? ; count of entries
stale dw ? ; count of stale entries
ends
; leaf block tail
struct xfs_dir2_leaf_tail
bestcount dd ?
ends
; leaf block
; bests and tail are at the end of the block for single-leaf only
; (magic = XFS_DIR2_LEAF1_MAGIC not XFS_DIR2_LEAFN_MAGIC)
struct xfs_dir2_leaf
hdr xfs_dir2_leaf_hdr ; leaf header
ents xfs_dir2_leaf_entry ; entries
; bests dw ? ; best free counts
; tail xfs_dir2_leaf_tail ; leaf tail
ends
; header of 'free' block part
struct xfs_dir2_free_hdr
magic dd ? ; XFS_DIR2_FREE_MAGIC
firstdb dd ? ; db of first entry
nvalid dd ? ; count of valid entries
nused dd ? ; count of used entries
ends
; 'free' part of directiry block
struct xfs_dir2_free
hdr xfs_dir2_free_hdr ; block header
bests dw ? ; best free counts
; unused entries are -1 (XFS_NULL)
ends
; b+tree node header
struct xfs_da_node_hdr
info xfs_da_blkinfo
count dw ?
level dw ?
ends
; b+tree node
struct xfs_da_node_entry
hashval dd ? ; hash value for this descendant
before dd ? ; Btree block before this key
ends
;
struct xfs_da_intnode
hdr xfs_da_node_hdr
btree xfs_da_node_entry
ends
; packet extent
struct xfs_bmbt_rec
l0 dq ?
l1 dq ?
ends
; unpacked extent
struct xfs_bmbt_irec
br_startoff dq ? ; starting file offset
br_startblock dq ? ; starting block number
br_blockcount dd ? ; number of blocks
br_state dd ? ; extent state
ends
; bmap root header, on-disk form only
struct xfs_bmdr_block
bb_level dw ? ; 0 is a leaf
bb_numrecs dw ? ; current number of data records
ends
; key structure for non-leaf levels of the tree
struct xfs_bmbt_key
br_startoff dq ? ; starting file offset
ends
sizeof.xfs_bmbt_ptr = 8 ; workaround
sizeof.xfs_bmdr_ptr = 8 ; workaround
; long form header: bmap btrees
; xfs_btree_lblock is xfs_bmbt_block (xfs_btree.h)
struct xfs_bmbt_block
bb_magic dd ? ; magic number for block type
bb_level dw ? ; 0 is a leaf
bb_numrecs dw ? ; current number of data records
bb_leftsib dq ? ; left sibling block or NULLDFSBNO
bb_rightsib dq ? ; right sibling block or NULLDFSBNO
ends
; high level inode structure
struct xfs_inode
di_core xfs_dinode_core ; main info, aka core
di_next_unlinked dd ? ; unlinked but still used inode (if any, XFS_NULL otherwise)
di_u db ? ; data fork inode part
; di_a db ? ; data attribute
ends
; internal data for every XFS partition
; this _is_ XFS partition structure
; most fields are unpacked or bswap'ed values from the superblock, so see xfs_sb structure above
struct XFS PARTITION
Lock MUTEX ? ; access mutex
blocksize dd ?
sectsize dd ?
dirblocksize dd ?
rootino dq ?
cur_block dd ?
cur_inode dd ?
cur_sect dd ?
cur_dirblock dd ?
tmp_inode dd ?
versionnum dd ?
features2 dd ?
inodesize dd ?
inopblock dd ?
blocklog dd ?
sectlog dd ?
inodelog dd ?
inopblog dd ?
agblklog dd ?
blockmsectlog dd ?
inodetoblocklog dd ?
dirblklog dd ?
sectpblock dd ?
agblocks dd ?
; helpers, temporary vars, etc
agblockmask dq ?
extent xfs_bmbt_irec
left_extents dd ?
left_leaves dd ?
bytes_to_read dd ?
bytes_read dd ?
entries_read dd ?
file_offset dq ?
max_dirblockaddr dd ?
next_block_num dq ?
dir2_leaf_offset_blocks dd ?
dir2_free_offset_blocks dd ?
cur_inode_save dd ?
bytes_left_in_file dq ?
ro_nextents dd ?
bb_ptrs dd ?
maxnumrecs dd ?
buffer_pos dd ?
eof dd ?
ends

View File

@ -233,6 +233,8 @@ align 4
FONT_I:
if lang eq sp
file 'char_sp.mt'
else if lang eq et
file 'char_et.mt'
else
file 'char.mt'
end if
@ -241,6 +243,8 @@ align 4
FONT_II:
if lang eq sp
file 'char2_sp.mt'
else if lang eq et
file 'char2_et.mt'
else
file 'char2.mt'
end if

View File

@ -144,6 +144,8 @@ use16
if lang eq sp
include "kernelsp.inc" ; spanish kernel messages
else if lang eq et
version db 'Kolibri OS versioon 0.7.7.0+ ',13,10,13,10,0
else
version db 'Kolibri OS version 0.7.7.0+ ',13,10,13,10,0
end if
@ -696,6 +698,19 @@ no_mode_0x12:
mov [mem_BACKGROUND], 4
mov [img_background], static_background_data
; set clipboard
xor eax, eax
mov [clipboard_slots], eax
mov [clipboard_write_lock], eax
stdcall kernel_alloc, 4096
test eax, eax
jnz @f
dec eax
@@:
mov [clipboard_main_list], eax
; SET UP OS TASK
mov esi, boot_setostask
@ -1093,6 +1108,8 @@ end if
@@:
DEBUGF 1, "K : %d CPU detected\n", eax
include "detect/vortex86.inc" ; Vortex86 SoC detection code
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
@ -1100,6 +1117,7 @@ end if
DEBUGF 1, "K : BAR4 %x \n", [IDEContrRegsBaseAddr]:4
DEBUGF 1, "K : IDEContrProgrammingInterface %x \n", [IDEContrProgrammingInterface]:4
DEBUGF 1, "K : IDE_Interrupt %x \n", [IDE_Interrupt]:4
; START MULTITASKING
; A 'All set - press ESC to start' messages if need
@ -3248,6 +3266,10 @@ sys_cpuusage:
mov EAX, dword [ECX+CURRENT_TASK+TASKDATA.event_mask]
stosd
; Keyboard mode (+75)
mov al, byte [ecx*8 + SLOT_BASE + APPDATA.keyboard_mode]
stosb
pop esi
pop edi
@ -3790,10 +3812,6 @@ newdw2:
mov eax, [edi + WDATA.box.left]
mov ebx, [edi + WDATA.box.top]
mov ecx, [edi + WDATA.box.width]
mov edx, [edi + WDATA.box.height]
add ecx, eax
add edx, ebx
mov ecx, [draw_limits.bottom] ; ecx = area y end ebx = window y start
cmp ecx, ebx
@ -3892,6 +3910,64 @@ align 4
align 4
newdw8:
nobgrd:
;--------------------------------------
push eax edi ebp
mov edi, [esp+12]
cmp edi, 1
je .found
mov eax, [draw_limits.left]
mov ebx, [draw_limits.top]
mov ecx, [draw_limits.right]
sub ecx, eax
test ecx, ecx
jz .not_found
mov edx, [draw_limits.bottom]
sub edx, ebx
test edx, edx
jz .not_found
; eax - x, ebx - y
; ecx - size x, edx - size y
add ebx, edx
;--------------------------------------
align 4
.start_y:
push ecx
;--------------------------------------
align 4
.start_x:
add eax, ecx
mov ebp, [d_width_calc_area + ebx*4]
add ebp, [_WinMapAddress]
movzx ebp, byte[eax+ebp] ; get value for current point
cmp ebp, edi
jne @f
pop ecx
jmp .found
;--------------------------------------
align 4
@@:
sub eax, ecx
dec ecx
jnz .start_x
pop ecx
dec ebx
dec edx
jnz .start_y
;--------------------------------------
align 4
.not_found:
pop ebp edi eax
jmp ricino
;--------------------------------------
align 4
.found:
pop ebp edi eax
mov [eax + WDATA.fl_redraw], byte 1 ; mark as redraw
;--------------------------------------
@ -5511,13 +5587,13 @@ syscall_reserveportarea: ; ReservePortArea and FreePortArea
align 4
syscall_threads: ; CreateThreads
; eax=1 create thread
;
; ebx=thread start
; ecx=thread stack value
; ecx=thread entry point
; edx=thread stack pointer
;
; on return : eax = pid
xor ebx, ebx
call new_sys_threads
mov [esp+32], eax

View File

@ -171,6 +171,7 @@ include "core/v86.inc" ; virtual-8086 manager
include "core/irq.inc" ; irq handling functions
include "core/apic.inc" ; Interrupt Controller functions
include "core/timers.inc"
include "core/clipboard.inc" ; custom clipboard
; GUI stuff
include "gui/window.inc"
@ -191,7 +192,8 @@ include "fs/fat12.inc" ; read / write for fat12 filesystem
include "blkdev/rd.inc" ; ramdisk read /write
include "fs/fs_lfn.inc" ; syscall, version 2
include "fs/iso9660.inc" ; read for iso9660 filesystem CD
include "fs/ext2.inc" ; read / write for ext2 filesystem
include "fs/ext2/ext2.asm" ; read / write for ext2 filesystem
include "fs/xfs.asm" ; read / write for xfs filesystem
; sound

View File

@ -1,4 +1,4 @@
; Éste archivo debe ser editado con codificación CP866
version: cp850 'Kolibri OS versión 0.7.7.0+ ',13,10,13,10,0
version cp850 'Kolibri OS versión 0.7.7.0+ ',13,10,13,10,0
diff16 "fin del código del kernel",0,$

View File

@ -18,7 +18,7 @@
$Revision: 3515 $
MAX_FRAGMENTS = 64
IPv4_MAX_FRAGMENTS = 64
struct IPv4_header
@ -35,7 +35,7 @@ struct IPv4_header
ends
struct FRAGMENT_slot
struct IPv4_FRAGMENT_slot
ttl dw ? ; Time to live for this entry, 0 for empty slot's
id dw ? ; Identification field from IP header
@ -45,7 +45,7 @@ struct FRAGMENT_slot
ends
struct FRAGMENT_entry ; This structure will replace the ethernet header in fragmented ip packets
struct IPv4_FRAGMENT_entry ; This structure will replace the ethernet header in fragmented ip packets
PrevPtr dd ? ; Pointer to previous fragment entry (-1 for first packet)
NextPtr dd ? ; Pointer to next fragment entry (-1 for last packet)
@ -64,11 +64,11 @@ align 4
GATEWAY_LIST rd NET_DEVICES_MAX
BROADCAST_LIST rd NET_DEVICES_MAX
IP_packets_tx rd NET_DEVICES_MAX
IP_packets_rx rd NET_DEVICES_MAX
IP_packets_dumped rd NET_DEVICES_MAX
IPv4_packets_tx rd NET_DEVICES_MAX
IPv4_packets_rx rd NET_DEVICES_MAX
IPv4_packets_dumped rd NET_DEVICES_MAX
FRAGMENT_LIST rb MAX_FRAGMENTS * sizeof.FRAGMENT_slot
IPv4_FRAGMENT_LIST rb IPv4_MAX_FRAGMENTS * sizeof.IPv4_FRAGMENT_slot
endg
@ -84,7 +84,7 @@ macro IPv4_init {
xor eax, eax
mov edi, IP_LIST
mov ecx, 7*NET_DEVICES_MAX + (sizeof.FRAGMENT_slot*MAX_FRAGMENTS)/4
mov ecx, 7*NET_DEVICES_MAX + (sizeof.IPv4_FRAGMENT_slot*IPv4_MAX_FRAGMENTS)/4
rep stosd
}
@ -99,15 +99,15 @@ macro IPv4_decrease_fragment_ttls {
local .loop, .next
mov esi, FRAGMENT_LIST
mov ecx, MAX_FRAGMENTS
mov esi, IPv4_FRAGMENT_LIST
mov ecx, IPv4_MAX_FRAGMENTS
.loop:
cmp [esi + FRAGMENT_slot.ttl], 0
cmp [esi + IPv4_FRAGMENT_slot.ttl], 0
je .next
dec [esi + FRAGMENT_slot.ttl]
dec [esi + IPv4_FRAGMENT_slot.ttl]
jz .died
.next:
add esi, sizeof.FRAGMENT_slot
add esi, sizeof.IPv4_FRAGMENT_slot
dec ecx
jnz .loop
jmp .done
@ -263,7 +263,7 @@ IPv4_input: ; TODO: add IPv4
; Now we can update stats
.ip_ok:
inc [IP_packets_rx + edi]
inc [IPv4_packets_rx + edi]
;----------------------------------
; Check if the packet is fragmented
@ -304,7 +304,7 @@ IPv4_input: ; TODO: add IPv4
.dump:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: dumping\n"
inc [IP_packets_dumped] ; FIXME: use correct interface
inc [IPv4_packets_dumped] ; FIXME: use correct interface
call NET_packet_free
add esp, 4 ; pop (balance stack)
ret
@ -319,7 +319,7 @@ IPv4_input: ; TODO: add IPv4
xchg al, ah
shl ax, 3
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: fragmented packet offset=%u id=%x\n", ax, [edx + IPv4_header.Identification]:4
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: fragmented packet offset=%u id=%x ptr=0x%x\n", ax, [edx + IPv4_header.Identification]:4, edx
test ax, ax ; Is this the first packet of the fragment?
jz .is_first_fragment
@ -334,24 +334,24 @@ IPv4_input: ; TODO: add IPv4
cmp esi, -1
je .dump
mov [esi + FRAGMENT_slot.ttl], 15 ; Reset the ttl
mov esi, [esi + FRAGMENT_slot.ptr]
mov [esi + IPv4_FRAGMENT_slot.ttl], 15 ; Reset the ttl
mov esi, [esi + IPv4_FRAGMENT_slot.ptr]
or edi, -1
.find_last_entry: ; The following routine will try to find the last entry
cmp edi, [esi + FRAGMENT_entry.PrevPtr]
cmp edi, [esi + IPv4_FRAGMENT_entry.PrevPtr]
jne .destroy_slot ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
mov edi, esi
mov esi, [esi + FRAGMENT_entry.NextPtr]
mov esi, [esi + IPv4_FRAGMENT_entry.NextPtr]
cmp esi, -1
jne .find_last_entry
; We found the last entry (pointer is now in edi)
; We are going to overwrite the ethernet header in received packet with a FRAGMENT_entry structure
pop eax ; pointer to packet
mov [edi + FRAGMENT_entry.NextPtr], eax ; update pointer of previous entry to the new entry
mov [eax + FRAGMENT_entry.NextPtr], -1
mov [eax + FRAGMENT_entry.PrevPtr], edi
mov [eax + FRAGMENT_entry.Owner], ebx
mov [edi + IPv4_FRAGMENT_entry.NextPtr], eax ; update pointer of previous entry to the new entry
mov [eax + IPv4_FRAGMENT_entry.NextPtr], -1
mov [eax + IPv4_FRAGMENT_entry.PrevPtr], edi
mov [eax + IPv4_FRAGMENT_entry.Owner], ebx
add esp, 4
ret
@ -363,29 +363,29 @@ IPv4_input: ; TODO: add IPv4
.is_first_fragment:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: First fragment packet received!\n"
; try to locate a free slot..
mov ecx, MAX_FRAGMENTS
mov esi, FRAGMENT_LIST
mov ecx, IPv4_MAX_FRAGMENTS
mov esi, IPv4_FRAGMENT_LIST
.find_free_slot:
cmp word [esi + FRAGMENT_slot.ttl], 0
cmp word [esi + IPv4_FRAGMENT_slot.ttl], 0
je .found_free_slot
add esi, sizeof.FRAGMENT_slot
add esi, sizeof.IPv4_FRAGMENT_slot
loop .find_free_slot
jmp .dump ; If no free slot was found, dump the packet
.found_free_slot: ; We found a free slot, let's fill in the FRAGMENT_slot structure
mov [esi + FRAGMENT_slot.ttl], 15 ; RFC recommends 15 secs as ttl
mov [esi + IPv4_FRAGMENT_slot.ttl], 15 ; RFC recommends 15 secs as ttl
mov ax, [edx + IPv4_header.Identification]
mov [esi + FRAGMENT_slot.id], ax
mov [esi + IPv4_FRAGMENT_slot.id], ax
mov eax, [edx + IPv4_header.SourceAddress]
mov [esi + FRAGMENT_slot.SrcIP], eax
mov [esi + IPv4_FRAGMENT_slot.SrcIP], eax
mov eax, [edx + IPv4_header.DestinationAddress]
mov [esi + FRAGMENT_slot.DstIP], eax
mov [esi + IPv4_FRAGMENT_slot.DstIP], eax
pop eax
mov [esi + FRAGMENT_slot.ptr], eax
mov [esi + IPv4_FRAGMENT_slot.ptr], eax
; Now, replace ethernet header in original buffer with a FRAGMENT_entry structure
mov [eax + FRAGMENT_entry.NextPtr], -1
mov [eax + FRAGMENT_entry.PrevPtr], -1
mov [eax + FRAGMENT_entry.Owner], ebx
mov [eax + IPv4_FRAGMENT_entry.NextPtr], -1
mov [eax + IPv4_FRAGMENT_entry.PrevPtr], -1
mov [eax + IPv4_FRAGMENT_entry.Owner], ebx
add esp, 4 ; balance stack and exit
ret
@ -401,33 +401,33 @@ IPv4_input: ; TODO: add IPv4
cmp esi, -1
je .dump
mov esi, [esi + FRAGMENT_slot.ptr] ; We found the first entry, let's calculate total size of the packet in eax, so we can allocate a buffer
mov esi, [esi + IPv4_FRAGMENT_slot.ptr] ; We found the first entry, let's calculate total size of the packet in eax, so we can allocate a buffer
push esi
xor eax, eax
or edi, -1
.count_bytes:
cmp [esi + FRAGMENT_entry.PrevPtr], edi
cmp [esi + IPv4_FRAGMENT_entry.PrevPtr], edi
jne .destroy_slot_pop ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
mov cx, [esi + sizeof.FRAGMENT_entry + IPv4_header.TotalLength] ; Add total length
mov cx, [esi + sizeof.IPv4_FRAGMENT_entry + IPv4_header.TotalLength] ; Add total length
xchg cl, ch
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Packet size=%u\n", cx
add ax, cx
movzx cx, [esi + sizeof.FRAGMENT_entry + IPv4_header.VersionAndIHL] ; Sub Header length
movzx cx, [esi + sizeof.IPv4_FRAGMENT_entry + IPv4_header.VersionAndIHL] ; Sub Header length
and cx, 0x000F
shl cx, 2
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Header size=%u\n", cx
sub ax, cx
mov edi, esi
mov esi, [esi + FRAGMENT_entry.NextPtr]
mov esi, [esi + IPv4_FRAGMENT_entry.NextPtr]
cmp esi, -1
jne .count_bytes
mov esi, [esp+4]
mov [edi + FRAGMENT_entry.NextPtr], esi ; Add this packet to the chain, this simplifies the following code
mov [esi + FRAGMENT_entry.NextPtr], -1
mov [esi + FRAGMENT_entry.PrevPtr], edi
mov [esi + FRAGMENT_entry.Owner], ebx
mov [edi + IPv4_FRAGMENT_entry.NextPtr], esi ; Add this packet to the chain, this simplifies the following code
mov [esi + IPv4_FRAGMENT_entry.NextPtr], -1
mov [esi + IPv4_FRAGMENT_entry.PrevPtr], edi
mov [esi + IPv4_FRAGMENT_entry.Owner], ebx
mov cx, [edx + IPv4_header.TotalLength] ; Note: This time we dont substract Header length
xchg cl, ch
@ -454,18 +454,18 @@ IPv4_input: ; TODO: add IPv4
mov edx, [esp+4] ; Get pointer to first fragment entry back in edx
.rebuild_packet_loop:
movzx ecx, [edx + sizeof.FRAGMENT_entry + IPv4_header.FlagsAndFragmentOffset] ; Calculate the fragment offset
movzx ecx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.FlagsAndFragmentOffset] ; Calculate the fragment offset
xchg cl, ch ; intel byte order
shl cx, 3 ; multiply by 8 and clear first 3 bits
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Fragment offset=%u\n", cx
lea edi, [eax + ecx] ; Notice that edi will be equal to eax for first fragment
movzx ebx, [edx + sizeof.FRAGMENT_entry + IPv4_header.VersionAndIHL] ; Find header size (in ebx) of fragment
movzx ebx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.VersionAndIHL] ; Find header size (in ebx) of fragment
and bx, 0x000F ;
shl bx, 2 ;
lea esi, [edx + sizeof.FRAGMENT_entry] ; Set esi to the correct begin of fragment
movzx ecx, [edx + sizeof.FRAGMENT_entry + IPv4_header.TotalLength] ; Calculate total length of fragment
lea esi, [edx + sizeof.IPv4_FRAGMENT_entry] ; Set esi to the correct begin of fragment
movzx ecx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.TotalLength] ; Calculate total length of fragment
xchg cl, ch ; intel byte order
cmp edi, eax ; Is this packet the first fragment ?
@ -474,6 +474,8 @@ IPv4_input: ; TODO: add IPv4
add esi, ebx ;
.first_fragment:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Copying %u bytes from 0x%x to 0x%x\n", ecx, esi, edi
push cx ; First copy dword-wise, then byte-wise
shr cx, 2 ;
rep movsd ;
@ -482,11 +484,12 @@ IPv4_input: ; TODO: add IPv4
rep movsb ;
push eax
push [edx + IPv4_FRAGMENT_entry.Owner] ; we need to remeber the owner, in case this is the last packet
push [edx + IPv4_FRAGMENT_entry.NextPtr] ; Set edx to the next pointer
push edx ; Push pointer to fragment onto stack
mov ebx, [edx + FRAGMENT_entry.Owner] ; we need to remeber the owner, in case this is the last packet
mov edx, [edx + FRAGMENT_entry.NextPtr] ; Set edx to the next pointer
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Next Fragment: 0x%x\n", edx
call NET_packet_free ; free the previous fragment buffer (this uses the value from stack)
pop eax
pop edx ebx eax
cmp edx, -1 ; Check if it is last fragment in chain
jne .rebuild_packet_loop
@ -494,11 +497,9 @@ IPv4_input: ; TODO: add IPv4
xchg cl, ch
mov edx, eax
mov [edx + IPv4_header.TotalLength], cx
add esp, 8
add esp, 12
xchg cl, ch
push ecx
push eax
push ecx edx ; size and pointer
jmp .handle_it ; edx = buf ptr, ecx = size, [esp] buf ptr, [esp+4], total size, ebx=device ptr
.destroy_slot_pop:
@ -527,19 +528,19 @@ IPv4_find_fragment_slot:
push eax ebx ecx edx
mov ax, [edx + IPv4_header.Identification]
mov ecx, MAX_FRAGMENTS
mov esi, FRAGMENT_LIST
mov ecx, IPv4_MAX_FRAGMENTS
mov esi, IPv4_FRAGMENT_LIST
mov ebx, [edx + IPv4_header.SourceAddress]
mov edx, [edx + IPv4_header.DestinationAddress]
.find_slot:
cmp [esi + FRAGMENT_slot.id], ax
cmp [esi + IPv4_FRAGMENT_slot.id], ax
jne .try_next
cmp [esi + FRAGMENT_slot.SrcIP], ebx
cmp [esi + IPv4_FRAGMENT_slot.SrcIP], ebx
jne .try_next
cmp [esi + FRAGMENT_slot.DstIP], edx
cmp [esi + IPv4_FRAGMENT_slot.DstIP], edx
je .found_slot
.try_next:
add esi, sizeof.FRAGMENT_slot
add esi, sizeof.IPv4_FRAGMENT_slot
loop .find_slot
or esi, -1
@ -552,10 +553,9 @@ IPv4_find_fragment_slot:
;
; IPv4_output
;
; IN: eax = dest ip
; ebx = output device ptr/0 for automatic choice
; IN: eax = Destination IP
; ecx = data length
; edx = source ip
; edx = Source IP
; di = TTL shl 8 + protocol
;
; OUT: eax = pointer to buffer start
@ -573,9 +573,9 @@ IPv4_output:
cmp ecx, 65500 ; Max IPv4 packet size
ja .too_large
push ecx eax edx di
call IPv4_route ; outputs device number in edi, dest ip in eax
push ecx di eax
call IPv4_route ; outputs device number in edi, dest ip in eax, source IP in edx
push edx
test edi, edi
jz .loopback
@ -586,12 +586,12 @@ IPv4_output:
push ebx ; push the mac onto the stack
push ax
inc [IP_packets_tx + edi] ; update stats
inc [IPv4_packets_tx + edi] ; update stats
mov ebx, [NET_DRV_LIST + edi]
lea eax, [ebx + ETH_DEVICE.mac]
mov edx, esp
mov ecx, [esp + 10 + 6]
mov ecx, [esp + 6 + 8 + 2]
add ecx, sizeof.IPv4_header
mov di, ETHER_PROTO_IPv4
call ETH_output
@ -605,12 +605,14 @@ IPv4_output:
mov [edi + IPv4_header.TotalLength], cx
mov [edi + IPv4_header.Identification], 0 ; fragment id: FIXME
mov [edi + IPv4_header.FlagsAndFragmentOffset], 0
pop word [edi + IPv4_header.TimeToLive] ; ttl shl 8 + protocol
; [edi + IPv4_header.Protocol]
mov [edi + IPv4_header.HeaderChecksum], 0
popd [edi + IPv4_header.SourceAddress]
popd [edi + IPv4_header.DestinationAddress]
pop word[edi + IPv4_header.TimeToLive] ; ttl shl 8 + protocol
; [edi + IPv4_header.Protocol]
pop ecx
IPv4_checksum edi
@ -677,7 +679,7 @@ IPv4_output_raw:
push ebx ; push the mac
push ax
inc [IP_packets_tx + 4*edi]
inc [IPv4_packets_tx + 4*edi]
mov ebx, [NET_DRV_LIST + 4*edi]
lea eax, [ebx + ETH_DEVICE.mac]
mov edx, esp
@ -857,40 +859,44 @@ IPv4_fragment:
; IPv4_route
;
; IN: eax = Destination IP
; OUT: edi = device number*4
; eax = ip of gateway if nescessary, unchanged otherwise
; edx = Source IP
; OUT: eax = Destination IP (or gateway IP)
; edx = Source IP
; edi = device number*4
; DESTROYED:
; ecx
;
;---------------------------------------------------------------------------
align 4
IPv4_route:
IPv4_route: ; TODO: return error if no valid route found
cmp eax, 0xffffffff
je .broadcast
xor edi, edi
mov ecx, NET_DEVICES_MAX
.loop:
mov ebx, [IP_LIST + edi]
and ebx, [SUBNET_LIST + edi]
jz .next
mov edx, eax
and edx, [SUBNET_LIST+edi]
cmp ebx, edx
jne .next
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_route: %u\n", edi
ret
mov ecx, eax
and ecx, [SUBNET_LIST + edi]
cmp ebx, ecx
je .got_it
.next:
add edi, 4
dec ecx
jnz .loop
cmp edi, 4*NET_DEVICES_MAX
jb .loop
.invalid:
mov eax, [GATEWAY_LIST+4] ;;; FIXME
mov eax, [GATEWAY_LIST + 4] ; TODO: let user (or a user space daemon) configure default route
.broadcast:
mov edi, 4 ; if none found, use device 1 as default ;;;; FIXME
mov edi, 4 ; TODO: same as above
.got_it:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_route: %u\n", edi
test edx, edx
jnz @f
mov edx, [IP_LIST + edi]
@@:
ret
@ -910,6 +916,45 @@ IPv4_get_frgmnt_num:
ret
;-----------------------------------------------------------------
;
; IPv4_connect
;
; IN: eax = socket pointer
; OUT: eax = 0 ok / -1 error
; ebx = error code
;
;-------------------------
align 4
IPv4_connect:
push eax edx
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
pop edx eax
; Fill in local IP
cmp [eax + IP_SOCKET.LocalIP], 0
jne @f
push [IP_LIST + 4] ; FIXME: use correct local IP
pop [eax + IP_SOCKET.LocalIP]
; Fill in remote IP
pushd [edx + 4]
pop [eax + IP_SOCKET.RemoteIP]
; Set up data receiving queue
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION)
pop eax
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
xor eax, eax
ret
;---------------------------------------------------------------------------
;
; IPv4_API
@ -952,11 +997,11 @@ IPv4_api:
ret
.packets_tx:
mov eax, [IP_packets_tx + eax]
mov eax, [IPv4_packets_tx + eax]
ret
.packets_rx:
mov eax, [IP_packets_rx + eax]
mov eax, [IPv4_packets_rx + eax]
ret
.read_ip:

View File

@ -17,6 +17,7 @@
$Revision: 3346 $
ETH_FRAME_MINIMUM = 60
ETH_QUEUE_SIZE = 255
struct ETH_header
@ -32,12 +33,40 @@ struct ETH_DEVICE NET_DEVICE
ends
struct ETH_queue_entry
device dd ?
packet dd ?
size dd ?
ends
iglobal
align 4
ETH_BROADCAST dp 0xffffffffffff
endg
uglobal
align 4
ETH_input_event dd ?
ETH_queue rd (ETH_QUEUE_SIZE*sizeof.ETH_queue_entry + sizeof.queue)/4
endg
macro ETH_init {
init_queue ETH_queue
movi ebx, 1
mov ecx, ETH_process_input
call new_sys_threads
test eax, eax
jns @f
DEBUGF DEBUG_NETWORK_ERROR,'K : cannot create kernel thread for ethernet, error %d\n', eax
@@:
}
;-----------------------------------------------------------------
;
; ETH_input
@ -53,8 +82,60 @@ endg
;-----------------------------------------------------------------
align 4
ETH_input:
mov eax, [esp]
mov ecx, [esp+4]
push ebx
mov esi, esp
pushf
cli
add_to_queue ETH_queue, ETH_QUEUE_SIZE, sizeof.ETH_queue_entry, .fail
popf
add esp, sizeof.ETH_queue_entry
xor edx, edx
mov eax, [ETH_input_event]
mov ebx, [eax + EVENT.id]
xor esi, esi
call raise_event
ret
.fail:
popf
DEBUGF DEBUG_NETWORK_VERBOSE, "ETH incoming queue is full, discarding packet!\n"
add esp, sizeof.ETH_queue_entry - 8
call NET_packet_free
add esp, 4
ret
align 4
ETH_process_input:
xor esi, esi
mov ecx, MANUAL_DESTROY
call create_event
mov [ETH_input_event], eax
.wait:
mov eax, [ETH_input_event]
mov ebx, [eax + EVENT.id]
call wait_event
.loop:
get_from_queue ETH_queue, ETH_QUEUE_SIZE, sizeof.ETH_queue_entry, .wait
mov eax, [esi + ETH_queue_entry.packet]
mov ecx, [esi + ETH_queue_entry.size]
mov ebx, [esi + ETH_queue_entry.device]
pushd .loop ; return address
push ecx eax
DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_input: size=%u\n", ecx
sub ecx, sizeof.ETH_header
@ -78,7 +159,7 @@ ETH_input:
cmp ax, ETHER_PROTO_PPP_SESSION
je PPPoE_session_input
DEBUGF DEBUG_NETWORK_ERROR, "ETH_input: Unknown packet type=%x\n", ax
DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_input: Unknown packet type=%x\n", ax
.dump:
DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_input: dumping\n"

View File

@ -310,15 +310,16 @@ ICMP_input:
ret
if 0
;-----------------------------------------------------------------
;
; ICMP_output
;
; IN: eax = dest ip
; ebx = source ip
; bh = type
; bl = code
; ecx = data length
; dh = type
; dl = code
; edx = source ip
; esi = data offset
; edi = identifier shl 16 + sequence number
;
@ -328,10 +329,7 @@ ICMP_output:
DEBUGF DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet\n"
push esi edi dx
mov edx, [eax + IP_SOCKET.LocalIP]
mov eax, [eax + IP_SOCKET.RemoteIP]
push esi edi bx
add ecx, sizeof.ICMP_header
mov di, IP_PROTO_ICMP SHL 8 + 128 ; TTL
call IPv4_output
@ -374,13 +372,14 @@ ICMP_output:
DEBUGF DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
add esp, 2*4 + 2
ret
end if
;-----------------------------------------------------------------
;
; ICMP_output
; ICMP_output_raw
;
; IN: eax = socket ptr
; ecx = data length

View File

@ -39,6 +39,7 @@ struct SOCKET
snd_proc dd ?
rcv_proc dd ?
connect_proc dd ?
ends
@ -131,6 +132,7 @@ struct TCP_SOCKET IP_SOCKET
timer_persist dd ?
timer_keepalive dd ? ; keepalive/syn timeout
timer_timed_wait dd ? ; also used as 2msl timer
timer_connect dd ?
; extra
@ -142,13 +144,13 @@ struct TCP_SOCKET IP_SOCKET
temp_bits db ?
rb 3 ; align
ends
struct UDP_SOCKET IP_SOCKET
LocalPort dw ? ; network byte order
RemotePort dw ? ; network byte order
firstpacket db ?
ends
@ -309,6 +311,7 @@ SOCKET_open:
mov [eax + SOCKET.Domain], ecx
mov [eax + SOCKET.Type], edx
mov [eax + SOCKET.Protocol], esi
mov [eax + SOCKET.connect_proc], connect_notsupp
cmp ecx, AF_INET4
jne .no_inet4
@ -357,6 +360,7 @@ align 4
mov [eax + SOCKET.Protocol], IP_PROTO_UDP
mov [eax + SOCKET.snd_proc], SOCKET_send_udp
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
mov [eax + SOCKET.connect_proc], UDP_connect
ret
align 4
@ -364,6 +368,7 @@ align 4
mov [eax + SOCKET.Protocol], IP_PROTO_TCP
mov [eax + SOCKET.snd_proc], SOCKET_send_tcp
mov [eax + SOCKET.rcv_proc], SOCKET_receive_stream
mov [eax + SOCKET.connect_proc], TCP_connect
TCP_init_socket eax
ret
@ -373,6 +378,7 @@ align 4
.raw_ip:
mov [eax + SOCKET.snd_proc], SOCKET_send_ip
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
mov [eax + SOCKET.connect_proc], IPv4_connect
ret
@ -380,6 +386,7 @@ align 4
.raw_icmp:
mov [eax + SOCKET.snd_proc], SOCKET_send_icmp
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
mov [eax + SOCKET.connect_proc], IPv4_connect
ret
align 4
@ -414,6 +421,9 @@ SOCKET_bind:
cmp esi, 2
jb .invalid
cmp [eax + UDP_SOCKET.LocalPort], 0 ; Socket can only be bound once
jnz .invalid
cmp word [edx], AF_INET4
je .af_inet4
@ -449,17 +459,21 @@ SOCKET_bind:
.tcp:
.udp:
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
@@:
mov [eax + IP_SOCKET.LocalIP], ebx
mov bx, [edx + 2] ; Now fill in the local port if it's still available
call SOCKET_check_port
jz .addrinuse ; ZF is set by socket_check_port, on error
pushd [edx + 4] ; First, fill in the IP
popd [eax + IP_SOCKET.LocalIP]
mov bx, [edx + 2] ; Did caller specify a local port?
test bx, bx
jnz .just_check
call SOCKET_find_port ; Nope, find an ephemeral one
jmp .done
.just_check:
call SOCKET_check_port ; Yes, check if it's still available
jz .addrinuse ; ZF is set by socket_check_port on error
.done:
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,\
[eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
@ -496,8 +510,18 @@ SOCKET_connect:
cmp esi, 8
jb .invalid
cmp word [edx], AF_INET4
je .af_inet4
cmp [eax + SOCKET.state], SS_ISCONNECTING
je .already
test [eax + SOCKET.options], SO_ACCEPTCON
jnz .notsupp
call [eax + SOCKET.connect_proc]
mov dword[esp+20], ebx
mov dword[esp+32], eax
ret
.notsupp:
mov dword[esp+20], EOPNOTSUPP
@ -509,150 +533,16 @@ SOCKET_connect:
mov dword[esp+32], -1
ret
.af_inet4:
cmp [eax + IP_SOCKET.LocalIP], 0
jne @f
push [IP_LIST + 4] ; FIXME !i!i!i!
pop [eax + IP_SOCKET.LocalIP]
@@:
cmp [eax + SOCKET.Protocol], IP_PROTO_UDP
je .udp
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
je .tcp
cmp [eax + SOCKET.Protocol], IP_PROTO_IP
je .ip
cmp [eax + SOCKET.Protocol], IP_PROTO_ICMP
je .ip
jmp .notsupp
align 4
.udp:
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
pushw [edx + 2]
pop [eax + UDP_SOCKET.RemotePort]
pushd [edx + 4]
pop [eax + IP_SOCKET.RemoteIP]
cmp [eax + UDP_SOCKET.LocalPort], 0
jne @f
call SOCKET_find_port
@@:
mov [eax + UDP_SOCKET.firstpacket], 0
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue
pop eax
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
mov dword[esp+32], 0
ret
align 4
.tcp:
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
pushw [edx + 2]
pop [eax + TCP_SOCKET.RemotePort]
pushd [edx + 4]
pop [eax + IP_SOCKET.RemoteIP]
cmp [eax + TCP_SOCKET.LocalPort], 0
jne @f
call SOCKET_find_port
@@:
mov [eax + TCP_SOCKET.timer_persist], 0
mov [eax + TCP_SOCKET.t_state], TCPS_SYN_SENT
push [TCP_sequence_num]
add [TCP_sequence_num], 6400
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 ; TODO: check if memory was available or not
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_create ; TODO: same here
pusha
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
popa
push ebx
mov eax, ebx
call TCP_output
pop eax
.block:
test [eax + SOCKET.options], SO_NONBLOCK
jz .loop
mov dword[esp+20], EWOULDBLOCK
.already:
mov dword[esp+20], EALREADY
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
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
pushd [edx + 4]
pop [eax + IP_SOCKET.RemoteIP]
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue
pop eax
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
mov dword[esp+32], 0
connect_notsupp:
xor eax, eax
dec eax
mov ebx, EOPNOTSUPP
ret
@ -865,15 +755,15 @@ SOCKET_receive:
call [eax + SOCKET.rcv_proc]
pop edi
test [eax + SOCKET.state], SS_CANTRCVMORE
jnz .return
cmp ebx, EWOULDBLOCK
jne .return
test edi, MSG_DONTWAIT
jnz .return_err
test [eax + SOCKET.state], SS_CANTRCVMORE
jnz .return_err
; test [eax + SOCKET.options], SO_NONBLOCK
; jnz .return_err
@ -885,10 +775,10 @@ SOCKET_receive:
push EINVAL
pop ebx
.return_err:
mov eax, -1
mov ecx, -1
.return:
mov [esp+20], ebx
mov [esp+32], eax
mov [esp+32], ecx
ret
@ -909,7 +799,7 @@ SOCKET_receive_dgram:
cmp ecx, ebx ; If data segment does not fit in applications buffer, abort
ja .too_small
push ecx
push eax ecx
push [esi + socket_queue_entry.buf_ptr] ; save the buffer addr so we can clear it later
mov esi, [esi + socket_queue_entry.data_ptr]
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
@ -930,12 +820,12 @@ SOCKET_receive_dgram:
.nd:
call NET_packet_free
pop eax ; return number of bytes copied to application
pop ecx eax ; return number of bytes copied to application
xor ebx, ebx
ret
.too_small:
mov eax, -1
mov ecx, -1
push EMSGSIZE
pop ebx
ret
@ -980,21 +870,23 @@ SOCKET_receive_stream:
mov edi, edx
xor edx, edx
push eax
add eax, STREAM_SOCKET.rcv
call SOCKET_ring_read ; copy data from kernel buffer to application buffer
call SOCKET_ring_free ; free read memory
pop eax
mov eax, ecx ; return number of bytes copied
xor ebx, ebx ; errorcode = 0 (no error)
ret
.wouldblock:
push EWOULDBLOCK
pop ebx
xor ecx, ecx
ret
.peek:
mov eax, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
mov ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
xor ebx, ebx
ret
@ -2193,6 +2085,7 @@ SOCKET_num_to_ptr:
mov eax, [eax + SOCKET.NextPtr]
or eax, eax
jz .error
diff16 "tetten", 0, $
cmp [eax + SOCKET.Number], ecx
jne .next_socket
@ -2321,6 +2214,11 @@ SOCKET_check_owner:
align 4
SOCKET_process_end:
cmp [net_sockets + SOCKET.NextPtr], 0 ; Are there any active sockets at all?
je .quickret ; nope, exit immediately
; TODO: run the following code in another thread, to avoid deadlock
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: %x\n", edx
pusha
@ -2371,6 +2269,7 @@ SOCKET_process_end:
call mutex_unlock
popa
.quickret:
ret
@ -2390,10 +2289,10 @@ SOCKET_is_connecting:
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_is_connecting: %x\n", eax
and [eax + SOCKET.options], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
or [eax + SOCKET.options], SS_ISCONNECTING
and [eax + SOCKET.state], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
or [eax + SOCKET.state], SS_ISCONNECTING
jmp SOCKET_notify
ret

View File

@ -115,6 +115,7 @@ MAX_backlog = 20 ; maximum backlog for stream sockets
; Error Codes
ENOBUFS = 1
EINPROGRESS = 2
EOPNOTSUPP = 4
EWOULDBLOCK = 6
ENOTCONN = 9
@ -125,6 +126,7 @@ ENOMEM = 18
EADDRINUSE = 20
ECONNREFUSED = 61
ECONNRESET = 52
EISCONN = 56
ETIMEDOUT = 60
ECONNABORTED = 53
@ -248,6 +250,8 @@ stack_init:
mov ecx, (NET_DEVICES_MAX + 2)
rep stosd
ETH_init
PPPoE_init
IPv4_init

View File

@ -71,6 +71,8 @@ TCP_time_rtt_default = 5 ; default Round Trip Time (3,2s)
TCP_time_srtt_default = 0 ;
TCP_time_max_idle = 8*TCP_time_keep_interval ; FIXME
TCP_time_connect = 300 ; in 1/100s (default=3s)
; timer constants
TCP_max_rxtshift = 12 ; max retransmissions waiting for ACK
TCP_max_keepcnt = 8 ; max keepalive probes

View File

@ -437,8 +437,6 @@ TCP_send:
; Create the IP packet
mov ecx, esi
mov ebx, [eax + SOCKET.device]
mov edx, [eax + IP_SOCKET.LocalIP] ; source ip
mov eax, [eax + IP_SOCKET.RemoteIP] ; dest ip
mov di, IP_PROTO_TCP shl 8 + 128

View File

@ -74,6 +74,137 @@ TCP_usrclosed:
ret
;-------------------------
;
; TCP_connect
;
; IN: eax = socket ptr
; OUT: eax = 0 ok / -1 error
; ebx = error code
;
;-------------------------
align 4
TCP_connect:
test [eax + SOCKET.state], SS_ISCONNECTED
jnz .eisconn
push eax edx
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
pop edx eax
; Fill in local IP
cmp [eax + IP_SOCKET.LocalIP], 0
jne @f
push [IP_LIST + 4] ; FIXME: use correct local IP
pop [eax + IP_SOCKET.LocalIP]
; Fill in remote port and IP
pushw [edx + 2]
pop [eax + TCP_SOCKET.RemotePort]
pushd [edx + 4]
pop [eax + IP_SOCKET.RemoteIP]
; Find a local port, if user didnt define one
cmp [eax + TCP_SOCKET.LocalPort], 0
jne @f
call SOCKET_find_port
@@:
; Start the TCP sequence
mov [eax + TCP_SOCKET.timer_persist], 0
mov [eax + TCP_SOCKET.t_state], TCPS_SYN_SENT
push [TCP_sequence_num]
add [TCP_sequence_num], 6400
pop [eax + TCP_SOCKET.ISS]
mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init
TCP_sendseqinit eax
mov ebx, eax
lea eax, [ebx + STREAM_SOCKET.snd]
call SOCKET_ring_create
test eax, eax
jz .nomem
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_create
test eax, eax
jz .nomem
push ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
pop eax
call SOCKET_is_connecting
; Now send the SYN packet to remote end
push eax
call TCP_output
pop eax
.block:
test [eax + SOCKET.options], SO_NONBLOCK
jz .waitforit
xor eax, eax
dec eax
mov ebx, EINPROGRESS
ret
.nomem:
xor eax, eax
dec eax
mov ebx, ENOMEM
ret
.eisconn:
xor eax, eax
dec eax
mov ebx, EISCONN
ret
.waitforit:
push eax
stdcall timer_hs, TCP_time_connect, 0, .timeout, eax
pop ebx
mov [ebx + TCP_SOCKET.timer_connect], eax
mov eax, ebx
.loop:
cmp [eax + SOCKET.errorcode], 0
jne .fail
cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
je .established
call SOCKET_block
jmp .loop
.timeout:
mov eax, [esp+4]
mov [eax + SOCKET.errorcode], ETIMEDOUT
and [eax + SOCKET.state], not SS_ISCONNECTING
call SOCKET_notify.unblock
ret 4
.fail:
mov ebx, [eax + SOCKET.errorcode]
mov [eax + SOCKET.errorcode], 0 ; Clear the error, we only need to send it to the caller once
xor eax, eax
dec eax
ret
.established:
stdcall cancel_timer_hs, [eax + TCP_SOCKET.timer_connect]
xor eax, eax
ret
;-------------------------

View File

@ -182,7 +182,7 @@ UDP_input:
;
; FIXME: UDP should check remote IP, but not under all circumstances!
cmp [eax + UDP_SOCKET.firstpacket], 0
cmp [eax + UDP_SOCKET.RemotePort], 0
je .updateport
cmp [eax + UDP_SOCKET.RemotePort], cx
@ -211,8 +211,6 @@ UDP_input:
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: new remote port=%x\n", cx ; FIXME: find a way to print big endian values with debugf
mov [eax + UDP_SOCKET.RemotePort], cx
inc [eax + UDP_SOCKET.firstpacket]
jmp .updatesock
.dump_:
@ -262,7 +260,6 @@ UDP_output:
sub esp, 8 ; Data ptr and data size will be placed here
push edx esi
mov ebx, [eax + SOCKET.device]
mov edx, [eax + IP_SOCKET.LocalIP]
mov eax, [eax + IP_SOCKET.RemoteIP]
mov di, IP_PROTO_UDP shl 8 + 128
@ -311,6 +308,84 @@ UDP_output:
;-----------------------------------------------------------------
;
; UDP_connect
;
; IN: eax = socket pointer
; OUT: eax = 0 ok / -1 error
; ebx = error code
;
;-------------------------
align 4
UDP_connect:
test [eax + SOCKET.state], SS_ISCONNECTED
jz @f
call UDP_disconnect
@@:
push eax edx
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
pop edx eax
; Fill in local IP
cmp [eax + IP_SOCKET.LocalIP], 0
jne @f
push [IP_LIST + 4] ; FIXME: use correct local IP
pop [eax + IP_SOCKET.LocalIP]
; Fill in remote port and IP, overwriting eventually previous values
pushw [edx + 2]
pop [eax + UDP_SOCKET.RemotePort]
pushd [edx + 4]
pop [eax + IP_SOCKET.RemoteIP]
; Find a local port, if user didnt define one
cmp [eax + UDP_SOCKET.LocalPort], 0
jne @f
call SOCKET_find_port
@@:
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue
pop eax
push eax
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
pop eax
call SOCKET_is_connected
xor eax, eax
ret
;-----------------------------------------------------------------
;
; UDP_disconnect
;
; IN: eax = socket pointer
; OUT: eax = socket pointer
;
;-------------------------
align 4
UDP_disconnect:
; TODO: remove the pending received data
call SOCKET_is_disconnected
ret
;---------------------------------------------------------------------------
;
; UDP_API