Subversion Repositories Kolibri OS

Compare Revisions

Ignore whitespace Rev 1241 → Rev 1249

/kernel/branches/net/kernel.asm
56,13 → 56,13
 
include 'macros.inc'
 
$Revision: 1025 $
$Revision$
 
 
USE_COM_IRQ equ 1 ; make irq 3 and irq 4 available for PCI devices
USE_COM_IRQ equ 1 ; make irq 3 and irq 4 available for PCI devices
 
; Enabling the next line will enable serial output console
;debug_com_base equ 0x3f8 ; 0x3f8 is com1, 0x2f8 is com2, 0x3e8 is com3, 0x2e8 is com4, no irq's are used
debug_com_base equ 0x3f8 ; 0x3f8 is com1, 0x2f8 is com2, 0x3e8 is com3, 0x2e8 is com4, no irq's are used
 
include "proc32.inc"
include "kglobals.inc"
69,14 → 69,14
lang fix en
 
include "const.inc"
max_processes equ 255
tss_step equ (128+8192) ; tss & i/o - 65535 ports, * 256=557056*4
max_processes equ 255
tss_step equ (128+8192) ; tss & i/o - 65535 ports, * 256=557056*4
 
 
os_stack equ (os_data_l-gdts) ; GDTs
os_stack equ (os_data_l-gdts) ; GDTs
os_code equ (os_code_l-gdts)
graph_data equ (3+graph_data_l-gdts)
tss0 equ (tss0_l-gdts)
tss0 equ (tss0_l-gdts)
app_code equ (3+app_code_l-gdts)
app_data equ (3+app_data_l-gdts)
pci_code_sel equ (pci_code_32-gdts)
114,8 → 114,8
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
use16
org 0x0
jmp start_of_code
org 0x0
jmp start_of_code
 
version db 'Kolibri OS version 0.7.5.0 ',13,10,13,10,0
 
126,10 → 126,10
include "boot/booteng.inc" ; english system boot messages
else if lang eq ru
include "boot/bootru.inc" ; russian system boot messages
include "boot/ru.inc" ; Russian font
include "boot/ru.inc" ; Russian font
else if lang eq et
include "boot/bootet.inc" ; estonian system boot messages
include "boot/et.inc" ; Estonian font
include "boot/et.inc" ; Estonian font
else
include "boot/bootge.inc" ; german system boot messages
end if
147,58 → 147,58
 
; CR0 Flags - Protected mode and Paging
 
mov ecx, CR0_PE
mov ecx, CR0_PE
 
; Enabling 32 bit protected mode
 
sidt [cs:old_ints_h]
sidt [cs:old_ints_h]
 
cli ; disable all irqs
cld
mov al,255 ; mask all irqs
out 0xa1,al
out 0x21,al
l.5: in al, 0x64 ; Enable A20
test al, 2
jnz l.5
mov al, 0xD1
out 0x64, al
l.6: in al, 0x64
test al, 2
jnz l.6
mov al, 0xDF
out 0x60, al
l.7: in al, 0x64
test al, 2
jnz l.7
mov al, 0xFF
out 0x64, al
cli ; disable all irqs
cld
mov al,255 ; mask all irqs
out 0xa1,al
out 0x21,al
l.5: in al, 0x64 ; Enable A20
test al, 2
jnz l.5
mov al, 0xD1
out 0x64, al
l.6: in al, 0x64
test al, 2
jnz l.6
mov al, 0xDF
out 0x60, al
l.7: in al, 0x64
test al, 2
jnz l.7
mov al, 0xFF
out 0x64, al
 
lgdt [cs:tmp_gdt] ; Load GDT
mov eax, cr0 ; protected mode
or eax, ecx
and eax, 10011111b *65536*256 + 0xffffff ; caching enabled
mov cr0, eax
jmp pword os_code:B32 ; jmp to enable 32 bit mode
lgdt [cs:tmp_gdt] ; Load GDT
mov eax, cr0 ; protected mode
or eax, ecx
and eax, 10011111b *65536*256 + 0xffffff ; caching enabled
mov cr0, eax
jmp pword os_code:B32 ; jmp to enable 32 bit mode
 
align 8
tmp_gdt:
 
dw 23
dd tmp_gdt+0x10000
dw 0
dw 23
dd tmp_gdt+0x10000
dw 0
 
dw 0xffff
dw 0x0000
db 0x00
dw 11011111b *256 +10011010b
db 0x00
dw 0xffff
dw 0x0000
db 0x00
dw 11011111b *256 +10011010b
db 0x00
 
dw 0xffff
dw 0x0000
db 0x00
dw 11011111b *256 +10010010b
db 0x00
dw 0xffff
dw 0x0000
db 0x00
dw 11011111b *256 +10010010b
db 0x00
 
include "data16.inc"
 
207,65 → 207,65
 
align 4
B32:
mov ax,os_stack ; Selector for os
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
mov esp,0x3ec00 ; Set stack
mov ax,os_stack ; Selector for os
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
mov esp,0x3ec00 ; Set stack
 
; CLEAR 0x280000 - HEAP_BASE
 
xor eax,eax
mov edi,0x280000
mov ecx,(HEAP_BASE-OS_BASE-0x280000) / 4
cld
rep stosd
xor eax,eax
mov edi,0x280000
mov ecx,(HEAP_BASE-OS_BASE-0x280000) / 4
cld
rep stosd
 
mov edi,0x40000
mov ecx,(0x90000-0x40000)/4
rep stosd
mov edi,0x40000
mov ecx,(0x90000-0x40000)/4
rep stosd
 
; CLEAR KERNEL UNDEFINED GLOBALS
mov edi, endofcode-OS_BASE
mov ecx, (uglobals_size/4)+4
rep stosd
mov edi, endofcode-OS_BASE
mov ecx, (uglobals_size/4)+4
rep stosd
 
; SAVE & CLEAR 0-0xffff
 
xor esi, esi
mov edi,0x2F0000
mov ecx,0x10000 / 4
rep movsd
mov edi,0x1000
mov ecx,0xf000 / 4
rep stosd
xor esi, esi
mov edi,0x2F0000
mov ecx,0x10000 / 4
rep movsd
mov edi,0x1000
mov ecx,0xf000 / 4
rep stosd
 
call test_cpu
bts [cpu_caps-OS_BASE], CAPS_TSC ;force use rdtsc
call test_cpu
bts [cpu_caps-OS_BASE], CAPS_TSC ;force use rdtsc
 
call init_BIOS32
call init_BIOS32
; MEMORY MODEL
call mem_test
call init_mem
call init_page_map
call mem_test
call init_mem
call init_page_map
 
; ENABLE PAGING
 
mov eax, sys_pgdir-OS_BASE
mov cr3, eax
mov eax, sys_pgdir-OS_BASE
mov cr3, eax
 
mov eax,cr0
or eax,CR0_PG+CR0_WP
mov cr0,eax
mov eax,cr0
or eax,CR0_PG+CR0_WP
mov cr0,eax
 
lgdt [gdts]
jmp pword os_code:high_code
lgdt [gdts]
jmp pword os_code:high_code
 
align 4
bios32_entry dd ?
tmp_page_tabs dd ?
bios32_entry dd ?
tmp_page_tabs dd ?
 
use16
org $-0x10000
281,45 → 281,45
 
align 4
high_code:
mov ax,os_stack
mov bx,app_data
mov ss,ax
add esp, OS_BASE
mov ax,os_stack
mov bx,app_data
mov ss,ax
add esp, OS_BASE
 
mov ds,bx
mov es,bx
mov fs,bx
mov gs,bx
mov ds,bx
mov es,bx
mov fs,bx
mov gs,bx
 
bt [cpu_caps], CAPS_PGE
jnc @F
bt [cpu_caps], CAPS_PGE
jnc @F
 
or dword [sys_pgdir+(OS_BASE shr 20)], PG_GLOBAL
or dword [sys_pgdir+(OS_BASE shr 20)], PG_GLOBAL
 
mov ebx, cr4
or ebx, CR4_PGE
mov cr4, ebx
mov ebx, cr4
or ebx, CR4_PGE
mov cr4, ebx
@@:
xor eax, eax
mov dword [sys_pgdir], eax
mov dword [sys_pgdir+4], eax
xor eax, eax
mov dword [sys_pgdir], eax
mov dword [sys_pgdir+4], eax
 
mov eax, cr3
mov cr3, eax ; flush TLB
mov eax, cr3
mov cr3, eax ; flush TLB
 
; SAVE REAL MODE VARIABLES
mov ax, [BOOT_VAR + 0x9031]
mov [IDEContrRegsBaseAddr], ax
mov ax, [BOOT_VAR + 0x9031]
mov [IDEContrRegsBaseAddr], ax
; --------------- APM ---------------------
 
; init selectors
mov ebx, [BOOT_VAR+0x9040] ; offset of APM entry point
mov ebx, [BOOT_VAR+0x9040] ; offset of APM entry point
movzx eax, word [BOOT_VAR+0x9050] ; real-mode segment base address of
; protected-mode 32-bit code segment
; protected-mode 32-bit code segment
movzx ecx, word [BOOT_VAR+0x9052] ; real-mode segment base address of
; protected-mode 16-bit code segment
; protected-mode 16-bit code segment
movzx edx, word [BOOT_VAR+0x9054] ; real-mode segment base address of
; protected-mode 16-bit data segment
; protected-mode 16-bit data segment
 
shl eax, 4
mov [dword apm_code_32 + 2], ax
344,240 → 344,240
; -----------------------------------------
; movzx eax,byte [BOOT_VAR+0x9010] ; mouse port
; mov [0xF604],byte 1 ;al
mov al, [BOOT_VAR+0x901F] ; DMA access
mov [allow_dma_access], al
mov al,[BOOT_VAR+0x9000] ; bpp
mov [ScreenBPP],al
mov al, [BOOT_VAR+0x901F] ; DMA access
mov [allow_dma_access], al
mov al,[BOOT_VAR+0x9000] ; bpp
mov [ScreenBPP],al
 
movzx eax,word [BOOT_VAR+0x900A] ; X max
dec eax
mov [Screen_Max_X],eax
mov [screen_workarea.right],eax
movzx eax,word [BOOT_VAR+0x900C] ; Y max
dec eax
mov [Screen_Max_Y],eax
mov [screen_workarea.bottom],eax
movzx eax,word [BOOT_VAR+0x9008] ; screen mode
mov [SCR_MODE],eax
mov eax,[BOOT_VAR+0x9014] ; Vesa 1.2 bnk sw add
mov [BANK_SWITCH],eax
mov [BytesPerScanLine],word 640*4 ; Bytes PerScanLine
cmp [SCR_MODE],word 0x13 ; 320x200
je @f
cmp [SCR_MODE],word 0x12 ; VGA 640x480
je @f
mov ax,[BOOT_VAR+0x9001] ; for other modes
mov [BytesPerScanLine],ax
movzx eax,word [BOOT_VAR+0x900A] ; X max
dec eax
mov [Screen_Max_X],eax
mov [screen_workarea.right],eax
movzx eax,word [BOOT_VAR+0x900C] ; Y max
dec eax
mov [Screen_Max_Y],eax
mov [screen_workarea.bottom],eax
movzx eax,word [BOOT_VAR+0x9008] ; screen mode
mov [SCR_MODE],eax
mov eax,[BOOT_VAR+0x9014] ; Vesa 1.2 bnk sw add
mov [BANK_SWITCH],eax
mov [BytesPerScanLine],word 640*4 ; Bytes PerScanLine
cmp [SCR_MODE],word 0x13 ; 320x200
je @f
cmp [SCR_MODE],word 0x12 ; VGA 640x480
je @f
mov ax,[BOOT_VAR+0x9001] ; for other modes
mov [BytesPerScanLine],ax
@@:
mov esi, BOOT_VAR+0x9080
movzx ecx, byte [esi-1]
mov [NumBiosDisks], ecx
mov edi, BiosDisksData
rep movsd
mov esi, BOOT_VAR+0x9080
movzx ecx, byte [esi-1]
mov [NumBiosDisks], ecx
mov edi, BiosDisksData
rep movsd
 
; GRAPHICS ADDRESSES
 
mov byte [BOOT_VAR+0x901e],0x0
mov eax,[BOOT_VAR+0x9018]
mov [LFBAddress],eax
mov byte [BOOT_VAR+0x901e],0x0
mov eax,[BOOT_VAR+0x9018]
mov [LFBAddress],eax
 
cmp [SCR_MODE],word 0100000000000000b
jge setvesa20
cmp [SCR_MODE],word 0x13
je v20ga32
mov [PUTPIXEL],dword Vesa12_putpixel24 ; Vesa 1.2
mov [GETPIXEL],dword Vesa12_getpixel24
cmp [ScreenBPP],byte 24
jz ga24
mov [PUTPIXEL],dword Vesa12_putpixel32
mov [GETPIXEL],dword Vesa12_getpixel32
cmp [SCR_MODE],word 0100000000000000b
jge setvesa20
cmp [SCR_MODE],word 0x13
je v20ga32
mov [PUTPIXEL],dword Vesa12_putpixel24 ; Vesa 1.2
mov [GETPIXEL],dword Vesa12_getpixel24
cmp [ScreenBPP],byte 24
jz ga24
mov [PUTPIXEL],dword Vesa12_putpixel32
mov [GETPIXEL],dword Vesa12_getpixel32
ga24:
jmp v20ga24
jmp v20ga24
setvesa20:
mov [PUTPIXEL],dword Vesa20_putpixel24 ; Vesa 2.0
mov [GETPIXEL],dword Vesa20_getpixel24
cmp [ScreenBPP],byte 24
jz v20ga24
mov [PUTPIXEL],dword Vesa20_putpixel24 ; Vesa 2.0
mov [GETPIXEL],dword Vesa20_getpixel24
cmp [ScreenBPP],byte 24
jz v20ga24
v20ga32:
mov [PUTPIXEL],dword Vesa20_putpixel32
mov [GETPIXEL],dword Vesa20_getpixel32
mov [PUTPIXEL],dword Vesa20_putpixel32
mov [GETPIXEL],dword Vesa20_getpixel32
v20ga24:
cmp [SCR_MODE],word 0x12 ; 16 C VGA 640x480
jne no_mode_0x12
mov [PUTPIXEL],dword VGA_putpixel
mov [GETPIXEL],dword Vesa20_getpixel32
cmp [SCR_MODE],word 0x12 ; 16 C VGA 640x480
jne no_mode_0x12
mov [PUTPIXEL],dword VGA_putpixel
mov [GETPIXEL],dword Vesa20_getpixel32
no_mode_0x12:
 
; -------- Fast System Call init ----------
; Intel SYSENTER/SYSEXIT (AMD CPU support it too)
bt [cpu_caps], CAPS_SEP
jnc .SEnP ; SysEnter not Present
xor edx, edx
mov ecx, MSR_SYSENTER_CS
mov eax, os_code
wrmsr
mov ecx, MSR_SYSENTER_ESP
bt [cpu_caps], CAPS_SEP
jnc .SEnP ; SysEnter not Present
xor edx, edx
mov ecx, MSR_SYSENTER_CS
mov eax, os_code
wrmsr
mov ecx, MSR_SYSENTER_ESP
; mov eax, sysenter_stack ; Check it
xor eax, eax
wrmsr
mov ecx, MSR_SYSENTER_EIP
mov eax, sysenter_entry
wrmsr
xor eax, eax
wrmsr
mov ecx, MSR_SYSENTER_EIP
mov eax, sysenter_entry
wrmsr
.SEnP:
; AMD SYSCALL/SYSRET
cmp byte[cpu_vendor], 'A'
jne .noSYSCALL
mov eax, 0x80000001
cpuid
test edx, 0x800 ; bit_11 - SYSCALL/SYSRET support
jz .noSYSCALL
mov ecx, MSR_AMD_EFER
rdmsr
or eax, 1 ; bit_0 - System Call Extension (SCE)
wrmsr
cmp byte[cpu_vendor], 'A'
jne .noSYSCALL
mov eax, 0x80000001
cpuid
test edx, 0x800 ; bit_11 - SYSCALL/SYSRET support
jz .noSYSCALL
mov ecx, MSR_AMD_EFER
rdmsr
or eax, 1 ; bit_0 - System Call Extension (SCE)
wrmsr
 
; !!!! It`s dirty hack, fix it !!!
; Bits of EDX :
; Bit 31–16 During the SYSRET instruction, this field is copied into the CS register
; and the contents of this field, plus 8, are copied into the SS register.
; Bit 15–0 During the SYSCALL instruction, this field is copied into the CS register
; and the contents of this field, plus 8, are copied into the SS register.
; !!!! It`s dirty hack, fix it !!!
; Bits of EDX :
; Bit 31–16 During the SYSRET instruction, this field is copied into the CS register
; and the contents of this field, plus 8, are copied into the SS register.
; Bit 15–0 During the SYSCALL instruction, this field is copied into the CS register
; and the contents of this field, plus 8, are copied into the SS register.
 
; mov edx, (os_code + 16) * 65536 + os_code
mov edx, 0x1B0008
; mov edx, (os_code + 16) * 65536 + os_code
mov edx, 0x1B0008
 
mov eax, syscall_entry
mov ecx, MSR_AMD_STAR
wrmsr
mov eax, syscall_entry
mov ecx, MSR_AMD_STAR
wrmsr
.noSYSCALL:
; -----------------------------------------
 
; LOAD IDT
 
call build_interrupt_table ;lidt is executed
;lidt [idtreg]
call build_interrupt_table ;lidt is executed
;lidt [idtreg]
 
call init_kernel_heap
stdcall kernel_alloc, RING0_STACK_SIZE+512
mov [os_stack_seg], eax
call init_kernel_heap
stdcall kernel_alloc, RING0_STACK_SIZE+512
mov [os_stack_seg], eax
 
lea esp, [eax+RING0_STACK_SIZE]
lea esp, [eax+RING0_STACK_SIZE]
 
mov [tss._ss0], os_stack
mov [tss._esp0], esp
mov [tss._esp], esp
mov [tss._cs],os_code
mov [tss._ss],os_stack
mov [tss._ds],app_data
mov [tss._es],app_data
mov [tss._fs],app_data
mov [tss._gs],app_data
mov [tss._io],128
mov [tss._ss0], os_stack
mov [tss._esp0], esp
mov [tss._esp], esp
mov [tss._cs],os_code
mov [tss._ss],os_stack
mov [tss._ds],app_data
mov [tss._es],app_data
mov [tss._fs],app_data
mov [tss._gs],app_data
mov [tss._io],128
;Add IO access table - bit array of permitted ports
mov edi, tss._io_map_0
xor eax, eax
not eax
mov ecx, 8192/4
rep stosd ; access to 4096*8=65536 ports
mov edi, tss._io_map_0
xor eax, eax
not eax
mov ecx, 8192/4
rep stosd ; access to 4096*8=65536 ports
 
mov ax,tss0
ltr ax
mov ax,tss0
ltr ax
 
mov [LFBSize], 0x800000
call init_LFB
call init_fpu
call init_malloc
mov [LFBSize], 0x800000
call init_LFB
call init_fpu
call init_malloc
 
stdcall alloc_kernel_space, 0x51000
mov [default_io_map], eax
stdcall alloc_kernel_space, 0x51000
mov [default_io_map], eax
 
add eax, 0x2000
mov [ipc_tmp], eax
mov ebx, 0x1000
add eax, 0x2000
mov [ipc_tmp], eax
mov ebx, 0x1000
 
add eax, 0x40000
mov [proc_mem_map], eax
add eax, 0x40000
mov [proc_mem_map], eax
 
add eax, 0x8000
mov [proc_mem_pdir], eax
add eax, 0x8000
mov [proc_mem_pdir], eax
 
add eax, ebx
mov [proc_mem_tab], eax
add eax, ebx
mov [proc_mem_tab], eax
 
add eax, ebx
mov [tmp_task_pdir], eax
add eax, ebx
mov [tmp_task_pdir], eax
 
add eax, ebx
mov [tmp_task_ptab], eax
add eax, ebx
mov [tmp_task_ptab], eax
 
add eax, ebx
mov [ipc_pdir], eax
add eax, ebx
mov [ipc_pdir], eax
 
add eax, ebx
mov [ipc_ptab], eax
add eax, ebx
mov [ipc_ptab], eax
 
stdcall kernel_alloc, (unpack.LZMA_BASE_SIZE+(unpack.LZMA_LIT_SIZE shl \
(unpack.lc+unpack.lp)))*4
stdcall kernel_alloc, (unpack.LZMA_BASE_SIZE+(unpack.LZMA_LIT_SIZE shl \
(unpack.lc+unpack.lp)))*4
 
mov [unpack.p], eax
mov [unpack.p], eax
 
call init_events
mov eax, srv.fd-SRV_FD_OFFSET
mov [srv.fd], eax
mov [srv.bk], eax
call init_events
mov eax, srv.fd-SRV_FD_OFFSET
mov [srv.fd], eax
mov [srv.bk], eax
 
mov edi, irq_tab
xor eax, eax
mov ecx, 16
rep stosd
mov edi, irq_tab
xor eax, eax
mov ecx, 16
rep stosd
 
;Set base of graphic segment to linear address of LFB
mov eax,[LFBAddress] ; set for gs
mov [graph_data_l+2],ax
shr eax,16
mov [graph_data_l+4],al
mov [graph_data_l+7],ah
mov eax,[LFBAddress] ; set for gs
mov [graph_data_l+2],ax
shr eax,16
mov [graph_data_l+4],al
mov [graph_data_l+7],ah
 
mov [CURRENT_TASK],dword 1
mov [TASK_COUNT],dword 1
mov [TASK_BASE],dword TASK_DATA
mov [current_slot], SLOT_BASE+256
mov [CURRENT_TASK],dword 1
mov [TASK_COUNT],dword 1
mov [TASK_BASE],dword TASK_DATA
mov [current_slot], SLOT_BASE+256
 
; set background
xor eax,eax
inc eax
mov [BgrDrawMode],eax
mov [BgrDataWidth],eax
mov [BgrDataHeight],eax
mov [mem_BACKGROUND], 4
mov [img_background], static_background_data
xor eax,eax
inc eax
mov [BgrDrawMode],eax
mov [BgrDataWidth],eax
mov [BgrDataHeight],eax
mov [mem_BACKGROUND], 4
mov [img_background], static_background_data
 
mov [SLOT_BASE + 256 + APPDATA.dir_table], sys_pgdir - OS_BASE
mov [SLOT_BASE + 256 + APPDATA.dir_table], sys_pgdir - OS_BASE
 
; REDIRECT ALL IRQ'S TO INT'S 0x20-0x2f
 
call rerouteirqs
call rerouteirqs
 
; Initialize system V86 machine
call init_sys_v86
call init_sys_v86
 
; TIMER SET TO 1/100 S
 
mov al,0x34 ; set to 100Hz
out 0x43,al
mov al,0x9b ; lsb 1193180 / 1193
out 0x40,al
mov al,0x2e ; msb
out 0x40,al
mov al,0x34 ; set to 100Hz
out 0x43,al
mov al,0x9b ; lsb 1193180 / 1193
out 0x40,al
mov al,0x2e ; msb
out 0x40,al
 
; Enable timer IRQ (IRQ0) and hard drives IRQs (IRQ14, IRQ15)
; they are used: when partitions are scanned, hd_read relies on timer
; Also enable IRQ2, because in some configurations
; IRQs from slave controller are not delivered until IRQ2 on master is enabled
mov al, 0xFA
out 0x21, al
mov al, 0x3F
out 0xA1, al
mov al, 0xFA
out 0x21, al
mov al, 0x3F
out 0xA1, al
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!
include 'detect/disks.inc'
593,7 → 593,7
; mov [dma_hdd],1
; CALCULATE FAT CHAIN FOR RAMDISK
 
call calculatefatchain
call calculatefatchain
 
; LOAD VMODE DRIVER
 
602,254 → 602,254
;!!!!!!!!!!!!!!!!!!!!!!!
 
mov ax,[OS_BASE+0x10000+bx_from_load]
cmp ax,'r1' ; if using not ram disk, then load librares and parameters {SPraid.simba}
cmp ax,'r1' ; if using not ram disk, then load librares and parameters {SPraid.simba}
je no_lib_load
; LOADING LIBRARES
stdcall dll.Load,@IMPORT ; loading librares for kernel (.obj files)
call load_file_parse_table ; prepare file parse table
call set_kernel_conf ; configure devices and gui
stdcall dll.Load,@IMPORT ; loading librares for kernel (.obj files)
call load_file_parse_table ; prepare file parse table
call set_kernel_conf ; configure devices and gui
no_lib_load:
 
; LOAD FONTS I and II
 
stdcall read_file, char, FONT_I, 0, 2304
stdcall read_file, char2, FONT_II, 0, 2560
stdcall read_file, char, FONT_I, 0, 2304
stdcall read_file, char2, FONT_II, 0, 2560
 
mov esi,boot_fonts
call boot_log
mov esi,boot_fonts
call boot_log
 
; PRINT AMOUNT OF MEMORY
mov esi, boot_memdetect
call boot_log
mov esi, boot_memdetect
call boot_log
 
movzx ecx, word [boot_y]
or ecx, (10+29*6) shl 16 ; "Determining amount of memory"
sub ecx, 10
mov edx, 0xFFFFFF
mov ebx, [MEM_AMOUNT]
shr ebx, 20
mov edi, 1
mov eax, 0x00040000
call display_number_force
movzx ecx, word [boot_y]
or ecx, (10+29*6) shl 16 ; "Determining amount of memory"
sub ecx, 10
mov edx, 0xFFFFFF
mov ebx, [MEM_AMOUNT]
shr ebx, 20
mov edi, 1
mov eax, 0x00040000
call display_number_force
 
; BUILD SCHEDULER
 
call build_scheduler ; sys32.inc
call build_scheduler ; sys32.inc
 
mov esi,boot_devices
call boot_log
mov esi,boot_devices
call boot_log
 
mov [pci_access_enabled],1
mov [pci_access_enabled],1
 
 
; SET PRELIMINARY WINDOW STACK AND POSITIONS
 
mov esi,boot_windefs
call boot_log
call setwindowdefaults
mov esi,boot_windefs
call boot_log
call setwindowdefaults
 
; SET BACKGROUND DEFAULTS
 
mov esi,boot_bgr
call boot_log
call init_background
call calculatebackground
mov esi,boot_bgr
call boot_log
call init_background
call calculatebackground
 
; RESERVE SYSTEM IRQ'S JA PORT'S
 
mov esi,boot_resirqports
call boot_log
call reserve_irqs_ports
mov esi,boot_resirqports
call boot_log
call reserve_irqs_ports
 
; SET PORTS FOR IRQ HANDLERS
 
mov esi,boot_setrports
call boot_log
;call setirqreadports
mov esi,boot_setrports
call boot_log
;call setirqreadports
 
; SET UP OS TASK
 
mov esi,boot_setostask
call boot_log
mov esi,boot_setostask
call boot_log
 
xor eax, eax
mov dword [SLOT_BASE+APPDATA.fpu_state], fpu_data
mov dword [SLOT_BASE+APPDATA.exc_handler], eax
mov dword [SLOT_BASE+APPDATA.except_mask], eax
xor eax, eax
mov dword [SLOT_BASE+APPDATA.fpu_state], fpu_data
mov dword [SLOT_BASE+APPDATA.exc_handler], eax
mov dword [SLOT_BASE+APPDATA.except_mask], eax
 
; name for OS/IDLE process
; name for OS/IDLE process
 
mov dword [SLOT_BASE+256+APPDATA.app_name], dword 'OS/I'
mov dword [SLOT_BASE+256+APPDATA.app_name+4], dword 'DLE '
mov edi, [os_stack_seg]
mov dword [SLOT_BASE+256+APPDATA.pl0_stack], edi
add edi, 0x2000-512
mov dword [SLOT_BASE+256+APPDATA.fpu_state], edi
mov dword [SLOT_BASE+256+APPDATA.saved_esp0], edi ; just for case
mov dword [SLOT_BASE+256+APPDATA.io_map],\
(tss._io_map_0-OS_BASE+PG_MAP)
mov dword [SLOT_BASE+256+APPDATA.io_map+4],\
(tss._io_map_1-OS_BASE+PG_MAP)
mov dword [SLOT_BASE+256+APPDATA.app_name], dword 'OS/I'
mov dword [SLOT_BASE+256+APPDATA.app_name+4], dword 'DLE '
mov edi, [os_stack_seg]
mov dword [SLOT_BASE+256+APPDATA.pl0_stack], edi
add edi, 0x2000-512
mov dword [SLOT_BASE+256+APPDATA.fpu_state], edi
mov dword [SLOT_BASE+256+APPDATA.saved_esp0], edi ; just for case
mov dword [SLOT_BASE+256+APPDATA.io_map],\
(tss._io_map_0-OS_BASE+PG_MAP)
mov dword [SLOT_BASE+256+APPDATA.io_map+4],\
(tss._io_map_1-OS_BASE+PG_MAP)
 
mov esi, fpu_data
mov ecx, 512/4
cld
rep movsd
mov esi, fpu_data
mov ecx, 512/4
cld
rep movsd
 
mov dword [SLOT_BASE+256+APPDATA.exc_handler], eax
mov dword [SLOT_BASE+256+APPDATA.except_mask], eax
mov dword [SLOT_BASE+256+APPDATA.exc_handler], eax
mov dword [SLOT_BASE+256+APPDATA.except_mask], eax
 
mov ebx, SLOT_BASE+256+APP_OBJ_OFFSET
mov dword [SLOT_BASE+256+APPDATA.fd_obj], ebx
mov dword [SLOT_BASE+256+APPDATA.bk_obj], ebx
mov ebx, SLOT_BASE+256+APP_OBJ_OFFSET
mov dword [SLOT_BASE+256+APPDATA.fd_obj], ebx
mov dword [SLOT_BASE+256+APPDATA.bk_obj], ebx
 
mov dword [SLOT_BASE+256+APPDATA.cur_dir], sysdir_path
mov dword [SLOT_BASE+256+APPDATA.cur_dir], sysdir_path
 
; task list
mov [CURRENT_TASK],dword 1
mov [TASK_COUNT],dword 1
mov [current_slot], SLOT_BASE+256
mov [TASK_BASE],dword TASK_DATA
mov [TASK_DATA+TASKDATA.wnd_number], 1 ; on screen number
mov [TASK_DATA+TASKDATA.pid], 1 ; process id number
mov [TASK_DATA+TASKDATA.mem_start], 0 ; process base address
; task list
mov [CURRENT_TASK],dword 1
mov [TASK_COUNT],dword 1
mov [current_slot], SLOT_BASE+256
mov [TASK_BASE],dword TASK_DATA
mov [TASK_DATA+TASKDATA.wnd_number], 1 ; on screen number
mov [TASK_DATA+TASKDATA.pid], 1 ; process id number
mov [TASK_DATA+TASKDATA.mem_start], 0 ; process base address
 
call init_cursors
call init_cursors
mov eax, [def_cursor]
mov [SLOT_BASE+APPDATA.cursor],eax
mov [SLOT_BASE+APPDATA.cursor+256],eax
mov [SLOT_BASE+APPDATA.cursor],eax
mov [SLOT_BASE+APPDATA.cursor+256],eax
 
; READ TSC / SECOND
 
mov esi,boot_tsc
call boot_log
cli
rdtsc ;call _rdtsc
mov ecx,eax
mov esi,250 ; wait 1/4 a second
call delay_ms
rdtsc ;call _rdtsc
sti
sub eax,ecx
shl eax,2
mov [CPU_FREQ],eax ; save tsc / sec
mov esi,boot_tsc
call boot_log
cli
rdtsc ;call _rdtsc
mov ecx,eax
mov esi,250 ; wait 1/4 a second
call delay_ms
rdtsc ;call _rdtsc
sti
sub eax,ecx
shl eax,2
mov [CPU_FREQ],eax ; save tsc / sec
; mov ebx, 1000000
; div ebx
; ¢®®¡é¥-â® ¯à®¨§¢®¤¨â¥«ì­®áâì ¢ ¤ ­­®¬ ª®­ªà¥â­®¬ ¬¥áâ¥
; ᮢ¥à襭­® ­¥ªà¨â¨ç­ , ­® çâ®¡ë § âª­ãâì «î¡¨â¥«¥©
; ®¯â¨¬¨§¨àãîé¨å ª®¬¯¨«ïâ®à®¢ Ÿ‚“...
mov edx, 2251799814
mul edx
shr edx, 19
mov [stall_mcs], edx
mov edx, 2251799814
mul edx
shr edx, 19
mov [stall_mcs], edx
; PRINT CPU FREQUENCY
mov esi, boot_cpufreq
call boot_log
mov esi, boot_cpufreq
call boot_log
 
mov ebx, edx
movzx ecx, word [boot_y]
add ecx, (10+17*6) shl 16 - 10 ; 'CPU frequency is '
mov edx, 0xFFFFFF
mov edi, 1
mov eax, 0x00040000
call display_number_force
mov ebx, edx
movzx ecx, word [boot_y]
add ecx, (10+17*6) shl 16 - 10 ; 'CPU frequency is '
mov edx, 0xFFFFFF
mov edi, 1
mov eax, 0x00040000
call display_number_force
 
; SET VARIABLES
 
call set_variables
call set_variables
 
; SET MOUSE
 
;call detect_devices
stdcall load_driver, szPS2MDriver
;call detect_devices
stdcall load_driver, szPS2MDriver
; stdcall load_driver, szCOM_MDriver
 
mov esi,boot_setmouse
call boot_log
call setmouse
mov esi,boot_setmouse
call boot_log
call setmouse
 
 
; STACK AND FDC
 
call stack_init
call fdc_init
call stack_init
call fdc_init
 
; PALETTE FOR 320x200 and 640x480 16 col
 
cmp [SCR_MODE],word 0x12
jne no_pal_vga
mov esi,boot_pal_vga
call boot_log
call paletteVGA
cmp [SCR_MODE],word 0x12
jne no_pal_vga
mov esi,boot_pal_vga
call boot_log
call paletteVGA
no_pal_vga:
 
cmp [SCR_MODE],word 0x13
jne no_pal_ega
mov esi,boot_pal_ega
call boot_log
call palette320x200
cmp [SCR_MODE],word 0x13
jne no_pal_ega
mov esi,boot_pal_ega
call boot_log
call palette320x200
no_pal_ega:
 
; LOAD DEFAULT SKIN
 
call load_default_skin
call load_default_skin
 
;protect io permission map
 
mov esi, [default_io_map]
stdcall map_page,esi,(tss._io_map_0-OS_BASE), PG_MAP
add esi, 0x1000
stdcall map_page,esi,(tss._io_map_1-OS_BASE), PG_MAP
mov esi, [default_io_map]
stdcall map_page,esi,(tss._io_map_0-OS_BASE), PG_MAP
add esi, 0x1000
stdcall map_page,esi,(tss._io_map_1-OS_BASE), PG_MAP
 
stdcall map_page,tss._io_map_0,\
(tss._io_map_0-OS_BASE), PG_MAP
stdcall map_page,tss._io_map_1,\
(tss._io_map_1-OS_BASE), PG_MAP
stdcall map_page,tss._io_map_0,\
(tss._io_map_0-OS_BASE), PG_MAP
stdcall map_page,tss._io_map_1,\
(tss._io_map_1-OS_BASE), PG_MAP
 
 
; LOAD FIRST APPLICATION
cli
cli
 
cmp byte [BOOT_VAR+0x9030],1
jne no_load_vrr_m
cmp byte [BOOT_VAR+0x9030],1
jne no_load_vrr_m
 
mov ebp, vrr_m
call fs_execute_from_sysdir
mov ebp, vrr_m
call fs_execute_from_sysdir
 
cmp eax,2 ; if vrr_m app found (PID=2)
je first_app_found
cmp eax,2 ; if vrr_m app found (PID=2)
je first_app_found
 
no_load_vrr_m:
 
mov ebp, firstapp
call fs_execute_from_sysdir
mov ebp, firstapp
call fs_execute_from_sysdir
 
cmp eax,2 ; continue if a process has been loaded
je first_app_found
cmp eax,2 ; continue if a process has been loaded
je first_app_found
 
mov esi, boot_failed
call boot_log
mov esi, boot_failed
call boot_log
 
mov eax, 0xDEADBEEF ; otherwise halt
hlt
mov eax, 0xDEADBEEF ; otherwise halt
hlt
 
first_app_found:
 
cli
cli
 
;mov [TASK_COUNT],dword 2
mov [CURRENT_TASK],dword 1 ; set OS task fisrt
;mov [TASK_COUNT],dword 2
mov [CURRENT_TASK],dword 1 ; set OS task fisrt
 
; SET KEYBOARD PARAMETERS
mov al, 0xf6 ; reset keyboard, scan enabled
call kb_write
mov al, 0xf6 ; reset keyboard, scan enabled
call kb_write
 
; wait until 8042 is ready
xor ecx,ecx
; wait until 8042 is ready
xor ecx,ecx
@@:
in al,64h
and al,00000010b
loopnz @b
in al,64h
and al,00000010b
loopnz @b
 
; mov al, 0xED ; svetodiody - only for testing!
; call kb_write
858,14 → 858,14
; call kb_write
; call kb_read
 
mov al, 0xF3 ; set repeat rate & delay
call kb_write
mov al, 0xF3 ; set repeat rate & delay
call kb_write
; call kb_read
mov al, 0 ; 30 250 ;00100010b ; 24 500 ;00100100b ; 20 500
call kb_write
mov al, 0 ; 30 250 ;00100010b ; 24 500 ;00100100b ; 20 500
call kb_write
; call kb_read
;// mike.dld [
call set_lights
call set_lights
;// mike.dld ]
 
 
913,11 → 913,11
; START MULTITASKING
 
if preboot_blogesc
mov esi, boot_tasking
call boot_log
.bll1: in al, 0x60 ; wait for ESC key press
cmp al, 129
jne .bll1
mov esi, boot_tasking
call boot_log
.bll1: in al, 0x60 ; wait for ESC key press
cmp al, 129
jne .bll1
end if
 
; mov [ENABLE_TASKSWITCH],byte 1 ; multitasking enabled
924,39 → 924,39
 
; UNMASK ALL IRQ'S
 
mov esi,boot_allirqs
call boot_log
mov esi,boot_allirqs
call boot_log
 
cli ;guarantee forbidance of interrupts.
mov al,0 ; unmask all irq's
out 0xA1,al
out 0x21,al
cli ;guarantee forbidance of interrupts.
mov al,0 ; unmask all irq's
out 0xA1,al
out 0x21,al
 
mov ecx,32
mov ecx,32
 
ready_for_irqs:
 
mov al,0x20 ; ready for irqs
out 0x20,al
out 0xa0,al
mov al,0x20 ; ready for irqs
out 0x20,al
out 0xa0,al
 
loop ready_for_irqs ; flush the queue
loop ready_for_irqs ; flush the queue
 
stdcall attach_int_handler, dword 1, irq1, dword 0
stdcall attach_int_handler, dword 1, irq1, dword 0
 
; mov [dma_hdd],1
cmp [IDEContrRegsBaseAddr], 0
setnz [dma_hdd]
mov [timer_ticks_enable],1 ; for cd driver
cmp [IDEContrRegsBaseAddr], 0
setnz [dma_hdd]
mov [timer_ticks_enable],1 ; for cd driver
 
sti
call change_task
sti
call change_task
 
jmp osloop
jmp osloop
 
; jmp $ ; wait here for timer to take control
 
; Fly :)
; Fly :)
 
include 'unpacker.inc'
include 'fdo.inc'
963,22 → 963,22
 
align 4
boot_log:
pushad
pushad
 
mov ebx,10*65536
mov bx,word [boot_y]
add [boot_y],dword 10
mov ecx,0x80ffffff ; ASCIIZ string with white color
mov edx,esi
mov edi,1
call dtext
mov ebx,10*65536
mov bx,word [boot_y]
add [boot_y],dword 10
mov ecx,0x80ffffff ; ASCIIZ string with white color
mov edx,esi
mov edi,1
call dtext
 
mov [novesachecksum],1000
call checkVga_N13
mov [novesachecksum],1000
call checkVga_N13
 
popad
popad
 
ret
ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
988,17 → 988,17
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 32
osloop:
call [draw_pointer]
call checkbuttons
call checkwindows
call [draw_pointer]
call checkbuttons
call checkwindows
; call check_window_move_request
call checkmisc
call checkVga_N13
call stack_handler
call checkidle
call check_fdd_motor_status
call check_ATAPI_device_event
jmp osloop
call checkmisc
call checkVga_N13
call stack_handler
call checkidle
call check_fdd_motor_status
call check_ATAPI_device_event
jmp osloop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; MAIN OS LOOP END ;
1006,33 → 1006,33
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
checkidle:
pushad
call change_task
jmp idle_loop_entry
pushad
call change_task
jmp idle_loop_entry
idle_loop:
cmp eax,[idlemem] ; eax == [timer_ticks]
jne idle_exit
rdtsc ;call _rdtsc
mov ecx,eax
hlt
rdtsc ;call _rdtsc
sub eax,ecx
add [idleuse],eax
cmp eax,[idlemem] ; eax == [timer_ticks]
jne idle_exit
rdtsc ;call _rdtsc
mov ecx,eax
hlt
rdtsc ;call _rdtsc
sub eax,ecx
add [idleuse],eax
idle_loop_entry:
mov eax,[timer_ticks] ; eax = [timer_ticks]
cmp [check_idle_semaphore],0
je idle_loop
dec [check_idle_semaphore]
mov eax,[timer_ticks] ; eax = [timer_ticks]
cmp [check_idle_semaphore],0
je idle_loop
dec [check_idle_semaphore]
idle_exit:
mov [idlemem],eax ; eax == [timer_ticks]
popad
ret
mov [idlemem],eax ; eax == [timer_ticks]
popad
ret
 
uglobal
idlemem dd 0x0
idleuse dd 0x0
idleusesec dd 0x0
check_idle_semaphore dd 0x0
idlemem dd 0x0
idleuse dd 0x0
idleusesec dd 0x0
check_idle_semaphore dd 0x0
endg
 
 
1055,57 → 1055,57
 
reserve_irqs_ports:
 
pushad
pushad
 
mov [irq_owner+4*0], 1 ; timer
;mov [irq_owner+4*1], 1 ; keyboard
mov [irq_owner+4*6], 1 ; floppy diskette
mov [irq_owner+4*13], 1 ; math co-pros
mov [irq_owner+4*14], 1 ; ide I
mov [irq_owner+4*15], 1 ; ide II
mov [irq_owner+4*0], 1 ; timer
;mov [irq_owner+4*1], 1 ; keyboard
mov [irq_owner+4*6], 1 ; floppy diskette
mov [irq_owner+4*13], 1 ; math co-pros
mov [irq_owner+4*14], 1 ; ide I
mov [irq_owner+4*15], 1 ; ide II
 
; RESERVE PORTS
mov edi,1 ; 0x00-0x2d
mov [RESERVED_PORTS],edi
shl edi,4
mov [RESERVED_PORTS+edi+0],dword 1
mov [RESERVED_PORTS+edi+4],dword 0x0
mov [RESERVED_PORTS+edi+8],dword 0x2d
; RESERVE PORTS
mov edi,1 ; 0x00-0x2d
mov [RESERVED_PORTS],edi
shl edi,4
mov [RESERVED_PORTS+edi+0],dword 1
mov [RESERVED_PORTS+edi+4],dword 0x0
mov [RESERVED_PORTS+edi+8],dword 0x2d
 
inc dword [RESERVED_PORTS] ; 0x30-0x4d
mov edi,[RESERVED_PORTS]
shl edi,4
mov [RESERVED_PORTS+edi+0],dword 1
mov [RESERVED_PORTS+edi+4],dword 0x30
mov [RESERVED_PORTS+edi+8],dword 0x4d
inc dword [RESERVED_PORTS] ; 0x30-0x4d
mov edi,[RESERVED_PORTS]
shl edi,4
mov [RESERVED_PORTS+edi+0],dword 1
mov [RESERVED_PORTS+edi+4],dword 0x30
mov [RESERVED_PORTS+edi+8],dword 0x4d
 
inc dword [RESERVED_PORTS] ; 0x50-0xdf
mov edi,[RESERVED_PORTS]
shl edi,4
mov [RESERVED_PORTS+edi+0],dword 1
mov [RESERVED_PORTS+edi+4],dword 0x50
mov [RESERVED_PORTS+edi+8],dword 0xdf
inc dword [RESERVED_PORTS] ; 0x50-0xdf
mov edi,[RESERVED_PORTS]
shl edi,4
mov [RESERVED_PORTS+edi+0],dword 1
mov [RESERVED_PORTS+edi+4],dword 0x50
mov [RESERVED_PORTS+edi+8],dword 0xdf
 
inc dword [RESERVED_PORTS] ; 0xe5-0xff
mov edi,[RESERVED_PORTS]
shl edi,4
mov [RESERVED_PORTS+edi+0],dword 1
mov [RESERVED_PORTS+edi+4],dword 0xe5
mov [RESERVED_PORTS+edi+8],dword 0xff
inc dword [RESERVED_PORTS] ; 0xe5-0xff
mov edi,[RESERVED_PORTS]
shl edi,4
mov [RESERVED_PORTS+edi+0],dword 1
mov [RESERVED_PORTS+edi+4],dword 0xe5
mov [RESERVED_PORTS+edi+8],dword 0xff
 
popad
ret
popad
ret
 
setirqreadports:
 
mov [irq12read+0],dword 0x60 + 0x01000000 ; read port 0x60 , byte
mov [irq12read+4],dword 0 ; end of port list
;mov [irq04read+0],dword 0x3f8 + 0x01000000 ; read port 0x3f8 , byte
;mov [irq04read+4],dword 0 ; end of port list
;mov [irq03read+0],dword 0x2f8 + 0x01000000 ; read port 0x2f8 , byte
;mov [irq03read+4],dword 0 ; end of port list
mov [irq12read+0],dword 0x60 + 0x01000000 ; read port 0x60 , byte
mov [irq12read+4],dword 0 ; end of port list
;mov [irq04read+0],dword 0x3f8 + 0x01000000 ; read port 0x3f8 , byte
;mov [irq04read+4],dword 0 ; end of port list
;mov [irq03read+0],dword 0x2f8 + 0x01000000 ; read port 0x2f8 , byte
;mov [irq03read+4],dword 0 ; end of port list
 
ret
ret
 
iglobal
process_number dd 0x1
1113,41 → 1113,41
 
set_variables:
 
mov ecx,0x100 ; flush port 0x60
.fl60: in al,0x60
loop .fl60
mov [MOUSE_BUFF_COUNT],byte 0 ; mouse buffer
mov [KEY_COUNT],byte 0 ; keyboard buffer
mov [BTN_COUNT],byte 0 ; button buffer
mov ecx,0x100 ; flush port 0x60
.fl60: in al,0x60
loop .fl60
mov [MOUSE_BUFF_COUNT],byte 0 ; mouse buffer
mov [KEY_COUNT],byte 0 ; keyboard buffer
mov [BTN_COUNT],byte 0 ; button buffer
; mov [MOUSE_X],dword 100*65536+100 ; mouse x/y
 
push eax
mov ax,[BOOT_VAR+0x900c]
shr ax,1
shl eax,16
mov ax,[BOOT_VAR+0x900A]
shr ax,1
mov [MOUSE_X],eax
pop eax
push eax
mov ax,[BOOT_VAR+0x900c]
shr ax,1
shl eax,16
mov ax,[BOOT_VAR+0x900A]
shr ax,1
mov [MOUSE_X],eax
pop eax
 
mov [BTN_ADDR],dword BUTTON_INFO ; address of button list
 
;!! IP 04.02.2005:
mov byte [DONT_SWITCH], 0 ; change task if possible
mov byte [DONT_SWITCH], 0 ; change task if possible
 
ret
ret
 
;* mouse centered - start code- Mario79
mouse_centered:
push eax
mov eax,[Screen_Max_X]
shr eax,1
mov [MOUSE_X],ax
mov eax,[Screen_Max_Y]
shr eax,1
mov [MOUSE_Y],ax
pop eax
ret
push eax
mov eax,[Screen_Max_X]
shr eax,1
mov [MOUSE_X],ax
mov eax,[Screen_Max_Y]
shr eax,1
mov [MOUSE_Y],ax
pop eax
ret
;* mouse centered - end code- Mario79
 
align 4
1154,7 → 1154,7
 
sys_outport:
 
mov edi,ebx ; separate flag for read / write
mov edi,ebx ; separate flag for read / write
and ebx,65535
 
mov ecx,[RESERVED_PORTS]
1176,9 → 1176,9
cmp edx,[esi+0]
jne sopl2
cmp ebx,[esi+4]
jb sopl2
jb sopl2
cmp ebx,[esi+8]
jg sopl2
jg sopl2
jmp sopl3
 
sopl2:
1193,7 → 1193,7
test edi,0x80000000 ; read ?
jnz sopl4
 
mov dx,bx ; write
mov dx,bx ; write
out dx,al
mov [esp+36],dword 0
ret
1200,8 → 1200,8
 
sopl4:
 
mov dx,bx ; read
in al,dx
mov dx,bx ; read
in al,dx
and eax,0xff
mov [esp+36],dword 0
mov [esp+24],eax
1220,11 → 1220,11
; ebx = number or pointer
; ecx = x shl 16 + y
; edx = color
xor edi, edi
xor edi, edi
display_number_force:
push eax
and eax,0x3fffffff
cmp eax,0xffff ; length > 0 ?
cmp eax,0xffff ; length > 0 ?
pop eax
jge cont_displ
ret
1231,7 → 1231,7
cont_displ:
push eax
and eax,0x3fffffff
cmp eax,61*0x10000 ; length <= 60 ?
cmp eax,61*0x10000 ; length <= 60 ?
pop eax
jb cont_displ2
ret
1239,7 → 1239,7
 
pushad
 
cmp al,1 ; ecx is a pointer ?
cmp al,1 ; ecx is a pointer ?
jne displnl1
mov ebp,ebx
add ebp,4
1248,7 → 1248,7
displnl1:
sub esp,64
 
cmp ah,0 ; DECIMAL
cmp ah,0 ; DECIMAL
jne no_display_desnum
shr eax,16
and eax,0xC03f
1276,7 → 1276,7
ret
no_display_desnum:
 
cmp ah,0x01 ; HEXADECIMAL
cmp ah,0x01 ; HEXADECIMAL
jne no_display_hexnum
shr eax,16
and eax,0xC03f
1306,7 → 1306,7
ret
no_display_hexnum:
 
cmp ah,0x02 ; BINARY
cmp ah,0x02 ; BINARY
jne no_display_binnum
shr eax,16
and eax,0xC03f
1385,9 → 1385,9
add eax,[edi+SLOT_BASE+APPDATA.wnd_clientbox.top]
add ebx,eax
mov ecx,[esp+64+32-12+4]
and ecx, not 0x80000000 ; force counted string
mov eax, [esp+64+8] ; background color (if given)
mov edi, [esp+64+4]
and ecx, not 0x80000000 ; force counted string
mov eax, [esp+64+8] ; background color (if given)
mov edi, [esp+64+4]
jmp dtext
 
align 4
1407,7 → 1407,7
 
 
mov [esp+36],dword 0
cmp eax,1 ; MIDI
cmp eax,1 ; MIDI
jnz nsyse1
cmp ebx,0x100
jb nsyse1
1426,7 → 1426,7
 
nsyse1:
 
cmp eax,2 ; KEYBOARD
cmp eax,2 ; KEYBOARD
jnz nsyse2
cmp ebx,1
jnz kbnobase
1466,7 → 1466,7
mov [esp+36],dword 1
ret
nsyse2:
cmp eax,3 ; CD
cmp eax,3 ; CD
jnz nsyse4
test ebx,ebx
jz nosesl
1499,13 → 1499,13
 
nsyse4:
 
cmp eax,5 ; SYSTEM LANGUAGE
cmp eax,5 ; SYSTEM LANGUAGE
jnz nsyse5
mov [syslang],ebx
ret
nsyse5:
 
cmp eax,7 ; HD BASE
cmp eax,7 ; HD BASE
jne nsyse7
test ebx,ebx
jz nosethd
1543,7 → 1543,7
call reserve_hd1
call reserve_hd_channel
call free_hd_channel
mov [hd1_status],0 ; free
mov [hd1_status],0 ; free
nosethd:
ret
 
1553,7 → 1553,7
 
nsyse7:
 
cmp eax,8 ; HD PARTITION
cmp eax,8 ; HD PARTITION
jne nsyse8
mov [fat32part],ebx
; call set_FAT32_variables
1563,11 → 1563,11
pusha
call choice_necessity_partition_1
popa
mov [hd1_status],0 ; free
mov [hd1_status],0 ; free
ret
 
nsyse8:
cmp eax,11 ; ENABLE LBA READ
cmp eax,11 ; ENABLE LBA READ
jne no_set_lba_read
and ebx,1
mov [lba_read_enabled],ebx
1699,10 → 1699,10
iglobal
align 4
mousefn dd msscreen, mswin, msbutton, msset
dd app_load_cursor
dd app_set_cursor
dd app_delete_cursor
dd msz
dd app_load_cursor
dd app_set_cursor
dd app_delete_cursor
dd msz
endg
 
readmousepos:
1716,89 → 1716,89
; eax=6 delete cursor ; reserved
; eax=7 get mouse_z
 
cmp eax, 7
ja msset
jmp [mousefn+eax*4]
cmp eax, 7
ja msset
jmp [mousefn+eax*4]
msscreen:
mov eax,[MOUSE_X]
shl eax,16
mov ax,[MOUSE_Y]
mov [esp+36],eax
ret
mov eax,[MOUSE_X]
shl eax,16
mov ax,[MOUSE_Y]
mov [esp+36],eax
ret
mswin:
mov eax,[MOUSE_X]
shl eax,16
mov ax,[MOUSE_Y]
mov esi,[TASK_BASE]
mov bx, word [esi-twdw+WDATA.box.left]
shl ebx,16
mov bx, word [esi-twdw+WDATA.box.top]
sub eax,ebx
mov eax,[MOUSE_X]
shl eax,16
mov ax,[MOUSE_Y]
mov esi,[TASK_BASE]
mov bx, word [esi-twdw+WDATA.box.left]
shl ebx,16
mov bx, word [esi-twdw+WDATA.box.top]
sub eax,ebx
 
mov edi,[CURRENT_TASK]
shl edi,8
sub ax,word[edi+SLOT_BASE+APPDATA.wnd_clientbox.top]
rol eax,16
sub ax,word[edi+SLOT_BASE+APPDATA.wnd_clientbox.left]
rol eax,16
mov [esp+36],eax
ret
mov edi,[CURRENT_TASK]
shl edi,8
sub ax,word[edi+SLOT_BASE+APPDATA.wnd_clientbox.top]
rol eax,16
sub ax,word[edi+SLOT_BASE+APPDATA.wnd_clientbox.left]
rol eax,16
mov [esp+36],eax
ret
msbutton:
movzx eax,byte [BTN_DOWN]
mov [esp+36],eax
ret
movzx eax,byte [BTN_DOWN]
mov [esp+36],eax
ret
msz:
mov edi, [TASK_COUNT]
movzx edi, word [WIN_POS + edi*2]
cmp edi, [CURRENT_TASK]
jne @f
mov ax,[MOUSE_SCROLL_H]
shl eax,16
mov ax,[MOUSE_SCROLL_V]
mov [esp+36],eax
mov [MOUSE_SCROLL_H],word 0
mov [MOUSE_SCROLL_V],word 0
ret
mov edi, [TASK_COUNT]
movzx edi, word [WIN_POS + edi*2]
cmp edi, [CURRENT_TASK]
jne @f
mov ax,[MOUSE_SCROLL_H]
shl eax,16
mov ax,[MOUSE_SCROLL_V]
mov [esp+36],eax
mov [MOUSE_SCROLL_H],word 0
mov [MOUSE_SCROLL_V],word 0
ret
@@:
mov [esp+36],dword 0
ret
mov [esp+36],dword 0
ret
msset:
ret
ret
 
app_load_cursor:
; add ebx, new_app_base
cmp ebx, OS_BASE
jae msset
stdcall load_cursor, ebx, ecx
mov [esp+36], eax
ret
cmp ebx, OS_BASE
jae msset
stdcall load_cursor, ebx, ecx
mov [esp+36], eax
ret
 
app_set_cursor:
stdcall set_cursor, ebx
mov [esp+36], eax
ret
stdcall set_cursor, ebx
mov [esp+36], eax
ret
 
app_delete_cursor:
stdcall delete_cursor, ebx
mov [esp+36], eax
ret
stdcall delete_cursor, ebx
mov [esp+36], eax
ret
 
is_input:
 
push edx
mov dx,word [midisp]
in al,dx
and al,0x80
pop edx
mov dx,word [midisp]
in al,dx
and al,0x80
pop edx
ret
 
is_output:
 
push edx
mov dx,word [midisp]
in al,dx
and al,0x40
pop edx
mov dx,word [midisp]
in al,dx
and al,0x40
pop edx
ret
 
 
1805,9 → 1805,9
get_mpu_in:
 
push edx
mov dx,word [mididp]
in al,dx
pop edx
mov dx,word [mididp]
in al,dx
pop edx
ret
 
 
1814,9 → 1814,9
put_mpu_out:
 
push edx
mov dx,word [mididp]
out dx,al
pop edx
mov dx,word [mididp]
out dx,al
pop edx
ret
 
 
1824,28 → 1824,28
 
su1:
call is_output
cmp al,0
jnz su1
mov dx,word [midisp]
mov al,0xff
out dx,al
cmp al,0
jnz su1
mov dx,word [midisp]
mov al,0xff
out dx,al
su2:
mov dx,word [midisp]
mov al,0xff
out dx,al
mov dx,word [midisp]
mov al,0xff
out dx,al
call is_input
cmp al,0
jnz su2
cmp al,0
jnz su2
call get_mpu_in
cmp al,0xfe
jnz su2
cmp al,0xfe
jnz su2
su3:
call is_output
cmp al,0
jnz su3
mov dx,word [midisp]
mov al,0x3f
out dx,al
cmp al,0
jnz su3
mov dx,word [midisp]
mov al,0x3f
out dx,al
 
ret
 
1898,7 → 1898,7
mov eax,[TASK_BASE]
mov [eax+TASKDATA.state], 3 ; terminate this program
 
waitterm: ; wait here for termination
waitterm: ; wait here for termination
mov ebx,100
call delay_hs
jmp waitterm
1906,42 → 1906,42
iglobal
align 4
sys_system_table:
dd exit_for_anyone ; 1 = obsolete
dd sysfn_terminate ; 2 = terminate thread
dd sysfn_activate ; 3 = activate window
dd sysfn_getidletime ; 4 = get idle time
dd sysfn_getcpuclock ; 5 = get cpu clock
dd sysfn_saveramdisk ; 6 = save ramdisk
dd sysfn_getactive ; 7 = get active window
dd sysfn_sound_flag ; 8 = get/set sound_flag
dd sysfn_shutdown ; 9 = shutdown with parameter
dd sysfn_minimize ; 10 = minimize window
dd sysfn_getdiskinfo ; 11 = get disk subsystem info
dd sysfn_lastkey ; 12 = get last pressed key
dd sysfn_getversion ; 13 = get kernel version
dd sysfn_waitretrace ; 14 = wait retrace
dd sysfn_centermouse ; 15 = center mouse cursor
dd sysfn_getfreemem ; 16 = get free memory size
dd sysfn_getallmem ; 17 = get total memory size
dd sysfn_terminate2 ; 18 = terminate thread using PID
; instead of slot
dd sysfn_mouse_acceleration; 19 = set/get mouse acceleration
dd sysfn_meminfo ; 20 = get extended memory info
dd sysfn_pid_to_slot ; 21 = get slot number for pid
dd sysfn_min_rest_window ; 22 = minimize and restore any window
dd exit_for_anyone ; 1 = obsolete
dd sysfn_terminate ; 2 = terminate thread
dd sysfn_activate ; 3 = activate window
dd sysfn_getidletime ; 4 = get idle time
dd sysfn_getcpuclock ; 5 = get cpu clock
dd sysfn_saveramdisk ; 6 = save ramdisk
dd sysfn_getactive ; 7 = get active window
dd sysfn_sound_flag ; 8 = get/set sound_flag
dd sysfn_shutdown ; 9 = shutdown with parameter
dd sysfn_minimize ; 10 = minimize window
dd sysfn_getdiskinfo ; 11 = get disk subsystem info
dd sysfn_lastkey ; 12 = get last pressed key
dd sysfn_getversion ; 13 = get kernel version
dd sysfn_waitretrace ; 14 = wait retrace
dd sysfn_centermouse ; 15 = center mouse cursor
dd sysfn_getfreemem ; 16 = get free memory size
dd sysfn_getallmem ; 17 = get total memory size
dd sysfn_terminate2 ; 18 = terminate thread using PID
; instead of slot
dd sysfn_mouse_acceleration; 19 = set/get mouse acceleration
dd sysfn_meminfo ; 20 = get extended memory info
dd sysfn_pid_to_slot ; 21 = get slot number for pid
dd sysfn_min_rest_window ; 22 = minimize and restore any window
sysfn_num = ($ - sys_system_table)/4
endg
 
sys_system:
dec ebx
cmp ebx, sysfn_num
jae @f
jmp dword [sys_system_table + ebx*4]
dec ebx
cmp ebx, sysfn_num
jae @f
jmp dword [sys_system_table + ebx*4]
@@:
ret
ret
 
 
sysfn_shutdown: ; 18.9 = system shutdown
sysfn_shutdown: ; 18.9 = system shutdown
cmp ecx,1
jl exit_for_anyone
cmp ecx,4
1958,7 → 1958,7
shutdown_processes: dd 0x0
endg
 
sysfn_terminate: ; 18.2 = TERMINATE
sysfn_terminate: ; 18.2 = TERMINATE
cmp ecx,2
jb noprocessterminate
mov edx,[TASK_COUNT]
1972,7 → 1972,7
jz noprocessterminate
 
;call MEM_Heap_Lock ;guarantee that process isn't working with heap
mov [ecx],byte 3 ; clear possible i40's
mov [ecx],byte 3 ; clear possible i40's
;call MEM_Heap_UnLock
 
cmp edx,[application_table_status] ; clear app table stat
1987,7 → 1987,7
.table_status:
cli
cmp [application_table_status],0
je .stf
je .stf
sti
call change_task
jmp .table_status
1996,7 → 1996,7
mov eax,ecx
call pid_to_slot
test eax,eax
jz .not_found
jz .not_found
mov ecx,eax
cli
call sysfn_terminate
2006,10 → 2006,10
ret
.not_found:
mov [application_table_status],0
or dword [esp+32],-1
or dword [esp+32],-1
ret
 
sysfn_activate: ; 18.3 = ACTIVATE WINDOW
sysfn_activate: ; 18.3 = ACTIVATE WINDOW
cmp ecx,2
jb .nowindowactivate
cmp ecx,[TASK_COUNT]
2030,12 → 2030,12
.nowindowactivate:
ret
 
sysfn_getidletime: ; 18.4 = GET IDLETIME
sysfn_getidletime: ; 18.4 = GET IDLETIME
mov eax,[idleusesec]
mov [esp+32], eax
ret
 
sysfn_getcpuclock: ; 18.5 = GET TSC/SEC
sysfn_getcpuclock: ; 18.5 = GET TSC/SEC
mov eax,[CPU_FREQ]
mov [esp+32], eax
ret
2045,13 → 2045,13
include 'blkdev/rdsave.inc'
;!!!!!!!!!!!!!!!!!!!!!!!!
 
sysfn_getactive: ; 18.7 = get active window
sysfn_getactive: ; 18.7 = get active window
mov eax, [TASK_COUNT]
movzx eax, word [WIN_POS + eax*2]
mov [esp+32],eax
ret
 
sysfn_sound_flag: ; 18.8 = get/set sound_flag
sysfn_sound_flag: ; 18.8 = get/set sound_flag
cmp ecx,1
jne nogetsoundflag
movzx eax,byte [sound_flag] ; get sound_flag
2064,11 → 2064,11
nosoundflag:
ret
 
sysfn_minimize: ; 18.10 = minimize window
sysfn_minimize: ; 18.10 = minimize window
mov [window_minimize],1
ret
 
sysfn_getdiskinfo: ; 18.11 = get disk info table
sysfn_getdiskinfo: ; 18.11 = get disk info table
cmp ecx,1
jnz full_table
small_table:
2090,11 → 2090,11
rep movsd
ret
 
sysfn_lastkey: ; 18.12 = return 0 (backward compatibility)
and dword [esp+32], 0
ret
sysfn_lastkey: ; 18.12 = return 0 (backward compatibility)
and dword [esp+32], 0
ret
 
sysfn_getversion: ; 18.13 = get kernel ID and version
sysfn_getversion: ; 18.13 = get kernel ID and version
mov edi,ebx
mov esi,version_inf
mov ecx,version_end-version_inf
2112,7 → 2112,7
and [esp+32],dword 0
ret
 
sysfn_centermouse: ; 18.15 = mouse centered
sysfn_centermouse: ; 18.15 = mouse centered
call mouse_centered
and [esp+32],dword 0
ret
2177,14 → 2177,14
 
sysfn_min_rest_window:
pushad
mov eax, edx ; ebx - operating
mov eax, edx ; ebx - operating
shr ecx, 1
jnc @f
call pid_to_slot
@@:
or eax, eax ; eax - number of slot
or eax, eax ; eax - number of slot
jz .error
cmp eax, 255 ; varify maximal slot number
cmp eax, 255 ; varify maximal slot number
ja .error
movzx eax, word [WIN_STACK + eax*2]
shr ecx, 1
2212,7 → 2212,7
screen_workarea RECT
;// mike.dld, 2006-29-01 ]
window_minimize db 0
sound_flag db 0
sound_flag db 0
endg
 
iglobal
2224,27 → 2224,27
endg
 
UID_NONE=0
UID_MENUETOS=1 ;official
UID_KOLIBRI=2 ;russian
UID_MENUETOS=1 ;official
UID_KOLIBRI=2 ;russian
 
sys_cachetodiskette:
cmp ebx, 1
jne .no_floppy_a_save
mov [flp_number], 1
jmp .save_image_on_floppy
cmp ebx, 1
jne .no_floppy_a_save
mov [flp_number], 1
jmp .save_image_on_floppy
.no_floppy_a_save:
cmp ebx, 2
jne .no_floppy_b_save
mov [flp_number], 2
cmp ebx, 2
jne .no_floppy_b_save
mov [flp_number], 2
.save_image_on_floppy:
call save_image
mov [esp + 32], dword 0
cmp [FDC_Status], 0
je .yes_floppy_save
call save_image
mov [esp + 32], dword 0
cmp [FDC_Status], 0
je .yes_floppy_save
.no_floppy_b_save:
mov [esp + 32], dword 1
mov [esp + 32], dword 1
.yes_floppy_save:
ret
ret
 
uglobal
; bgrchanged dd 0x0
2255,18 → 2255,18
 
sys_background:
 
cmp ebx,1 ; BACKGROUND SIZE
cmp ebx,1 ; BACKGROUND SIZE
jnz nosb1
cmp ecx,0
je sbgrr
je sbgrr
cmp edx,0
je sbgrr
je sbgrr
@@:
;;Maxis use atomic bts for mutexes 4.4.2009
bts dword [bgrlock], 0
jnc @f
call change_task
jmp @b
bts dword [bgrlock], 0
jnc @f
call change_task
jmp @b
@@:
mov [BgrDataWidth],ecx
mov [BgrDataHeight],edx
2274,10 → 2274,10
 
pushad
; return memory for old background
mov eax, [img_background]
cmp eax, static_background_data
jz @f
stdcall kernel_free, eax
mov eax, [img_background]
cmp eax, static_background_data
jz @f
stdcall kernel_free, eax
@@:
; calculate RAW size
xor eax,eax
2302,15 → 2302,15
jmp .exit
.memfailed:
; revert to static monotone data
mov [img_background], static_background_data
xor eax, eax
inc eax
mov [BgrDataWidth], eax
mov [BgrDataHeight], eax
mov [mem_BACKGROUND], 4
mov [img_background], static_background_data
xor eax, eax
inc eax
mov [BgrDataWidth], eax
mov [BgrDataHeight], eax
mov [mem_BACKGROUND], 4
.exit:
popad
mov [bgrlock], 0
mov [bgrlock], 0
 
sbgrr:
ret
2317,14 → 2317,14
 
nosb1:
 
cmp ebx,2 ; SET PIXEL
cmp ebx,2 ; SET PIXEL
jnz nosb2
 
mov eax, [img_background]
test ecx, ecx
jz @f
jz @f
cmp eax, static_background_data
jz .ret
jz .ret
@@:
mov ebx, [mem_BACKGROUND]
add ebx, 4095
2331,7 → 2331,7
and ebx, -4096
sub ebx, 4
cmp ecx, ebx
ja .ret
ja .ret
 
mov ebx,[eax+ecx]
and ebx,0xFF000000 ;255*256*256*256
2342,7 → 2342,7
ret
nosb2:
 
cmp ebx,3 ; DRAW BACKGROUND
cmp ebx,3 ; DRAW BACKGROUND
jnz nosb3
draw_background_temp:
; cmp [bgrchanged],1 ;0
2356,10 → 2356,10
ret
nosb3:
 
cmp ebx,4 ; TILED / STRETCHED
cmp ebx,4 ; TILED / STRETCHED
jnz nosb4
cmp ecx,[BgrDrawMode]
je nosb41
je nosb41
mov [BgrDrawMode],ecx
; mov [bgrchanged],1
nosb41:
2366,7 → 2366,7
ret
nosb4:
 
cmp ebx,5 ; BLOCK MOVE TO BGR
cmp ebx,5 ; BLOCK MOVE TO BGR
jnz nosb5
cmp [img_background], static_background_data
jnz @f
2373,7 → 2373,7
test edx, edx
jnz .fin
cmp esi, 4
ja .fin
ja .fin
@@:
; bughere
mov eax, ecx
2385,86 → 2385,86
ret
nosb5:
 
cmp ebx, 6
jnz nosb6
cmp ebx, 6
jnz nosb6
;;Maxis use atomic bts for mutex 4.4.2009
@@:
bts dword [bgrlock], 0
jnc @f
call change_task
jmp @b
bts dword [bgrlock], 0
jnc @f
call change_task
jmp @b
@@:
mov eax, [CURRENT_TASK]
mov [bgrlockpid], eax
cmp [img_background], static_background_data
jz .nomem
stdcall user_alloc, [mem_BACKGROUND]
mov [esp+32], eax
test eax, eax
jz .nomem
mov ebx, eax
shr ebx, 12
or dword [page_tabs+(ebx-1)*4], DONT_FREE_BLOCK
mov esi, [img_background]
shr esi, 12
mov ecx, [mem_BACKGROUND]
add ecx, 0xFFF
shr ecx, 12
mov eax, [CURRENT_TASK]
mov [bgrlockpid], eax
cmp [img_background], static_background_data
jz .nomem
stdcall user_alloc, [mem_BACKGROUND]
mov [esp+32], eax
test eax, eax
jz .nomem
mov ebx, eax
shr ebx, 12
or dword [page_tabs+(ebx-1)*4], DONT_FREE_BLOCK
mov esi, [img_background]
shr esi, 12
mov ecx, [mem_BACKGROUND]
add ecx, 0xFFF
shr ecx, 12
.z:
mov eax, [page_tabs+ebx*4]
test al, 1
jz @f
call free_page
mov eax, [page_tabs+ebx*4]
test al, 1
jz @f
call free_page
@@:
mov eax, [page_tabs+esi*4]
or al, PG_UW
mov [page_tabs+ebx*4], eax
mov eax, ebx
shl eax, 12
invlpg [eax]
inc ebx
inc esi
loop .z
ret
mov eax, [page_tabs+esi*4]
or al, PG_UW
mov [page_tabs+ebx*4], eax
mov eax, ebx
shl eax, 12
invlpg [eax]
inc ebx
inc esi
loop .z
ret
.nomem:
and [bgrlockpid], 0
mov [bgrlock], 0
and [bgrlockpid], 0
mov [bgrlock], 0
nosb6:
cmp ebx, 7
jnz nosb7
cmp [bgrlock], 0
jz .err
mov eax, [CURRENT_TASK]
cmp [bgrlockpid], eax
jnz .err
mov eax, ecx
mov ebx, ecx
shr eax, 12
mov ecx, [page_tabs+(eax-1)*4]
test cl, USED_BLOCK+DONT_FREE_BLOCK
jz .err
jnp .err
push eax
shr ecx, 12
cmp ebx, 7
jnz nosb7
cmp [bgrlock], 0
jz .err
mov eax, [CURRENT_TASK]
cmp [bgrlockpid], eax
jnz .err
mov eax, ecx
mov ebx, ecx
shr eax, 12
mov ecx, [page_tabs+(eax-1)*4]
test cl, USED_BLOCK+DONT_FREE_BLOCK
jz .err
jnp .err
push eax
shr ecx, 12
@@:
and dword [page_tabs+eax*4], 0
mov edx, eax
shl edx, 12
and dword [page_tabs+eax*4], 0
mov edx, eax
shl edx, 12
push eax
invlpg [edx]
invlpg [edx]
pop eax
inc eax
loop @b
pop eax
and dword [page_tabs+(eax-1)*4], not DONT_FREE_BLOCK
stdcall user_free, ebx
mov [esp+32], eax
and [bgrlockpid], 0
mov [bgrlock], 0
ret
inc eax
loop @b
pop eax
and dword [page_tabs+(eax-1)*4], not DONT_FREE_BLOCK
stdcall user_free, ebx
mov [esp+32], eax
and [bgrlockpid], 0
mov [bgrlock], 0
ret
.err:
and dword [esp+32], 0
ret
and dword [esp+32], 0
ret
 
nosb7:
ret
2485,7 → 2485,7
 
sys_getbackground:
 
cmp eax,1 ; SIZE
cmp eax,1 ; SIZE
jnz nogb1
mov eax,[BgrDataWidth]
shl eax,16
2495,14 → 2495,14
 
nogb1:
 
cmp eax,2 ; PIXEL
cmp eax,2 ; PIXEL
jnz nogb2
 
mov eax, [img_background]
test ebx, ebx
jz @f
cmp eax, static_background_data
jz .ret
mov eax, [img_background]
test ebx, ebx
jz @f
cmp eax, static_background_data
jz .ret
@@:
mov ecx, [mem_BACKGROUND]
add ecx, 4095
2509,7 → 2509,7
and ecx, -4096
sub ecx, 4
cmp ebx, ecx
ja .ret
ja .ret
 
mov eax,[ebx+eax]
 
2519,7 → 2519,7
ret
nogb2:
 
cmp eax,4 ; TILED / STRETCHED
cmp eax,4 ; TILED / STRETCHED
jnz nogb4
mov eax,[BgrDrawMode]
nogb4:
2530,71 → 2530,71
align 4
 
sys_getkey:
mov [esp + 32],dword 1
; test main buffer
mov ebx, [CURRENT_TASK] ; TOP OF WINDOW STACK
movzx ecx, word [WIN_STACK + ebx * 2]
mov edx, [TASK_COUNT]
cmp ecx, edx
jne .finish
cmp [KEY_COUNT], byte 0
je .finish
movzx eax, byte [KEY_BUFF]
shl eax, 8
push eax
dec byte [KEY_COUNT]
and byte [KEY_COUNT], 127
movzx ecx, byte [KEY_COUNT]
add ecx, 2
mov eax, KEY_BUFF + 1
mov ebx, KEY_BUFF
call memmove
pop eax
mov [esp + 32],dword 1
; test main buffer
mov ebx, [CURRENT_TASK] ; TOP OF WINDOW STACK
movzx ecx, word [WIN_STACK + ebx * 2]
mov edx, [TASK_COUNT]
cmp ecx, edx
jne .finish
cmp [KEY_COUNT], byte 0
je .finish
movzx eax, byte [KEY_BUFF]
shl eax, 8
push eax
dec byte [KEY_COUNT]
and byte [KEY_COUNT], 127
movzx ecx, byte [KEY_COUNT]
add ecx, 2
mov eax, KEY_BUFF + 1
mov ebx, KEY_BUFF
call memmove
pop eax
.ret_eax:
mov [esp + 32], eax
ret
mov [esp + 32], eax
ret
.finish:
; test hotkeys buffer
mov ecx, hotkey_buffer
mov ecx, hotkey_buffer
@@:
cmp [ecx], ebx
jz .found
add ecx, 8
cmp ecx, hotkey_buffer + 120 * 8
jb @b
ret
cmp [ecx], ebx
jz .found
add ecx, 8
cmp ecx, hotkey_buffer + 120 * 8
jb @b
ret
.found:
mov ax, [ecx + 6]
shl eax, 16
mov ah, [ecx + 4]
mov al, 2
and dword [ecx + 4], 0
and dword [ecx], 0
jmp .ret_eax
mov ax, [ecx + 6]
shl eax, 16
mov ah, [ecx + 4]
mov al, 2
and dword [ecx + 4], 0
and dword [ecx], 0
jmp .ret_eax
 
align 4
 
sys_getbutton:
 
mov ebx, [CURRENT_TASK] ; TOP OF WINDOW STACK
mov [esp + 32], dword 1
movzx ecx, word [WIN_STACK + ebx * 2]
mov edx, [TASK_COUNT] ; less than 256 processes
cmp ecx, edx
jne .exit
movzx eax, byte [BTN_COUNT]
test eax, eax
jz .exit
mov eax, [BTN_BUFF]
shl eax, 8
mov ebx, [CURRENT_TASK] ; TOP OF WINDOW STACK
mov [esp + 32], dword 1
movzx ecx, word [WIN_STACK + ebx * 2]
mov edx, [TASK_COUNT] ; less than 256 processes
cmp ecx, edx
jne .exit
movzx eax, byte [BTN_COUNT]
test eax, eax
jz .exit
mov eax, [BTN_BUFF]
shl eax, 8
; // Alver 22.06.2008 // {
mov al, byte [btn_down_determ]
and al,0xFE ; delete left button bit
; } \\ Alver \\
mov [BTN_COUNT], byte 0
mov [esp + 32], eax
mov [BTN_COUNT], byte 0
mov [esp + 32], eax
.exit:
ret
ret
 
 
align 4
2612,78 → 2612,78
; +30 dword PID , process idenfification number
;
 
cmp ecx,-1 ; who am I ?
cmp ecx,-1 ; who am I ?
jne .no_who_am_i
mov ecx,[CURRENT_TASK]
.no_who_am_i:
cmp ecx, max_processes
ja .nofillbuf
cmp ecx, max_processes
ja .nofillbuf
 
; +4: word: position of the window of thread in the window stack
mov ax, [WIN_STACK + ecx * 2]
mov [ebx+4], ax
mov ax, [WIN_STACK + ecx * 2]
mov [ebx+4], ax
; +6: word: number of the thread slot, which window has in the window stack
; position ecx (has no relation to the specific thread)
mov ax, [WIN_POS + ecx * 2]
mov [ebx+6], ax
mov ax, [WIN_POS + ecx * 2]
mov [ebx+6], ax
 
shl ecx, 5
shl ecx, 5
 
; +0: dword: memory usage
mov eax, [ecx+CURRENT_TASK+TASKDATA.cpu_usage]
mov [ebx], eax
mov eax, [ecx+CURRENT_TASK+TASKDATA.cpu_usage]
mov [ebx], eax
; +10: 11 bytes: name of the process
push ecx
lea eax, [ecx*8+SLOT_BASE+APPDATA.app_name]
add ebx, 10
mov ecx, 11
call memmove
pop ecx
push ecx
lea eax, [ecx*8+SLOT_BASE+APPDATA.app_name]
add ebx, 10
mov ecx, 11
call memmove
pop ecx
 
; +22: address of the process in memory
; +26: size of used memory - 1
push edi
lea edi, [ebx+12]
xor eax, eax
mov edx, 0x100000*16
cmp ecx, 1 shl 5
je .os_mem
mov edx, [SLOT_BASE+ecx*8+APPDATA.mem_size]
mov eax, std_application_base_address
push edi
lea edi, [ebx+12]
xor eax, eax
mov edx, 0x100000*16
cmp ecx, 1 shl 5
je .os_mem
mov edx, [SLOT_BASE+ecx*8+APPDATA.mem_size]
mov eax, std_application_base_address
.os_mem:
stosd
lea eax, [edx-1]
stosd
stosd
lea eax, [edx-1]
stosd
 
; +30: PID/TID
mov eax, [ecx+CURRENT_TASK+TASKDATA.pid]
stosd
mov eax, [ecx+CURRENT_TASK+TASKDATA.pid]
stosd
 
; window position and size
push esi
lea esi, [ecx + window_data + WDATA.box]
movsd
movsd
movsd
movsd
push esi
lea esi, [ecx + window_data + WDATA.box]
movsd
movsd
movsd
movsd
 
; Process state (+50)
mov eax, dword [ecx+CURRENT_TASK+TASKDATA.state]
stosd
mov eax, dword [ecx+CURRENT_TASK+TASKDATA.state]
stosd
 
; Window client area box
lea esi, [ecx*8 + SLOT_BASE + APPDATA.wnd_clientbox]
movsd
movsd
movsd
movsd
lea esi, [ecx*8 + SLOT_BASE + APPDATA.wnd_clientbox]
movsd
movsd
movsd
movsd
 
; Window state
mov al, [ecx+window_data+WDATA.fl_wstate]
stosb
mov al, [ecx+window_data+WDATA.fl_wstate]
stosb
 
pop esi
pop edi
pop esi
pop edi
 
.nofillbuf:
; return number of processes
2694,38 → 2694,38
 
align 4
sys_clock:
cli
cli
; Mikhail Lisovin xx Jan 2005
@@: mov al, 10
out 0x70, al
in al, 0x71
test al, al
jns @f
mov esi, 1
call delay_ms
jmp @b
@@: mov al, 10
out 0x70, al
in al, 0x71
test al, al
jns @f
mov esi, 1
call delay_ms
jmp @b
@@:
; end Lisovin's fix
 
xor al,al ; seconds
out 0x70,al
in al,0x71
movzx ecx,al
mov al,02 ; minutes
shl ecx,16
out 0x70,al
in al,0x71
movzx edx,al
mov al,04 ; hours
shl edx,8
out 0x70,al
in al,0x71
add ecx,edx
movzx edx,al
add ecx,edx
sti
mov [esp + 32], ecx
ret
xor al,al ; seconds
out 0x70,al
in al,0x71
movzx ecx,al
mov al,02 ; minutes
shl ecx,16
out 0x70,al
in al,0x71
movzx edx,al
mov al,04 ; hours
shl edx,8
out 0x70,al
in al,0x71
add ecx,edx
movzx edx,al
add ecx,edx
sti
mov [esp + 32], ecx
ret
 
 
align 4
2732,95 → 2732,95
 
sys_date:
 
cli
@@: mov al, 10
out 0x70, al
in al, 0x71
test al, al
jns @f
mov esi, 1
call delay_ms
jmp @b
cli
@@: mov al, 10
out 0x70, al
in al, 0x71
test al, al
jns @f
mov esi, 1
call delay_ms
jmp @b
@@:
 
mov ch,0
mov al,7 ; date
out 0x70,al
in al,0x71
mov cl,al
mov al,8 ; month
shl ecx,16
out 0x70,al
in al,0x71
mov ch,al
mov al,9 ; year
out 0x70,al
in al,0x71
mov cl,al
sti
mov [esp+32], ecx
ret
mov ch,0
mov al,7 ; date
out 0x70,al
in al,0x71
mov cl,al
mov al,8 ; month
shl ecx,16
out 0x70,al
in al,0x71
mov ch,al
mov al,9 ; year
out 0x70,al
in al,0x71
mov cl,al
sti
mov [esp+32], ecx
ret
 
 
; redraw status
 
sys_redrawstat:
cmp ebx, 1
jne no_widgets_away
; buttons away
mov ecx,[CURRENT_TASK]
cmp ebx, 1
jne no_widgets_away
; buttons away
mov ecx,[CURRENT_TASK]
sys_newba2:
mov edi,[BTN_ADDR]
cmp [edi], dword 0 ; empty button list ?
je end_of_buttons_away
movzx ebx, word [edi]
inc ebx
mov eax,edi
mov edi,[BTN_ADDR]
cmp [edi], dword 0 ; empty button list ?
je end_of_buttons_away
movzx ebx, word [edi]
inc ebx
mov eax,edi
sys_newba:
dec ebx
jz end_of_buttons_away
dec ebx
jz end_of_buttons_away
 
add eax, 0x10
cmp cx, [eax]
jnz sys_newba
add eax, 0x10
cmp cx, [eax]
jnz sys_newba
 
push eax ebx ecx
mov ecx,ebx
inc ecx
shl ecx, 4
mov ebx, eax
add eax, 0x10
call memmove
dec dword [edi]
pop ecx ebx eax
push eax ebx ecx
mov ecx,ebx
inc ecx
shl ecx, 4
mov ebx, eax
add eax, 0x10
call memmove
dec dword [edi]
pop ecx ebx eax
 
jmp sys_newba2
jmp sys_newba2
 
end_of_buttons_away:
 
ret
ret
 
no_widgets_away:
 
cmp ebx, 2
jnz srl1
cmp ebx, 2
jnz srl1
 
mov edx, [TASK_BASE] ; return whole screen draw area for this app
add edx, draw_data - CURRENT_TASK
mov [edx + RECT.left], 0
mov [edx + RECT.top], 0
mov eax, [Screen_Max_X]
mov [edx + RECT.right], eax
mov eax, [Screen_Max_Y]
mov [edx + RECT.bottom], eax
mov edx, [TASK_BASE] ; return whole screen draw area for this app
add edx, draw_data - CURRENT_TASK
mov [edx + RECT.left], 0
mov [edx + RECT.top], 0
mov eax, [Screen_Max_X]
mov [edx + RECT.right], eax
mov eax, [Screen_Max_Y]
mov [edx + RECT.bottom], eax
 
mov edi, [TASK_BASE]
or [edi - twdw + WDATA.fl_wdrawn], 1 ; no new position & buttons from app
call sys_window_mouse
ret
mov edi, [TASK_BASE]
or [edi - twdw + WDATA.fl_wdrawn], 1 ; no new position & buttons from app
call sys_window_mouse
ret
 
srl1:
ret
ret
 
 
sys_drawwindow:
2842,7 → 2842,7
jmp draw_window_caption.2
nosyswI:
 
cmp al,1 ; type II - only reserve area, no draw
cmp al,1 ; type II - only reserve area, no draw
jne nosyswII
inc [mouse_pause]
call [disable_mouse]
2854,7 → 2854,7
ret
nosyswII:
 
cmp al,2 ; type III - new style
cmp al,2 ; type III - new style
jne nosyswIII
inc [mouse_pause]
call [disable_mouse]
2867,9 → 2867,9
jmp draw_window_caption.2
nosyswIII:
 
cmp al,3 ; type IV - skinned window
je draw_skin_window
cmp al,4 ; type V - skinned window not sized! {not_sized_skin_window}
cmp al,3 ; type IV - skinned window
je draw_skin_window
cmp al,4 ; type V - skinned window not sized! {not_sized_skin_window}
jne nosyswV
draw_skin_window:
 
2894,180 → 2894,180
 
 
draw_window_caption:
inc [mouse_pause]
call [disable_mouse]
inc [mouse_pause]
call [disable_mouse]
 
xor eax,eax
mov edx,[TASK_COUNT]
movzx edx,word[WIN_POS+edx*2]
cmp edx,[CURRENT_TASK]
jne @f
inc eax
@@: mov edx,[CURRENT_TASK]
shl edx,5
add edx,window_data
movzx ebx,[edx+WDATA.fl_wstyle]
and bl,0x0F
cmp bl,3
je .draw_caption_style_3 ;{for 3 and 4 style write caption}
cmp bl,4
je .draw_caption_style_3
xor eax,eax
mov edx,[TASK_COUNT]
movzx edx,word[WIN_POS+edx*2]
cmp edx,[CURRENT_TASK]
jne @f
inc eax
@@: mov edx,[CURRENT_TASK]
shl edx,5
add edx,window_data
movzx ebx,[edx+WDATA.fl_wstyle]
and bl,0x0F
cmp bl,3
je .draw_caption_style_3 ;{for 3 and 4 style write caption}
cmp bl,4
je .draw_caption_style_3
 
jmp .not_style_3
jmp .not_style_3
.draw_caption_style_3:
 
push edx
call drawwindow_IV_caption
add esp,4
jmp .2
push edx
call drawwindow_IV_caption
add esp,4
jmp .2
 
.not_style_3:
cmp bl,2
jne .not_style_2
cmp bl,2
jne .not_style_2
 
call drawwindow_III_caption
jmp .2
call drawwindow_III_caption
jmp .2
 
.not_style_2:
cmp bl,0
jne .2
cmp bl,0
jne .2
 
call drawwindow_I_caption
call drawwindow_I_caption
 
;--------------------------------------------------------------
.2: ;jmp @f
mov edi,[CURRENT_TASK]
shl edi,5
test [edi+window_data+WDATA.fl_wstyle],WSTYLE_HASCAPTION
jz @f
mov edx,[edi*8+SLOT_BASE+APPDATA.wnd_caption]
or edx,edx
jz @f
.2: ;jmp @f
mov edi,[CURRENT_TASK]
shl edi,5
test [edi+window_data+WDATA.fl_wstyle],WSTYLE_HASCAPTION
jz @f
mov edx,[edi*8+SLOT_BASE+APPDATA.wnd_caption]
or edx,edx
jz @f
 
movzx eax,[edi+window_data+WDATA.fl_wstyle]
and al,0x0F
cmp al,3
je .skinned
cmp al,4
je .skinned
movzx eax,[edi+window_data+WDATA.fl_wstyle]
and al,0x0F
cmp al,3
je .skinned
cmp al,4
je .skinned
 
jmp .not_skinned
jmp .not_skinned
.skinned:
mov ebp,[edi+window_data+WDATA.box.left-2]
mov bp,word[edi+window_data+WDATA.box.top]
movzx eax,word[edi+window_data+WDATA.box.width]
sub ax,[_skinmargins.left]
sub ax,[_skinmargins.right]
push edx
cwde
cdq
mov ebx,6
idiv ebx
pop edx
or eax,eax
js @f
mov esi,eax
mov ebx,dword[_skinmargins.left-2]
mov bx,word[_skinh]
sub bx,[_skinmargins.bottom]
sub bx,[_skinmargins.top]
sar bx,1
adc bx,0
add bx,[_skinmargins.top]
add bx,-3
add ebx,ebp
jmp .dodraw
mov ebp,[edi+window_data+WDATA.box.left-2]
mov bp,word[edi+window_data+WDATA.box.top]
movzx eax,word[edi+window_data+WDATA.box.width]
sub ax,[_skinmargins.left]
sub ax,[_skinmargins.right]
push edx
cwde
cdq
mov ebx,6
idiv ebx
pop edx
or eax,eax
js @f
mov esi,eax
mov ebx,dword[_skinmargins.left-2]
mov bx,word[_skinh]
sub bx,[_skinmargins.bottom]
sub bx,[_skinmargins.top]
sar bx,1
adc bx,0
add bx,[_skinmargins.top]
add bx,-3
add ebx,ebp
jmp .dodraw
 
.not_skinned:
cmp al,1
je @f
cmp al,1
je @f
 
mov ebp,[edi+window_data+WDATA.box.left-2]
mov bp,word[edi+window_data+WDATA.box.top]
movzx eax,word[edi+window_data+WDATA.box.width]
sub eax,16
push edx
cwde
cdq
mov ebx,6
idiv ebx
pop edx
or eax,eax
js @f
mov esi,eax
mov ebx,0x00080007
add ebx,ebp
mov ebp,[edi+window_data+WDATA.box.left-2]
mov bp,word[edi+window_data+WDATA.box.top]
movzx eax,word[edi+window_data+WDATA.box.width]
sub eax,16
push edx
cwde
cdq
mov ebx,6
idiv ebx
pop edx
or eax,eax
js @f
mov esi,eax
mov ebx,0x00080007
add ebx,ebp
.dodraw:
mov ecx,[common_colours+16];0x00FFFFFF
or ecx, 0x80000000
xor edi,edi
mov ecx,[common_colours+16];0x00FFFFFF
or ecx, 0x80000000
xor edi,edi
; // Alver 22.06.2008 // {
; call dtext
call dtext_asciiz_esi
call dtext_asciiz_esi
; } \\ Alver \\
 
@@:
;--------------------------------------------------------------
dec [mouse_pause]
call [draw_pointer]
ret
dec [mouse_pause]
call [draw_pointer]
ret
 
iglobal
align 4
window_topleft dd \
1, 21,\ ;type 0
0, 0,\ ;type 1
5, 20,\ ;type 2
5, ?,\ ;type 3 {set by skin}
5, ? ;type 4 {set by skin}
1, 21,\ ;type 0
0, 0,\ ;type 1
5, 20,\ ;type 2
5, ?,\ ;type 3 {set by skin}
5, ? ;type 4 {set by skin}
endg
 
set_window_clientbox:
push eax ecx edi
push eax ecx edi
 
mov eax,[_skinh]
mov [window_topleft+4*7],eax
mov [window_topleft+4*9],eax
mov eax,[_skinh]
mov [window_topleft+4*7],eax
mov [window_topleft+4*9],eax
 
mov ecx,edi
sub edi,window_data
shl edi,3
test [ecx+WDATA.fl_wstyle],WSTYLE_CLIENTRELATIVE
jz @f
mov ecx,edi
sub edi,window_data
shl edi,3
test [ecx+WDATA.fl_wstyle],WSTYLE_CLIENTRELATIVE
jz @f
 
movzx eax,[ecx+WDATA.fl_wstyle]
and eax,0x0F
mov eax,[eax*8+window_topleft+0]
mov [edi+SLOT_BASE+APPDATA.wnd_clientbox.left],eax
shl eax,1
neg eax
add eax,[ecx+WDATA.box.width]
mov [edi+SLOT_BASE+APPDATA.wnd_clientbox.width],eax
movzx eax,[ecx+WDATA.fl_wstyle]
and eax,0x0F
mov eax,[eax*8+window_topleft+0]
mov [edi+SLOT_BASE+APPDATA.wnd_clientbox.left],eax
shl eax,1
neg eax
add eax,[ecx+WDATA.box.width]
mov [edi+SLOT_BASE+APPDATA.wnd_clientbox.width],eax
 
movzx eax,[ecx+WDATA.fl_wstyle]
and eax,0x0F
push [eax*8+window_topleft+0]
mov eax,[eax*8+window_topleft+4]
mov [edi+SLOT_BASE+APPDATA.wnd_clientbox.top],eax
neg eax
sub eax,[esp]
add eax,[ecx+WDATA.box.height]
mov [edi+SLOT_BASE+APPDATA.wnd_clientbox.height],eax
add esp,4
movzx eax,[ecx+WDATA.fl_wstyle]
and eax,0x0F
push [eax*8+window_topleft+0]
mov eax,[eax*8+window_topleft+4]
mov [edi+SLOT_BASE+APPDATA.wnd_clientbox.top],eax
neg eax
sub eax,[esp]
add eax,[ecx+WDATA.box.height]
mov [edi+SLOT_BASE+APPDATA.wnd_clientbox.height],eax
add esp,4
 
pop edi ecx eax
ret
pop edi ecx eax
ret
@@:
xor eax,eax
mov [edi+SLOT_BASE+APPDATA.wnd_clientbox.left],eax
mov [edi+SLOT_BASE+APPDATA.wnd_clientbox.top],eax
mov eax,[ecx+WDATA.box.width]
mov [edi+SLOT_BASE+APPDATA.wnd_clientbox.width],eax
mov eax,[ecx+WDATA.box.height]
mov [edi+SLOT_BASE+APPDATA.wnd_clientbox.height],eax
xor eax,eax
mov [edi+SLOT_BASE+APPDATA.wnd_clientbox.left],eax
mov [edi+SLOT_BASE+APPDATA.wnd_clientbox.top],eax
mov eax,[ecx+WDATA.box.width]
mov [edi+SLOT_BASE+APPDATA.wnd_clientbox.width],eax
mov eax,[ecx+WDATA.box.height]
mov [edi+SLOT_BASE+APPDATA.wnd_clientbox.height],eax
 
pop edi ecx eax
ret
pop edi ecx eax
ret
 
sys_set_window:
 
3101,39 → 3101,39
 
call check_window_position
 
push ecx esi edi ; save for window fullscreen/resize
push ecx esi edi ; save for window fullscreen/resize
;mov esi,edi
 
mov cl, [edi+WDATA.fl_wstyle]
mov eax, [edi+WDATA.cl_frames]
mov cl, [edi+WDATA.fl_wstyle]
mov eax, [edi+WDATA.cl_frames]
 
sub edi,window_data
shl edi,3
add edi,SLOT_BASE
 
and cl,0x0F
mov [edi+APPDATA.wnd_caption],0
cmp cl,3
je set_APPDATA_wnd_caption
cmp cl,4 ; {SPraid.simba}
je set_APPDATA_wnd_caption
and cl,0x0F
mov [edi+APPDATA.wnd_caption],0
cmp cl,3
je set_APPDATA_wnd_caption
cmp cl,4 ; {SPraid.simba}
je set_APPDATA_wnd_caption
 
jmp @f
jmp @f
set_APPDATA_wnd_caption:
mov [edi+APPDATA.wnd_caption],eax
@@: mov esi,[esp+0]
mov [edi+APPDATA.wnd_caption],eax
@@: mov esi,[esp+0]
 
add edi, APPDATA.saved_box
movsd
movsd
movsd
movsd
movsd
movsd
movsd
movsd
pop edi esi ecx
 
mov esi, [CURRENT_TASK]
movzx esi, word [WIN_STACK+esi*2]
lea esi, [WIN_POS+esi*2]
call waredraw
mov esi, [CURRENT_TASK]
movzx esi, word [WIN_STACK+esi*2]
lea esi, [WIN_POS+esi*2]
call waredraw
 
;;; mov ebx, 1
;;; call delay_hs
3145,13 → 3145,13
add edx, ebx
call calculatescreen
 
mov [KEY_COUNT],byte 0 ; empty keyboard buffer
mov [BTN_COUNT],byte 0 ; empty button buffer
mov [KEY_COUNT],byte 0 ; empty keyboard buffer
mov [BTN_COUNT],byte 0 ; empty button buffer
 
newd:
call set_window_clientbox
 
mov [edi+WDATA.fl_redraw],byte 0 ; no redraw
mov [edi+WDATA.fl_redraw],byte 0 ; no redraw
mov edx,edi
 
ret
3159,18 → 3159,18
syscall_windowsettings:
 
.set_window_caption:
dec eax ; subfunction #1 - set window caption
jnz .get_window_caption
dec eax ; subfunction #1 - set window caption
jnz .get_window_caption
 
; NOTE: only window owner thread can set its caption,
; so there's no parameter for PID/TID
; NOTE: only window owner thread can set its caption,
; so there's no parameter for PID/TID
 
mov edi,[CURRENT_TASK]
shl edi,5
mov edi,[CURRENT_TASK]
shl edi,5
 
; have to check if caption is within application memory limit
; check is trivial, and if application resizes its memory,
; caption still can become over bounds
; have to check if caption is within application memory limit
; check is trivial, and if application resizes its memory,
; caption still can become over bounds
; diamond, 31.10.2006: check removed because with new memory manager
; there can be valid data after APPDATA.mem_size bound
; mov ecx,[edi*8+SLOT_BASE+APPDATA.mem_size]
3178,115 → 3178,115
; cmp ebx,ecx
; ja .exit_fail
 
mov [edi*8+SLOT_BASE+APPDATA.wnd_caption],ebx
or [edi+window_data+WDATA.fl_wstyle],WSTYLE_HASCAPTION
mov [edi*8+SLOT_BASE+APPDATA.wnd_caption],ebx
or [edi+window_data+WDATA.fl_wstyle],WSTYLE_HASCAPTION
 
call draw_window_caption
call draw_window_caption
 
xor eax,eax ; eax = 0 (success)
ret
xor eax,eax ; eax = 0 (success)
ret
 
.get_window_caption:
dec eax ; subfunction #2 - get window caption
jnz .exit_fail
dec eax ; subfunction #2 - get window caption
jnz .exit_fail
 
; not implemented yet
; not implemented yet
 
.exit_fail:
xor eax,eax
inc eax ; eax = 1 (fail)
ret
xor eax,eax
inc eax ; eax = 1 (fail)
ret
 
 
sys_window_move:
 
mov edi,[CURRENT_TASK]
shl edi,5
add edi,window_data
mov edi,[CURRENT_TASK]
shl edi,5
add edi,window_data
 
test [edi+WDATA.fl_wstate],WSTATE_MAXIMIZED
jnz .window_move_return
test [edi+WDATA.fl_wstate],WSTATE_MAXIMIZED
jnz .window_move_return
 
push dword [edi + WDATA.box.left] ; save old coordinates
push dword [edi + WDATA.box.top]
push dword [edi + WDATA.box.width]
push dword [edi + WDATA.box.height]
push dword [edi + WDATA.box.left] ; save old coordinates
push dword [edi + WDATA.box.top]
push dword [edi + WDATA.box.width]
push dword [edi + WDATA.box.height]
 
cmp eax,-1 ; set new position and size
je .no_x_reposition
mov [edi + WDATA.box.left], eax
cmp eax,-1 ; set new position and size
je .no_x_reposition
mov [edi + WDATA.box.left], eax
.no_x_reposition:
cmp ebx,-1
je .no_y_reposition
mov [edi + WDATA.box.top], ebx
cmp ebx,-1
je .no_y_reposition
mov [edi + WDATA.box.top], ebx
.no_y_reposition:
 
test [edi+WDATA.fl_wstate],WSTATE_ROLLEDUP
jnz .no_y_resizing
test [edi+WDATA.fl_wstate],WSTATE_ROLLEDUP
jnz .no_y_resizing
 
cmp ecx,-1
je .no_x_resizing
mov [edi + WDATA.box.width], ecx
cmp ecx,-1
je .no_x_resizing
mov [edi + WDATA.box.width], ecx
.no_x_resizing:
cmp edx,-1
je .no_y_resizing
mov [edi + WDATA.box.height], edx
cmp edx,-1
je .no_y_resizing
mov [edi + WDATA.box.height], edx
.no_y_resizing:
 
call check_window_position
call set_window_clientbox
call check_window_position
call set_window_clientbox
 
pushad ; save for window fullscreen/resize
mov esi,edi
sub edi,window_data
shr edi,5
shl edi,8
add edi, SLOT_BASE + APPDATA.saved_box
mov ecx,4
cld
rep movsd
popad
pushad ; save for window fullscreen/resize
mov esi,edi
sub edi,window_data
shr edi,5
shl edi,8
add edi, SLOT_BASE + APPDATA.saved_box
mov ecx,4
cld
rep movsd
popad
 
pushad ; calculcate screen at new position
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
pushad ; calculcate screen at new position
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
 
call calculatescreen
popad
call calculatescreen
popad
 
pop edx ; calculcate screen at old position
pop ecx
pop ebx
pop eax
add ecx,eax
add edx,ebx
mov [dlx],eax ; save for drawlimits
mov [dly],ebx
mov [dlxe],ecx
mov [dlye],edx
call calculatescreen
pop edx ; calculcate screen at old position
pop ecx
pop ebx
pop eax
add ecx,eax
add edx,ebx
mov [dlx],eax ; save for drawlimits
mov [dly],ebx
mov [dlxe],ecx
mov [dlye],edx
call calculatescreen
 
mov [edi + WDATA.fl_redraw], 1 ; flag the process as redraw
mov [edi + WDATA.fl_redraw], 1 ; flag the process as redraw
 
mov eax,edi ; redraw screen at old position
xor esi,esi
call redrawscreen
mov eax,edi ; redraw screen at old position
xor esi,esi
call redrawscreen
 
mov [DONT_DRAW_MOUSE],byte 0 ; mouse pointer
mov [MOUSE_BACKGROUND],byte 0 ; no mouse under
mov [MOUSE_DOWN],byte 0 ; react to mouse up/down
mov [DONT_DRAW_MOUSE],byte 0 ; mouse pointer
mov [MOUSE_BACKGROUND],byte 0 ; no mouse under
mov [MOUSE_DOWN],byte 0 ; react to mouse up/down
 
call [draw_pointer]
call [draw_pointer]
 
mov [window_move_pr],0
mov [window_move_pr],0
 
.window_move_return:
 
ret
ret
 
uglobal
window_move_pr dd 0x0
3358,22 → 3358,22
wrmsr_instr:
;now counter in ecx
;(edx:eax) esi:edi => edx:esi
; Fast Call MSR can't be destroy
; Íî MSR_AMD_EFER ìîæíî èçìåíÿòü, ò.ê. â ýòîì ðåãèñòðå ëèø
; âêëþ÷àþòñÿ/âûêëþ÷àþòñÿ ðàñøèðåííûå âîçìîæíîñòè
cmp ecx, MSR_SYSENTER_CS
je @f
cmp ecx, MSR_SYSENTER_ESP
je @f
cmp ecx, MSR_SYSENTER_EIP
je @f
cmp ecx, MSR_AMD_STAR
je @f
; Fast Call MSR can't be destroy
; Íî MSR_AMD_EFER ìîæíî èçìåíÿòü, ò.ê. â ýòîì ðåãèñòðå ëèø
; âêëþ÷àþòñÿ/âûêëþ÷àþòñÿ ðàñøèðåííûå âîçìîæíîñòè
cmp ecx, MSR_SYSENTER_CS
je @f
cmp ecx, MSR_SYSENTER_ESP
je @f
cmp ecx, MSR_SYSENTER_EIP
je @f
cmp ecx, MSR_AMD_STAR
je @f
 
mov eax, esi
wrmsr
; mov [esp + 36], eax
; mov [esp + 24], edx ;ret in ebx?
mov eax, esi
wrmsr
; mov [esp + 36], eax
; mov [esp + 24], edx ;ret in ebx?
@@:
ret
 
3415,20 → 3415,20
; check if pixel is allowed to be drawn
 
checkpixel:
push eax edx
push eax edx
 
mov edx,[Screen_Max_X] ; screen x size
inc edx
imul edx, ebx
mov dl, [eax+edx+display_data] ; lea eax, [...]
mov edx,[Screen_Max_X] ; screen x size
inc edx
imul edx, ebx
mov dl, [eax+edx+display_data] ; lea eax, [...]
 
xor ecx, ecx
mov eax, [CURRENT_TASK]
cmp al, dl
setne cl
xor ecx, ecx
mov eax, [CURRENT_TASK]
cmp al, dl
setne cl
 
pop edx eax
ret
pop edx eax
ret
 
iglobal
cpustring db 'CPU',0
3435,7 → 3435,7
endg
 
uglobal
background_defined db 0 ; diamond, 11.04.2006
background_defined db 0 ; diamond, 11.04.2006
endg
 
align 4
3446,8 → 3446,8
cmp [ctrl_alt_del], 1
jne nocpustart
 
mov ebp, cpustring
call fs_execute_from_sysdir
mov ebp, cpustring
call fs_execute_from_sysdir
 
mov [ctrl_alt_del], 0
 
3456,24 → 3456,24
jne mouse_not_active
mov [mouse_active], 0
xor edi, edi
mov ecx, [TASK_COUNT]
mov ecx, [TASK_COUNT]
set_mouse_event:
add edi, 256
or [edi+SLOT_BASE+APPDATA.event_mask], dword 100000b
or [edi+SLOT_BASE+APPDATA.event_mask], dword 100000b
loop set_mouse_event
 
mouse_not_active:
cmp [REDRAW_BACKGROUND],byte 0 ; background update ?
jz nobackgr
cmp [REDRAW_BACKGROUND],byte 0 ; background update ?
jz nobackgr
cmp [background_defined], 0
jz nobackgr
jz nobackgr
cmp [REDRAW_BACKGROUND], byte 2
jnz no_set_bgr_event
xor edi, edi
mov ecx, [TASK_COUNT]
mov ecx, [TASK_COUNT]
set_bgr_event:
add edi, 256
or [edi+SLOT_BASE+APPDATA.event_mask], 16
or [edi+SLOT_BASE+APPDATA.event_mask], 16
loop set_bgr_event
no_set_bgr_event:
; mov [draw_data+32 + RECT.left],dword 0
3491,7 → 3491,7
; system shutdown request
 
cmp [SYS_SHUTDOWN],byte 0
je noshutdown
je noshutdown
 
mov edx,[shutdown_processes]
 
3512,12 → 3512,12
call [disable_mouse]
 
dec byte [SYS_SHUTDOWN]
je system_shutdown
je system_shutdown
 
noshutdown:
 
 
mov eax,[TASK_COUNT] ; termination
mov eax,[TASK_COUNT] ; termination
mov ebx,TASK_DATA+TASKDATA.state
mov esi,1
 
3524,9 → 3524,9
newct:
mov cl,[ebx]
cmp cl,byte 3
jz terminate
jz terminate
cmp cl,byte 4
jz terminate
jz terminate
 
add ebx,0x20
inc esi
3540,144 → 3540,144
 
; eax , if process window_data base is eax, do not set flag/limits
 
pushad
push eax
pushad
push eax
 
;;; mov ebx,2
;;; call delay_hs
 
;mov ecx,0 ; redraw flags for apps
xor ecx,ecx
;mov ecx,0 ; redraw flags for apps
xor ecx,ecx
newdw2:
 
inc ecx
push ecx
inc ecx
push ecx
 
mov eax,ecx
shl eax,5
add eax,window_data
mov eax,ecx
shl eax,5
add eax,window_data
 
cmp eax,[esp+4]
je not_this_task
; check if window in redraw area
mov edi,eax
cmp eax,[esp+4]
je not_this_task
; check if window in redraw area
mov edi,eax
 
cmp ecx,1 ; limit for background
jz bgli
cmp ecx,1 ; limit for background
jz bgli
 
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 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,[dlye] ; ecx = area y end ebx = window y start
cmp ecx,ebx
jb ricino
mov ecx,[dlye] ; ecx = area y end ebx = window y start
cmp ecx,ebx
jb ricino
 
mov ecx,[dlxe] ; ecx = area x end eax = window x start
cmp ecx,eax
jb ricino
mov ecx,[dlxe] ; ecx = area x end eax = window x start
cmp ecx,eax
jb ricino
 
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 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 eax,[dly] ; eax = area y start edx = window y end
cmp edx,eax
jb ricino
mov eax,[dly] ; eax = area y start edx = window y end
cmp edx,eax
jb ricino
 
mov eax,[dlx] ; eax = area x start ecx = window x end
cmp ecx,eax
jb ricino
mov eax,[dlx] ; eax = area x start ecx = window x end
cmp ecx,eax
jb ricino
 
bgli:
bgli:
 
cmp ecx,1
jnz .az
mov al,[REDRAW_BACKGROUND]
cmp al,2
jz newdw8
test al,al
jz .az
lea eax,[edi+draw_data-window_data]
mov ebx,[dlx]
cmp ebx,[eax+RECT.left]
jae @f
mov [eax+RECT.left],ebx
@@:
mov ebx,[dly]
cmp ebx,[eax+RECT.top]
jae @f
mov [eax+RECT.top],ebx
@@:
mov ebx,[dlxe]
cmp ebx,[eax+RECT.right]
jbe @f
mov [eax+RECT.right],ebx
@@:
mov ebx,[dlye]
cmp ebx,[eax+RECT.bottom]
jbe @f
mov [eax+RECT.bottom],ebx
@@:
jmp newdw8
.az:
cmp ecx,1
jnz .az
mov al,[REDRAW_BACKGROUND]
cmp al,2
jz newdw8
test al,al
jz .az
lea eax,[edi+draw_data-window_data]
mov ebx,[dlx]
cmp ebx,[eax+RECT.left]
jae @f
mov [eax+RECT.left],ebx
@@:
mov ebx,[dly]
cmp ebx,[eax+RECT.top]
jae @f
mov [eax+RECT.top],ebx
@@:
mov ebx,[dlxe]
cmp ebx,[eax+RECT.right]
jbe @f
mov [eax+RECT.right],ebx
@@:
mov ebx,[dlye]
cmp ebx,[eax+RECT.bottom]
jbe @f
mov [eax+RECT.bottom],ebx
@@:
jmp newdw8
.az:
 
mov eax,edi
add eax,draw_data-window_data
mov eax,edi
add eax,draw_data-window_data
 
mov ebx,[dlx] ; set limits
mov [eax + RECT.left], ebx
mov ebx,[dly]
mov [eax + RECT.top], ebx
mov ebx,[dlxe]
mov [eax + RECT.right], ebx
mov ebx,[dlye]
mov [eax + RECT.bottom], ebx
mov ebx,[dlx] ; set limits
mov [eax + RECT.left], ebx
mov ebx,[dly]
mov [eax + RECT.top], ebx
mov ebx,[dlxe]
mov [eax + RECT.right], ebx
mov ebx,[dlye]
mov [eax + RECT.bottom], ebx
 
sub eax,draw_data-window_data
sub eax,draw_data-window_data
 
cmp dword [esp],1
jne nobgrd
mov byte [REDRAW_BACKGROUND], 1
cmp dword [esp],1
jne nobgrd
mov byte [REDRAW_BACKGROUND], 1
 
newdw8:
nobgrd:
 
mov [eax + WDATA.fl_redraw],byte 1 ; mark as redraw
mov [eax + WDATA.fl_redraw],byte 1 ; mark as redraw
 
ricino:
 
not_this_task:
 
pop ecx
pop ecx
 
cmp ecx,[TASK_COUNT]
jle newdw2
cmp ecx,[TASK_COUNT]
jle newdw2
 
pop eax
popad
pop eax
popad
 
ret
ret
 
calculatebackground: ; background
 
mov edi,display_data ; set os to use all pixels
mov eax,0x01010101
mov ecx,1280*1024 / 4
rep stosd
mov edi,display_data ; set os to use all pixels
mov eax,0x01010101
mov ecx,1280*1024 / 4
rep stosd
 
mov byte [REDRAW_BACKGROUND], 0 ; do not draw background!
mov byte [REDRAW_BACKGROUND], 0 ; do not draw background!
 
ret
ret
 
uglobal
imax dd 0x0
imax dd 0x0
endg
 
 
3685,65 → 3685,65
delay_ms: ; delay in 1/1000 sec
 
 
push eax
push ecx
push eax
push ecx
 
mov ecx,esi
; <CPU clock fix by Sergey Kuzmin aka Wildwest>
imul ecx, 33941
shr ecx, 9
; </CPU clock fix>
mov ecx,esi
; <CPU clock fix by Sergey Kuzmin aka Wildwest>
imul ecx, 33941
shr ecx, 9
; </CPU clock fix>
 
in al,0x61
and al,0x10
mov ah,al
cld
in al,0x61
and al,0x10
mov ah,al
cld
 
cnt1: in al,0x61
and al,0x10
cmp al,ah
jz cnt1
cnt1: in al,0x61
and al,0x10
cmp al,ah
jz cnt1
 
mov ah,al
loop cnt1
mov ah,al
loop cnt1
 
pop ecx
pop eax
pop ecx
pop eax
 
ret
ret
 
 
set_app_param:
mov edi, [TASK_BASE]
mov eax, [edi + TASKDATA.event_mask]
mov [edi + TASKDATA.event_mask], ebx
mov [esp+32], eax
ret
mov edi, [TASK_BASE]
mov eax, [edi + TASKDATA.event_mask]
mov [edi + TASKDATA.event_mask], ebx
mov [esp+32], eax
ret
 
 
 
delay_hs: ; delay in 1/100 secs
; ebx = delay time
push ecx
push edx
push ecx
push edx
 
mov edx,[timer_ticks]
mov edx,[timer_ticks]
 
newtic:
mov ecx,[timer_ticks]
sub ecx,edx
cmp ecx,ebx
jae zerodelay
mov ecx,[timer_ticks]
sub ecx,edx
cmp ecx,ebx
jae zerodelay
 
call change_task
call change_task
 
jmp newtic
jmp newtic
 
zerodelay:
pop edx
pop ecx
pop edx
pop ecx
 
ret
ret
 
 
memmove: ; memory move in bytes
3761,7 → 3761,7
mov esi, eax
 
test ecx, not 11b
jz @f
jz @f
 
push ecx
shr ecx, 2
3768,7 → 3768,7
rep movsd
pop ecx
and ecx, 11b
jz .finish
jz .finish
@@:
rep movsb
 
3837,7 → 3837,7
jae .not_owner
mov edi, [eax + TASKDATA.pid]
cmp edi, [irq_owner + 4 * ecx]
je .spril1
je .spril1
.not_owner:
xor ecx, ecx
inc ecx
3860,11 → 3860,11
align 4
 
get_irq_data:
movzx esi, bh ; save number of subfunction, if bh = 1, return data size, otherwise, read data
movzx esi, bh ; save number of subfunction, if bh = 1, return data size, otherwise, read data
xor bh, bh
cmp ebx, 16
jae .not_owner
mov edx, [4 * ebx + irq_owner] ; check for irq owner
mov edx, [4 * ebx + irq_owner] ; check for irq owner
 
mov eax,[TASK_BASE]
 
3878,19 → 3878,19
gidril1:
 
shl ebx, 12
lea eax, [ebx + IRQ_SAVE] ; calculate address of the beginning of buffer + 0x0 - data size
mov edx, [eax] ; + 0x4 - data offset
lea eax, [ebx + IRQ_SAVE] ; calculate address of the beginning of buffer + 0x0 - data size
mov edx, [eax] ; + 0x4 - data offset
dec esi
jz gid1
test edx, edx ; check if buffer is empty
test edx, edx ; check if buffer is empty
jz gid1
 
mov ebx, [eax + 0x4]
mov edi, ecx
 
mov ecx, 4000 ; buffer size, used frequently
mov ecx, 4000 ; buffer size, used frequently
 
cmp ebx, ecx ; check for the end of buffer, if end of buffer, begin cycle again
cmp ebx, ecx ; check for the end of buffer, if end of buffer, begin cycle again
jb @f
 
xor ebx, ebx
3897,9 → 3897,9
 
@@:
 
lea esi, [ebx + edx] ; calculate data size and offset
lea esi, [ebx + edx] ; calculate data size and offset
cld
cmp esi, ecx ; if greater than the buffer size, begin cycle again
cmp esi, ecx ; if greater than the buffer size, begin cycle again
jbe @f
 
sub ecx, ebx
3916,11 → 3916,11
 
rep movsb
mov edx, [eax]
mov [eax], ecx ; set data size to zero
mov [eax + 0x4], ebx ; set data offset
mov [eax], ecx ; set data size to zero
mov [eax + 0x4], ebx ; set data offset
 
gid1:
mov [esp+32], edx ; eax
mov [esp+32], edx ; eax
ret
 
 
3939,7 → 3939,7
; mov ebx,1
; shl ebx,cl
 
cmp ebp,0 ; enable access - ebp = 0
cmp ebp,0 ; enable access - ebp = 0
jne siar1
 
; not ebx
3970,14 → 3970,14
 
pushad
 
cmp ebx,ecx ; beginning > end ?
cmp ebx,ecx ; beginning > end ?
ja rpal1
cmp ecx,65536
jae rpal1
mov esi,[RESERVED_PORTS]
test esi,esi ; no reserved areas ?
test esi,esi ; no reserved areas ?
je rpal2
cmp esi,255 ; max reserved
cmp esi,255 ; max reserved
jae rpal1
rpal3:
mov edi,esi
4005,7 → 4005,7
 
; enable port access at port IO map
cli
pushad ; start enable io map
pushad ; start enable io map
 
cmp ecx,65536 ;16384
jae no_unmask_io ; jge
4016,7 → 4016,7
 
pushad
 
xor ebp,ebp ; enable - eax = port
xor ebp,ebp ; enable - eax = port
call set_io_access_rights
 
popad
4027,7 → 4027,7
 
no_unmask_io:
 
popad ; end enable io map
popad ; end enable io map
sti
 
mov edi,[RESERVED_PORTS]
4087,7 → 4087,7
 
; disable port access at port IO map
 
pushad ; start disable io map
pushad ; start disable io map
 
cmp ecx,65536 ;16384
jge no_mask_io
4098,7 → 4098,7
 
pushad
 
mov ebp,1 ; disable - eax = port
mov ebp,1 ; disable - eax = port
call set_io_access_rights
 
popad
4109,7 → 4109,7
 
no_mask_io:
 
popad ; end disable io map
popad ; end disable io map
 
xor eax, eax
ret
4203,7 → 4203,7
 
align 4
 
syscall_putimage: ; PutImage
syscall_putimage: ; PutImage
sys_putimage:
test ecx,0x80008000
jnz .exit
4214,40 → 4214,40
.exit:
ret
@@:
mov edi,[current_slot]
add dx,word[edi+APPDATA.wnd_clientbox.top]
rol edx,16
add dx,word[edi+APPDATA.wnd_clientbox.left]
rol edx,16
mov edi,[current_slot]
add dx,word[edi+APPDATA.wnd_clientbox.top]
rol edx,16
add dx,word[edi+APPDATA.wnd_clientbox.left]
rol edx,16
.forced:
push ebp esi 0
mov ebp, putimage_get24bpp
mov esi, putimage_init24bpp
push ebp esi 0
mov ebp, putimage_get24bpp
mov esi, putimage_init24bpp
sys_putimage_bpp:
; call [disable_mouse] ; this will be done in xxx_putimage
; mov eax, vga_putimage
cmp [SCR_MODE], word 0x12
jz @f ;.doit
mov eax, vesa12_putimage
cmp [SCR_MODE], word 0100000000000000b
jae @f
cmp [SCR_MODE], word 0x13
jnz .doit
cmp [SCR_MODE], word 0x12
jz @f ;.doit
mov eax, vesa12_putimage
cmp [SCR_MODE], word 0100000000000000b
jae @f
cmp [SCR_MODE], word 0x13
jnz .doit
@@:
mov eax, vesa20_putimage
mov eax, vesa20_putimage
.doit:
inc [mouse_pause]
call eax
dec [mouse_pause]
pop ebp esi ebp
jmp [draw_pointer]
inc [mouse_pause]
call eax
dec [mouse_pause]
pop ebp esi ebp
jmp [draw_pointer]
 
syscall_putimage_palette:
mov edi, esi
mov esi, edx
mov edx, ecx
mov ecx, ebx
mov ebx, eax
mov edi, esi
mov esi, edx
mov edx, ecx
mov ecx, ebx
mov ebx, eax
sys_putimage_palette:
; ebx = pointer to image
; ecx = [xsize]*65536 + [ysize]
4255,12 → 4255,12
; esi = number of bits per pixel, must be 8, 24 or 32
; edi = pointer to palette
; ebp = row delta
mov eax, [CURRENT_TASK]
shl eax, 8
add dx, word [eax+SLOT_BASE+APPDATA.wnd_clientbox.top]
rol edx, 16
add dx, word [eax+SLOT_BASE+APPDATA.wnd_clientbox.left]
rol edx, 16
mov eax, [CURRENT_TASK]
shl eax, 8
add dx, word [eax+SLOT_BASE+APPDATA.wnd_clientbox.top]
rol edx, 16
add dx, word [eax+SLOT_BASE+APPDATA.wnd_clientbox.left]
rol edx, 16
.forced:
cmp esi, 1
jnz @f
4315,20 → 4315,20
mov esi, putimage_init16bpp
jmp sys_putimage_bpp
@@:
cmp esi, 24
jnz @f
mov ebp, putimage_get24bpp
mov esi, putimage_init24bpp
jmp sys_putimage_bpp
cmp esi, 24
jnz @f
mov ebp, putimage_get24bpp
mov esi, putimage_init24bpp
jmp sys_putimage_bpp
@@:
cmp esi, 32
jnz @f
mov ebp, putimage_get32bpp
mov esi, putimage_init32bpp
jmp sys_putimage_bpp
cmp esi, 32
jnz @f
mov ebp, putimage_get32bpp
mov esi, putimage_init32bpp
jmp sys_putimage_bpp
@@:
pop ebp esi ebp
ret
pop ebp esi ebp
ret
 
put_mono_image:
push ebp esi ebp
4347,53 → 4347,53
jmp sys_putimage_bpp
 
putimage_init24bpp:
lea eax, [eax*3]
lea eax, [eax*3]
putimage_init8bpp:
ret
ret
 
align 16
putimage_get24bpp:
movzx eax, byte [esi+2]
shl eax, 16
mov ax, [esi]
add esi, 3
ret 4
movzx eax, byte [esi+2]
shl eax, 16
mov ax, [esi]
add esi, 3
ret 4
align 16
putimage_get8bpp:
movzx eax, byte [esi]
push edx
mov edx, [esp+8]
mov eax, [edx+eax*4]
pop edx
inc esi
ret 4
movzx eax, byte [esi]
push edx
mov edx, [esp+8]
mov eax, [edx+eax*4]
pop edx
inc esi
ret 4
 
putimage_init1bpp:
add eax, ecx
push ecx
add eax, 7
add ecx, 7
shr eax, 3
shr ecx, 3
sub eax, ecx
pop ecx
ret
add eax, ecx
push ecx
add eax, 7
add ecx, 7
shr eax, 3
shr ecx, 3
sub eax, ecx
pop ecx
ret
align 16
putimage_get1bpp:
push edx
mov edx, [esp+8]
mov al, [edx]
add al, al
jnz @f
lodsb
adc al, al
push edx
mov edx, [esp+8]
mov al, [edx]
add al, al
jnz @f
lodsb
adc al, al
@@:
mov [edx], al
sbb eax, eax
and eax, [edx+8]
add eax, [edx+4]
pop edx
ret 4
mov [edx], al
sbb eax, eax
and eax, [edx+8]
add eax, [edx+4]
pop edx
ret 4
 
putimage_init2bpp:
add eax, ecx
4428,44 → 4428,44
ret 4
 
putimage_init4bpp:
add eax, ecx
push ecx
add ecx, 1
add eax, 1
shr ecx, 1
shr eax, 1
sub eax, ecx
pop ecx
ret
add eax, ecx
push ecx
add ecx, 1
add eax, 1
shr ecx, 1
shr eax, 1
sub eax, ecx
pop ecx
ret
align 16
putimage_get4bpp:
push edx
mov edx, [esp+8]
add byte [edx], 80h
jc @f
movzx eax, byte [edx+1]
mov edx, [edx+4]
and eax, 0x0F
mov eax, [edx+eax*4]
pop edx
ret 4
push edx
mov edx, [esp+8]
add byte [edx], 80h
jc @f
movzx eax, byte [edx+1]
mov edx, [edx+4]
and eax, 0x0F
mov eax, [edx+eax*4]
pop edx
ret 4
@@:
movzx eax, byte [esi]
add esi, 1
mov [edx+1], al
shr eax, 4
mov edx, [edx+4]
mov eax, [edx+eax*4]
pop edx
ret 4
movzx eax, byte [esi]
add esi, 1
mov [edx+1], al
shr eax, 4
mov edx, [edx+4]
mov eax, [edx+eax*4]
pop edx
ret 4
 
putimage_init32bpp:
shl eax, 2
ret
shl eax, 2
ret
align 16
putimage_get32bpp:
lodsd
ret 4
lodsd
ret 4
 
putimage_init15bpp:
putimage_init16bpp:
4512,25 → 4512,25
; eax x beginning
; ebx y beginning
; ecx x end
; edx y end
; edx y end
; edi color
 
__sys_drawbar:
mov esi,[current_slot]
add eax,[esi+APPDATA.wnd_clientbox.left]
add ecx,[esi+APPDATA.wnd_clientbox.left]
add ebx,[esi+APPDATA.wnd_clientbox.top]
add edx,[esi+APPDATA.wnd_clientbox.top]
mov esi,[current_slot]
add eax,[esi+APPDATA.wnd_clientbox.left]
add ecx,[esi+APPDATA.wnd_clientbox.left]
add ebx,[esi+APPDATA.wnd_clientbox.top]
add edx,[esi+APPDATA.wnd_clientbox.top]
.forced:
inc [mouse_pause]
; call [disable_mouse]
cmp [SCR_MODE],word 0x12
je dbv20
je dbv20
sdbv20:
cmp [SCR_MODE],word 0100000000000000b
jge dbv20
cmp [SCR_MODE],word 0x13
je dbv20
je dbv20
call vesa12_drawbar
dec [mouse_pause]
call [draw_pointer]
4545,36 → 4545,36
 
kb_read:
 
push ecx edx
push ecx edx
 
mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's
mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's
kr_loop:
in al,0x64
test al,1
jnz kr_ready
loop kr_loop
mov ah,1
jmp kr_exit
in al,0x64
test al,1
jnz kr_ready
loop kr_loop
mov ah,1
jmp kr_exit
kr_ready:
push ecx
mov ecx,32
push ecx
mov ecx,32
kr_delay:
loop kr_delay
pop ecx
in al,0x60
xor ah,ah
loop kr_delay
pop ecx
in al,0x60
xor ah,ah
kr_exit:
 
pop edx ecx
pop edx ecx
 
ret
ret
 
 
kb_write:
 
push ecx edx
push ecx edx
 
mov dl,al
mov dl,al
; mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's
; kw_loop1:
; in al,0x64
4584,75 → 4584,75
; mov ah,1
; jmp kw_exit
; kw_ok1:
in al,0x60
mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's
in al,0x60
mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's
kw_loop:
in al,0x64
test al,2
jz kw_ok
loop kw_loop
mov ah,1
jmp kw_exit
in al,0x64
test al,2
jz kw_ok
loop kw_loop
mov ah,1
jmp kw_exit
kw_ok:
mov al,dl
out 0x60,al
mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's
mov al,dl
out 0x60,al
mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's
kw_loop3:
in al,0x64
test al,2
jz kw_ok3
loop kw_loop3
mov ah,1
jmp kw_exit
in al,0x64
test al,2
jz kw_ok3
loop kw_loop3
mov ah,1
jmp kw_exit
kw_ok3:
mov ah,8
mov ah,8
kw_loop4:
mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's
mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's
kw_loop5:
in al,0x64
test al,1
jnz kw_ok4
loop kw_loop5
dec ah
jnz kw_loop4
in al,0x64
test al,1
jnz kw_ok4
loop kw_loop5
dec ah
jnz kw_loop4
kw_ok4:
xor ah,ah
xor ah,ah
kw_exit:
 
pop edx ecx
pop edx ecx
 
ret
ret
 
 
kb_cmd:
 
mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's
mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's
c_wait:
in al,0x64
test al,2
jz c_send
loop c_wait
jmp c_error
in al,0x64
test al,2
jz c_send
loop c_wait
jmp c_error
c_send:
mov al,bl
out 0x64,al
mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's
mov al,bl
out 0x64,al
mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's
c_accept:
in al,0x64
test al,2
jz c_ok
loop c_accept
in al,0x64
test al,2
jz c_ok
loop c_accept
c_error:
mov ah,1
jmp c_exit
mov ah,1
jmp c_exit
c_ok:
xor ah,ah
xor ah,ah
c_exit:
ret
ret
 
 
setmouse: ; set mousepicture -pointer
; ps2 mouse enable
; ps2 mouse enable
 
mov [MOUSE_PICTURE],dword mousepointer
 
4674,60 → 4674,60
 
rerouteirqs:
 
cli
cli
 
mov al,0x11 ; icw4, edge triggered
out 0x20,al
call pic_delay
out 0xA0,al
call pic_delay
mov al,0x11 ; icw4, edge triggered
out 0x20,al
call pic_delay
out 0xA0,al
call pic_delay
 
mov al,0x20 ; generate 0x20 +
out 0x21,al
call pic_delay
mov al,0x28 ; generate 0x28 +
out 0xA1,al
call pic_delay
mov al,0x20 ; generate 0x20 +
out 0x21,al
call pic_delay
mov al,0x28 ; generate 0x28 +
out 0xA1,al
call pic_delay
 
mov al,0x04 ; slave at irq2
out 0x21,al
call pic_delay
mov al,0x02 ; at irq9
out 0xA1,al
call pic_delay
mov al,0x04 ; slave at irq2
out 0x21,al
call pic_delay
mov al,0x02 ; at irq9
out 0xA1,al
call pic_delay
 
mov al,0x01 ; 8086 mode
out 0x21,al
call pic_delay
out 0xA1,al
call pic_delay
mov al,0x01 ; 8086 mode
out 0x21,al
call pic_delay
out 0xA1,al
call pic_delay
 
mov al,255 ; mask all irq's
out 0xA1,al
call pic_delay
out 0x21,al
call pic_delay
mov al,255 ; mask all irq's
out 0xA1,al
call pic_delay
out 0x21,al
call pic_delay
 
mov ecx,0x1000
cld
picl1: call pic_delay
loop picl1
mov ecx,0x1000
cld
picl1: call pic_delay
loop picl1
 
mov al,255 ; mask all irq's
out 0xA1,al
call pic_delay
out 0x21,al
call pic_delay
mov al,255 ; mask all irq's
out 0xA1,al
call pic_delay
out 0x21,al
call pic_delay
 
cli
cli
 
ret
ret
 
 
pic_delay:
 
jmp pdl1
pdl1: ret
jmp pdl1
pdl1: ret
 
 
sys_msg_board_str:
4749,43 → 4749,43
; in: al = byte to display
; out: nothing
; destroys: nothing
pushad
mov ecx, 2
shl eax, 24
jmp @f
pushad
mov ecx, 2
shl eax, 24
jmp @f
 
sys_msg_board_word:
; in: ax = word to display
; out: nothing
; destroys: nothing
pushad
mov ecx, 4
shl eax, 16
jmp @f
pushad
mov ecx, 4
shl eax, 16
jmp @f
 
sys_msg_board_dword:
; in: eax = dword to display
; out: nothing
; destroys: nothing
pushad
mov ecx, 8
pushad
mov ecx, 8
@@:
push ecx
rol eax, 4
push eax
and al, 0xF
cmp al, 10
sbb al, 69h
das
mov bl, al
xor eax, eax
inc eax
call sys_msg_board
pop eax
pop ecx
loop @b
popad
ret
push ecx
rol eax, 4
push eax
and al, 0xF
cmp al, 10
sbb al, 69h
das
mov bl, al
xor eax, eax
inc eax
call sys_msg_board
pop eax
pop ecx
loop @b
popad
ret
 
uglobal
msg_board_data: times 4096 db 0
4797,9 → 4797,9
; eax=1 : write : bl byte to write
; eax=2 : read : ebx=0 -> no data, ebx=1 -> data in al
 
mov ecx, [msg_board_count]
cmp eax, 1
jne .smbl1
mov ecx, [msg_board_count]
cmp eax, 1
jne .smbl1
 
if defined debug_com_base
 
4827,30 → 4827,30
mov [check_idle_semaphore], 5
ret
.smbl1:
cmp eax, 2
jne .smbl2
test ecx, ecx
jz .smbl21
mov eax, msg_board_data+1
mov ebx, msg_board_data
movzx edx, byte [ebx]
call memmove
dec [msg_board_count]
mov [esp + 36], edx ;eax
mov [esp + 24], dword 1
ret
cmp eax, 2
jne .smbl2
test ecx, ecx
jz .smbl21
mov eax, msg_board_data+1
mov ebx, msg_board_data
movzx edx, byte [ebx]
call memmove
dec [msg_board_count]
mov [esp + 36], edx ;eax
mov [esp + 24], dword 1
ret
.smbl21:
mov [esp+36], ecx
mov [esp+24], ecx
mov [esp+36], ecx
mov [esp+24], ecx
.smbl2:
ret
ret
 
 
 
sys_process_def:
mov edi, [CURRENT_TASK]
mov edi, [CURRENT_TASK]
 
dec eax ; 1 = set keyboard mode
dec eax ; 1 = set keyboard mode
jne no_set_keyboard_setup
 
shl edi,8
4860,7 → 4860,7
 
no_set_keyboard_setup:
 
dec eax ; 2 = get keyboard mode
dec eax ; 2 = get keyboard mode
jne no_get_keyboard_setup
 
shl edi,8
4872,7 → 4872,7
 
no_get_keyboard_setup:
 
dec eax ; 3 = get keyboard ctrl, alt, shift
dec eax ; 3 = get keyboard ctrl, alt, shift
jne no_get_keyboard_cas
 
; xor eax,eax
4894,70 → 4894,70
 
no_get_keyboard_cas:
 
dec eax
jnz no_add_keyboard_hotkey
dec eax
jnz no_add_keyboard_hotkey
 
mov eax, hotkey_list
mov eax, hotkey_list
@@:
cmp dword [eax+8], 0
jz .found_free
add eax, 16
cmp eax, hotkey_list+16*256
jb @b
mov dword [esp+36], 1
ret
cmp dword [eax+8], 0
jz .found_free
add eax, 16
cmp eax, hotkey_list+16*256
jb @b
mov dword [esp+36], 1
ret
.found_free:
mov [eax+8], edi
mov [eax+4], ecx
movzx ebx, bl
lea ebx, [hotkey_scancodes+ebx*4]
mov ecx, [ebx]
mov [eax], ecx
mov [ebx], eax
mov [eax+12], ebx
jecxz @f
mov [ecx+12], eax
mov [eax+8], edi
mov [eax+4], ecx
movzx ebx, bl
lea ebx, [hotkey_scancodes+ebx*4]
mov ecx, [ebx]
mov [eax], ecx
mov [ebx], eax
mov [eax+12], ebx
jecxz @f
mov [ecx+12], eax
@@:
and dword [esp+36], 0
ret
and dword [esp+36], 0
ret
 
no_add_keyboard_hotkey:
 
dec eax
jnz no_del_keyboard_hotkey
dec eax
jnz no_del_keyboard_hotkey
 
movzx ebx, bl
lea ebx, [hotkey_scancodes+ebx*4]
mov eax, [ebx]
movzx ebx, bl
lea ebx, [hotkey_scancodes+ebx*4]
mov eax, [ebx]
.scan:
test eax, eax
jz .notfound
cmp [eax+8], edi
jnz .next
cmp [eax+4], ecx
jz .found
test eax, eax
jz .notfound
cmp [eax+8], edi
jnz .next
cmp [eax+4], ecx
jz .found
.next:
mov eax, [eax]
jmp .scan
mov eax, [eax]
jmp .scan
.notfound:
mov dword [esp+36], 1
ret
mov dword [esp+36], 1
ret
.found:
mov ecx, [eax]
jecxz @f
mov edx, [eax+12]
mov [ecx+12], edx
mov ecx, [eax]
jecxz @f
mov edx, [eax+12]
mov [ecx+12], edx
@@:
mov ecx, [eax+12]
mov edx, [eax]
mov [ecx], edx
xor edx, edx
mov [eax+4], edx
mov [eax+8], edx
mov [eax+12], edx
mov [eax], edx
mov [esp+36], edx
ret
mov ecx, [eax+12]
mov edx, [eax]
mov [ecx], edx
xor edx, edx
mov [eax+4], edx
mov [eax+8], edx
mov [eax+12], edx
mov [eax], edx
mov [esp+36], edx
ret
 
no_del_keyboard_hotkey:
ret
4965,9 → 4965,9
 
align 4
 
sys_gs: ; direct screen access
sys_gs: ; direct screen access
 
cmp eax,1 ; resolution
cmp eax,1 ; resolution
jne no_gs1
mov eax,[Screen_Max_X]
shl eax,16
4977,7 → 4977,7
ret
no_gs1:
 
cmp eax,2 ; bits per pixel
cmp eax,2 ; bits per pixel
jne no_gs2
movzx eax,byte [ScreenBPP]
mov [esp+36],eax
4984,7 → 4984,7
ret
no_gs2:
 
cmp eax,3 ; bytes per scanline
cmp eax,3 ; bytes per scanline
jne no_gs3
mov eax,[BytesPerScanLine]
mov [esp+36],eax
5006,110 → 5006,110
 
align 4 ; system functions
 
syscall_setpixel: ; SetPixel
syscall_setpixel: ; SetPixel
 
mov eax, ebx
mov ebx, ecx
mov ecx, edx
mov edx, [TASK_BASE]
add eax, [edx-twdw+WDATA.box.left]
add ebx, [edx-twdw+WDATA.box.top]
mov edi, [current_slot]
add eax, [edi+APPDATA.wnd_clientbox.left]
add ebx, [edi+APPDATA.wnd_clientbox.top]
xor edi, edi ; no force
mov eax, ebx
mov ebx, ecx
mov ecx, edx
mov edx, [TASK_BASE]
add eax, [edx-twdw+WDATA.box.left]
add ebx, [edx-twdw+WDATA.box.top]
mov edi, [current_slot]
add eax, [edi+APPDATA.wnd_clientbox.left]
add ebx, [edi+APPDATA.wnd_clientbox.top]
xor edi, edi ; no force
; mov edi, 1
call [disable_mouse]
jmp [putpixel]
call [disable_mouse]
jmp [putpixel]
 
align 4
 
syscall_writetext: ; WriteText
syscall_writetext: ; WriteText
 
mov eax,[TASK_BASE]
mov ebp,[eax-twdw+WDATA.box.left]
push esi
mov esi,[current_slot]
add ebp,[esi+APPDATA.wnd_clientbox.left]
shl ebp,16
add ebp,[eax-twdw+WDATA.box.top]
add bp,word[esi+APPDATA.wnd_clientbox.top]
pop esi
add ebx,ebp
mov eax,edi
xor edi,edi
jmp dtext
mov eax,[TASK_BASE]
mov ebp,[eax-twdw+WDATA.box.left]
push esi
mov esi,[current_slot]
add ebp,[esi+APPDATA.wnd_clientbox.left]
shl ebp,16
add ebp,[eax-twdw+WDATA.box.top]
add bp,word[esi+APPDATA.wnd_clientbox.top]
pop esi
add ebx,ebp
mov eax,edi
xor edi,edi
jmp dtext
 
align 4
 
syscall_openramdiskfile: ; OpenRamdiskFile
syscall_openramdiskfile: ; OpenRamdiskFile
 
mov eax, ebx
mov ebx, ecx
mov ecx, edx
mov edx, esi
mov esi, 12
call fileread
mov [esp+32], eax
ret
mov eax, ebx
mov ebx, ecx
mov ecx, edx
mov edx, esi
mov esi, 12
call fileread
mov [esp+32], eax
ret
 
align 4
 
syscall_drawrect: ; DrawRect
syscall_drawrect: ; DrawRect
 
mov edi, edx ; color + gradient
and edi, 0x80FFFFFF
test bx, bx ; x.size
je .drectr
test cx, cx ; y.size
je .drectr
mov edi, edx ; color + gradient
and edi, 0x80FFFFFF
test bx, bx ; x.size
je .drectr
test cx, cx ; y.size
je .drectr
 
mov eax, ebx ; bad idea
mov ebx, ecx
mov eax, ebx ; bad idea
mov ebx, ecx
 
movzx ecx, ax ; ecx - x.size
shr eax, 16 ; eax - x.coord
movzx edx, bx ; edx - y.size
shr ebx, 16 ; ebx - y.coord
mov esi, [current_slot]
movzx ecx, ax ; ecx - x.size
shr eax, 16 ; eax - x.coord
movzx edx, bx ; edx - y.size
shr ebx, 16 ; ebx - y.coord
mov esi, [current_slot]
 
add eax, [esi + APPDATA.wnd_clientbox.left]
add ebx, [esi + APPDATA.wnd_clientbox.top]
add ecx, eax
add edx, ebx
jmp [drawbar]
add eax, [esi + APPDATA.wnd_clientbox.left]
add ebx, [esi + APPDATA.wnd_clientbox.top]
add ecx, eax
add edx, ebx
jmp [drawbar]
.drectr:
ret
ret
 
align 4
syscall_getscreensize: ; GetScreenSize
mov ax, [Screen_Max_X]
shl eax, 16
mov ax, [Screen_Max_Y]
mov [esp + 32], eax
ret
syscall_getscreensize: ; GetScreenSize
mov ax, [Screen_Max_X]
shl eax, 16
mov ax, [Screen_Max_Y]
mov [esp + 32], eax
ret
 
align 4
 
syscall_cdaudio: ; CD
syscall_cdaudio: ; CD
 
cmp eax, 4
jb .audio
jz .eject
cmp eax, 5
jnz .ret
cmp eax, 4
jb .audio
jz .eject
cmp eax, 5
jnz .ret
.load:
call .reserve
call LoadMedium
call .free
ret
call .reserve
call LoadMedium
call .free
ret
.eject:
call .reserve
call clear_CD_cache
call allow_medium_removal
call EjectMedium
call .free
ret
call .reserve
call clear_CD_cache
call allow_medium_removal
call EjectMedium
call .free
ret
.audio:
call sys_cd_audio
mov [esp+36],eax
5117,39 → 5117,39
ret
 
.reserve:
call reserve_cd
mov eax, ebx
shr eax, 1
and eax, 1
inc eax
mov [ChannelNumber], ax
mov eax, ebx
and eax, 1
mov [DiskNumber], al
call reserve_cd_channel
and ebx, 3
inc ebx
mov [cdpos], ebx
add ebx, ebx
mov cl, 8
sub cl, bl
mov al, [DRIVE_DATA+1]
shr al, cl
test al, 2
jz .err
ret
call reserve_cd
mov eax, ebx
shr eax, 1
and eax, 1
inc eax
mov [ChannelNumber], ax
mov eax, ebx
and eax, 1
mov [DiskNumber], al
call reserve_cd_channel
and ebx, 3
inc ebx
mov [cdpos], ebx
add ebx, ebx
mov cl, 8
sub cl, bl
mov al, [DRIVE_DATA+1]
shr al, cl
test al, 2
jz .err
ret
.free:
call free_cd_channel
and [cd_status], 0
ret
call free_cd_channel
and [cd_status], 0
ret
.err:
call .free
pop eax
ret
call .free
pop eax
ret
 
align 4
 
syscall_getpixel: ; GetPixel
syscall_getpixel: ; GetPixel
mov ecx, [Screen_Max_X]
inc ecx
xor edx, edx
5169,10 → 5169,10
;ecx = [size x]*65536 + [size y]
;edx = [start x]*65536 + [start y]
pushad
inc [mouse_pause]
inc [mouse_pause]
; Check of use of the hardware cursor.
cmp [disable_mouse],__sys_disable_mouse
jne @f
jne @f
; Since the test for the coordinates of the mouse should not be used,
; then use the call [disable_mouse] is not possible!
cmp dword [MOUSE_VISIBLE],dword 0
5197,22 → 5197,22
and edx,0xffff
mov esi,ecx
; ecx - size x, edx - size y
mov ebp,edx
dec ebp
mov ebp,edx
dec ebp
lea ebp,[ebp*3]
imul ebp,esi
mov esi,ecx
dec esi
lea esi,[esi*3]
imul ebp,esi
mov esi,ecx
dec esi
lea esi,[esi*3]
add ebp,esi
add ebp,edi
 
add ebx,edx
.start_y:
push ecx edx
.start_x:
5229,15 → 5229,15
sub ebp,3
dec ecx
jnz .start_x
pop edx ecx
dec ebx
pop edx ecx
dec ebx
dec edx
jnz .start_y
dec [mouse_pause]
dec [mouse_pause]
; Check of use of the hardware cursor.
cmp [disable_mouse],__sys_disable_mouse
jne @f
call [draw_pointer]
jne @f
call [draw_pointer]
@@:
popad
ret
5244,31 → 5244,31
 
align 4
 
syscall_drawline: ; DrawLine
syscall_drawline: ; DrawLine
 
mov edi, [TASK_BASE]
movzx eax, word[edi-twdw+WDATA.box.left]
mov ebp, eax
mov esi, [current_slot]
add ebp, [esi+APPDATA.wnd_clientbox.left]
add ax, word[esi+APPDATA.wnd_clientbox.left]
add ebp,ebx
shl eax, 16
movzx ebx, word[edi-twdw+WDATA.box.top]
add eax, ebp
mov ebp, ebx
add ebp, [esi+APPDATA.wnd_clientbox.top]
add bx, word[esi+APPDATA.wnd_clientbox.top]
add ebp, ecx
shl ebx, 16
xor edi, edi
add ebx, ebp
mov ecx, edx
jmp [draw_line]
mov edi, [TASK_BASE]
movzx eax, word[edi-twdw+WDATA.box.left]
mov ebp, eax
mov esi, [current_slot]
add ebp, [esi+APPDATA.wnd_clientbox.left]
add ax, word[esi+APPDATA.wnd_clientbox.left]
add ebp,ebx
shl eax, 16
movzx ebx, word[edi-twdw+WDATA.box.top]
add eax, ebp
mov ebp, ebx
add ebp, [esi+APPDATA.wnd_clientbox.top]
add bx, word[esi+APPDATA.wnd_clientbox.top]
add ebp, ecx
shl ebx, 16
xor edi, edi
add ebx, ebp
mov ecx, edx
jmp [draw_line]
 
align 4
 
syscall_getirqowner: ; GetIrqOwner
syscall_getirqowner: ; GetIrqOwner
 
cmp ebx,16
jae .err
5286,7 → 5286,7
 
align 4
 
syscall_reserveportarea: ; ReservePortArea and FreePortArea
syscall_reserveportarea: ; ReservePortArea and FreePortArea
 
call r_f_port_area
mov [esp+36],eax
5294,7 → 5294,7
 
align 4
 
syscall_threads: ; CreateThreads
syscall_threads: ; CreateThreads
 
call sys_threads
mov [esp+36],eax
5303,7 → 5303,7
 
align 4
 
read_from_hd: ; Read from hd - fn not in use
read_from_hd: ; Read from hd - fn not in use
 
mov edi,[TASK_BASE]
add edi,TASKDATA.mem_start
5318,53 → 5318,53
ret
 
paleholder:
ret
ret
 
align 4
set_screen:
cmp eax, [Screen_Max_X]
jne .set
cmp eax, [Screen_Max_X]
jne .set
 
cmp edx, [Screen_Max_Y]
jne .set
ret
cmp edx, [Screen_Max_Y]
jne .set
ret
.set:
pushfd
cli
pushfd
cli
 
mov [Screen_Max_X], eax
mov [Screen_Max_Y], edx
mov [Screen_Max_X], eax
mov [Screen_Max_Y], edx
 
mov [screen_workarea.right],eax
mov [screen_workarea.bottom], edx
inc eax
shl eax, 2 ;32 bpp
mov [BytesPerScanLine], eax
push ebx
push esi
push edi
call repos_windows
mov eax, 0
mov ebx, 0
mov ecx, [Screen_Max_X]
mov edx, [Screen_Max_Y]
call calculatescreen
pop edi
pop esi
pop ebx
mov [screen_workarea.right],eax
mov [screen_workarea.bottom], edx
inc eax
shl eax, 2 ;32 bpp
mov [BytesPerScanLine], eax
push ebx
push esi
push edi
call repos_windows
mov eax, 0
mov ebx, 0
mov ecx, [Screen_Max_X]
mov edx, [Screen_Max_Y]
call calculatescreen
pop edi
pop esi
pop ebx
 
popfd
ret
popfd
ret
 
; --------------- APM ---------------------
apm_entry dp 0
apm_vf dd 0
apm_vf dd 0
align 4
sys_apm:
cmp word [apm_vf], 0 ; Check APM BIOS enable
jne @f
or [esp + 48], byte 1 ; error
mov [esp + 36], dword 8 ; 32-bit protected-mode interface not supported
or [esp + 48], byte 1 ; error
mov [esp + 36], dword 8 ; 32-bit protected-mode interface not supported
ret
 
@@:
5372,7 → 5372,7
xchg ebx, ecx
 
cmp al, 3
ja @f
ja @f
and [esp + 48], byte 0xfe ; emulate func 0..3 as func 0
mov eax, [apm_vf]
mov [esp + 36], eax
5386,9 → 5386,9
xchg [master_tab], esi
push esi
mov edi, cr3
mov cr3, edi ;flush TLB
mov cr3, edi ;flush TLB
 
call pword [apm_entry] ; call APM BIOS
call pword [apm_entry] ; call APM BIOS
 
xchg eax, [esp]
mov [master_tab], eax
5404,7 → 5404,7
mov [esp + 36], eax
setc al
and [esp + 48], byte 0xfe
or [esp + 48], al
or [esp + 48], al
 
 
ret
5412,248 → 5412,248
 
align 4
 
undefined_syscall: ; Undefined system call
undefined_syscall: ; Undefined system call
mov [esp + 32], dword -1
ret
 
align 4
system_shutdown: ; shut down the system
system_shutdown: ; shut down the system
 
cmp byte [BOOT_VAR+0x9030], 1
jne @F
ret
cmp byte [BOOT_VAR+0x9030], 1
jne @F
ret
@@:
call stop_all_services
push 3 ; stop playing cd
pop eax
call sys_cd_audio
call stop_all_services
push 3 ; stop playing cd
pop eax
call sys_cd_audio
 
yes_shutdown_param:
cli
cli
 
mov eax, kernel_file ; load kernel.mnt to 0x7000:0
push 12
pop esi
xor ebx,ebx
or ecx,-1
mov edx, OS_BASE+0x70000
call fileread
mov eax, kernel_file ; load kernel.mnt to 0x7000:0
push 12
pop esi
xor ebx,ebx
or ecx,-1
mov edx, OS_BASE+0x70000
call fileread
 
mov esi, restart_kernel_4000+OS_BASE+0x10000 ; move kernel re-starter to 0x4000:0
mov edi,OS_BASE+0x40000
mov ecx,1000
rep movsb
mov esi, restart_kernel_4000+OS_BASE+0x10000 ; move kernel re-starter to 0x4000:0
mov edi,OS_BASE+0x40000
mov ecx,1000
rep movsb
 
mov esi,OS_BASE+0x2F0000 ; restore 0x0 - 0xffff
mov edi, OS_BASE
mov ecx,0x10000/4
cld
rep movsd
mov esi,OS_BASE+0x2F0000 ; restore 0x0 - 0xffff
mov edi, OS_BASE
mov ecx,0x10000/4
cld
rep movsd
 
call restorefatchain
call restorefatchain
 
mov al, 0xFF
out 0x21, al
out 0xA1, al
mov al, 0xFF
out 0x21, al
out 0xA1, al
 
if 0
mov word [OS_BASE+0x467+0],pr_mode_exit
mov word [OS_BASE+0x467+2],0x1000
mov word [OS_BASE+0x467+0],pr_mode_exit
mov word [OS_BASE+0x467+2],0x1000
 
mov al,0x0F
out 0x70,al
mov al,0x05
out 0x71,al
mov al,0x0F
out 0x70,al
mov al,0x05
out 0x71,al
 
mov al,0xFE
out 0x64,al
mov al,0xFE
out 0x64,al
 
hlt
jmp $-1
hlt
jmp $-1
 
else
cmp byte [OS_BASE + 0x9030], 2
jnz no_acpi_power_off
cmp byte [OS_BASE + 0x9030], 2
jnz no_acpi_power_off
 
; scan for RSDP
; 1) The first 1 Kb of the Extended BIOS Data Area (EBDA).
movzx eax, word [OS_BASE + 0x40E]
shl eax, 4
jz @f
mov ecx, 1024/16
call scan_rsdp
jnc .rsdp_found
movzx eax, word [OS_BASE + 0x40E]
shl eax, 4
jz @f
mov ecx, 1024/16
call scan_rsdp
jnc .rsdp_found
@@:
; 2) The BIOS read-only memory space between 0E0000h and 0FFFFFh.
mov eax, 0xE0000
mov ecx, 0x2000
call scan_rsdp
jc no_acpi_power_off
mov eax, 0xE0000
mov ecx, 0x2000
call scan_rsdp
jc no_acpi_power_off
.rsdp_found:
mov esi, [eax+16] ; esi contains physical address of the RSDT
mov ebp, [ipc_tmp]
stdcall map_page, ebp, esi, PG_MAP
lea eax, [esi+1000h]
lea edx, [ebp+1000h]
stdcall map_page, edx, eax, PG_MAP
and esi, 0xFFF
add esi, ebp
cmp dword [esi], 'RSDT'
jnz no_acpi_power_off
mov ecx, [esi+4]
sub ecx, 24h
jbe no_acpi_power_off
shr ecx, 2
add esi, 24h
mov esi, [eax+16] ; esi contains physical address of the RSDT
mov ebp, [ipc_tmp]
stdcall map_page, ebp, esi, PG_MAP
lea eax, [esi+1000h]
lea edx, [ebp+1000h]
stdcall map_page, edx, eax, PG_MAP
and esi, 0xFFF
add esi, ebp
cmp dword [esi], 'RSDT'
jnz no_acpi_power_off
mov ecx, [esi+4]
sub ecx, 24h
jbe no_acpi_power_off
shr ecx, 2
add esi, 24h
.scan_fadt:
lodsd
mov ebx, eax
lea eax, [ebp+2000h]
stdcall map_page, eax, ebx, PG_MAP
lea eax, [ebp+3000h]
add ebx, 0x1000
stdcall map_page, eax, ebx, PG_MAP
and ebx, 0xFFF
lea ebx, [ebx+ebp+2000h]
cmp dword [ebx], 'FACP'
jz .fadt_found
loop .scan_fadt
jmp no_acpi_power_off
lodsd
mov ebx, eax
lea eax, [ebp+2000h]
stdcall map_page, eax, ebx, PG_MAP
lea eax, [ebp+3000h]
add ebx, 0x1000
stdcall map_page, eax, ebx, PG_MAP
and ebx, 0xFFF
lea ebx, [ebx+ebp+2000h]
cmp dword [ebx], 'FACP'
jz .fadt_found
loop .scan_fadt
jmp no_acpi_power_off
.fadt_found:
; ebx is linear address of FADT
mov edi, [ebx+40] ; physical address of the DSDT
lea eax, [ebp+4000h]
stdcall map_page, eax, edi, PG_MAP
lea eax, [ebp+5000h]
lea esi, [edi+0x1000]
stdcall map_page, eax, esi, PG_MAP
and esi, 0xFFF
sub edi, esi
cmp dword [esi+ebp+4000h], 'DSDT'
jnz no_acpi_power_off
mov eax, [esi+ebp+4004h] ; DSDT length
sub eax, 36+4
jbe no_acpi_power_off
add esi, 36
mov edi, [ebx+40] ; physical address of the DSDT
lea eax, [ebp+4000h]
stdcall map_page, eax, edi, PG_MAP
lea eax, [ebp+5000h]
lea esi, [edi+0x1000]
stdcall map_page, eax, esi, PG_MAP
and esi, 0xFFF
sub edi, esi
cmp dword [esi+ebp+4000h], 'DSDT'
jnz no_acpi_power_off
mov eax, [esi+ebp+4004h] ; DSDT length
sub eax, 36+4
jbe no_acpi_power_off
add esi, 36
.scan_dsdt:
cmp dword [esi+ebp+4000h], '_S5_'
jnz .scan_dsdt_cont
cmp byte [esi+ebp+4000h+4], 12h ; DefPackage opcode
jnz .scan_dsdt_cont
mov dl, [esi+ebp+4000h+6]
cmp dl, 4 ; _S5_ package must contain 4 bytes
; ...in theory; in practice, VirtualBox has 2 bytes
ja .scan_dsdt_cont
cmp dl, 1
jb .scan_dsdt_cont
lea esi, [esi+ebp+4000h+7]
xor ecx, ecx
cmp byte [esi], 0 ; 0 means zero byte, 0Ah xx means byte xx
jz @f
cmp byte [esi], 0xA
jnz no_acpi_power_off
inc esi
mov cl, [esi]
cmp dword [esi+ebp+4000h], '_S5_'
jnz .scan_dsdt_cont
cmp byte [esi+ebp+4000h+4], 12h ; DefPackage opcode
jnz .scan_dsdt_cont
mov dl, [esi+ebp+4000h+6]
cmp dl, 4 ; _S5_ package must contain 4 bytes
; ...in theory; in practice, VirtualBox has 2 bytes
ja .scan_dsdt_cont
cmp dl, 1
jb .scan_dsdt_cont
lea esi, [esi+ebp+4000h+7]
xor ecx, ecx
cmp byte [esi], 0 ; 0 means zero byte, 0Ah xx means byte xx
jz @f
cmp byte [esi], 0xA
jnz no_acpi_power_off
inc esi
mov cl, [esi]
@@:
inc esi
cmp dl, 2
jb @f
cmp byte [esi], 0
jz @f
cmp byte [esi], 0xA
jnz no_acpi_power_off
inc esi
mov ch, [esi]
inc esi
cmp dl, 2
jb @f
cmp byte [esi], 0
jz @f
cmp byte [esi], 0xA
jnz no_acpi_power_off
inc esi
mov ch, [esi]
@@:
jmp do_acpi_power_off
jmp do_acpi_power_off
.scan_dsdt_cont:
inc esi
cmp esi, 0x1000
jb @f
sub esi, 0x1000
add edi, 0x1000
push eax
lea eax, [ebp+4000h]
stdcall map_page, eax, edi, PG_MAP
push PG_MAP
lea eax, [edi+1000h]
push eax
lea eax, [ebp+5000h]
push eax
stdcall map_page
pop eax
inc esi
cmp esi, 0x1000
jb @f
sub esi, 0x1000
add edi, 0x1000
push eax
lea eax, [ebp+4000h]
stdcall map_page, eax, edi, PG_MAP
push PG_MAP
lea eax, [edi+1000h]
push eax
lea eax, [ebp+5000h]
push eax
stdcall map_page
pop eax
@@:
dec eax
jnz .scan_dsdt
jmp no_acpi_power_off
dec eax
jnz .scan_dsdt
jmp no_acpi_power_off
do_acpi_power_off:
mov edx, [ebx+48]
test edx, edx
jz .nosmi
mov al, [ebx+52]
out dx, al
mov edx, [ebx+64]
mov edx, [ebx+48]
test edx, edx
jz .nosmi
mov al, [ebx+52]
out dx, al
mov edx, [ebx+64]
@@:
in ax, dx
test al, 1
jz @b
in ax, dx
test al, 1
jz @b
.nosmi:
and cx, 0x0707
shl cx, 2
or cx, 0x2020
mov edx, [ebx+64]
in ax, dx
and ax, 203h
or ah, cl
out dx, ax
mov edx, [ebx+68]
test edx, edx
jz @f
in ax, dx
and ax, 203h
or ah, ch
out dx, ax
and cx, 0x0707
shl cx, 2
or cx, 0x2020
mov edx, [ebx+64]
in ax, dx
and ax, 203h
or ah, cl
out dx, ax
mov edx, [ebx+68]
test edx, edx
jz @f
in ax, dx
and ax, 203h
or ah, ch
out dx, ax
@@:
jmp $
jmp $
 
 
no_acpi_power_off:
mov word [OS_BASE+0x467+0],pr_mode_exit
mov word [OS_BASE+0x467+2],0x1000
mov word [OS_BASE+0x467+0],pr_mode_exit
mov word [OS_BASE+0x467+2],0x1000
 
mov al,0x0F
out 0x70,al
mov al,0x05
out 0x71,al
mov al,0x0F
out 0x70,al
mov al,0x05
out 0x71,al
 
mov al,0xFE
out 0x64,al
mov al,0xFE
out 0x64,al
 
hlt
jmp $-1
hlt
jmp $-1
 
scan_rsdp:
add eax, OS_BASE
add eax, OS_BASE
.s:
cmp dword [eax], 'RSD '
jnz .n
cmp dword [eax+4], 'PTR '
jnz .n
xor edx, edx
xor esi, esi
cmp dword [eax], 'RSD '
jnz .n
cmp dword [eax+4], 'PTR '
jnz .n
xor edx, edx
xor esi, esi
@@:
add dl, [eax+esi]
inc esi
cmp esi, 20
jnz @b
test dl, dl
jz .ok
add dl, [eax+esi]
inc esi
cmp esi, 20
jnz @b
test dl, dl
jz .ok
.n:
add eax, 10h
loop .s
stc
add eax, 10h
loop .s
stc
.ok:
ret
ret
end if
 
include "data32.inc"
/kernel/branches/net/network/ARP.inc
221,7 → 221,7
mov ecx, 60 ; minimum packet size
mov edx, edi ;;;
mov di , ETHER_ARP
call ETH_create_Packet
call ETH_create_packet
cmp edi, -1
je .exit
 
248,7 → 248,7
DEBUGF 1,"ARP Packet for device %x created successfully\n", ebx
 
push edx ecx
jmp ETH_Sender
jmp ETH_sender
 
.exit:
add esp, 8
555,7 → 555,7
 
DEBUGF 1,"ARP_Handler - Sending reply \n"
 
jmp ETH_Sender ; And send it!
jmp ETH_sender ; And send it!
 
.exit:
call kernel_free
/kernel/branches/net/network/IPv4.inc
3,7 → 3,7
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; IP.INC ;;
;; IPv4.INC ;;
;; ;;
;; Part of the tcp/ip network stack for KolibriOS ;;
;; ;;
52,7 → 52,7
.PrevPtr dd ? ; Pointer to previous fragment entry (-1 for first packet)
.NextPtr dd ? ; Pointer to next fragment entry (-1 for last packet)
.Owner dd ? ; Pointer to structure of driver
rb 2 ; to match ethernet header size
rb 2 ; to match ethernet header size ; TODO: fix this hack
.Data: ; Ip header begins here (we will need the IP header to re-construct the complete packet)
ends
 
99,10 → 99,9
 
;-----------------------------------------------------------------
;
; IP_Handler:
; IPv4_Handler:
;
; Called by eth_handler,
; will check if IP Packet isnt damaged
; Will check if IP Packet isnt damaged
; and call appropriate handler. (TCP/UDP/ICMP/..)
;
; It will also re-construct fragmented packets
119,21 → 118,28
IPv4_handler:
 
DEBUGF 1,"IP_Handler - start\n"
mov cx , [edx + IPv4_Packet.HeaderChecksum]
xchg ch , cl ; Get the checksum in intel format
mov word [edx + IPv4_Packet.HeaderChecksum], 0 ; Clear checksum field to recalculating checksum
 
movzx eax, byte [edx + IPv4_Packet.VersionAndIHL] ; Calculate Header length by using IHL field
and eax, 0x0000000F ;
shl eax, 2 ;
push edx ebx
 
push edx
stdcall checksum_jb, edx, eax ; buf_ptr, buf_size
pop edx
cmp cx , ax
jnz .dump ; if CHECKSUM isn't valid then dump Packet
; save checksum, and clear it in original packet
mov di , [edx + IPv4_Packet.HeaderChecksum]
DEBUGF 1,"checksum: %x\n",di
mov word [edx + IPv4_Packet.HeaderChecksum], 0
 
; Re-calculate checksum
movzx ecx, byte [edx + IPv4_Packet.VersionAndIHL] ; Calculate Header length by using IHL field
and ecx, 0x0000000F ;
shl cx , 2 ;
mov esi, edx
xor edx, edx
call checksum_1
call checksum_2
 
; now compare the two..
cmp dx, di
pop ebx edx
jne .dump ; if checksum isn't valid then dump packet
 
mov eax, [edx + IPv4_Packet.DestinationAddress]
mov edi, BROADCAST
mov ecx, MAX_IP+1
183,10 → 189,14
add eax, edx
push eax
mov al , [edx + IPv4_Packet.Protocol]
;----------------------- experimental
mov esi, [edx + IPv4_Packet.SourceAddress]
mov edi, [edx + IPv4_Packet.DestinationAddress]
;-----------------------
pop edx ; Offset to data (tcp/udp/icmp/.. Packet)
 
cmp al , IP_PROTO_TCP
; je TCP_handler
je TCP_handler
 
cmp al , IP_PROTO_UDP
je UDP_handler
385,14 → 395,21
movzx eax, byte [edx + IPv4_Packet.VersionAndIHL] ; Calculate Header length by using IHL field
and ax, 0x000F ;
shl ax, 2 ;
sub ecx, eax ;
 
sub ecx, eax
 
 
add eax, edx
push eax
mov al , [edx + IPv4_Packet.Protocol]
;----------------------- experimental
mov esi, [edx + IPv4_Packet.SourceAddress]
mov edi, [edx + IPv4_Packet.DestinationAddress]
;-----------------------
pop edx ; Offset to data (tcp/udp/icmp/.. Packet)
 
cmp al , IP_PROTO_TCP
; je TCP_handler
je TCP_handler
 
cmp al , IP_PROTO_UDP
je UDP_handler
493,12 → 510,12
; dx = fragment id
; di = protocol
;
; OUT: eax points to buffer start
; ebx is size of complete buffer
; edi = pointer to start of data (-1 on error)
; OUT: eax = pointer to buffer start
; ebx = pointer to device struct (needed for sending procedure)
; ecx = unchanged (packet size of embedded data)
; edx = pointer to device struct (needed for sending procedure)
; edx = size of complete buffer
; esi = pointer to sending procedure
; edi = pointer to start of data (-1 on error)
;
;-----------------------------------------------------------------
 
550,7 → 567,7
mov ecx, [esp+18] ;; 18 or 22 ??
add ecx, IPv4_Packet.DataOrOptional
mov di , ETHER_IPv4
call ETH_create_Packet ; TODO: figure out a way to make this work with other protocols too
call ETH_create_packet ; TODO: figure out a way to make this work with other protocols too
add esp, 6
cmp edi, -1
je .exit
571,14 → 588,18
pop ecx
mov [edi + IPv4_Packet.DestinationAddress], ecx
 
push eax
stdcall checksum_jb, edi, IPv4_Packet.DataOrOptional ; buf_ptr, buf_size
xchg al, ah
mov [edi + IPv4_Packet.HeaderChecksum], ax
pop eax ecx
push eax ebx edx
; calculate checksum
xor edx, edx
mov esi, edi
mov ecx, IPv4_Packet.DataOrOptional
call checksum_1
call checksum_2
mov [edi + IPv4_Packet.HeaderChecksum], dx
pop edx ebx eax ecx
add edi, IPv4_Packet.DataOrOptional
 
DEBUGF 1,"IPv4 Packet for device %x created successfully\n", edx
DEBUGF 1,"IPv4 Packet for device %x created successfully\n", ebx
 
ret
 
585,7 → 606,7
 
.not_found:
DEBUGF 1,"Create IPv4 Packet - ARP entry not found!\n"
; TODO: QUEUE!
; TODO: QUEUE the packet to resend later!
.exit:
add esp, 16
.exit_:
/kernel/branches/net/network/ethernet.inc
80,14 → 80,9
mov ecx, (1+MAX_ETH_DEVICES)
rep stosd
 
mov dword [ETH_IN_QUEUE], ETH_QUEUE_SIZE
mov dword [ETH_IN_QUEUE+4], ETH_IN_QUEUE + queue.data
mov dword [ETH_IN_QUEUE+8], ETH_IN_QUEUE + queue.data
init_queue ETH_IN_QUEUE
init_queue ETH_OUT_QUEUE
 
mov dword [ETH_OUT_QUEUE], ETH_QUEUE_SIZE
mov dword [ETH_OUT_QUEUE+4], ETH_OUT_QUEUE + queue.data
mov dword [ETH_OUT_QUEUE+8], ETH_OUT_QUEUE + queue.data
 
ret
 
 
104,7 → 99,7
;---------------------------------------------------------
 
align 4
ETH_Add_Device:
ETH_add_device:
 
DEBUGF 1,"ETH_Add_Device: %x ", ebx
 
122,7 → 117,6
mov ecx, MAX_ETH_DEVICES ; We need to check whole list because a device may be removed without re-organizing list
mov edi, ETH_DRV_LIST
 
cld
repne scasd ; See if device is already in the list
jz .error
 
167,7 → 161,7
;--------------------------------
 
align 4
ETH_Remove_Device:
ETH_remove_device:
 
cmp [ETH_RUNNING], 0
je .error
212,12 → 206,21
;-------------------------------------------------------------
 
align 4
ETH_Receiver:
DEBUGF 1,"ETH_Receiver \n"
ETH_receiver:
DEBUGF 1,"ETH_Receiver: "
 
add_to_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, .gohome
push ebx
mov esi, esp
add_to_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .fail
DEBUGF 1,"Queued packet successfully\n"
add esp, 4*3
ret
 
.gohome:
.fail:
DEBUGF 1,"ETH_IN_QUEUE is full!\n"
add esp, 4
call kernel_free
add esp, 4
ret
 
 
238,8 → 241,19
align 4
ETH_handler:
 
get_from_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, .gohome
get_from_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .gohome
 
push ETH_handler
 
lodsd
mov ebx, eax
lodsd
mov ecx, eax
lodsd
xchg eax, ecx
push ecx
push eax
 
DEBUGF 1,"ETH_Handler - size: %u\n", ecx
cmp ecx, 60 ; check packet length
jl .dump
262,13 → 276,13
add esp, 4
 
.gohome:
ret ; return 1. to get more from queue / 2. to caller
ret ; return to get more from queue / to caller
 
 
 
;-----------------------------------------------------------------
;
; ETH_Sender:
; ETH_sender:
;
; This function sends an ethernet packet to the correct driver.
;
280,35 → 294,66
;-----------------------------------------------------------------
 
align 4
ETH_Sender:
DEBUGF 1,"ETH_Sender \n"
ETH_sender:
DEBUGF 1,"ETH_Sender: queuing for device: %x, %u bytes\n", [esp], [esp + 4]
 
add_to_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, .gohome
push ebx
mov esi, esp
add_to_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .fail
DEBUGF 1,"Queued packet successfully\n"
add esp, 3*4
ret
 
.gohome:
.fail:
DEBUGF 1,"ETH_OUT_QUEUE is full!\n"
add esp, 4
call kernel_free
add esp, 4
ret
 
 
 
;-----------------------------------------------------------------
;
; ETH_send_queued:
;
; IN: /
; OUT: /
;
;-----------------------------------------------------------------
 
align 4
ETH_send_queued:
 
get_from_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, .gohome
get_from_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .gohome
 
call ETH_struc2dev ; convert struct ptr to device num (this way we know if driver is still mounted)
push ETH_send_queued
 
lodsd
mov ebx, eax
 
sub esp, 8
mov edi, esp
movsd
movsd
 
DEBUGF 1,"dequeued packet for device %x\n", ebx
 
call ETH_struc2dev ; convert struct ptr to device num (this way we know if driver is still mounted)
cmp edi, -1
je .fail
 
DEBUGF 1,"ETH_Sender - device: %u\n", edi
jmp [ebx+ETH_DEVICE.transmit] ; we will return to get_from_queue macro after transmitting packet
 
jmp [ebx+ETH_DEVICE.transmit]
 
.fail:
call kernel_free
add esp, 4 ; pop (balance stack)
DEBUGF 1,"ETH_Sender - fail\n"
 
.gohome:
ret
 
 
;---------------------------------------------------------------------------
;
; ETH_struc2dev
362,7 → 407,7
;---------------------------------------------------------------------------
 
align 4
ETH_create_Packet:
ETH_create_packet:
 
DEBUGF 1,"Creating Ethernet Packet (size=%u): \n", ecx
 
394,7 → 439,7
lea eax, [edi - ETH_FRAME.Data] ; Set eax to buffer start
mov edx, ecx ; Set ebx to complete buffer size
pop ecx
mov esi, ETH_Sender
mov esi, ETH_sender
 
xor ebx, ebx ;;;; TODO: Fixme
mov ebx, [ETH_DRV_LIST + ebx]
/kernel/branches/net/network/icmp.inc
133,8 → 133,8
;
; ICMP_Handler:
;
; Called by IP_handler,
; this procedure will send reply's to ICMP echo's etc ;;; TODO: update this to work with fragmented packets too!
; this procedure will send reply's to ICMP echo's
; and insert packets into sockets when needed ;;; TODO: update this to work with fragmented packets too!
;
; IN: Pointer to buffer in [esp]
; size of buffer in [esp+4]
181,33 → 181,31
mov dword [esi + ETH_FRAME.Data + IPv4_Packet.SourceAddress], ecx
 
; Recalculate ip header checksum
; mov esi, [esp]
add esi, ETH_FRAME.Data ; Point esi to start of IP Packet
movzx eax, byte [esi + IPv4_Packet.VersionAndIHL] ; Calculate IP Header length by using IHL field
and eax, 0x0000000F ;
shl eax, 2 ;
push ebx edx esi
stdcall checksum_jb, esi, eax ; calculate the checksum
pop esi edx ebx
xchg al, ah ; convert to intel byte order
; mov esi, [esp]
mov word [esi + IPv4_Packet.HeaderChecksum], ax ; Store it in the IP Packet header
movzx ecx, byte [esi + IPv4_Packet.VersionAndIHL] ; Calculate IP Header length by using IHL field
and ecx, 0x0000000F ;
shl cx , 2
push ebx edx ecx esi
xor edx, edx
call checksum_1
call checksum_2
pop esi
mov word [esi + IPv4_Packet.HeaderChecksum], dx ; Store it in the IP Packet header
 
; Recalculate ICMP CheckSum
; mov esi, [esp] ; Find length of IP Packet
movzx eax, word[esi + IPv4_Packet.TotalLength] ;
movzx eax, word[esi + IPv4_Packet.TotalLength] ; Find length of IP Packet
xchg ah , al ;
movzx edi, byte [esi + IPv4_Packet.VersionAndIHL] ; Calculate IP Header length by using IHL field
and edi, 0x0000000F ;
shl edi, 2 ;
sub ax , di ; Now we know the length of ICMP data in eax
push ebx edx
stdcall checksum_jb,edx,eax ; Calculate the checksum of icmp data
pop edx ebx
xchg al, ah ; Convert to intel byte order
sub eax, [esp] ; Now we know the length of ICMP data in eax
mov ecx, eax
mov esi, [esp + 4]
xor edx, edx
call checksum_1
call checksum_2
mov ax , dx
pop ecx edx ebx
mov word [edx + ICMP_Packet.Checksum], ax
 
jmp ETH_Sender ; Send the reply
jmp ETH_sender ; Send the reply
 
 
 
222,20 → 220,14
.try_more:
mov ax , [edx + ICMP_Packet.Identifier]
.next_socket:
mov esi, [esi + SOCKET.NextPtr]
mov esi, [esi + SOCKET_head.NextPtr]
or esi, esi
jz .dump
cmp [esi + SOCKET.Type], IP_PROTO_ICMP
cmp [esi + SOCKET_head.Type], IP_PROTO_ICMP
jne .next_socket
cmp [esi + SOCKET.LocalPort], ax
cmp [esi + SOCKET_head.end + IPv4_SOCKET.end + ICMP_SOCKET.Identifier], ax
jne .next_socket
 
cmp [esi + SOCKET.rxDataCount],0 ; get # of bytes already in buffer
jnz .dump ; only one packet at a time may be in the buffer!
 
cmp ecx, SOCKETBUFFSIZE - SOCKETHEADERSIZE; TODO: fix this problem !
jg .dump
 
call IPv4_dest_to_dev
cmp edi,-1
je .dump
243,60 → 235,25
 
DEBUGF 1,"Found valid ICMP packet for socket %x\n", esi
 
lea ebx, [esi + SOCKET.lock]
lea ebx, [esi + SOCKET_head.lock]
call wait_mutex
 
; Now, copy data to socket. We have socket address in esi.
; Now, assign data to socket. We have socket address in esi.
; We have ICMP Packet in edx
; number of bytes in ecx
 
; note: we do not strip the header!
 
DEBUGF 1,"bytes: %u\n", ecx
 
mov [esi + SOCKET.rxDataCount], ecx
 
lea edi, [esi + SOCKETHEADERSIZE]
push esi
push ecx
mov esi, edx
shr ecx, 2
rep movsd ; copy the data across
pop ecx
and ecx, 3
rep movsb
mov eax, esi
pop esi
add esp, 4
sub edx, esi
mov edi, edx
jmp socket_internal_receiver
 
DEBUGF 1,"ICMP socket updated\n"
 
mov [esi + SOCKET.lock], 0
 
; flag an event to the application
mov eax, [esi + SOCKET.PID] ; get socket owner PID
mov ecx, 1
mov esi, TASK_DATA + TASKDATA.pid
 
.next_pid:
cmp [esi], eax
je .found_pid
inc ecx
add esi, 0x20
cmp ecx, [TASK_COUNT]
jbe .next_pid
 
jmp .dump
 
.found_pid:
shl ecx, 8
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event
 
mov [check_idle_semaphore], 200
 
.dump:
DEBUGF 1,"ICMP_Handler - dumping\n"
 
call kernel_free
add esp, 8 ; pop (balance stack)
add esp, 4 ; pop (balance stack)
 
ret
 
351,7 → 308,7
DEBUGF 1,"ICMP_Handler_fragments - end\n"
 
call kernel_free
add esp, 8 ; pop (balance stack)
add esp, 4 ; pop (balance stack)
ret
 
;-----------------------------------------------------------------
397,11 → 354,14
mov [edi + ICMP_Packet.Identifier], ax
mov [edi + ICMP_Packet.Checksum], 0
 
stdcall checksum_jb, edi , ecx
xchg al, ah
mov [edi + ICMP_Packet.Checksum], ax
push eax ebx ecx edx
mov esi, edi
xor edx, edx
call checksum_1
call checksum_2
mov [edi + ICMP_Packet.Checksum], dx
pop edx ecx ebx eax esi
 
pop esi
sub ecx, ICMP_Packet.Data
add edi, ICMP_Packet.Data
push cx
/kernel/branches/net/network/queue.inc
15,13 → 15,13
$Revision$
 
struct queue
.size dd ?
.w_ptr dd ?
.r_ptr dd ?
.size dd ? ; number of queued packets in thsi queue
.w_ptr dd ? ; current writing pointer in queue
.r_ptr dd ? ; current reading pointer
.data:
ends
 
struct queue_entry
struct eth_queue_entry
.owner dd ?
.data_ptr dd ?
.data_size dd ?
28,75 → 28,84
.size:
ends
 
struct tcp_in_queue_entry
.data_ptr dd ?
.data_size dd ?
.offset dd ?
.size:
ends
 
macro add_to_queue ptr, size, returnaddr {
struct tcp_out_queue_entry
.data_ptr dd ?
.data_size dd ?
.ttl dd ?
.retries dd ?
.owner dd ?
.sendproc dd ?
.ack_num dd ?
.size:
ends
 
cmp dword [ptr + queue.size], size ; Check if queue isnt full
jge .fail
struct socket_queue_entry
.data_ptr dd ?
.data_size dd ?
.offset dd ?
.size:
ends
 
DEBUGF 1,"Queuing packet for device %x\n",ebx
macro add_to_queue ptr, size, entry_size, failaddr {
 
inc dword [ptr + queue.size]
cmp [ptr + queue.size], size ; Check if queue isnt full
jge failaddr
 
mov edi, dword [ptr + queue.w_ptr] ; Current write pointer (FIFO!)
inc [ptr + queue.size]
 
mov eax, ebx
stosd
pop eax
stosd
pop eax
stosd
mov edi, [ptr + queue.w_ptr] ; Current write pointer (FIFO!)
mov ecx, entry_size/4 ; Write the queue entry
rep movsd ;
 
cmp edi, size*queue_entry.size+ptr+queue.data ; entry size
lea ecx, [size*entry_size+ptr+queue.data]
cmp edi, ecx ; entry size
jl .no_wrap
 
sub edi, size*queue_entry.size
sub edi, size*entry_size
 
.no_wrap:
mov dword [ptr + queue.w_ptr], edi
jmp returnaddr
mov [ptr + queue.w_ptr], edi
 
.fail:
DEBUGF 1,"queuing failed\n"
 
call kernel_free
add esp, 4
ret
 
}
 
 
macro get_from_queue ptr, size, returnaddr {
 
.start_of_code:
cmp dword [ptr + queue.size], 0 ; any packets queued?
je returnaddr
macro get_from_queue ptr, size, entry_size, failaddr {
 
DEBUGF 1,"Dequeuing packet"
cmp [ptr + queue.size], 0 ; any packets queued?
je failaddr
 
dec dword [ptr + queue.size]
dec [ptr + queue.size]
 
push dword .start_of_code ; return address for call's
 
mov esi, [ptr + queue.r_ptr]
lodsd
mov ebx, eax
lodsd
mov ecx, eax
lodsd
push eax
push ecx
xchg eax, ecx
push esi
 
DEBUGF 1," for device %x\n", ebx
add esi, entry_size
 
cmp esi, size*queue_entry.size+ptr+queue.data ; entry size
lea ecx, [size*entry_size+ptr+queue.data]
cmp esi, ecx ; entry size
jl .no_wrap
 
sub esi, size*queue_entry.size
sub esi, size*entry_size
 
.no_wrap:
mov dword [ptr + queue.r_ptr], esi
 
pop esi
 
}
 
macro init_queue queue_ptr {
 
mov [queue_ptr + queue.size] , 0
lea esi, [queue_ptr + queue.data]
mov [queue_ptr + queue.w_ptr], esi
mov [queue_ptr + queue.r_ptr], esi
}
/kernel/branches/net/network/socket.inc
5,7 → 5,6
;; ;;
;; SOCKET.INC ;;
;; ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; based on code by mike.dld ;;
;; ;;
16,8 → 15,7
 
$Revision$
 
align 4
struct SOCKET
struct SOCKET_head
.PrevPtr dd ? ; pointer to previous socket in list
.NextPtr dd ? ; pointer to next socket in list
.Number dd ? ; socket number (unique within single process)
25,19 → 23,34
.Domain dd ? ; INET/UNIX/..
.Type dd ? ; RAW/UDP/TCP/...
.Protocol dd ? ; ICMP/IPv4/ARP/
.LocalIP dd ? ; local IP address
.RemoteIP dd ? ; remote IP address
.LocalPort dw ? ; local port (In INET byte order)
.RemotePort dw ? ; remote port (IN INET byte order
.lock dd ? ; lock mutex
.end:
ends
 
struct IPv4_SOCKET
.LocalIP dd ?
.RemoteIP dd ?
.SequenceNumber dd ?
 
; todo: add options (for func 8 and 9)
 
.end:
ends
 
struct TCP_SOCKET
 
.LocalPort dw ? ; In INET byte order
.RemotePort dw ? ; In INET byte order
 
.backlog dw ? ; Backlog
.OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state)
.OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state)
.rxDataCount dd ? ; rx data count
.TCBState dd ? ; TCB state
.TCBTimer dd ? ; TCB timer (seconds)
.ISS dd ? ; initial send sequence
.IRS dd ? ; initial receive sequence
.SND_UNA dd ? ; sequence number of unack'ed sent Packets
.SND_NXT dd ? ; bext send sequence number to use
.SND_NXT dd ? ; next send sequence number to use
.SND_WND dd ? ; send window
.RCV_NXT dd ? ; next receive sequence number to use
.RCV_WND dd ? ; receive window
44,17 → 57,40
.SEG_LEN dd ? ; segment length
.SEG_WND dd ? ; segment window
.wndsizeTimer dd ? ; window size timer
.lock dd ? ; lock mutex
.backlog dw ? ; Backlog
.rxData: ; receive data buffer here
 
.flags db ? ; packet flags
 
.end:
ends
 
MAX_backlog equ 20
struct UDP_SOCKET
 
; socket buffers
SOCKETBUFFSIZE equ 4096 ; state + config + buffer.
SOCKETHEADERSIZE equ SOCKET.rxData ; thus 4096 - SOCKETHEADERSIZE bytes data
.LocalPort dw ? ; In INET byte order
.RemotePort dw ? ; In INET byte order
 
.end:
ends
 
struct ICMP_SOCKET
 
.Identifier dw ? ;
 
.end:
 
ends
 
struct IPC_SOCKET
 
.ConnectedTo dd ? ; Socket number of other socket this one is connected to
 
.end:
 
ends
 
MAX_backlog equ 20 ; backlog for stream sockets
SOCKETBUFFSIZE equ 4096 ; in bytes
SOCKET_QUEUE_SIZE equ 10 ; maximum number ofincoming packets queued for 1 socket
 
uglobal
net_sockets rd 2
last_UDP_port dw ? ; These values give the number of the last used ephemeral port
110,6 → 146,10
jz socket_send ; 6
dec bl
jz socket_recv ; 7
dec bl
; jz socket_get_opt ; 8
dec bl
; jz socket_set_opt ; 9
 
s_error:
mov dword [esp+32],-1
139,9 → 179,9
or eax, eax
jz s_error
 
mov [eax + SOCKET.Domain], ecx
mov [eax + SOCKET.Type], edx
mov [eax + SOCKET.Protocol], esi
mov [eax + SOCKET_head.Domain], ecx
mov [eax + SOCKET_head.Type], edx
mov [eax + SOCKET_head.Protocol], esi
 
stdcall net_socket_addr_to_num, eax
DEBUGF 1,", socketnumber: %u\n", eax
153,6 → 193,10
 
 
 
 
 
 
 
;-----------------------------------------------
;
; SOCKET_bind
176,14 → 220,28
jl s_error
 
cmp word [edx], AF_INET4
jne s_error
je .af_inet4
 
cmp word [edx], AF_UNIX
je .af_unix
 
jmp s_error
 
.af_unix:
 
; TODO: write code here
 
 
mov dword [esp+32],0
ret
 
.af_inet4:
 
cmp esi, 6
jl s_error
 
mov ecx, [eax + SOCKET.Type]
mov ecx, [eax + SOCKET_head.Type]
 
mov bx, word [edx + 2]
DEBUGF 1,"local port: %x ",bx
test bx, bx
194,21 → 252,22
je s_error
jmp .got_port
 
.find_free:
.find_free:
 
call socket_find_port
test bx, bx
je s_error
 
.got_port:
.got_port:
DEBUGF 1,"using port: %x ",bx
mov word [eax + SOCKET.LocalPort], bx
mov word [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
 
mov ebx, dword [edx + 4]
mov dword [eax + SOCKET.LocalIP], ebx
mov dword [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP], ebx
 
DEBUGF 1,"local ip: %u.%u.%u.%u\n",\
[eax + SOCKET.LocalIP]:1,[eax + SOCKET.LocalIP + 1]:1,[eax + SOCKET.LocalIP + 2]:1,[eax + SOCKET.LocalIP + 3]:1
[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 0]:1,[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 1]:1,\
[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 2]:1,[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 3]:1
 
mov dword [esp+32],0
ret
249,32 → 308,33
cmp esi, 8
jl s_error
 
cmp [eax + SOCKET.Type], IP_PROTO_UDP
cmp [eax + SOCKET_head.Type], IP_PROTO_UDP
je .udp
 
cmp [eax + SOCKET.Type], IP_PROTO_ICMP
cmp [eax + SOCKET_head.Type], IP_PROTO_ICMP
je .icmp
 
cmp [eax + SOCKET.Type], IP_PROTO_TCP
cmp [eax + SOCKET_head.Type], IP_PROTO_TCP
je .tcp
 
jmp s_error
 
.udp:
.udp:
 
mov bx , word [edx + 2]
mov word [eax + SOCKET.RemotePort], bx
mov word [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], bx
DEBUGF 1,"remote port: %x ",bx
 
mov ebx, dword [edx + 4]
mov dword [eax + SOCKET.RemoteIP], ebx
mov dword [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], ebx
DEBUGF 1,"remote ip: %u.%u.%u.%u\n",[edx+4]:1,[edx+5]:1,[edx+6]:1,[edx+7]:1
 
mov dword [esp+32],0
ret
 
.icmp:
.icmp:
 
; TODO: write code here
 
ret
 
387,7 → 447,7
mov dx , 20
.ok:
 
mov [eax + SOCKET.backlog], dx
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], dx
 
; TODO: insert code for active connections like TCP
 
420,7 → 480,21
jz s_error
mov esi, eax
 
cmp [esi + SOCKET.backlog], 0
cmp word [esi + SOCKET_head.Domain], AF_INET4
je .af_inet4
 
jmp s_error
 
.af_inet4:
 
cmp [esi + SOCKET_head.Type], IP_PROTO_TCP
je .tcp
 
jmp s_error
 
.tcp:
 
cmp [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], 0
jz s_error
 
call net_socket_alloc
428,19 → 502,21
jz s_error
mov edi, eax
 
dec [esi + SOCKET.backlog]
dec [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog]
 
mov ecx, (SOCKET.rxData+3)/4
mov ecx, (SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.end+3)/4
push esi edi
rep movsd
pop edi esi
 
mov [edi + SOCKET.backlog], 0
mov [edi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], 0
 
; TODO: fill in structure in ecx
 
mov [esi + SOCKET.RemoteIP], 0
mov [esi + SOCKET.RemotePort], 0
mov [esi + SOCKET_head.end + IPv4_SOCKET.RemoteIP], 0
mov [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], 0
 
stdcall net_socket_addr_to_num, eax
stdcall net_socket_addr_to_num, edi
mov [esp+32], eax
 
ret
465,14 → 541,16
or eax, eax
jz s_error
 
cmp [eax + SOCKET_head.Domain], AF_INET4
jne s_error
 
cmp [eax + SOCKET.Type], IP_PROTO_UDP
cmp [eax + SOCKET_head.Type], IP_PROTO_UDP
je .udp
 
cmp [eax + SOCKET.Type], IP_PROTO_ICMP
cmp [eax + SOCKET_head.Type], IP_PROTO_ICMP
je .icmp
 
cmp [eax + SOCKET.Type], IP_PROTO_TCP
cmp [eax + SOCKET_head.Type], IP_PROTO_TCP
je .tcp
 
jmp s_error
479,12 → 557,7
 
.udp:
 
lea ebx, [eax + SOCKET.lock]
call wait_mutex
; TODO: mark the socket for deletion, using the mutex
 
stdcall net_socket_free, eax
 
mov dword [esp+32],0
ret
 
600,8 → 673,8
;
;
; IN: socket number in ecx
; addr in edx
; addrlen in esi
; addr to buffer in edx
; length of buffer in esi
; flags in edi
; OUT: eax is number of bytes copied, -1 on error
;
609,71 → 682,47
align 4
socket_recv:
 
DEBUGF 1,"Socket_receive: socknum: %u sockaddr: %x, length: %u, flags: %x\n",ecx,edx,esi,edi
DEBUGF 1,"Socket_receive: socknum: %u bufferaddress: %x, length: %u, flags: %x\n",ecx,edx,esi,edi
 
stdcall net_socket_num_to_addr, ecx ; get real socket address
or eax, eax
jz s_error
 
DEBUGF 1,"real socket address:%x\n", eax
DEBUGF 1,"Socket pointer: %x\n", eax
 
mov dword[esp+32], -1
get_from_queue (eax + 2048), SOCKET_QUEUE_SIZE, 4*3, s_error
 
mov edi, edx
mov ecx, [esi + socket_queue_entry.data_size]
 
lea ebx, [eax + SOCKET.lock]
call wait_mutex
DEBUGF 1,"Got %u bytes of data\n", ecx
 
mov ecx, [eax + SOCKET.rxDataCount] ; get count of bytes
DEBUGF 1,"bytes in socket:%u\n", ecx
test ecx, ecx ; if count of bytes is zero..
jz .exit ; exit function (eax will be zero)
cmp ecx, edx
jle .large_enough
DEBUGF 1,"Buffer too small...\n"
jmp s_error
.large_enough:
 
cmp ecx, esi ; if buffer size is larger then the bytes of data, copy all data
jle .copy_all_bytes
push [esi + socket_queue_entry.data_ptr]
mov esi, [esi + socket_queue_entry.offset]
add esi, [esp]
DEBUGF 1,"Source buffer: %x, real addr: %x\n", [esp], esi
 
sub ecx, esi ; store new count (data bytes in buffer - bytes we're about to copy)
mov [eax + SOCKET.rxDataCount], ecx ;
push ecx
mov edx, esi
mov dword[esp+32+4], ecx ; return number of bytes copied
 
call .start_copy ; copy to the application
shr ecx, 1
jnc .nb
movsb
.nb: shr ecx, 1
jnc .nw
movsw
.nw: rep movsd
 
mov dword[esp+32], edx
call kernel_free
 
lea edi, [eax + SOCKET.rxData] ; Now shift the remaining bytes to start of buffer
lea esi, [edi + edx]
mov ecx, [esp]
shr ecx, 2 ; divide eax by 4
rep movsd ; copy all full dwords
pop ecx
and ecx, 3
rep movsb ; copy remaining bytes
 
.exit:
mov [eax + SOCKET.lock], 0
ret
 
.copy_all_bytes:
mov dword[esp+32], ecx
mov [eax + SOCKET.rxDataCount], 0 ; store new count (zero)
push dword .exit ; this code results in same as commented out code
 
.start_copy:
DEBUGF 1,"copying %u bytes\n",ecx
 
lea esi, [eax + SOCKET.rxData]
push ecx
shr ecx, 2 ; divide eax by 4
rep movsd
pop ecx
and ecx, 3
rep movsb ; copy the rest bytes
 
ret ; exit, or go back to shift remaining bytes if any
 
 
 
;-----------------------------------------------
;
; SOCKET_send
695,87 → 744,100
or eax, eax
jz s_error
 
cmp word [eax + SOCKET.Domain], AF_INET4
cmp word [eax + SOCKET_head.Domain], AF_INET4
je .af_inet4
 
jmp s_error
 
;---------
.af_inet4:
DEBUGF 1,"Socket type:%u\n", [eax + SOCKET_head.Type]:4
 
DEBUGF 1,"Socket type:%u\n", [eax + SOCKET.Type]:4
cmp [eax + SOCKET_head.Type], IP_PROTO_TCP
je .tcp
 
cmp [eax + SOCKET.Type], IP_PROTO_UDP
cmp [eax + SOCKET_head.Type], IP_PROTO_UDP
je .udp
 
cmp [eax + SOCKET.Type], IP_PROTO_ICMP
je .icmp
cmp [eax + SOCKET_head.Type], SOCK_RAW
je .raw
 
cmp [eax + SOCKET.Type], IP_PROTO_TCP
je .tcp
 
jmp s_error
;--------
 
.udp:
 
DEBUGF 1,"type: UDP, "
 
cmp [eax + SOCKET.LocalPort],0
jne .port_ok
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort],0
jne @f
 
push esi
mov ecx, [eax + SOCKET.Type]
mov ecx, [eax + SOCKET_head.Type]
call socket_find_port
test bx, bx
pop esi
je s_error
mov [eax + SOCKET.LocalPort], bx
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
 
.port_ok:
@@:
 
mov ecx, esi
mov esi, edx
mov edx, dword [eax + SOCKET.LocalPort] ; load local port and remote port at once
DEBUGF 1,"local port: %x, remote port: %x\n",[eax + SOCKET.LocalPort]:4, [eax + SOCKET.RemotePort]:4
mov ebx, [eax + SOCKET.LocalIP]
mov eax, [eax + SOCKET.RemoteIP]
 
call UDP_create_packet
call UDP_socket_send
 
mov [esp+32], eax
ret
 
.icmp:
; note: for ICMP sockets the SOCKET.LocalPort is used as the 'Identifier' value for ICMP packets
; the application must add the header to the data, the kernel will fill in 'identifier' and 'checksum'
.tcp:
 
sub ecx, ICMP_Packet.Data
mov esi, edx
push ax
call IPv4_get_frgmnt_num
mov dx, ax
pop ax
shl edx, 16
mov dh , [esi + ICMP_Packet.Type]
mov dl , [esi + ICMP_Packet.Code]
mov di , [esi + ICMP_Packet.Identifier]
; mov [eax + SOCKET.LocalPort], di ; Set localport to the identifier number, so we can receive reply's
shl edi, 16
mov di , [esi + ICMP_Packet.SequenceNumber]
add esi, ICMP_Packet.Data
mov ebx, [eax + SOCKET.LocalIP]
mov eax, [eax + SOCKET.RemoteIP]
call ICMP_create_packet
mov [esp+32], eax
ret
 
;--------
.raw:
cmp [eax + SOCKET_head.Protocol], IP_PROTO_IP
je .raw_ip
 
cmp [eax + SOCKET_head.Protocol], IP_PROTO_ICMP
je .raw_icmp
 
jmp s_error
;--------
 
 
.raw_ip:
 
mov [esp+32], eax
ret
 
.tcp:
 
.raw_icmp:
 
; sub ecx, ICMP_Packet.Data
; mov esi, edx
; push ax
; call IPv4_get_frgmnt_num
; mov dx, ax
; pop ax
; shl edx, 16
; mov dh , [esi + ICMP_Packet.Type]
; mov dl , [esi + ICMP_Packet.Code]
; mov di , [esi + ICMP_Packet.Identifier]
; mov [eax + SOCKET.LocalPort], di ; Set localport to the identifier number, so we can receive reply's
; shl edi, 16
; mov di , [esi + ICMP_Packet.SequenceNumber]
; add esi, ICMP_Packet.Data
; mov ebx, [eax + SOCKET.LocalIP]
; mov eax, [eax + SOCKET.RemoteIP]
; call ICMP_create_packet
 
mov [esp+32], eax
ret
 
 
 
 
;-----------------------------------------------
;
; SOCKET_find_free_port (local port)
812,15 → 874,15
mov esi, net_sockets
 
.next_socket:
mov esi, [esi + SOCKET.NextPtr]
mov esi, [esi + SOCKET_head.NextPtr]
or esi, esi
jz .port_ok
 
cmp [esi + SOCKET.Type], ecx
cmp [esi + SOCKET_head.Type], ecx
jne .next_socket
 
rol bx, 8
cmp [esi + SOCKET.LocalPort], bx
cmp [esi + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
rol bx, 8 ; this doesnt change the zero flag, does it ?
jne .next_socket
 
852,14 → 914,14
mov esi, net_sockets
 
.next_socket:
mov esi, [esi + SOCKET.NextPtr]
mov esi, [esi + SOCKET_head.NextPtr]
or esi, esi
jz .port_ok
 
cmp [esi + SOCKET.Type], ecx
cmp [esi + SOCKET_head.Type], ecx
jne .next_socket
 
cmp [esi + SOCKET.LocalPort], bx
cmp [esi + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
jne .next_socket
 
xor ebx, ebx
868,20 → 930,19
ret
 
 
 
;-----------------------------------------------
;
; SOCKET_internal_receiver
;
; Checks if any socket wants the received data
; If so, update the socket
; Updates a socket with received data
;
; IN: eax = socket number
; ecx = number of bytes
; esi = pointer to beginning of data
; dx = Remote port (in INET byte order)
; edi = IP address of sender
; Note: the mutex must already be set !
;
; IN: eax = socket ptr
; ecx = size
; esi = pointer to buffer
; edi = offset
;
; OUT: xxx
;
;-----------------------------------------------
888,39 → 949,20
align 4
socket_internal_receiver:
 
DEBUGF 1,"internal socket receiver\n"
DEBUGF 1,"Internal socket receiver: buffer %x, offset: %x\n", esi, edi
 
lea ebx, [eax + SOCKET.lock]
call wait_mutex
push edi ; offset
push ecx ; size
push esi ; data_ptr
mov esi, esp
add_to_queue (eax + 2048), SOCKET_QUEUE_SIZE, 3*4, .full
DEBUGF 1,"Queued packet successfully\n"
add esp, 4*3
 
mov [eax + SOCKET.RemotePort], dx ; update remote port number
mov [eax + SOCKET.RemoteIP], edi
mov [eax + SOCKET_head.lock], 0
 
mov edx, [eax + SOCKET.rxDataCount] ; get # of bytes already in buffer
DEBUGF 1,"bytes already in socket: %u ", edx
 
lea edi, [ecx + edx] ; check for buffer overflow
cmp edi, SOCKETBUFFSIZE - SOCKETHEADERSIZE ;
jg .dump ;
 
lea edi, [eax + SOCKET.rxData + edx]
add [eax + SOCKET.rxDataCount], ecx ; increment the count of bytes in buffer
DEBUGF 1,"adding %u bytes\n", ecx
 
; copy the data across
push cx
shr ecx, 2
rep movsd
pop cx
and cx, 3
rep movsb
 
DEBUGF 1,"socket updated\n"
 
mov [eax + SOCKET.lock], 0
 
; flag an event to the application
mov edx, [eax + SOCKET.PID] ; get socket owner PID
mov edx, [eax + SOCKET_head.PID] ; get socket owner PID
mov ecx, 1
mov esi, TASK_DATA + TASKDATA.pid
 
935,18 → 977,20
 
.found_pid:
shl ecx, 8
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event
mov [check_idle_semaphore], 200
ret
 
.dump:
mov [eax + SOCKET.lock], 0
.full:
DEBUGF 1,"Socket %x is full!\n",eax
mov [eax + SOCKET_head.lock], 0
call kernel_free
add esp, 8
ret
 
 
 
 
 
; Allocate memory for socket data and put new socket into the list
; Newly created socket is initialized with calling PID and number and
; put into beginning of list (which is a fastest way).
963,6 → 1007,7
; zero-initialize allocated memory
push eax
mov edi, eax
 
mov ecx, SOCKETBUFFSIZE / 4
; cld
xor eax, eax
969,21 → 1014,23
rep stosd
pop eax
 
init_queue (eax + 2048)
 
; add socket to the list by changing pointers
mov ebx, net_sockets
push [ebx + SOCKET.NextPtr]
mov [ebx + SOCKET.NextPtr], eax
mov [eax + SOCKET.PrevPtr], ebx
push [ebx + SOCKET_head.NextPtr]
mov [ebx + SOCKET_head.NextPtr], eax
mov [eax + SOCKET_head.PrevPtr], ebx
pop ebx
mov [eax + SOCKET.NextPtr], ebx
mov [eax + SOCKET_head.NextPtr], ebx
or ebx, ebx
jz @f
mov [ebx + SOCKET.PrevPtr], eax
mov [ebx + SOCKET_head.PrevPtr], eax
 
@@: ; set socket owner PID to the one of calling process
mov ebx, [TASK_BASE]
mov ebx, [ebx + TASKDATA.pid]
mov [eax + SOCKET.PID], ebx
mov [eax + SOCKET_head.PID], ebx
 
; find first free socket number and use it
;mov edx, ebx
992,10 → 1039,10
.next_socket_number:
inc ecx
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
mov ebx, [ebx + SOCKET_head.NextPtr]
or ebx, ebx
jz .last_socket_number
cmp [ebx + SOCKET.Number], ecx
cmp [ebx + SOCKET_head.Number], ecx
jne .next_socket
;cmp [ebx + SOCKET.PID], edx
;jne .next_socket
1003,7 → 1050,7
jmp .next_socket_number
 
.last_socket_number:
mov [eax + SOCKET.Number], ecx
mov [eax + SOCKET_head.Number], ecx
 
.exit:
ret
1025,7 → 1072,7
;mov ecx, [TASK_BASE]
;mov ecx, [ecx + TASKDATA.pid]
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
mov ebx, [ebx + SOCKET_head.NextPtr]
or ebx, ebx
jz .error
cmp ebx, eax
1035,13 → 1082,16
 
; okay, we found the correct one
; remove it from the list first, changing pointers
mov ebx, [eax + SOCKET.NextPtr]
mov eax, [eax + SOCKET.PrevPtr]
mov [eax + SOCKET.NextPtr], ebx
mov ebx, [eax + SOCKET_head.NextPtr]
mov eax, [eax + SOCKET_head.PrevPtr]
mov [eax + SOCKET_head.NextPtr], ebx
or ebx, ebx
jz @f
mov [ebx + SOCKET.PrevPtr], eax
mov [ebx + SOCKET_head.PrevPtr], eax
 
lea ebx, [eax + SOCKET_head.lock]
call wait_mutex
 
@@: ; and finally free the memory structure used
stdcall kernel_free, [sockAddr]
ret
1070,10 → 1120,10
;mov ecx, [TASK_BASE]
;mov ecx, [ecx + TASKDATA.pid]
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
mov ebx, [ebx + SOCKET_head.NextPtr]
or ebx, ebx
jz .error
cmp [ebx + SOCKET.Number], eax
cmp [ebx + SOCKET_head.Number], eax
jne .next_socket
;cmp [ebx + SOCKET.PID], ecx
;jne .next_socket
1106,7 → 1156,7
;mov ecx, [TASK_BASE]
;mov ecx, [ecx + TASKDATA.pid]
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
mov ebx, [ebx + SOCKET_head.NextPtr]
or ebx, ebx
jz .error
cmp ebx, eax
1115,7 → 1165,7
;jne .next_socket
 
; okay, we found the correct one
mov eax, [ebx + SOCKET.Number]
mov eax, [ebx + SOCKET_head.Number]
ret
 
.error:
/kernel/branches/net/network/stack.inc
33,7 → 33,7
ETHER_ARP equ 0x0608
 
;AF_UNSPEC equ 0
;AF_UNIX equ 1
AF_UNIX equ 1
AF_INET4 equ 2
;AF_AX25 equ 3
;AF_IPX equ 4
64,7 → 64,7
include "IPv4.inc"
include "ethernet.inc"
include "socket.inc"
;include "tcp.inc"
include "tcp.inc"
include "udp.inc"
include "icmp.inc"
 
86,6 → 86,7
call IPv4_init
call ARP_init
call UDP_init
call TCP_init
call ICMP_init
call socket_init
 
115,20 → 116,20
cmp [ETH_RUNNING], 0
je .exit
 
call ETH_handler ; handle all queued ethernet packets
call ETH_send_queued
 
; Test for 10ms tick, call tcp timer
; Test for 10ms tick
mov eax, [timer_ticks]
cmp eax, [last_1hsTick]
je .exit
 
mov [last_1hsTick], eax
; call tcp_tx_handler
 
call ETH_handler ; handle all queued ethernet packets
call ETH_send_queued
call TCP_send_queued
 
.sec_tick:
 
; Test for 1 second event, call 1s timer functions
; Test for 1 second event
mov al, 0x0 ;second
out 0x70, al
in al, 0x71
139,7 → 140,7
 
call ARP_decrease_entry_ttls
call IPv4_decrease_fragment_ttls
; call tcp_tcb_handler
call TCP_decrease_socket_ttls
 
.exit:
ret
146,44 → 147,80
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Checksum [by Johnny_B]
;; IN:
;; buf_ptr=POINTER to buffer
;; buf_size=SIZE of buffer
;; OUT:
;; AX=16-bit checksum
;; Saves all used registers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc checksum_jb stdcall uses ebx esi ecx,\
buf_ptr:DWORD, buf_size:DWORD
 
xor eax, eax
xor ebx, ebx ;accumulator
mov esi, dword[buf_ptr]
mov ecx, dword[buf_size]
shr ecx, 1 ; ecx=ecx/2
jnc @f ; if CF==0 then size is even number
mov bh, byte[esi + ecx*2]
@@:
cld
 
.loop:
lodsw ;eax=word[esi],esi=esi+2
xchg ah,al ;cause must be a net byte-order
add ebx, eax
loop .loop
;-----------------------------------------------------------------
;
; checksum_1
;
; This is the first of two functions needed to calculate the TCP checksum.
;
; IN: edx = start offeset for semi-checksum
; esi = pointer to data
; ecx = data size
; OUT: edx = semi-checksum
;
;-----------------------------------------------------------------
 
mov eax, ebx
shr eax, 16
add ax, bx
not ax
align 4
checksum_1:
 
ret
endp
xor eax, eax
shr ecx, 1
pushf
.loop:
lodsw
xchg al, ah
add edx, eax
loop .loop
 
popf
jnc .end
 
lodsb
shl ax, 8
add edx, eax
 
.end:
 
ret
 
 
 
;-----------------------------------------------------------------
;
; checksum_2
;
; This function calculates the final ip/tcp/udp checksum for you
;
; IN: edx = semi-checksum
; OUT: dx = checksum (in INET byte order)
;
;-----------------------------------------------------------------
 
align 4
checksum_2:
 
mov ecx, edx
shr ecx, 16
and edx, 0xffff
add edx, ecx
mov eax, edx
shr eax, 16
add edx, eax
 
not dx
jnz .not_zero
dec dx
.not_zero:
xchg dl, dh
 
DEBUGF 1,"Checksum: %x\n",dx
 
ret
 
 
 
;----------------------------------------------------------------
;
; System function to work with network devices (73)
250,7 → 287,15
jmp .return
 
@@:
dec bl ; 4 = Get driver pointer
jnz @f
 
; ..;
 
 
@@:
; ... ; 5 Get driver name
 
.doesnt_exist:
DEBUGF 1,"sys_network: invalid device/function specified!\n"
mov eax, -1
/kernel/branches/net/network/tcp.inc
18,7 → 18,6
$Revision$
 
 
; TCP TCB states
TCB_LISTEN equ 1
TCB_SYN_SENT equ 2
TCB_SYN_RECEIVED equ 3
31,20 → 30,21
TCB_TIMED_WAIT equ 10
TCB_CLOSED equ 11
 
TH_FIN equ 0x01
TH_SYN equ 0x02
TH_RST equ 0x04
TH_PUSH equ 0x08
TH_ACK equ 0x10
TH_URG equ 0x20
TH_FIN equ 1 shl 0
TH_SYN equ 1 shl 1
TH_RST equ 1 shl 2
TH_PUSH equ 1 shl 3
TH_ACK equ 1 shl 4
TH_URG equ 1 shl 5
 
TWOMSL equ 10 ; # of secs to wait before closing socket
 
TCP_RETRIES equ 5 ; Number of times to resend a Packet
TCP_TIMEOUT equ 10 ; resend if not replied to in x hs
TCP_TIMEOUT equ 10 ; resend if not replied to in 1/100 s
 
TCP_QUEUE_SIZE equ 16
 
 
struct TCP_Packet
.SourcePort dw ?
.DestinationPort dw ?
65,14 → 65,55
TCP_PACKETS_TX rd MAX_IP
TCP_PACKETS_RX rd MAX_IP
 
TCP_IN_QUEUE rd 3*TCP_QUEUE_SIZE+3
TCP_OUT_QUEUE rd 3*TCP_QUEUE_SIZE+3
TCP_IN_QUEUE rd (tcp_in_queue_entry.size*TCP_QUEUE_SIZE+queue.data)/4
TCP_OUT_QUEUE dd ?
rd (tcp_out_queue_entry.size*TCP_QUEUE_SIZE)/4
endg
 
align 4
iglobal
 
TCBStateHandler:
 
dd stateTCB_LISTEN
dd stateTCB_SYN_SENT
dd stateTCB_SYN_RECEIVED
dd stateTCB_ESTABLISHED
dd stateTCB_FIN_WAIT_1
dd stateTCB_FIN_WAIT_2
dd stateTCB_CLOSE_WAIT
dd stateTCB_CLOSING
dd stateTCB_LAST_ACK
dd stateTCB_TIME_WAIT
dd stateTCB_CLOSED
 
endg
 
 
macro inc_INET reg {
 
inc byte [reg + 0]
adc byte [reg + 1], 0
adc byte [reg + 2], 0
adc byte [reg + 3], 0
 
}
 
 
macro add_INET reg {
 
rol ecx, 16
adc byte [reg + 0], ch
adc byte [reg + 1], cl
rol ecx, 16
adc byte [reg + 2], ch
adc byte [reg + 3], cl
 
}
 
 
 
 
;-----------------------------------------------------------------
;
; TCP_init
92,58 → 133,55
mov ecx, 2*MAX_IP
rep stosd
 
mov dword [TCP_IN_QUEUE], TCP_QUEUE_SIZE
mov dword [TCP_IN_QUEUE+4], TCP_IN_QUEUE + queue.data
mov dword [TCP_IN_QUEUE+8], TCP_IN_QUEUE + queue.data
init_queue TCP_IN_QUEUE
init_queue TCP_OUT_QUEUE
 
mov dword [TCP_OUT_QUEUE], TCP_QUEUE_SIZE
mov dword [TCP_OUT_QUEUE+4], TCP_OUT_QUEUE + queue.data
mov dword [TCP_OUT_QUEUE+8], TCP_OUT_QUEUE + queue.data
 
ret
 
 
;-----------------------------------------------------------------
;
; tcp_tcb_handler
; TCP_decrease_socket_ttls
;
; Handles sockets in the timewait state, closing them
; when the TCB timer expires
; IN: /
; OUT: /
;
;-----------------------------------------------------------------
 
align 4
tcp_tcb_handler:
TCP_decrease_socket_ttls:
; scan through all the sockets, decrementing active timers
 
mov ebx, net_sockets
 
cmp [ebx + SOCKET.NextPtr], 0
cmp [ebx + SOCKET_head.NextPtr], 0
je .exit
DEBUGF 1, "K : sockets:\n"
 
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
mov ebx, [ebx + SOCKET_head.NextPtr]
or ebx, ebx
jz .exit
 
cmp [ebx + SOCKET_head.Type], IP_PROTO_TCP
jne .next_socket
 
; DEBUGF 1, "K : %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState]
 
cmp [ebx + SOCKET.TCBTimer], 0
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBTimer], 0
jne .decrement_tcb
cmp [ebx + SOCKET.wndsizeTimer], 0
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 0
jne .decrement_wnd
jmp .next_socket
 
.decrement_tcb:
; decrement it, delete socket if TCB timer = 0 & socket in timewait state
dec [ebx + SOCKET.TCBTimer]
dec [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBTimer]
jnz .next_socket
 
cmp [ebx + SOCKET.TCBState], TCB_TIMED_WAIT
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT
jne .next_socket
 
push [ebx + SOCKET.PrevPtr]
push [ebx + SOCKET_head.PrevPtr]
stdcall net_socket_free, ebx
pop ebx
jmp .next_socket
150,7 → 188,7
 
.decrement_wnd:
; TODO - prove it works!
dec [ebx + SOCKET.wndsizeTimer]
dec [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer]
jmp .next_socket
 
.exit:
157,120 → 195,124
ret
 
 
;***************************************************************************
; Function
; tcp_tx_handler
 
;-----------------------------------------------------------------
;
; Description
; Handles queued TCP data
; This is a kernel function, called by stack_handler
; TCP_send_queued:
;
;***************************************************************************
; Decreases 'ttl' of tcp packets queued.
; if 'ttl' reaches 0, resend the packet and decrease 'retries'
; if 'retries' reaches zero, remove the queued packet
;
; IN: /
; OUT: /
;
;-----------------------------------------------------------------
 
align 4
tcp_tx_handler:
; decrement all resend buffers timers. If they
; expire, queue them for sending, and restart the timer.
; If the retries counter reach 0, delete the entry
TCP_send_queued:
 
mov esi, resendQ
mov ecx, 0
cmp [TCP_OUT_QUEUE], 0
je .exit
 
.next_resendq:
; cmp ecx, NUMRESENDENTRIES
je .exit ; None left
cmp dword[esi + 4], 0
jne @f ; found one
inc ecx
add esi, 8
jmp .next_resendq
mov eax, TCP_QUEUE_SIZE
mov ecx, [TCP_OUT_QUEUE]
mov esi, TCP_OUT_QUEUE+4
 
@@: ; we have one. decrement it's timer by 1
dec word[esi + 2]
jz @f
inc ecx
add esi, 8
jmp .next_resendq ; Timer not zero, so move on
.loop:
cmp [esi + tcp_out_queue_entry.data_ptr], 0
jnz .found_one
add esi, tcp_out_queue_entry.size
loop .loop
.exit:
ret
 
@@:
xor ebx, ebx
; restart timer, and decrement retries
; After the first resend, back of on next, by a factor of 5
mov [esi + 2], word TCP_TIMEOUT * 5
dec byte[esi + 1]
jnz @f
.found_one:
dec [esi + tcp_out_queue_entry.ttl]
jz .send_it
.find_next:
dec eax
jz .exit
jmp .loop
 
; retries now 0, so delete from queue
xchg [esi + 4], ebx
.send_it:
push eax ecx esi
 
@@: ; resend Packet
pushad
push [esi + tcp_out_queue_entry.data_size]
push [esi + tcp_out_queue_entry.data_ptr]
mov ebx, [esi + tcp_out_queue_entry.owner]
 
; mov eax, EMPTY_QUEUE
; call dequeue
; cmp ax, NO_BUFFER
jne .tth004z
call [esi + tcp_out_queue_entry.sendproc]
 
; TODO - try again in 10ms.
test ebx, ebx
jnz @f
mov [esi + 4], ebx
pop esi ecx eax
 
@@: ; Mark it to expire in 10ms - 1 tick
mov byte[esi + 1], 1
mov word[esi + 2], 1
jmp .tth005
dec [esi + tcp_out_queue_entry.retries]
jz .remove_it
mov [esi + tcp_out_queue_entry.ttl], TCP_TIMEOUT
jmp .find_next
 
.tth004z:
; we have a buffer # in ax
; push eax ecx
; mov ecx, IPBUFFSIZE
; mul ecx
; add eax, IPbuffs
.remove_it:
push [esi + tcp_out_queue_entry.data_ptr]
mov [esi + tcp_out_queue_entry.data_ptr], 0
dec [TCP_OUT_QUEUE]
call kernel_free
jmp .find_next
 
; we have the buffer address in eax
mov edi, eax
pop ecx
; Now get buffer location, and copy buffer across. argh! more copying,,
; mov esi, resendBuffer
; @@: add esi, IPBUFFSIZE
loop @b
 
; we have resend buffer location in esi
; mov ecx, IPBUFFSIZE
 
; copy data across
push edi
cld
rep movsb
pop edi
;-----------------------------------------------------------------
;
; TCP_add_to_queue:
;
; Queue a TCP packet for sending
;
; IN: [esp] pointer to buffer
; [esp + 4] size of buffer
; ebx = driver struct
; esi = sender proc
; edx = acknum
; OUT: /
;
;-----------------------------------------------------------------
 
; queue Packet
; mov eax, NET1OUT_QUEUE
; mov edx, [IP_LIST]
; cmp edx, [edi + IP_Packet.DestinationAddress]
; jne .not_local
; mov eax, IPIN_QUEUE
align 4
TCP_add_to_queue:
 
.not_local:
pop ebx
; call queue
cmp [TCP_OUT_QUEUE], TCP_QUEUE_SIZE
jge .full
 
.tth005:
popad
mov ecx, TCP_QUEUE_SIZE
mov eax, TCP_OUT_QUEUE+4
 
inc ecx
add esi, 8
jmp .next_resendq
.loop:
cmp [eax + tcp_out_queue_entry.data_ptr], 0
je .found_it
add eax, tcp_out_queue_entry.size
loop .loop
 
.exit:
.full: ; silently discard the packet
call kernel_free
add esp, 4
 
ret
 
.found_it: ; eax point to empty queue entry
 
pop [eax + tcp_out_queue_entry.data_ptr]
pop [eax + tcp_out_queue_entry.data_size]
mov [eax + tcp_out_queue_entry.ttl], 1 ; send immediately
mov [eax + tcp_out_queue_entry.retries], TCP_RETRIES
mov [eax + tcp_out_queue_entry.owner], ebx
mov [eax + tcp_out_queue_entry.sendproc], esi
mov [eax + tcp_out_queue_entry.ack_num], edx
 
 
ret
 
 
;-----------------------------------------------------------------
;
; TCP_Handler:
; TCP_handler:
;
; Called by IPv4_handler,
; this procedure will inject the tcp data diagrams in the application sockets.
285,509 → 327,330
;
;-----------------------------------------------------------------
 
TCP_Handler :
align 4
TCP_handler :
 
 
DEBUGF 1,"TCP_Handler\n"
 
jmp .exit ;;;;
 
; Look for a socket where
; IP Packet TCP Destination Port = local Port
; IP Packet SA = Remote IP
; IP Packet TCP Source Port = remote Port
; IP Packet SA = Remote IP OR = 0
; IP Packet TCP Source Port = remote Port OR = 0
 
mov ebx, net_sockets
 
.next_socket.1:
mov ebx, [ebx + SOCKET.NextPtr]
.socket_loop:
mov ebx, [ebx + SOCKET_head.NextPtr]
or ebx, ebx
jz .next_socket.1.exit
jz .dump
 
; DEBUGF 1, "K : tcp_rx - 1.dport: %x - %x\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4
mov ax, [edx + TCP_Packet.DestinationPort]
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort], ax
jne .socket_loop
 
mov ax, [edx + TCP_Packet.DestinationPort] ; get the dest. port from the TCP hdr
cmp [ebx + SOCKET.LocalPort], ax ; get the dest. port from the TCP hdr
jne .next_socket.1 ; different - try next socket
mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
cmp eax, esi
je @f
test eax, eax
jne .socket_loop
@@:
 
; DEBUGF 1, "K : tcp_rx - 1.addr: %x - %x\n", [edx + IP_Packet.SourceAddress], [ebx + SOCKET.RemoteIP]
mov ax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort]
cmp [edx + TCP_Packet.SourcePort] , ax
je .change_state
test ax, ax
jne .socket_loop
 
mov eax, esi ;[edx + IP_Packet.SourceAddress] ; get the source IP Addr from the IP hdr
cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP
jne .next_socket.1 ; different - try next socket
.change_state:
 
; DEBUGF 1, "K : tcp_rx - 1.sport: %x - %x\n", [edx + 20 + TCP_Packet.SourcePort]:4, [ebx + SOCKET.RemotePort]:4
push ebx
lea ebx, [ebx + SOCKET_head.lock]
call wait_mutex
pop ebx
 
mov ax, [edx + TCP_Packet.SourcePort] ; get the source port from the TCP hdr
cmp [ebx + SOCKET.RemotePort], ax ; compare with socket's remote port
jne .next_socket.1 ; different - try next socket
;----------------------------------
; ebx is pointer to socket
; ecx is size of tcp packet
; edx is pointer to tcp packet
 
; We have a complete match - use this socket
jmp .change_state
; as a Packet has been received, update the TCB timer
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBTimer], TWOMSL
 
.next_socket.1.exit:
; If the received Packet has an ACK bit set, remove any Packets in the resend queue that this received Packet acknowledges
test [edx + TCP_Packet.Flags], TH_ACK
jz .call_handler ; No ACK, so no data yet
 
; If we got here, there was no match
; Look for a socket where
; IP Packet TCP Destination Port = local Port
; IP Packet SA = Remote IP
; socket remote Port = 0
mov eax, [edx + TCP_Packet.SequenceNumber] ; Calculate sequencenumber in eax
bswap eax ;
add eax, ecx ;
 
mov ebx, net_sockets
cmp [TCP_OUT_QUEUE], 0
je .call_handler
 
.next_socket.2:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .next_socket.2.exit
push ecx
mov ecx, TCP_QUEUE_SIZE
mov esi, TCP_OUT_QUEUE+4
 
; DEBUGF 1, "K : tcp_rx - 2.dport: %x - %x\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4
.loop:
cmp [esi + tcp_out_queue_entry.data_ptr], 0
jne .maybe_next
cmp [esi + tcp_out_queue_entry.ack_num], eax
jg .maybe_next
 
mov ax, [edx + TCP_Packet.DestinationPort] ; get the dest. port from the TCP hdr
cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port
jne .next_socket.2 ; different - try next socket
push [esi + tcp_out_queue_entry.data_ptr]
mov [esi + tcp_out_queue_entry.data_ptr], 0
dec [TCP_OUT_QUEUE]
call kernel_free
 
; DEBUGF 1, "K : tcp_rx - 2.addr: %x - %x\n", [edx + IP_Packet.SourceAddress], [ebx + SOCKET.RemoteIP]
.maybe_next:
add esi, tcp_out_queue_entry.size
loop .loop
pop ecx
 
; mov eax, esi ;[edx + IP_Packet.SourceAddress] ; get the source IP Addr from the IP hdr
cmp [ebx + SOCKET.RemoteIP], esi ; compare with socket's remote IP
jne .next_socket.2 ; different - try next socket
.call_handler:
; Call handler for given TCB state
mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState]
cmp eax, TCB_LISTEN
jb .exit
cmp eax, TCB_CLOSED
ja .exit
 
; DEBUGF 1, "K : tcp_rx - 2.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4
shl eax, 2
add eax, TCBStateHandler - 4
 
cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0
jne .next_socket.2 ; different - try next socket
push .exit
jmp eax
 
; We have a complete match - use this socket
jmp .change_state
 
.next_socket.2.exit:
 
; If we got here, there was no match
; Look for a socket where
; IP Packet TCP Destination Port = local Port
; socket Remote IP = 0
; socket remote Port = 0
 
mov ebx, net_sockets
 
.next_socket.3:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .next_socket.3.exit
 
; DEBUGF 1, "K : tcp_rx - 3.dport: %x - %x\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4
 
mov ax, [edx + TCP_Packet.DestinationPort] ; get destination port from the TCP hdr
cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port
jne .next_socket.3 ; different - try next socket
 
; DEBUGF 1, "K : tcp_rx - 3.addr: 00000000 - %x\n", [ebx + SOCKET.RemoteIP]
 
cmp [ebx + SOCKET.RemoteIP], 0 ; only match a socket remote IP of 0
jne .next_socket.3 ; different - try next socket
 
; DEBUGF 1, "K : tcp_rx - 3.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4
 
cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0
jne .next_socket.3 ; different - try next socket
 
; We have a complete match - use this socket
jmp .change_state
 
.next_socket.3.exit:
 
; If we got here, we need to reject the Packet
 
DEBUGF 1, "K : tcp_rx - dumped\n"
; DEBUGF 1, "K : --------: %x-%x-%x (flags: %x)\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [edx + IP_Packet.SourceAddress], [edx + 20 + TCP_Packet.SourcePort]:4, [edx + 20 + TCP_Packet.Flags]:2
 
; inc [dumped_rx_count]
jmp .exit
 
.change_state:
 
; We have a valid socket/TCB, so call the TCB State Machine for that skt.
; socket is pointed to by ebx
; IP Packet is pointed to by edx
; IP buffer number is on stack ( it will be popped at the end)
 
stdcall tcpStateMachine, ebx
 
.exit:
mov [ebx + SOCKET_head.lock], 0
 
.dump:
DEBUGF 1,"Dumping TCP packet\n"
call kernel_free
add esp, 4 ; pop (balance stack)
 
ret
ret
 
 
 
;-----------------------------------------------------------------
;
; IN: eax = dest ip
; ebx = source ip
; ecx = data length
; edx = remote port shl 16 + local port
; esi = data offset
; TCP_socket_send
;
; IN: eax = socket pointer
; ecx = number of bytes to send
; esi = pointer to data
;
;-----------------------------------------------------------------
 
TCP_create_Packet:
align 4
TCP_socket_send:
 
DEBUGF 1,"Create TCP Packet\n"
;***************************************************************************
; Function
; buildTCPPacket
;
; Description
; builds an IP Packet with TCP data fully populated for transmission
; You may destroy any and all registers
; TCP control flags specified in bl
; This TCB is in [sktAddr]
; User data pointed to by esi
; Data length in ecx
; Transmit buffer number in eax
;
;***************************************************************************
DEBUGF 1,"Creating TCP Packet\n"
 
push ecx ; Save data length
mov di , IP_PROTO_TCP
 
add ecx, UDP_Packet.Data
mov di , IP_PROTO_UDP
; Create an IPv4 Packet of the correct size
push eax
mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
 
; dx = fragment id
 
call IPv4_create_Packet ; TODO: figure out a way to choose between IPv4 and IPv6
cmp edi, -1
je .exit
 
mov [edi + TCP_Packet.Flags], bl ; TCP flags
 
; mov ebx, [sockAddr];---------------------------------------------------------- eof
 
; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
 
; Fill in the IP header ( some data is in the socket descriptor)
mov eax, [ebx + SOCKET.LocalIP]
; mov [edx + IP_Packet.SourceAddress], eax
mov eax, [ebx + SOCKET.RemoteIP]
; mov [edx + IP_Packet.DestinationAddress], eax
 
; mov [edx + IP_Packet.VersionAndIHL], 0x45
; mov [edx + IP_Packet.TypeOfService], 0
 
pop eax ; Get the TCP data length
; meanwhile, create the pseudoheader in stack,
; (now that we still have all the variables that are needed.)
push cx
push di
push eax
push ebx
 
add eax, 20 + 20 ; add IP header and TCP header lengths
rol ax, 8
; mov [edx + IP_Packet.TotalLength], ax
; mov [edx + IP_Packet.Identification], 0
; mov [edx + IP_Packet.FlagsAndFragmentOffset], 0x0040
; mov [edx + IP_Packet.TimeToLive], 0x20
; mov [edx + IP_Packet.Protocol], PROTOCOL_TCP
 
; Checksum left unfilled
; mov [edx + IP_Packet.HeaderChecksum], 0
push ecx esi eax ; save some variables for later
add ecx, TCP_Packet.Data
call IPv4_create_packet
cmp edi, -1
je .fail
 
; Fill in the TCP header (some data is in the socket descriptor)
mov ax, [ebx + SOCKET.LocalPort]
mov [edx + 20 + TCP_Packet.SourcePort], ax ; Local Port
pop esi
 
mov ax, [ebx + SOCKET.RemotePort]
mov [edx + 20 + TCP_Packet.DestinationPort], ax ; desitination Port
; Now add the TCP header to the IPv4 packet
 
; Checksum left unfilled
mov [edx + 20 + TCP_Packet.Checksum], 0
push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
pop [edi + TCP_Packet.SequenceNumber]
 
; sequence number
mov eax, [ebx + SOCKET.SND_NXT]
mov [edx + 20 + TCP_Packet.SequenceNumber], eax
push dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort]
pop dword [edi + TCP_Packet.SourcePort]
 
; ack number
mov eax, [ebx + SOCKET.RCV_NXT]
mov [edx + 20 + TCP_Packet.AckNumber], eax
 
; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size)
; 768 bytes seems better
mov [edx + 20 + TCP_Packet.Window], 0x0003
push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
pop [edi + TCP_Packet.AckNumber]
 
; Urgent pointer (0)
mov [edx + 20 + TCP_Packet.UrgentPointer], 0
mov al, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.flags]
mov [edi + TCP_Packet.Flags], al
 
; data offset ( 0x50 )
mov [edx + 20 + TCP_Packet.DataOffset], 0x50
mov [edi + TCP_Packet.Window], 0x0005 ; 1280 bytes ;;; TODO: read RFC !
mov [edi + TCP_Packet.UrgentPointer], 0
mov [edi + TCP_Packet.DataOffset], 0x50
mov [edi + TCP_Packet.Checksum], 0
 
pop ecx ; count of bytes to send
mov ebx, ecx ; need the length later
; Copy the data
mov esi, [esp]
mov ecx, [esp+4]
add edi, TCP_Packet.Data
 
cmp ebx, 0
jz @f
shr ecx, 1
jnc .nb
movsb
.nb: shr ecx, 1
jnc .nw
movsw
.nw: rep movsd
 
mov edi, edx
add edi, 40
cld
rep movsb ; copy the data across
; Now, calculate the checksum for pseudoheader
xor edx, edx
mov ecx, 12
mov esi, esp
call checksum_1
add esp, 12 ; remove the pseudoheader from stack
; And that of the data
pop esi
pop ecx
call checksum_1
; Now create the final checksum and store it in TCP header
call checksum_2
mov [edi + TCP_Packet.Checksum], dx
 
@@: ; we have edx as IPbuffer ptr.
; Fill in the TCP checksum
; First, fill in pseudoheader
; mov eax, [edx + IP_Packet.SourceAddress]
; mov [pseudoHeader], eax
; mov eax, [edx + IP_Packet.DestinationAddress]
; mov [pseudoHeader + 4], eax
; mov word[pseudoHeader + 8], PROTOCOL_TCP shl 8 + 0
; add ebx, 20
; mov [pseudoHeader + 10], bh
; mov [pseudoHeader + 11], bl
;
; mov eax, pseudoHeader
; mov [checkAdd1], eax
; mov word[checkSize1], 12
; mov eax, edx
; add eax, 20
; mov [checkAdd2], eax
; mov eax, ebx
; mov [checkSize2], ax
;
; call checksum
; And now, send it!
DEBUGF 1,"Sending TCP Packet to device %x\n", ebx
mov esi, ETH_sender
mov edx, [edi + TCP_Packet.AckNumber]
jmp TCP_add_to_queue
 
; store it in the TCP checksum ( in the correct order! )
; mov ax, [checkResult]
; rol ax, 8
; mov [edx + 20 + TCP_Packet.Checksum], ax
 
; Fill in the IP header checksum
; movzx eax, byte [edx + IP_Packet.VersionAndIHL] ; Calculate Header length by using IHL field
; and eax, 0x0000000F ;
; shl eax, 2 ;
;
stdcall checksum_jb, edx, eax ; buf_ptr, buf_size
rol ax, 8
; mov [edx + IP_Packet.HeaderChecksum], ax
 
 
.exit:
 
call kernel_free
add esp, 4 ; pop (balance stack)
 
.fail:
add esp, 12+4
ret
;endp
 
 
; Increments the 32 bit value pointed to by esi in internet order
proc inc_inet_esi stdcall
; push eax
; mov eax, [esi]
; bswap eax
; inc eax
; bswap eax
; mov [esi], eax
; pop eax
; ret
inc byte[esi+0]
adc byte[esi+1],0
adc byte[esi+2],0
adc byte[esi+3],0
endp
 
 
; Increments the 32 bit value pointed to by esi in internet order
; by the value in ecx
proc add_inet_esi stdcall
push eax
mov eax, [esi]
bswap eax
add eax, ecx
bswap eax
mov [esi], eax
pop eax
ret
endp
 
 
iglobal
TCBStateHandler dd \
stateTCB_LISTEN, \
stateTCB_SYN_SENT, \
stateTCB_SYN_RECEIVED, \
stateTCB_ESTABLISHED, \
stateTCB_FIN_WAIT_1, \
stateTCB_FIN_WAIT_2, \
stateTCB_CLOSE_WAIT, \
stateTCB_CLOSING, \
stateTCB_LAST_ACK, \
stateTCB_TIME_WAIT, \
stateTCB_CLOSED
endg
 
 
;***************************************************************************
; Function
; tcpStateMachine
;-----------------------------------------------------------------
;
; Description
; TCP state machine
; This is a kernel function, called by tcp_rx
; TCP_send_ack
;
; IP buffer address given in edx
; Socket/TCB address in ebx
; IN: eax = socket pointer
; bl = flags
;
; The IP buffer will be released by the caller
;***************************************************************************
;-----------------------------------------------------------------
 
proc tcpStateMachine stdcall, sockAddr:DWORD
; as a Packet has been received, update the TCB timer
mov [ebx + SOCKET.TCBTimer], TWOMSL
align 4
TCP_send_ack:
 
; If the received Packet has an ACK bit set,
; remove any Packets in the resend queue that this
; received Packet acknowledges
pushad
test [edx + 20 + TCP_Packet.Flags], TH_ACK
jz .call_handler ; No ACK, so no data yet
DEBUGF 1,"Creating TCP ACK\n"
 
; get skt number in eax
stdcall net_socket_addr_to_num, ebx
mov di , IP_PROTO_TCP
mov cx , TCP_Packet.Data
 
; The ack number is in [edx + 28], inet format
; skt in eax
push bx eax
 
mov esi, resendQ
xor ecx, ecx
; Create an IPv4 Packet of the correct size
mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
 
.next_resendq:
; cmp ecx, NUMRESENDENTRIES
je .call_handler ; None left
cmp [esi + 4], eax
je @f ; found one
inc ecx
add esi, 8
jmp .next_resendq
call IPv4_create_packet
cmp edi, -1
je .fail
 
@@: ; Can we delete this buffer?
; Fill in the TCP header
pop esi
 
; If yes, goto @@. No, goto .next_resendq
; Get Packet data address
push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
pop [edi + TCP_Packet.SequenceNumber]
 
push ecx
; Now get buffer location, and copy buffer across. argh! more copying,,
; imul edi, ecx, IPBUFFSIZE
; add edi, resendBuffer
push dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort]
pop dword [edi + TCP_Packet.SourcePort]
 
; we have dest buffer location in edi. incoming Packet in edx.
; Get this Packets sequence number
; preserve al, ecx, esi, edx
mov ecx, [edi + 20 + TCP_Packet.SequenceNumber]
bswap ecx
movzx ebx, word[edi + 2]
xchg bl, bh
sub ebx, 40
add ecx, ebx ; ecx is now seq# of last byte +1, intel format
push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
pop [edi + TCP_Packet.AckNumber]
 
; get recievd ack #, in intel format
mov ebx, [edx + 20 + TCP_Packet.AckNumber]
bswap ebx
pop cx
mov [edi + TCP_Packet.Flags], cl
mov [edi + TCP_Packet.Window], 0x0005 ; 1280 bytes
mov [edi + TCP_Packet.UrgentPointer], 0
mov [edi + TCP_Packet.DataOffset], 0x50
 
cmp ebx, ecx ; Finally. ecx = rx'ed ack. ebx = last byte in que
; DANGER! need to handle case that we have just
; passed the 2**32, and wrapped round!
pop ecx
jae @f ; if rx > old, delete old
push eax edx
 
inc ecx
add esi, 8
jmp .next_resendq
push word TCP_Packet.Data shl 8
push IP_PROTO_TCP
push [esi + SOCKET_head.end + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
push [esi + SOCKET_head.end + SOCKET_head.end + IPv4_SOCKET.LocalIP]
 
@@: mov dword[esi + 4], 0
inc ecx
add esi, 8
jmp .next_resendq
; Now, calculate the checksum for pseudoheader
xor edx, edx
mov ecx, 12
mov esi, esp
call checksum_1
add esp, 12 ; remove the pseudoheader from stack
; Now create the final checksum and store it in TCP header
call checksum_2
mov [edi + TCP_Packet.Checksum], dx
 
.call_handler:
popad
; And now, send it!
DEBUGF 1,"Sending TCP Packet to device %x\n", ebx
mov esi, ETH_sender
mov edx, [edi + TCP_Packet.AckNumber]
jmp TCP_add_to_queue
 
; Call handler for given TCB state
.fail:
add esp, 12+4
ret
 
mov eax, [ebx + SOCKET.TCBState]
cmp eax, TCB_LISTEN
jb .exit
cmp eax, TCB_CLOSED
ja .exit
 
stdcall [TCBStateHandler + (eax - 1) * 4], [sockAddr]
 
.exit:
ret
endp
 
 
proc stateTCB_LISTEN stdcall, sockAddr:DWORD
align 4
stateTCB_LISTEN:
; In this case, we are expecting a SYN Packet
; For now, if the Packet is a SYN, process it, and send a response
; If not, ignore it
 
; Look at control flags
test [edx + 20 + TCP_Packet.Flags], TH_SYN
test [edx + TCP_Packet.Flags], TH_SYN
jz .exit
 
; We have a SYN. update the socket with this IP Packets details,
; And send a response
 
; mov eax, [edx + IP_Packet.SourceAddress]
; mov [ebx + SOCKET.RemoteIP], eax
; mov ax, [edx + 20 + TCP_Packet.SourcePort]
; mov [ebx + SOCKET.RemotePort], ax
; mov eax, [edx + 20 + TCP_Packet.SequenceNumber]
; mov [ebx + SOCKET.IRS], eax
; mov [ebx + SOCKET.RCV_NXT], eax
; lea esi, [ebx + SOCKET.RCV_NXT]
; call inc_inet_esi ; RCV.NXT
; mov eax, [ebx + SOCKET.ISS]
; mov [ebx + SOCKET.SND_NXT], eax
;
; Now construct the response, and queue for sending by IP
; mov eax, EMPTY_QUEUE
; call dequeue
; cmp ax, NO_BUFFER
; je .exit
mov [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP], esi ; IP source address
mov ax, [edx + TCP_Packet.SourcePort]
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], ax
mov eax, [edx + TCP_Packet.SequenceNumber]
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.IRS], eax
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], eax
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
inc_INET esi ; RCV.NXT
mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.ISS]
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT], eax
 
push eax
; Now construct the response
mov bl, TH_SYN + TH_ACK
xor ecx, ecx
xor esi, esi
; stdcall build_tcp_Packet, [sockAddr]
call TCP_send_ack
 
; mov eax, NET1OUT_QUEUE
;;; mov edx, [stack_ip]
mov ecx, [sockAddr]
cmp edx, [ecx + SOCKET.RemoteIP]
jne .not_local
; mov eax, IPIN_QUEUE
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_SYN_RECEIVED
 
.not_local:
; Send it.
pop ebx
;;; call queue
 
mov esi, [sockAddr]
mov [esi + SOCKET.TCBState], TCB_SYN_RECEIVED
 
; increment SND.NXT in socket
add esi, SOCKET.SND_NXT
call inc_inet_esi
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
inc_INET esi
 
.exit:
ret
endp
 
 
proc stateTCB_SYN_SENT stdcall, sockAddr:DWORD
align 4
stateTCB_SYN_SENT:
; We are awaiting an ACK to our SYN, with a SYM
; Look at control flags - expecting an ACK
 
mov al, [edx + 20 + TCP_Packet.Flags]
mov al, [edx + TCP_Packet.Flags]
and al, TH_SYN + TH_ACK
cmp al, TH_SYN + TH_ACK
je .syn_ack
795,139 → 658,89
test al, TH_SYN
jz .exit
 
mov [ebx + SOCKET.TCBState], TCB_SYN_RECEIVED
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_SYN_RECEIVED
push TH_SYN + TH_ACK
jmp .send
 
.syn_ack:
mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_ESTABLISHED
push TH_ACK
 
.send:
; Store the recv.nxt field
mov eax, [edx + 20 + TCP_Packet.SequenceNumber]
mov eax, [edx + TCP_Packet.SequenceNumber]
 
; Update our recv.nxt field
mov [ebx + SOCKET.RCV_NXT], eax
lea esi, [ebx + SOCKET.RCV_NXT]
call inc_inet_esi
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], eax
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
inc_INET esi
 
; Send an ACK
; Now construct the response, and queue for sending by IP
; mov eax, EMPTY_QUEUE
; call dequeue
; cmp ax, NO_BUFFER
pop ebx
je .exit
call TCP_send_ack
 
push eax
 
xor ecx, ecx
xor esi, esi
; stdcall build_tcp_Packet, [sockAddr]
 
; mov eax, NET1OUT_QUEUE
;;; mov edx, [stack_ip]
; mov ecx, [sockAddr]
; cmp edx, [ecx + SOCKET.RemoteIP]
; jne .not_local
; mov eax, IPIN_QUEUE
 
.not_local:
; Send it.
pop ebx
;;; call queue
 
.exit:
ret
endp
 
 
proc stateTCB_SYN_RECEIVED stdcall, sockAddr:DWORD
 
align 4
stateTCB_SYN_RECEIVED:
; In this case, we are expecting an ACK Packet
; For now, if the Packet is an ACK, process it,
; If not, ignore it
 
test [edx + 20 + TCP_Packet.Flags], TH_RST
test [edx + TCP_Packet.Flags], TH_RST
jz .check_ack
 
push [ebx + SOCKET.OrigRemotePort] [ebx + SOCKET.OrigRemoteIP]
pop [ebx + SOCKET.RemoteIP] [ebx + SOCKET.RemotePort]
push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemotePort]
pop [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort]
push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemoteIP]
pop [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
 
mov [ebx + SOCKET.TCBState], TCB_LISTEN
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_LISTEN
jmp .exit
 
.check_ack:
; Look at control flags - expecting an ACK
test [edx + 20 + TCP_Packet.Flags], TH_ACK
test [edx + TCP_Packet.Flags], TH_ACK
jz .exit
 
mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_ESTABLISHED
 
.exit:
ret
endp
 
 
proc stateTCB_ESTABLISHED stdcall, sockAddr:DWORD
 
align 4
stateTCB_ESTABLISHED:
; Here we are expecting data, or a request to close
; OR both...
 
; Did we receive a FIN or RST?
test [edx + 20 + TCP_Packet.Flags], TH_FIN
test [edx + TCP_Packet.Flags], TH_FIN
jz .check_ack
 
; It was a fin or reset.
 
; Remove resend entries from the queue - I dont want to send any more data
pushad
; Send an ACK to that fin, and enter closewait state
 
; get skt #
stdcall net_socket_addr_to_num, ebx
 
mov esi, resendQ
mov ecx, 0
 
.next_resendq:
; cmp ecx, NUMRESENDENTRIES
; je .last_resendq ; None left
; cmp [esi + 4], eax
; je @f ; found one
; inc ecx
; add esi, 8
; jmp .next_resendq
 
@@: mov dword[esi + 4], 0
inc ecx
add esi, 8
jmp .next_resendq
 
.last_resendq:
popad
 
@@: ; Send an ACK to that fin, and enter closewait state
 
mov [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT
lea esi, [ebx + SOCKET.RCV_NXT]
mov eax, [esi] ; save original
call inc_inet_esi
;; jmp ste_ack - NO, there may be data
 
.check_ack:
; Check that we received an ACK
test [edx + 20 + TCP_Packet.Flags], TH_ACK
test [edx + TCP_Packet.Flags], TH_ACK
jz .exit
 
; TODO - done, I think!
; First, look at the incoming window. If this is less than or equal to 1024,
; Set the socket window timer to 1. This will stop an additional Packets being queued.
; ** I may need to tweak this value, since I do not know how many Packets are already queued
mov cx, [edx + 20 + TCP_Packet.Window]
mov cx, [edx + TCP_Packet.Window]
xchg cl, ch
cmp cx, 1024
ja @f
 
mov [ebx + SOCKET.wndsizeTimer], 1
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 1
 
@@: ; OK, here is the deal
; My recv.nct field holds the seq of the expected next rec byte
938,117 → 751,41
; recv.nxt is in dword [edx+24], in inet format
; recv seq is in [sktAddr]+56, in inet format
; just do a comparision
mov ecx, [ebx + SOCKET.RCV_NXT]
cmp [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT
mov ecx, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_CLOSE_WAIT
jne @f
mov ecx, eax
 
@@: cmp ecx, [edx + 20 + TCP_Packet.SequenceNumber]
@@: cmp ecx, [edx + TCP_Packet.SequenceNumber]
jne .ack
 
test ecx, ecx
jnz .data
 
; Read the data bytes, store in socket buffer
; movzx ecx, [edx + IP_Packet.TotalLength]
xchg cl, ch
sub ecx, 40 ; Discard 40 bytes of header
ja .data ; Read data, if any
 
; If we had received a fin, we need to ACK it.
cmp [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_CLOSE_WAIT
je .ack
jmp .exit
 
.data:
push ebx
add ebx, SOCKET.lock
call wait_mutex
pop ebx
mov esi, [esp + 4]
sub edx, esi
mov edi, edx
call socket_internal_receiver
 
push ecx
push [ebx + SOCKET.PID] ; get socket owner PID
mov eax, [ebx + SOCKET.rxDataCount]
add eax, ecx
cmp eax, SOCKETBUFFSIZE - SOCKETHEADERSIZE
ja .overflow
 
mov [ebx + SOCKET.rxDataCount], eax ; increment the count of bytes in buffer
 
; point to the location to store the data
lea edi, [ebx + eax + SOCKETHEADERSIZE]
sub edi, ecx
 
add edx, 40 ; edx now points to the data
mov esi, edx
 
cld
rep movsb ; copy the data across
mov [ebx + SOCKET.lock], 0 ; release mutex
 
; flag an event to the application
pop eax
mov ecx, 1
mov esi, TASK_DATA + TASKDATA.pid
 
.next_pid:
cmp [esi], eax
je .found_pid
inc ecx
add esi, 0x20
cmp ecx, [TASK_COUNT]
jbe .next_pid
 
.found_pid:
shl ecx, 8
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event
 
pop ecx
 
; Update our recv.nxt field
lea esi, [ebx + SOCKET.RCV_NXT]
call add_inet_esi
 
.ack:
; Send an ACK
; Now construct the response, and queue for sending by IP
; mov eax, EMPTY_QUEUE
; call dequeue
; cmp ax, NO_BUFFER
je .exit
 
push eax
 
mov bl, TH_ACK
xor ecx, ecx
xor esi, esi
; stdcall build_tcp_Packet, [sockAddr]
 
; mov eax, NET1OUT_QUEUE
 
;;; mov edx, [stack_ip]
; mov ecx, [sockAddr]
; cmp edx, [ecx + SOCKET.RemoteIP]
; jne .not_local
; mov eax, IPIN_QUEUE
 
.not_local:
; Send it.
pop ebx
;;; call queue
 
call TCP_send_ack
.exit:
ret
.overflow:
; no place in buffer
; so simply restore stack and exit
pop eax ecx
mov [ebx + SOCKET.lock], 0
ret
endp
 
 
proc stateTCB_FIN_WAIT_1 stdcall, sockAddr:DWORD
 
align 4
stateTCB_FIN_WAIT_1:
; We can either receive an ACK of a fin, or a fin
mov al, [edx + 20 + TCP_Packet.Flags]
mov al, [edx + TCP_Packet.Flags]
and al, TH_FIN + TH_ACK
 
cmp al, TH_ACK
1055,109 → 792,69
jne @f
 
; It was an ACK
mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_2
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_FIN_WAIT_2
jmp .exit
 
@@: mov [ebx + SOCKET.TCBState], TCB_CLOSING
@@: mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_CLOSING
cmp al, TH_FIN
je @f
mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT
 
@@: lea esi, [ebx + SOCKET.RCV_NXT]
call inc_inet_esi
 
@@: lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
inc_INET esi
; Send an ACK
; mov eax, EMPTY_QUEUE
; call dequeue
; cmp ax, NO_BUFFER
je .exit
 
push eax
 
mov bl, TH_ACK
xor ecx, ecx
xor esi, esi
; stdcall build_tcp_Packet, [sockAddr]
call TCP_send_ack
 
; mov eax, NET1OUT_QUEUE
;;; mov edx, [stack_ip]
; mov ecx, [sockAddr]
; cmp edx, [ecx + SOCKET.RemoteIP]
; jne .not_local
; mov eax, IPIN_QUEUE
 
.not_local:
; Send it.
pop ebx
;;; call queue
 
.exit:
ret
endp
 
 
proc stateTCB_FIN_WAIT_2 stdcall, sockAddr:DWORD
test [edx + 20 + TCP_Packet.Flags], TH_FIN
 
align 4
stateTCB_FIN_WAIT_2:
test [edx + TCP_Packet.Flags], TH_FIN
jz .exit
 
; Change state, as we have a fin
mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT
 
lea esi, [ebx + SOCKET.RCV_NXT]
call inc_inet_esi
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
inc_INET esi
 
; Send an ACK
; mov eax, EMPTY_QUEUE
; call dequeue
;; cmp ax, NO_BUFFER
; je .exit
 
push eax
 
mov bl, TH_ACK
xor ecx, ecx
xor esi, esi
; stdcall build_tcp_Packet, [sockAddr]
call TCP_send_ack
 
; mov eax, NET1OUT_QUEUE
;;; mov edx, [stack_ip]
mov ecx, [sockAddr]
cmp edx, [ecx + SOCKET.RemoteIP]
jne .not_local
; mov eax, IPIN_QUEUE
 
.not_local:
; Send it.
pop ebx
;;; call queue
 
.exit:
ret
endp
 
 
proc stateTCB_CLOSE_WAIT stdcall, sockAddr:DWORD
 
align 4
stateTCB_CLOSE_WAIT:
; Intentionally left empty
; socket_close_tcp handles this
ret
endp
 
 
proc stateTCB_CLOSING stdcall, sockAddr:DWORD
 
align 4
stateTCB_CLOSING:
; We can either receive an ACK of a fin, or a fin
test [edx + 20 + TCP_Packet.Flags], TH_ACK
test [edx + TCP_Packet.Flags], TH_ACK
jz .exit
 
mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT
 
.exit:
ret
endp
 
 
proc stateTCB_LAST_ACK stdcall, sockAddr:DWORD
align 4
stateTCB_LAST_ACK:
; Look at control flags - expecting an ACK
test [edx + 20 + TCP_Packet.Flags], TH_ACK
test [edx + TCP_Packet.Flags], TH_ACK
jz .exit
 
; delete the socket
1165,235 → 862,17
 
.exit:
ret
endp
 
 
proc stateTCB_TIME_WAIT stdcall, sockAddr:DWORD
align 4
stateTCB_TIME_WAIT:
ret
endp
 
 
proc stateTCB_CLOSED stdcall, sockAddr:DWORD
align 4
stateTCB_CLOSED:
ret
endp
 
 
 
;; [53.7] Send data through STREAM socket
;
; @param EBX is socket number
; @param ECX is application data size (number of bytes to send)
; @param EDX is pointer to application data buffer
; @return 0 (sent successfully) or -1 (error) in EAX
;;
;proc socket_write_tcp stdcall
;local sockAddr dd ?
 
; DEBUGF 1, "socket_write_tcp(0x%x)\n", ebx
stdcall net_socket_num_to_addr, ebx
or eax, eax
jz .error
 
mov ebx, eax
; mov [sockAddr], ebx
 
; If the sockets window timer is nonzero, do not queue Packet
cmp [ebx + SOCKET.wndsizeTimer], 0
jne .error
 
; mov eax, EMPTY_QUEUE
; call dequeue
; cmp ax, NO_BUFFER
; je .error
 
push eax
 
; Get the address of the callers data
mov edi, [TASK_BASE]
add edi, TASKDATA.mem_start
add edx, [edi]
mov esi, edx
 
pop eax
push eax
 
push ecx
mov bl, TH_ACK
; stdcall build_tcp_Packet, [sockAddr]
pop ecx
 
; Check destination IP address.
; If it is the local host IP, route it back to IP_RX
 
pop ebx
push ecx
 
; mov eax, NET1OUT_QUEUE
;;; TODO: get device id in edx
xor edx, edx
 
shl edx, 2
mov edx, [IP_LIST+edx]
; mov ecx, [sockAddr]
; cmp edx, [ecx + SOCKET.RemoteIP]
; jne .not_local
; mov eax, IPIN_QUEUE
 
.not_local:
pop ecx
push ebx ; save ipbuffer number
 
;;;; call queue
 
; mov esi, [sockAddr]
 
; increament SND.NXT in socket
; Amount to increment by is in ecx
add esi, SOCKET.SND_NXT
call add_inet_esi
 
pop ebx
 
; Copy the IP buffer to a resend queue
; If there isn't one, dont worry about it for now
mov esi, resendQ
mov ecx, 0
 
.next_resendq:
; cmp ecx, NUMRESENDENTRIES
je .exit ; None found
cmp dword[esi + 4], 0
je @f ; found one
inc ecx
add esi, 8
jmp .next_resendq
 
@@: push ebx
 
; OK, we have a buffer descriptor ptr in esi.
; resend entry # in ecx
; Populate it
; socket #
; retries count
; retry time
; fill IP buffer associated with this descriptor
 
; stdcall net_socket_addr_to_num, [sockAddr]
mov [esi + 4], eax
mov byte[esi + 1], TCP_RETRIES
mov word[esi + 2], TCP_TIMEOUT
 
inc ecx
; Now get buffer location, and copy buffer across. argh! more copying,,
; mov edi, resendBuffer - IPBUFFSIZE
 
; @@: add edi, IPBUFFSIZE
loop @b
 
; we have dest buffer location in edi
pop eax
; convert source buffer pointer eax to the absolute address
; mov ecx, IPBUFFSIZE
; mul ecx
; add eax, IPbuffs
; mov esi, eax
 
; do copy
; mov ecx, IPBUFFSIZE
; cld
rep movsb
 
.exit:
xor eax, eax
ret
 
.error:
or eax, -1
ret
;endp
 
 
 
;***************************************************************************
; Function
; checksum
;
; Description
; checkAdd1,checkAdd2, checkSize1, checkSize2, checkResult
; Dont break anything; Most registers are used by the caller
; This code is derived from the 'C' source, cksum.c, in the book
; Internetworking with TCP/IP Volume II by D.E. Comer
;
;***************************************************************************
 
 
checksum:
pusha
; mov eax, [checkAdd1]
xor edx, edx ; edx is the accumulative checksum
xor ebx, ebx
; mov cx, [checkSize1]
shr cx, 1
jz cs1_1
 
cs1:
mov bh, [eax]
mov bl, [eax + 1]
 
add eax, 2
add edx, ebx
 
loopw cs1
 
cs1_1:
; and word [checkSize1], 0x01
jz cs_test2
 
mov bh, [eax]
xor bl, bl
 
add edx, ebx
 
cs_test2:
; mov cx, [checkSize2]
cmp cx, 0
jz cs_exit ; Finished if no 2nd buffer
 
; mov eax, [checkAdd2]
 
shr cx, 1
jz cs2_1
 
cs2:
mov bh, [eax]
mov bl, [eax + 1]
 
add eax, 2
add edx, ebx
 
loopw cs2
 
cs2_1:
; and word [checkSize2], 0x01
jz cs_exit
 
mov bh, [eax]
xor bl, bl
 
add edx, ebx
 
cs_exit:
mov ebx, edx
 
shr ebx, 16
and edx, 0xffff
add edx, ebx
mov eax, edx
shr eax, 16
add edx, eax
not dx
 
; mov [checkResult], dx
popa
ret
 
/kernel/branches/net/network/udp.inc
75,8 → 75,34
UDP_handler:
 
DEBUGF 1,"UDP_Handler\n"
; TODO: First validate the header & checksum!
; First validate, checksum:
 
DEBUGF 1,"Real UDP checksum: %x\n", [edx + UDP_Packet.Checksum]:4
mov [edx + UDP_Packet.Checksum], 0
 
pusha
 
rol cx, 8
push cx
rol cx, 8
push word IP_PROTO_UDP shl 8
push edi
push esi
 
mov esi, edx
xor edx, edx
call checksum_1
; Checksum for pseudoheader
mov ecx, 12
mov esi, esp
call checksum_1
add esp, 12
call checksum_2
 
popa
 
 
 
; Look for a socket where
; IP Packet UDP Destination Port = local Port
; IP Packet SA = Remote IP
85,14 → 111,14
.try_more:
mov bx , [edx + UDP_Packet.DestinationPort] ; get the local port from the IP Packet's UDP header
.next_socket:
mov eax, [eax + SOCKET.NextPtr]
mov eax, [eax + SOCKET_head.NextPtr]
or eax, eax
jz .dump
cmp [eax + SOCKET.Domain], AF_INET4
cmp [eax + SOCKET_head.Domain], AF_INET4
jne .next_socket
cmp [eax + SOCKET.Type], IP_PROTO_UDP
cmp [eax + SOCKET_head.Type], IP_PROTO_UDP
jne .next_socket
cmp [eax + SOCKET.LocalPort], bx
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
jne .next_socket
 
DEBUGF 1,"found socket with matching domain, type and localport\n"
101,12 → 127,12
; I will accept the first incoming response to be the one
; I bind to, if the socket is opened with a destination IP address of
; 255.255.255.255
cmp [eax + SOCKET.RemoteIP], 0xffffffff
cmp [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], 0xffffffff
je .ok1
 
mov ebx, [esp]
mov ebx, [ebx + ETH_FRAME.Data + IPv4_Packet.SourceAddress] ; get the Source address from the IP Packet FIXME
cmp [eax + SOCKET.RemoteIP], ebx
cmp [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], ebx
jne .try_more ; Quit if the source IP is not valid, check for more sockets with this IP/PORT combination
 
 
115,10 → 141,10
 
mov bx, [edx + UDP_Packet.SourcePort] ; Remote port must be 0, or equal to sourceport of packet
 
cmp [eax + SOCKET.RemotePort], 0
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], 0
je .ok2
 
cmp [eax + SOCKET.RemotePort], bx
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], bx
jne .dump
 
.ok2:
130,10 → 156,21
sub cx , UDP_Packet.Data
mov dx , bx
 
call socket_internal_receiver
 
lea ebx, [eax + SOCKET_head.lock]
call wait_mutex
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], dx ; update remote port number
mov [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], edi
inc [UDP_PACKETS_RX]
 
pop edi
add esp, 4
 
sub esi, edi
xchg esi, edi
jmp socket_internal_receiver
 
 
.dump:
DEBUGF 1,"Dumping UDP packet\n"
call kernel_free
146,69 → 183,93
 
;-----------------------------------------------------------------
;
; Note: UDP works only on top of IP protocol :)
; UDP_socket_send
;
; IN: eax = dest ip
; ebx = source ip
; ecx = data length
; edx = remote port shl 16 + local port (both in INET order)
; esi = data offset
; IN: eax = socket pointer
; ecx = number of bytes to send
; esi = pointer to data
;
;-----------------------------------------------------------------
 
UDP_create_packet:
align 4
UDP_socket_send:
 
mov edx, dword [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort] ; load local port and remote port at once
DEBUGF 1,"local port: %x, remote port: %x\n",\
[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort]:4,\
[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort]:4
mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
 
DEBUGF 1,"Create UDP Packet (size=%u)\n",ecx
 
push edx esi
mov di , IP_PROTO_UDP
 
sub esp, 8 ; reserve some place in stack for later
 
; Create the pseudoheader in stack,
; (now that we still have all the variables that are needed.)
push dword IP_PROTO_UDP shl 8
push eax
push ebx
 
add ecx, UDP_Packet.Data
mov di , IP_PROTO_UDP
 
; dx = fragment id
; TODO: fill in: dx = fragment id
 
push edx esi
call IPv4_create_packet ; TODO: figure out a way to choose between IPv4 and IPv6
cmp edi, -1
je .fail
 
mov byte[edi + UDP_Packet.Length], ch
mov byte[edi + UDP_Packet.Length+1], cl
sub ecx , UDP_Packet.Data
mov [esp + 8 + 12], eax ; pointer to buffer start
mov [esp + 8 + 12 + 4], edx ; buffer size
 
rol cx, 8
mov [edi + UDP_Packet.Length], cx
mov [esp + 8 + 10], cx
ror cx, 8
 
pop esi
push edi
push edi ecx
sub ecx, UDP_Packet.Data
add edi, UDP_Packet.Data
push cx
shr ecx, 2
rep movsd
pop cx
mov ecx, [esp]
and cx , 3
rep movsb
pop edi
pop ecx edi
 
pop ecx
mov dword [edi + UDP_Packet.SourcePort], ecx ; notice: we write both port's at once
pop dword [edi + UDP_Packet.SourcePort] ; fill in both portnumbers
mov [edi + UDP_Packet.Checksum], 0 ; set it to zero, to calculate checksum
 
mov [edi + UDP_Packet.Checksum], 0
; Checksum for UDP header + data
xor edx, edx
mov esi, edi
call checksum_1
; Checksum for pseudoheader
mov ecx, 12
mov esi, esp
call checksum_1
add esp, 12 ; remove the pseudoheader from stack
; Now create the final checksum and store it in UDP header
call checksum_2
mov [edi + UDP_Packet.Checksum], dx
 
; TODO: calculate checksum using Pseudo-header (However, using a 0 as checksum shouldnt generate any errors :)
 
inc [UDP_PACKETS_TX]
 
push edx eax ; TODO: make this work on other protocols besides ethernet
DEBUGF 1,"Sending UDP Packet to device %x\n", ebx ;
jmp ETH_Sender ;
jmp ETH_sender ;
 
.exit:
ret
 
.fail:
; todo: queue the packet
add esp, 8
add esp, 8+12+8
ret
 
 
 
 
;---------------------------------------------------------------------------
;
; UDP_API